Page MenuHomeFreeBSD

D10293.id29244.diff
No OneTemporary

D10293.id29244.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -2121,10 +2121,18 @@
compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP"
dev/ixgbe/if_ixv.c optional ixv inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP"
+dev/ixgbe/if_bypass.c optional ix inet \
+ compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/if_fdir.c optional ix inet \
+ compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/if_sriov.c optional ix inet \
+ compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ix_txrx.c optional ix inet | ixv inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_osdep.c optional ix inet | ixv inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_sysctl.c optional ix inet | ixv inet \
+ compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_phy.c optional ix inet | ixv inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_api.c optional ix inet | ixv inet \
Index: sys/dev/ixgbe/if_bypass.c
===================================================================
--- /dev/null
+++ sys/dev/ixgbe/if_bypass.c
@@ -0,0 +1,797 @@
+/******************************************************************************
+
+ Copyright (c) 2001-2017, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*$FreeBSD$*/
+
+
+#include "ixgbe.h"
+
+/************************************************************************
+ * ixgbe_bypass_mutex_enter
+ *
+ * Mutex support for the bypass feature. Using a dual lock
+ * to facilitate a privileged access to the watchdog update
+ * over other threads.
+ ************************************************************************/
+static void
+ixgbe_bypass_mutex_enter(struct adapter *adapter)
+{
+ while (atomic_cmpset_int(&adapter->bypass.low, 0, 1) == 0)
+ usec_delay(3000);
+ while (atomic_cmpset_int(&adapter->bypass.high, 0, 1) == 0)
+ usec_delay(3000);
+ return;
+} /* ixgbe_bypass_mutex_enter */
+
+/************************************************************************
+ * ixgbe_bypass_mutex_clear
+ ************************************************************************/
+static void
+ixgbe_bypass_mutex_clear(struct adapter *adapter)
+{
+ while (atomic_cmpset_int(&adapter->bypass.high, 1, 0) == 0)
+ usec_delay(6000);
+ while (atomic_cmpset_int(&adapter->bypass.low, 1, 0) == 0)
+ usec_delay(6000);
+ return;
+} /* ixgbe_bypass_mutex_clear */
+
+/************************************************************************
+ * ixgbe_bypass_wd_mutex_enter
+ *
+ * Watchdog entry is allowed to simply grab the high priority
+ ************************************************************************/
+static void
+ixgbe_bypass_wd_mutex_enter(struct adapter *adapter)
+{
+ while (atomic_cmpset_int(&adapter->bypass.high, 0, 1) == 0)
+ usec_delay(3000);
+ return;
+} /* ixgbe_bypass_wd_mutex_enter */
+
+/************************************************************************
+ * ixgbe_bypass_wd_mutex_clear
+ ************************************************************************/
+static void
+ixgbe_bypass_wd_mutex_clear(struct adapter *adapter)
+{
+ while (atomic_cmpset_int(&adapter->bypass.high, 1, 0) == 0)
+ usec_delay(6000);
+ return;
+} /* ixgbe_bypass_wd_mutex_clear */
+
+/************************************************************************
+ * ixgbe_get_bypass_time
+ ************************************************************************/
+static void
+ixgbe_get_bypass_time(u32 *year, u32 *sec)
+{
+ struct timespec current;
+
+ *year = 1970; /* time starts at 01/01/1970 */
+ nanotime(&current);
+ *sec = current.tv_sec;
+
+ while(*sec > SEC_THIS_YEAR(*year)) {
+ *sec -= SEC_THIS_YEAR(*year);
+ (*year)++;
+ }
+} /* ixgbe_get_bypass_time */
+
+/************************************************************************
+ * ixgbe_bp_version
+ *
+ * Display the feature version
+ ************************************************************************/
+static int
+ixgbe_bp_version(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error = 0;
+ static int version = 0;
+ u32 cmd;
+
+ ixgbe_bypass_mutex_enter(adapter);
+ cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
+ cmd |= (BYPASS_EEPROM_VER_ADD << BYPASS_CTL2_OFFSET_SHIFT) &
+ BYPASS_CTL2_OFFSET_M;
+ if ((error = hw->mac.ops.bypass_rw(hw, cmd, &version) != 0))
+ goto err;
+ msec_delay(100);
+ cmd &= ~BYPASS_WE;
+ if ((error = hw->mac.ops.bypass_rw(hw, cmd, &version) != 0))
+ goto err;
+ ixgbe_bypass_mutex_clear(adapter);
+ version &= BYPASS_CTL2_DATA_M;
+ error = sysctl_handle_int(oidp, &version, 0, req);
+ return (error);
+err:
+ ixgbe_bypass_mutex_clear(adapter);
+ return (error);
+
+} /* ixgbe_bp_version */
+
+/************************************************************************
+ * ixgbe_bp_set_state
+ *
+ * Show/Set the Bypass State:
+ * 1 = NORMAL
+ * 2 = BYPASS
+ * 3 = ISOLATE
+ *
+ * With no argument the state is displayed,
+ * passing a value will set it.
+ ************************************************************************/
+static int
+ixgbe_bp_set_state(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error = 0;
+ static int state = 0;
+
+ /* Get the current state */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw,
+ BYPASS_PAGE_CTL0, &state);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error != 0)
+ return (error);
+ state = (state >> BYPASS_STATUS_OFF_SHIFT) & 0x3;
+
+ error = sysctl_handle_int(oidp, &state, 0, req);
+ if ((error != 0) || (req->newptr == NULL))
+ return (error);
+
+ /* Sanity check new state */
+ switch (state) {
+ case BYPASS_NORM:
+ case BYPASS_BYPASS:
+ case BYPASS_ISOLATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+ ixgbe_bypass_mutex_enter(adapter);
+ if ((error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+ BYPASS_MODE_OFF_M, state) != 0))
+ goto out;
+ /* Set AUTO back on so FW can receive events */
+ error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+ BYPASS_MODE_OFF_M, BYPASS_AUTO);
+out:
+ ixgbe_bypass_mutex_clear(adapter);
+ usec_delay(6000);
+ return (error);
+} /* ixgbe_bp_set_state */
+
+/************************************************************************
+ * The following routines control the operational
+ * "rules" of the feature, what behavior will occur
+ * when particular events occur.
+ * Values are:
+ * 0 - no change for the event (NOP)
+ * 1 - go to Normal operation
+ * 2 - go to Bypass operation
+ * 3 - go to Isolate operation
+ * Calling the entry with no argument just displays
+ * the current rule setting.
+ ************************************************************************/
+
+/************************************************************************
+ * ixgbe_bp_timeout
+ *
+ * This is to set the Rule for the watchdog,
+ * not the actual watchdog timeout value.
+ ************************************************************************/
+static int
+ixgbe_bp_timeout(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error = 0;
+ static int timeout = 0;
+
+ /* Get the current value */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &timeout);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (error);
+ timeout = (timeout >> BYPASS_WDTIMEOUT_SHIFT) & 0x3;
+
+ error = sysctl_handle_int(oidp, &timeout, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ /* Sanity check on the setting */
+ switch (timeout) {
+ case BYPASS_NOP:
+ case BYPASS_NORM:
+ case BYPASS_BYPASS:
+ case BYPASS_ISOLATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Set the new state */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+ BYPASS_WDTIMEOUT_M, timeout << BYPASS_WDTIMEOUT_SHIFT);
+ ixgbe_bypass_mutex_clear(adapter);
+ usec_delay(6000);
+ return (error);
+} /* ixgbe_bp_timeout */
+
+/************************************************************************
+ * ixgbe_bp_main_on
+ ************************************************************************/
+static int
+ixgbe_bp_main_on(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error = 0;
+ static int main_on = 0;
+
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_on);
+ main_on = (main_on >> BYPASS_MAIN_ON_SHIFT) & 0x3;
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (error);
+
+ error = sysctl_handle_int(oidp, &main_on, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ /* Sanity check on the setting */
+ switch (main_on) {
+ case BYPASS_NOP:
+ case BYPASS_NORM:
+ case BYPASS_BYPASS:
+ case BYPASS_ISOLATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Set the new state */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+ BYPASS_MAIN_ON_M, main_on << BYPASS_MAIN_ON_SHIFT);
+ ixgbe_bypass_mutex_clear(adapter);
+ usec_delay(6000);
+ return (error);
+} /* ixgbe_bp_main_on */
+
+/************************************************************************
+ * ixgbe_bp_main_off
+ ************************************************************************/
+static int
+ixgbe_bp_main_off(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error = 0;
+ static int main_off = 0;
+
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_off);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (error);
+ main_off = (main_off >> BYPASS_MAIN_OFF_SHIFT) & 0x3;
+
+ error = sysctl_handle_int(oidp, &main_off, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ /* Sanity check on the setting */
+ switch (main_off) {
+ case BYPASS_NOP:
+ case BYPASS_NORM:
+ case BYPASS_BYPASS:
+ case BYPASS_ISOLATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Set the new state */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+ BYPASS_MAIN_OFF_M, main_off << BYPASS_MAIN_OFF_SHIFT);
+ ixgbe_bypass_mutex_clear(adapter);
+ usec_delay(6000);
+ return (error);
+} /* ixgbe_bp_main_off */
+
+/************************************************************************
+ * ixgbe_bp_aux_on
+ ************************************************************************/
+static int
+ixgbe_bp_aux_on(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error = 0;
+ static int aux_on = 0;
+
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_on);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (error);
+ aux_on = (aux_on >> BYPASS_AUX_ON_SHIFT) & 0x3;
+
+ error = sysctl_handle_int(oidp, &aux_on, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ /* Sanity check on the setting */
+ switch (aux_on) {
+ case BYPASS_NOP:
+ case BYPASS_NORM:
+ case BYPASS_BYPASS:
+ case BYPASS_ISOLATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Set the new state */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+ BYPASS_AUX_ON_M, aux_on << BYPASS_AUX_ON_SHIFT);
+ ixgbe_bypass_mutex_clear(adapter);
+ usec_delay(6000);
+ return (error);
+} /* ixgbe_bp_aux_on */
+
+/************************************************************************
+ * ixgbe_bp_aux_off
+ ************************************************************************/
+static int
+ixgbe_bp_aux_off(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error = 0;
+ static int aux_off = 0;
+
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_off);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (error);
+ aux_off = (aux_off >> BYPASS_AUX_OFF_SHIFT) & 0x3;
+
+ error = sysctl_handle_int(oidp, &aux_off, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ /* Sanity check on the setting */
+ switch (aux_off) {
+ case BYPASS_NOP:
+ case BYPASS_NORM:
+ case BYPASS_BYPASS:
+ case BYPASS_ISOLATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Set the new state */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+ BYPASS_AUX_OFF_M, aux_off << BYPASS_AUX_OFF_SHIFT);
+ ixgbe_bypass_mutex_clear(adapter);
+ usec_delay(6000);
+ return (error);
+} /* ixgbe_bp_aux_off */
+
+/************************************************************************
+ * ixgbe_bp_wd_set - Set the Watchdog timer value
+ *
+ * Valid settings are:
+ * - 0 will disable the watchdog
+ * - 1, 2, 3, 4, 8, 16, 32
+ * - anything else is invalid and will be ignored
+ ************************************************************************/
+static int
+ixgbe_bp_wd_set(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error, tmp;
+ static int timeout = 0;
+ u32 mask, arg;
+
+ /* Get the current hardware value */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &tmp);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (error);
+ /*
+ * If armed keep the displayed value,
+ * else change the display to zero.
+ */
+ if ((tmp & (0x1 << BYPASS_WDT_ENABLE_SHIFT)) == 0)
+ timeout = 0;
+
+ error = sysctl_handle_int(oidp, &timeout, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ arg = 0x1 << BYPASS_WDT_ENABLE_SHIFT;
+ mask = BYPASS_WDT_ENABLE_M | BYPASS_WDT_VALUE_M;
+ switch (timeout) {
+ case 0: /* disables the timer */
+ arg = BYPASS_PAGE_CTL0;
+ mask = BYPASS_WDT_ENABLE_M;
+ break;
+ case 1:
+ arg |= BYPASS_WDT_1_5 << BYPASS_WDT_TIME_SHIFT;
+ break;
+ case 2:
+ arg |= BYPASS_WDT_2 << BYPASS_WDT_TIME_SHIFT;
+ break;
+ case 3:
+ arg |= BYPASS_WDT_3 << BYPASS_WDT_TIME_SHIFT;
+ break;
+ case 4:
+ arg |= BYPASS_WDT_4 << BYPASS_WDT_TIME_SHIFT;
+ break;
+ case 8:
+ arg |= BYPASS_WDT_8 << BYPASS_WDT_TIME_SHIFT;
+ break;
+ case 16:
+ arg |= BYPASS_WDT_16 << BYPASS_WDT_TIME_SHIFT;
+ break;
+ case 32:
+ arg |= BYPASS_WDT_32 << BYPASS_WDT_TIME_SHIFT;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Set the new watchdog */
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, mask, arg);
+ ixgbe_bypass_mutex_clear(adapter);
+
+ return (error);
+} /* ixgbe_bp_wd_set */
+
+/************************************************************************
+ * ixgbe_bp_wd_reset - Reset the Watchdog timer
+ *
+ * To activate this it must be called with any argument.
+ ************************************************************************/
+static int
+ixgbe_bp_wd_reset(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 sec, year;
+ int cmd, count = 0, error = 0;
+ int reset_wd = 0;
+
+ error = sysctl_handle_int(oidp, &reset_wd, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ cmd = BYPASS_PAGE_CTL1 | BYPASS_WE | BYPASS_CTL1_WDT_PET;
+
+ /* Resync the FW time while writing to CTL1 anyway */
+ ixgbe_get_bypass_time(&year, &sec);
+
+ cmd |= (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID;
+ cmd |= BYPASS_CTL1_OFFTRST;
+
+ ixgbe_bypass_wd_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rw(hw, cmd, &reset_wd);
+
+ /* Read until it matches what we wrote, or we time out */
+ do {
+ if (count++ > 10) {
+ error = IXGBE_BYPASS_FW_WRITE_FAILURE;
+ break;
+ }
+ error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL1, &reset_wd);
+ if (error != 0) {
+ error = IXGBE_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ } while (!hw->mac.ops.bypass_valid_rd(cmd, reset_wd));
+
+ reset_wd = 0;
+ ixgbe_bypass_wd_mutex_clear(adapter);
+ return (error);
+} /* ixgbe_bp_wd_reset */
+
+/************************************************************************
+ * ixgbe_bp_log - Display the bypass log
+ *
+ * You must pass a non-zero arg to sysctl
+ ************************************************************************/
+static int
+ixgbe_bp_log(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 cmd, base, head;
+ u32 log_off, count = 0;
+ static int status = 0;
+ u8 data;
+ struct ixgbe_bypass_eeprom eeprom[BYPASS_MAX_LOGS];
+ int i, error = 0;
+
+ error = sysctl_handle_int(oidp, &status, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ /* Keep the log display single-threaded */
+ while (atomic_cmpset_int(&adapter->bypass.log, 0, 1) == 0)
+ usec_delay(3000);
+
+ ixgbe_bypass_mutex_enter(adapter);
+
+ /* Find Current head of the log eeprom offset */
+ cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
+ cmd |= (0x1 << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
+ error = hw->mac.ops.bypass_rw(hw, cmd, &status);
+ if (error)
+ goto unlock_err;
+
+ /* wait for the write to stick */
+ msec_delay(100);
+
+ /* Now read the results */
+ cmd &= ~BYPASS_WE;
+ error = hw->mac.ops.bypass_rw(hw, cmd, &status);
+ if (error)
+ goto unlock_err;
+
+ ixgbe_bypass_mutex_clear(adapter);
+
+ base = status & BYPASS_CTL2_DATA_M;
+ head = (status & BYPASS_CTL2_HEAD_M) >> BYPASS_CTL2_HEAD_SHIFT;
+
+ /* address of the first log */
+ log_off = base + (head * 5);
+
+ /* extract all the log entries */
+ while (count < BYPASS_MAX_LOGS) {
+ eeprom[count].logs = 0;
+ eeprom[count].actions = 0;
+
+ /* Log 5 bytes store in on u32 and a u8 */
+ for (i = 0; i < 4; i++) {
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rd_eep(hw, log_off + i,
+ &data);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (EINVAL);
+ eeprom[count].logs += data << (8 * i);
+ }
+
+ ixgbe_bypass_mutex_enter(adapter);
+ error = hw->mac.ops.bypass_rd_eep(hw,
+ log_off + i, &eeprom[count].actions);
+ ixgbe_bypass_mutex_clear(adapter);
+ if (error)
+ return (EINVAL);
+
+ /* Quit if not a unread log */
+ if (!(eeprom[count].logs & BYPASS_LOG_CLEAR_M))
+ break;
+ /*
+ * Log looks good so store the address where it's
+ * Unread Log bit is so we can clear it after safely
+ * pulling out all of the log data.
+ */
+ eeprom[count].clear_off = log_off;
+
+ count++;
+ head = head ? head - 1 : BYPASS_MAX_LOGS;
+ log_off = base + (head * 5);
+ }
+
+ /* reverse order (oldest first) for output */
+ while (count--) {
+ int year;
+ u32 mon, days, hours, min, sec;
+ u32 time = eeprom[count].logs & BYPASS_LOG_TIME_M;
+ u32 event = (eeprom[count].logs & BYPASS_LOG_EVENT_M) >>
+ BYPASS_LOG_EVENT_SHIFT;
+ u8 action = eeprom[count].actions & BYPASS_LOG_ACTION_M;
+ u16 day_mon[2][13] = {
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+ {0, 31, 59, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
+ };
+ char *event_str[] = {"unknown", "main on", "aux on",
+ "main off", "aux off", "WDT", "user" };
+ char *action_str[] = {"ignore", "normal", "bypass", "isolate",};
+
+ /* verify vaild data 1 - 6 */
+ if (event < BYPASS_EVENT_MAIN_ON || event > BYPASS_EVENT_USR)
+ event = 0;
+
+ /*
+ * time is in sec's this year, so convert to something
+ * printable.
+ */
+ ixgbe_get_bypass_time(&year, &sec);
+ days = time / SEC_PER_DAY;
+ for (i = 11; days < day_mon[LEAP_YR(year)][i]; i--)
+ continue;
+ mon = i + 1; /* display month as 1-12 */
+ time -= (day_mon[LEAP_YR(year)][i] * SEC_PER_DAY);
+ days = (time / SEC_PER_DAY) + 1; /* first day is 1 */
+ time %= SEC_PER_DAY;
+ hours = time / (60 * 60);
+ time %= (60 * 60);
+ min = time / 60;
+ sec = time % 60;
+ device_printf(adapter->dev,
+ "UT %02d/%02d %02d:%02d:%02d %8.8s -> %7.7s\n",
+ mon, days, hours, min, sec, event_str[event],
+ action_str[action]);
+ cmd = BYPASS_PAGE_CTL2 | BYPASS_WE | BYPASS_CTL2_RW;
+ cmd |= ((eeprom[count].clear_off + 3)
+ << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
+ cmd |= ((eeprom[count].logs & ~BYPASS_LOG_CLEAR_M) >> 24);
+
+ ixgbe_bypass_mutex_enter(adapter);
+
+ error = hw->mac.ops.bypass_rw(hw, cmd, &status);
+
+ /* wait for the write to stick */
+ msec_delay(100);
+
+ ixgbe_bypass_mutex_clear(adapter);
+
+ if (error)
+ return (EINVAL);
+ }
+
+ status = 0; /* reset */
+ /* Another log command can now run */
+ while (atomic_cmpset_int(&adapter->bypass.log, 1, 0) == 0)
+ usec_delay(3000);
+ return (error);
+
+unlock_err:
+ ixgbe_bypass_mutex_clear(adapter);
+ status = 0; /* reset */
+ while (atomic_cmpset_int(&adapter->bypass.log, 1, 0) == 0)
+ usec_delay(3000);
+ return (EINVAL);
+} /* ixgbe_bp_log */
+
+/************************************************************************
+ * ixgbe_bypass_init - Set up infrastructure for the bypass feature
+ *
+ * Do time and sysctl initialization here. This feature is
+ * only enabled for the first port of a bypass adapter.
+ ************************************************************************/
+void
+ixgbe_bypass_init(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ device_t dev = adapter->dev;
+ struct sysctl_oid *bp_node;
+ struct sysctl_oid_list *bp_list;
+ u32 mask, value, sec, year;
+
+ if (!(adapter->feat_cap & IXGBE_FEATURE_BYPASS))
+ return;
+
+ /* First set up time for the hardware */
+ ixgbe_get_bypass_time(&year, &sec);
+
+ mask = BYPASS_CTL1_TIME_M
+ | BYPASS_CTL1_VALID_M
+ | BYPASS_CTL1_OFFTRST_M;
+
+ value = (sec & BYPASS_CTL1_TIME_M)
+ | BYPASS_CTL1_VALID
+ | BYPASS_CTL1_OFFTRST;
+
+ ixgbe_bypass_mutex_enter(adapter);
+ hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL1, mask, value);
+ ixgbe_bypass_mutex_clear(adapter);
+
+ /* Now set up the SYSCTL infrastructure */
+
+ /*
+ * The log routine is kept separate from the other
+ * children so a general display command like:
+ * `sysctl dev.ix.0.bypass` will not show the log.
+ */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "bypass_log", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_log, "I", "Bypass Log");
+
+ /* All other setting are hung from the 'bypass' node */
+ bp_node = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "bypass", CTLFLAG_RD, NULL, "Bypass");
+
+ bp_list = SYSCTL_CHILDREN(bp_node);
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "version", CTLTYPE_INT | CTLFLAG_RD,
+ adapter, 0, ixgbe_bp_version, "I", "Bypass Version");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_set_state, "I", "Bypass State");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "timeout", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_timeout, "I", "Bypass Timeout");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "main_on", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_main_on, "I", "Bypass Main On");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "main_off", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_main_off, "I", "Bypass Main Off");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "aux_on", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_aux_on, "I", "Bypass Aux On");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "aux_off", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_aux_off, "I", "Bypass Aux Off");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "wd_set", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_bp_wd_set, "I", "Set BP Watchdog");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
+ OID_AUTO, "wd_reset", CTLTYPE_INT | CTLFLAG_WR,
+ adapter, 0, ixgbe_bp_wd_reset, "S", "Bypass WD Reset");
+
+ adapter->feat_en |= IXGBE_FEATURE_BYPASS;
+} /* ixgbe_bypass_init */
+
Index: sys/dev/ixgbe/if_fdir.c
===================================================================
--- /dev/null
+++ sys/dev/ixgbe/if_fdir.c
@@ -0,0 +1,155 @@
+/******************************************************************************
+
+ Copyright (c) 2001-2017, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*$FreeBSD$*/
+
+#include "ixgbe.h"
+
+#ifdef IXGBE_FDIR
+
+void
+ixgbe_init_fdir(struct adapter *adapter)
+{
+ u32 hdrm = 32 << fdir_pballoc;
+
+ if (!(adapter->feat_en & IXGBE_FEATURE_FDIR))
+ return;
+
+ adapter->hw.mac.ops.setup_rxpba(&adapter->hw, 0, hdrm,
+ PBA_STRATEGY_EQUAL);
+ ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
+} /* ixgbe_init_fdir */
+
+void
+ixgbe_reinit_fdir(void *context)
+{
+ if_ctx_t ctx = context;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+
+ if (!(adapter->feat_en & IXGBE_FEATURE_FDIR))
+ return;
+ if (adapter->fdir_reinit != 1) /* Shouldn't happen */
+ return;
+ ixgbe_reinit_fdir_tables_82599(&adapter->hw);
+ adapter->fdir_reinit = 0;
+ /* re-enable flow director interrupts */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
+ /* Restart the interface */
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+} /* ixgbe_reinit_fdir */
+
+/************************************************************************
+ * ixgbe_atr
+ *
+ * Parse packet headers so that Flow Director can make
+ * a hashed filter table entry allowing traffic flows
+ * to be identified and kept on the same cpu. This
+ * would be a performance hit, but we only do it at
+ * IXGBE_FDIR_RATE of packets.
+ ************************************************************************/
+void
+ixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
+{
+ struct adapter *adapter = txr->adapter;
+ struct ix_queue *que;
+ struct ip *ip;
+ struct tcphdr *th;
+ struct udphdr *uh;
+ struct ether_vlan_header *eh;
+ union ixgbe_atr_hash_dword input = {.dword = 0};
+ union ixgbe_atr_hash_dword common = {.dword = 0};
+ int ehdrlen, ip_hlen;
+ u16 etype;
+
+ eh = mtod(mp, struct ether_vlan_header *);
+ if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
+ ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+ etype = eh->evl_proto;
+ } else {
+ ehdrlen = ETHER_HDR_LEN;
+ etype = eh->evl_encap_proto;
+ }
+
+ /* Only handling IPv4 */
+ if (etype != htons(ETHERTYPE_IP))
+ return;
+
+ ip = (struct ip *)(mp->m_data + ehdrlen);
+ ip_hlen = ip->ip_hl << 2;
+
+ /* check if we're UDP or TCP */
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
+ /* src and dst are inverted */
+ common.port.dst ^= th->th_sport;
+ common.port.src ^= th->th_dport;
+ input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_TCPV4;
+ break;
+ case IPPROTO_UDP:
+ uh = (struct udphdr *)((caddr_t)ip + ip_hlen);
+ /* src and dst are inverted */
+ common.port.dst ^= uh->uh_sport;
+ common.port.src ^= uh->uh_dport;
+ input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_UDPV4;
+ break;
+ default:
+ return;
+ }
+
+ input.formatted.vlan_id = htobe16(mp->m_pkthdr.ether_vtag);
+ if (mp->m_pkthdr.ether_vtag)
+ common.flex_bytes ^= htons(ETHERTYPE_VLAN);
+ else
+ common.flex_bytes ^= etype;
+ common.ip ^= ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
+
+ que = &adapter->queues[txr->me];
+ /*
+ * This assumes the Rx queue and Tx
+ * queue are bound to the same CPU
+ */
+ ixgbe_fdir_add_signature_filter_82599(&adapter->hw,
+ input, common, que->msix);
+} /* ixgbe_atr */
+
+#else
+
+/* TASK_INIT needs this function defined regardless if it's enabled */
+void
+ixgbe_reinit_fdir(void *context)
+{
+ UNREFERENCED_PARAMETER(context);
+} /* ixgbe_reinit_fdir */
+
+#endif
Index: sys/dev/ixgbe/if_ix.c
===================================================================
--- sys/dev/ixgbe/if_ix.c
+++ sys/dev/ixgbe/if_ix.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -33,23 +33,20 @@
/*$FreeBSD$*/
-#ifndef IXGBE_STANDALONE_BUILD
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_rss.h"
-#endif
#include "ixgbe.h"
+#include "ifdi_if.h"
-#ifdef RSS
-#include <net/rss_config.h>
-#include <netinet/in_rss.h>
-#endif
+#include <net/netmap.h>
+#include <dev/netmap/netmap_kern.h>
/*********************************************************************
* Driver version
*********************************************************************/
-char ixgbe_driver_version[] = "3.1.13-k";
+char ixgbe_driver_version[] = "3.2.12-k";
/*********************************************************************
@@ -61,201 +58,237 @@
*
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
*********************************************************************/
-
-static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
+static pci_vendor_info_t ixgbe_vendor_info_array[] =
{
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
- /* required last entry */
- {0, 0, 0, 0, 0}
-};
-
-/*********************************************************************
- * Table of branding strings
- *********************************************************************/
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
-static char *ixgbe_strings[] = {
- "Intel(R) PRO/10GbE PCI-Express Network Driver"
+ /* required last entry */
+ PVID_END
};
/*********************************************************************
* Function prototypes
*********************************************************************/
-static int ixgbe_probe(device_t);
-static int ixgbe_attach(device_t);
-static int ixgbe_detach(device_t);
-static int ixgbe_shutdown(device_t);
-static int ixgbe_suspend(device_t);
-static int ixgbe_resume(device_t);
-static int ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
-static void ixgbe_init(void *);
-static void ixgbe_init_locked(struct adapter *);
-static void ixgbe_stop(void *);
+static void *ixgbe_register(device_t dev);
+static int ixgbe_if_attach_pre(if_ctx_t ctx);
+static int ixgbe_if_attach_post(if_ctx_t ctx);
+static int ixgbe_if_detach(if_ctx_t ctx);
+static int ixgbe_if_shutdown(if_ctx_t ctx);
+static int ixgbe_if_suspend(if_ctx_t ctx);
+static int ixgbe_if_resume(if_ctx_t ctx);
+
+static void ixgbe_if_stop(if_ctx_t ctx);
+void ixgbe_if_enable_intr(if_ctx_t ctx);
+static void ixgbe_if_disable_intr(if_ctx_t ctx);
+static int ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
+static void ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr);
+static int ixgbe_if_media_change(if_ctx_t ctx);
+static int ixgbe_if_msix_intr_assign(if_ctx_t, int);
+static int ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
+static void ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int strip);
+static void ixgbe_if_multi_set(if_ctx_t ctx);
+static int ixgbe_if_promisc_set(if_ctx_t ctx, int flags);
+static int ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets);
+static int ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets);
+static void ixgbe_if_queues_free(if_ctx_t ctx);
+static void ixgbe_if_timer(if_ctx_t ctx, uint16_t);
+static void ixgbe_if_update_admin_status(if_ctx_t ctx);
+static void ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag);
+static void ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
+
+int ixgbe_intr(void *arg);
+
#if __FreeBSD_version >= 1100036
-static uint64_t ixgbe_get_counter(struct ifnet *, ift_counter);
+static uint64_t ixgbe_if_get_counter(if_ctx_t, ift_counter);
#endif
-static void ixgbe_add_media_types(struct adapter *);
-static void ixgbe_media_status(struct ifnet *, struct ifmediareq *);
-static int ixgbe_media_change(struct ifnet *);
-static void ixgbe_identify_hardware(struct adapter *);
-static int ixgbe_allocate_pci_resources(struct adapter *);
-static void ixgbe_get_slot_info(struct adapter *);
-static int ixgbe_allocate_msix(struct adapter *);
-static int ixgbe_allocate_legacy(struct adapter *);
-static int ixgbe_setup_msix(struct adapter *);
-static void ixgbe_free_pci_resources(struct adapter *);
-static void ixgbe_local_timer(void *);
-static int ixgbe_setup_interface(device_t, struct adapter *);
-static void ixgbe_config_gpie(struct adapter *);
-static void ixgbe_config_dmac(struct adapter *);
-static void ixgbe_config_delay_values(struct adapter *);
-static void ixgbe_config_link(struct adapter *);
-static void ixgbe_check_wol_support(struct adapter *);
-static int ixgbe_setup_low_power_mode(struct adapter *);
-static void ixgbe_rearm_queues(struct adapter *, u64);
-
-static void ixgbe_initialize_transmit_units(struct adapter *);
-static void ixgbe_initialize_receive_units(struct adapter *);
-static void ixgbe_enable_rx_drop(struct adapter *);
-static void ixgbe_disable_rx_drop(struct adapter *);
-static void ixgbe_initialize_rss_mapping(struct adapter *);
-
-static void ixgbe_enable_intr(struct adapter *);
-static void ixgbe_disable_intr(struct adapter *);
-static void ixgbe_update_stats_counters(struct adapter *);
-static void ixgbe_set_promisc(struct adapter *);
-static void ixgbe_set_multi(struct adapter *);
-static void ixgbe_update_link_status(struct adapter *);
-static void ixgbe_set_ivar(struct adapter *, u8, u8, s8);
-static void ixgbe_configure_ivars(struct adapter *);
-static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
-
-static void ixgbe_setup_vlan_hw_support(struct adapter *);
-static void ixgbe_register_vlan(void *, struct ifnet *, u16);
-static void ixgbe_unregister_vlan(void *, struct ifnet *, u16);
-
-static void ixgbe_add_device_sysctls(struct adapter *);
-static void ixgbe_add_hw_stats(struct adapter *);
-static int ixgbe_set_flowcntl(struct adapter *, int);
-static int ixgbe_set_advertise(struct adapter *, int);
+
+static void ixgbe_enable_queue(struct adapter *adapter, u32 vector);
+static void ixgbe_disable_queue(struct adapter *adapter, u32 vector);
+static void ixgbe_add_device_sysctls(if_ctx_t ctx);
+static int ixgbe_allocate_pci_resources(if_ctx_t ctx);
+static int ixgbe_setup_low_power_mode(if_ctx_t ctx);
+
+static void ixgbe_config_dmac(struct adapter *adapter);
+static void ixgbe_configure_ivars(struct adapter *adapter);
+static void ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type);
+static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
+static bool ixgbe_sfp_probe(if_ctx_t ctx);
+
+static void ixgbe_free_pci_resources(if_ctx_t ctx);
+
+static int ixgbe_msix_link(void *arg);
+static int ixgbe_msix_que(void *arg);
+static void ixgbe_initialize_rss_mapping(struct adapter *adapter);
+static void ixgbe_initialize_receive_units(if_ctx_t ctx);
+static void ixgbe_initialize_transmit_units(if_ctx_t ctx);
+
+static int ixgbe_setup_interface(if_ctx_t ctx);
+static void ixgbe_init_device_features(struct adapter *adapter);
+static void ixgbe_check_fan_failure(struct adapter *, u32, bool);
+static void ixgbe_add_media_types(if_ctx_t ctx);
+static void ixgbe_update_stats_counters(struct adapter *adapter);
+static void ixgbe_config_link(struct adapter *adapter);
+static void ixgbe_get_slot_info(struct adapter *);
+static void ixgbe_check_wol_support(struct adapter *adapter);
+static void ixgbe_enable_rx_drop(struct adapter *);
+static void ixgbe_disable_rx_drop(struct adapter *);
+
+static void ixgbe_add_hw_stats(struct adapter *adapter);
+static int ixgbe_set_flowcntl(struct adapter *, int);
+static int ixgbe_set_advertise(struct adapter *, int);
+static void ixgbe_setup_vlan_hw_support(if_ctx_t ctx);
+static void ixgbe_setup_optics(struct adapter *adapter);
+static void ixgbe_config_gpie(struct adapter *adapter);
+static void ixgbe_config_delay_values(struct adapter *adapter);
/* Sysctl handlers */
-static void ixgbe_set_sysctl_value(struct adapter *, const char *,
- const char *, int *, int);
-static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS);
+static void ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
+ const char *description, int *limit, int value);
+static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS);
#ifdef IXGBE_DEBUG
static int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS);
#endif
-static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS);
-static int ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS);
-
-/* Support for pluggable optic modules */
-static bool ixgbe_sfp_probe(struct adapter *);
-static void ixgbe_setup_optics(struct adapter *);
-
-/* Legacy (single vector interrupt handler */
-static void ixgbe_legacy_irq(void *);
-
-/* The MSI/X Interrupt handlers */
-static void ixgbe_msix_que(void *);
-static void ixgbe_msix_link(void *);
+static int ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS);
/* Deferred interrupt tasklets */
-static void ixgbe_handle_que(void *, int);
-static void ixgbe_handle_link(void *, int);
-static void ixgbe_handle_msf(void *, int);
-static void ixgbe_handle_mod(void *, int);
-static void ixgbe_handle_phy(void *, int);
-
-#ifdef IXGBE_FDIR
-static void ixgbe_reinit_fdir(void *, int);
-#endif
-
-#ifdef PCI_IOV
-static void ixgbe_ping_all_vfs(struct adapter *);
-static void ixgbe_handle_mbx(void *, int);
-static int ixgbe_init_iov(device_t, u16, const nvlist_t *);
-static void ixgbe_uninit_iov(device_t);
-static int ixgbe_add_vf(device_t, u16, const nvlist_t *);
-static void ixgbe_initialize_iov(struct adapter *);
-static void ixgbe_recalculate_max_frame(struct adapter *);
-static void ixgbe_init_vf(struct adapter *, struct ixgbe_vf *);
-#endif /* PCI_IOV */
-
+static void ixgbe_handle_msf(void *);
+static void ixgbe_handle_mod(void *);
+static void ixgbe_handle_phy(void *);
-/*********************************************************************
+/**********************************************************************
* FreeBSD Device Interface Entry Points
*********************************************************************/
-
-static device_method_t ix_methods[] = {
+static device_method_t ixgbe_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, ixgbe_probe),
- DEVMETHOD(device_attach, ixgbe_attach),
- DEVMETHOD(device_detach, ixgbe_detach),
- DEVMETHOD(device_shutdown, ixgbe_shutdown),
- DEVMETHOD(device_suspend, ixgbe_suspend),
- DEVMETHOD(device_resume, ixgbe_resume),
+ DEVMETHOD(device_register, ixgbe_register),
+ DEVMETHOD(device_probe, iflib_device_probe),
+ DEVMETHOD(device_attach, iflib_device_attach),
+ DEVMETHOD(device_detach, iflib_device_detach),
+ DEVMETHOD(device_shutdown, iflib_device_shutdown),
+ DEVMETHOD(device_suspend, iflib_device_suspend),
+ DEVMETHOD(device_resume, iflib_device_resume),
#ifdef PCI_IOV
- DEVMETHOD(pci_iov_init, ixgbe_init_iov),
- DEVMETHOD(pci_iov_uninit, ixgbe_uninit_iov),
- DEVMETHOD(pci_iov_add_vf, ixgbe_add_vf),
+ DEVMETHOD(pci_iov_init, iflib_device_iov_init),
+ DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit),
+ DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf),
#endif /* PCI_IOV */
DEVMETHOD_END
};
-static driver_t ix_driver = {
- "ix", ix_methods, sizeof(struct adapter),
+static driver_t ixgbe_driver = {
+ "ix", ixgbe_methods, sizeof(struct adapter),
};
devclass_t ix_devclass;
-DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0);
+DRIVER_MODULE(ix, pci, ixgbe_driver, ix_devclass, 0, 0);
MODULE_DEPEND(ix, pci, 1, 1, 1);
MODULE_DEPEND(ix, ether, 1, 1, 1);
-#ifdef DEV_NETMAP
-MODULE_DEPEND(ix, netmap, 1, 1, 1);
-#endif /* DEV_NETMAP */
+MODULE_DEPEND(ix, iflib, 1, 1, 1);
+
+static device_method_t ixgbe_if_methods[] = {
+ DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre),
+ DEVMETHOD(ifdi_attach_post, ixgbe_if_attach_post),
+ DEVMETHOD(ifdi_detach, ixgbe_if_detach),
+ DEVMETHOD(ifdi_shutdown, ixgbe_if_shutdown),
+ DEVMETHOD(ifdi_suspend, ixgbe_if_suspend),
+ DEVMETHOD(ifdi_resume, ixgbe_if_resume),
+ DEVMETHOD(ifdi_init, ixgbe_if_init),
+ DEVMETHOD(ifdi_stop, ixgbe_if_stop),
+ DEVMETHOD(ifdi_msix_intr_assign, ixgbe_if_msix_intr_assign),
+ DEVMETHOD(ifdi_intr_enable, ixgbe_if_enable_intr),
+ DEVMETHOD(ifdi_intr_disable, ixgbe_if_disable_intr),
+ DEVMETHOD(ifdi_tx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable),
+ DEVMETHOD(ifdi_rx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable),
+ DEVMETHOD(ifdi_tx_queues_alloc, ixgbe_if_tx_queues_alloc),
+ DEVMETHOD(ifdi_rx_queues_alloc, ixgbe_if_rx_queues_alloc),
+ DEVMETHOD(ifdi_queues_free, ixgbe_if_queues_free),
+ DEVMETHOD(ifdi_update_admin_status, ixgbe_if_update_admin_status),
+ DEVMETHOD(ifdi_multi_set, ixgbe_if_multi_set),
+ DEVMETHOD(ifdi_mtu_set, ixgbe_if_mtu_set),
+ DEVMETHOD(ifdi_crcstrip_set, ixgbe_if_crcstrip_set),
+ DEVMETHOD(ifdi_media_status, ixgbe_if_media_status),
+ DEVMETHOD(ifdi_media_change, ixgbe_if_media_change),
+ DEVMETHOD(ifdi_promisc_set, ixgbe_if_promisc_set),
+ DEVMETHOD(ifdi_timer, ixgbe_if_timer),
+ DEVMETHOD(ifdi_vlan_register, ixgbe_if_vlan_register),
+ DEVMETHOD(ifdi_vlan_unregister, ixgbe_if_vlan_unregister),
+ DEVMETHOD(ifdi_get_counter, ixgbe_if_get_counter),
+#ifdef PCI_IOV
+ DEVMETHOD(ifdi_iov_init, ixgbe_if_iov_init),
+ DEVMETHOD(ifdi_iov_uninit, ixgbe_if_iov_uninit),
+ DEVMETHOD(ifdi_iov_vf_add, ixgbe_if_iov_vf_add),
+#endif /* PCI_IOV */
+ DEVMETHOD_END
+};
+
+/*
+ * note that if (adapter->msix_mem) is replaced by:
+ * if (adapter->intr_type == IFLIB_INTR_MSIX)
+ */
+
+static driver_t ixgbe_if_driver = {
+ "ixgbe_if", ixgbe_if_methods, sizeof(struct adapter)
+};
/*
** TUNEABLE PARAMETERS:
@@ -282,15 +315,13 @@
static int ixgbe_rx_process_limit = 256;
SYSCTL_INT(_hw_ix, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
&ixgbe_rx_process_limit, 0,
- "Maximum number of received packets to process at a time,"
- "-1 means unlimited");
+ "Maximum number of received packets to process at a time, -1 means unlimited");
/* How many packets txeof tries to clean at a time */
static int ixgbe_tx_process_limit = 256;
SYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN,
&ixgbe_tx_process_limit, 0,
- "Maximum number of sent packets to process at a time,"
- "-1 means unlimited");
+ "Maximum number of sent packets to process at a time, -1 means unlimited");
/* Flow control setting, default to full */
static int ixgbe_flow_control = ixgbe_fc_full;
@@ -303,12 +334,12 @@
&ixgbe_advertise_speed, 0, "Default advertised speed for all adapters");
/*
-** Smart speed setting, default to on
-** this only works as a compile option
-** right now as its during attach, set
-** this to 'ixgbe_smart_speed_off' to
-** disable.
-*/
+ * Smart speed setting, default to on
+ * this only works as a compile option
+ * right now as its during attach, set
+ * this to 'ixgbe_smart_speed_off' to
+ * disable.
+ */
static int ixgbe_smart_speed = ixgbe_smart_speed_on;
/*
@@ -320,3687 +351,2467 @@
"Enable MSI-X interrupts");
/*
- * Number of Queues, can be set to 0,
- * it then autoconfigures based on the
- * number of cpus with a max of 8. This
- * can be overriden manually here.
+ * Defining this on will allow the use
+ * of unsupported SFP+ modules, note that
+ * doing so you are on your own :)
*/
-static int ixgbe_num_queues = 0;
-SYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0,
- "Number of queues to configure, 0 indicates autoconfigure");
+static int allow_unsupported_sfp = FALSE;
+TUNABLE_INT("hw.ix.unsupported_sfp", &allow_unsupported_sfp);
/*
-** Number of TX descriptors per ring,
-** setting higher than RX as this seems
-** the better performing choice.
-*/
-static int ixgbe_txd = PERFORM_TXD;
-SYSCTL_INT(_hw_ix, OID_AUTO, txd, CTLFLAG_RDTUN, &ixgbe_txd, 0,
- "Number of transmit descriptors per queue");
-
-/* Number of RX descriptors per ring */
-static int ixgbe_rxd = PERFORM_RXD;
-SYSCTL_INT(_hw_ix, OID_AUTO, rxd, CTLFLAG_RDTUN, &ixgbe_rxd, 0,
- "Number of receive descriptors per queue");
+ * Not sure if Flow Director is fully baked,
+ * so we'll default to turning it off.
+ */
+static int ixgbe_enable_fdir = 0;
+SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0,
+ "Enable Flow Director");
-/*
-** Defining this on will allow the use
-** of unsupported SFP+ modules, note that
-** doing so you are on your own :)
-*/
-static int allow_unsupported_sfp = FALSE;
-TUNABLE_INT("hw.ix.unsupported_sfp", &allow_unsupported_sfp);
+/* Receive-Side Scaling */
+static int ixgbe_enable_rss = 1;
+SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0,
+ "Enable Receive-Side Scaling (RSS)");
+#if 0
/* Keep running tab on them for sanity check */
static int ixgbe_total_ports;
-
-#ifdef IXGBE_FDIR
-/*
-** Flow Director actually 'steals'
-** part of the packet buffer as its
-** filter pool, this variable controls
-** how much it uses:
-** 0 = 64K, 1 = 128K, 2 = 256K
-*/
-static int fdir_pballoc = 1;
#endif
-#ifdef DEV_NETMAP
+MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations");
+
/*
- * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
- * be a reference on how to implement netmap support in a driver.
- * Additional comments are in ixgbe_netmap.h .
+ * For Flow Director: this is the number of TX packets we sample
+ * for the filter pool, this means every 20th packet will be probed.
*
- * <dev/netmap/ixgbe_netmap.h> contains functions for netmap support
- * that extend the standard driver.
+ * This feature can be disabled by setting this to 0.
*/
-#include <dev/netmap/ixgbe_netmap.h>
-#endif /* DEV_NETMAP */
-
-static MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations");
+static int atr_sample_rate = 20;
+
+extern struct if_txrx ixgbe_txrx;
+
+static struct if_shared_ctx ixgbe_sctx_init = {
+ .isc_magic = IFLIB_MAGIC,
+ .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */
+ .isc_tx_maxsize = IXGBE_TSO_SIZE,
+
+ .isc_tx_maxsegsize = PAGE_SIZE,
+
+ .isc_rx_maxsize = PAGE_SIZE*4,
+ .isc_rx_nsegments = 1,
+ .isc_rx_maxsegsize = PAGE_SIZE*4,
+ .isc_nfl = 1,
+ .isc_ntxqs = 1,
+ .isc_nrxqs = 1,
+
+ .isc_admin_intrcnt = 1,
+ .isc_vendor_info = ixgbe_vendor_info_array,
+ .isc_driver_version = ixgbe_driver_version,
+ .isc_driver = &ixgbe_if_driver,
+
+ .isc_nrxd_min = {MIN_RXD},
+ .isc_ntxd_min = {MIN_TXD},
+ .isc_nrxd_max = {MAX_RXD},
+ .isc_ntxd_max = {MAX_TXD},
+ .isc_nrxd_default = {DEFAULT_RXD},
+ .isc_ntxd_default = {DEFAULT_TXD},
+};
-/*********************************************************************
- * Device identification routine
- *
- * ixgbe_probe determines if the driver should be loaded on
- * adapter based on PCI vendor/device id of the adapter.
- *
- * return BUS_PROBE_DEFAULT on success, positive on failure
- *********************************************************************/
+if_shared_ctx_t ixgbe_sctx = &ixgbe_sctx_init;
static int
-ixgbe_probe(device_t dev)
+ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets)
{
- ixgbe_vendor_info_t *ent;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx = adapter->shared;
+ struct ix_tx_queue *que;
+ int i, j, error;
+
+ MPASS(adapter->num_tx_queues > 0);
+ MPASS(adapter->num_tx_queues == ntxqsets);
+ MPASS(ntxqs == 1);
+
+ /* Allocate queue structure memory */
+ adapter->tx_queues =
+ (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * ntxqsets,
+ M_IXGBE, M_NOWAIT | M_ZERO);
+ if (!adapter->tx_queues) {
+ device_printf(iflib_get_dev(ctx),
+ "Unable to allocate TX ring memory\n");
+ return (ENOMEM);
+ }
- u16 pci_vendor_id = 0;
- u16 pci_device_id = 0;
- u16 pci_subvendor_id = 0;
- u16 pci_subdevice_id = 0;
- char adapter_name[256];
+ for (i = 0, que = adapter->tx_queues; i < ntxqsets; i++, que++) {
+ struct tx_ring *txr = &que->txr;
- INIT_DEBUGOUT("ixgbe_probe: begin");
+ /* In case SR-IOV is enabled, align the index properly */
+ txr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool,
+ i);
- pci_vendor_id = pci_get_vendor(dev);
- if (pci_vendor_id != IXGBE_INTEL_VENDOR_ID)
- return (ENXIO);
+ txr->adapter = que->adapter = adapter;
+ adapter->active_queues |= (u64)1 << txr->me;
- pci_device_id = pci_get_device(dev);
- pci_subvendor_id = pci_get_subvendor(dev);
- pci_subdevice_id = pci_get_subdevice(dev);
-
- ent = ixgbe_vendor_info_array;
- while (ent->vendor_id != 0) {
- if ((pci_vendor_id == ent->vendor_id) &&
- (pci_device_id == ent->device_id) &&
-
- ((pci_subvendor_id == ent->subvendor_id) ||
- (ent->subvendor_id == 0)) &&
-
- ((pci_subdevice_id == ent->subdevice_id) ||
- (ent->subdevice_id == 0))) {
- sprintf(adapter_name, "%s, Version - %s",
- ixgbe_strings[ent->index],
- ixgbe_driver_version);
- device_set_desc_copy(dev, adapter_name);
- ++ixgbe_total_ports;
- return (BUS_PROBE_DEFAULT);
+ /* Allocate report status array */
+ if (!(txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXGBE, M_NOWAIT | M_ZERO))) {
+ error = ENOMEM;
+ goto fail;
}
- ent++;
+ for (j = 0; j < scctx->isc_ntxd[0]; j++)
+ txr->tx_rsq[j] = QIDX_INVALID;
+ /* get the virtual and physical address of the hardware queues */
+ txr->tail = IXGBE_TDT(txr->me);
+ txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i];
+ txr->tx_paddr = paddrs[i];
+
+ txr->bytes = 0;
+ txr->total_packets = 0;
+
+ /* Set the rate at which we sample packets */
+ if (adapter->feat_en & IXGBE_FEATURE_FDIR)
+ txr->atr_sample = atr_sample_rate;
+
}
- return (ENXIO);
-}
-/*********************************************************************
- * Device initialization routine
- *
- * The attach entry point is called when the driver is being loaded.
- * This routine identifies the type of hardware, allocates all resources
- * and initializes the hardware.
- *
- * return 0 on success, positive on failure
- *********************************************************************/
+ iflib_config_gtask_init(ctx, &adapter->mod_task, ixgbe_handle_mod, "mod_task");
+ iflib_config_gtask_init(ctx, &adapter->msf_task, ixgbe_handle_msf, "msf_task");
+ iflib_config_gtask_init(ctx, &adapter->phy_task, ixgbe_handle_phy, "phy_task");
+ if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
+ iflib_config_gtask_init(ctx, &adapter->mbx_task, ixgbe_handle_mbx, "mbx_task");
+ if (adapter->feat_en & IXGBE_FEATURE_FDIR)
+ iflib_config_gtask_init(ctx, &adapter->fdir_task, ixgbe_reinit_fdir, "fdir_task");
+
+ device_printf(iflib_get_dev(ctx), "allocated for %d queues\n", adapter->num_tx_queues);
+ return (0);
+
+fail:
+ ixgbe_if_queues_free(ctx);
+ return (error);
+}
static int
-ixgbe_attach(device_t dev)
+ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets)
{
- struct adapter *adapter;
- struct ixgbe_hw *hw;
- int error = 0;
- u16 csum;
- u32 ctrl_ext;
-
- INIT_DEBUGOUT("ixgbe_attach: begin");
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_rx_queue *que;
+ int i;
- /* Allocate, clear, and link in our adapter structure */
- adapter = device_get_softc(dev);
- adapter->dev = dev;
- hw = &adapter->hw;
+ MPASS(adapter->num_rx_queues > 0);
+ MPASS(adapter->num_rx_queues == nrxqsets);
+ MPASS(nrxqs == 1);
+
+ /* Allocate queue structure memory */
+ adapter->rx_queues =
+ (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue)*nrxqsets,
+ M_IXGBE, M_NOWAIT | M_ZERO);
+ if (!adapter->rx_queues) {
+ device_printf(iflib_get_dev(ctx),
+ "Unable to allocate TX ring memory\n");
+ return (ENOMEM);
+ }
-#ifdef DEV_NETMAP
- adapter->init_locked = ixgbe_init_locked;
- adapter->stop_locked = ixgbe_stop;
-#endif
+ for (i = 0, que = adapter->rx_queues; i < nrxqsets; i++, que++) {
+ struct rx_ring *rxr = &que->rxr;
- /* Core Lock Init*/
- IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
+ /* In case SR-IOV is enabled, align the index properly */
+ rxr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool,
+ i);
- /* Set up the timer callout */
- callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
+ rxr->adapter = que->adapter = adapter;
- /* Determine hardware revision */
- ixgbe_identify_hardware(adapter);
+ /* get the virtual and physical address of the hardware queues */
- /* Do base PCI setup - map BAR0 */
- if (ixgbe_allocate_pci_resources(adapter)) {
- device_printf(dev, "Allocation of PCI resources failed\n");
- error = ENXIO;
- goto err_out;
+ rxr->tail = IXGBE_RDT(rxr->me);
+ rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i];
+ rxr->rx_paddr = paddrs[i];
+ rxr->bytes = 0;
+ rxr->que = que;
}
- /* Sysctls for limiting the amount of work done in the taskqueues */
- ixgbe_set_sysctl_value(adapter, "rx_processing_limit",
- "max number of rx packets to process",
- &adapter->rx_process_limit, ixgbe_rx_process_limit);
+ device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n", adapter->num_rx_queues);
+ return (0);
+}
- ixgbe_set_sysctl_value(adapter, "tx_processing_limit",
- "max number of tx packets to process",
- &adapter->tx_process_limit, ixgbe_tx_process_limit);
+static void
+ixgbe_if_queues_free(if_ctx_t ctx)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_tx_queue *tx_que = adapter->tx_queues;
+ struct ix_rx_queue *rx_que = adapter->rx_queues;
+ int i;
- /* Do descriptor calc and sanity checks */
- if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
- ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) {
- device_printf(dev, "TXD config issue, using default!\n");
- adapter->num_tx_desc = DEFAULT_TXD;
- } else
- adapter->num_tx_desc = ixgbe_txd;
+ if (tx_que != NULL) {
+ for (i = 0; i < adapter->num_tx_queues; i++, tx_que++) {
+ struct tx_ring *txr = &tx_que->txr;
+ if (txr->tx_rsq == NULL)
+ break;
- /*
- ** With many RX rings it is easy to exceed the
- ** system mbuf allocation. Tuning nmbclusters
- ** can alleviate this.
- */
- if (nmbclusters > 0) {
- int s;
- s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports;
- if (s > nmbclusters) {
- device_printf(dev, "RX Descriptors exceed "
- "system mbuf max, using default instead!\n");
- ixgbe_rxd = DEFAULT_RXD;
+ free(txr->tx_rsq, M_IXGBE);
+ txr->tx_rsq = NULL;
}
- }
- if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
- ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) {
- device_printf(dev, "RXD config issue, using default!\n");
- adapter->num_rx_desc = DEFAULT_RXD;
- } else
- adapter->num_rx_desc = ixgbe_rxd;
-
- /* Allocate our TX/RX Queues */
- if (ixgbe_allocate_queues(adapter)) {
- error = ENOMEM;
- goto err_out;
- }
-
- /* Allocate multicast array memory. */
- adapter->mta = malloc(sizeof(*adapter->mta) *
- MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
- if (adapter->mta == NULL) {
- device_printf(dev, "Can not allocate multicast setup array\n");
- error = ENOMEM;
- goto err_late;
+ free(adapter->tx_queues, M_IXGBE);
+ adapter->tx_queues = NULL;
}
-
- /* Initialize the shared code */
- hw->allow_unsupported_sfp = allow_unsupported_sfp;
- error = ixgbe_init_shared_code(hw);
- if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
- /*
- ** No optics in this port, set up
- ** so the timer routine will probe
- ** for later insertion.
- */
- adapter->sfp_probe = TRUE;
- error = 0;
- } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev, "Unsupported SFP+ module detected!\n");
- error = EIO;
- goto err_late;
- } else if (error) {
- device_printf(dev, "Unable to initialize the shared code\n");
- error = EIO;
- goto err_late;
+ if (rx_que != NULL) {
+ free(adapter->rx_queues, M_IXGBE);
+ adapter->rx_queues = NULL;
}
+}
- /* Make sure we have a good EEPROM before we read from it */
- if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) {
- device_printf(dev, "The EEPROM Checksum Is Not Valid\n");
- error = EIO;
- goto err_late;
+static void
+ixgbe_initialize_rss_mapping(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reta = 0, mrqc, rss_key[10];
+ int queue_id, table_size, index_mult;
+ int i, j;
+ u32 rss_hash_config;
+
+ if (adapter->feat_en & IXGBE_FEATURE_RSS) {
+ /* Fetch the configured RSS key */
+ rss_getkey((uint8_t *)&rss_key);
+ } else {
+ /* set up random bits */
+ arc4rand(&rss_key, sizeof(rss_key), 0);
}
- error = ixgbe_init_hw(hw);
- switch (error) {
- case IXGBE_ERR_EEPROM_VERSION:
- device_printf(dev, "This device is a pre-production adapter/"
- "LOM. Please be aware there may be issues associated "
- "with your hardware.\nIf you are experiencing problems "
- "please contact your Intel or hardware representative "
- "who provided you with this hardware.\n");
+ /* Set multiplier for RETA setup and table size based on MAC */
+ index_mult = 0x1;
+ table_size = 128;
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82598EB:
+ index_mult = 0x11;
+ break;
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ table_size = 512;
break;
- case IXGBE_ERR_SFP_NOT_SUPPORTED:
- device_printf(dev, "Unsupported SFP+ Module\n");
- error = EIO;
- goto err_late;
- case IXGBE_ERR_SFP_NOT_PRESENT:
- device_printf(dev, "No SFP+ Module found\n");
- /* falls thru */
default:
break;
}
- /* hw.ix defaults init */
- ixgbe_set_advertise(adapter, ixgbe_advertise_speed);
- ixgbe_set_flowcntl(adapter, ixgbe_flow_control);
- adapter->enable_aim = ixgbe_enable_aim;
-
- if ((adapter->msix > 1) && (ixgbe_enable_msix))
- error = ixgbe_allocate_msix(adapter);
- else
- error = ixgbe_allocate_legacy(adapter);
- if (error)
- goto err_late;
-
- /* Enable the optics for 82599 SFP+ fiber */
- ixgbe_enable_tx_laser(hw);
-
- /* Enable power to the phy. */
- ixgbe_set_phy_power(hw, TRUE);
-
- /* Setup OS specific network interface */
- if (ixgbe_setup_interface(dev, adapter) != 0)
- goto err_late;
-
- /* Initialize statistics */
- ixgbe_update_stats_counters(adapter);
-
- /* Register for VLAN events */
- adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
- ixgbe_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
- adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
- ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
-
- /* Check PCIE slot type/speed/width */
- ixgbe_get_slot_info(adapter);
-
- /* Set an initial default flow control & dmac value */
- adapter->fc = ixgbe_fc_full;
- adapter->dmac = 0;
- adapter->eee_enabled = 0;
-
-#ifdef PCI_IOV
- if ((hw->mac.type != ixgbe_mac_82598EB) && (adapter->msix > 1)) {
- nvlist_t *pf_schema, *vf_schema;
+ /* Set up the redirection table */
+ for (i = 0, j = 0; i < table_size; i++, j++) {
+ if (j == adapter->num_rx_queues)
+ j = 0;
+ if (adapter->feat_en & IXGBE_FEATURE_RSS) {
+ /*
+ * Fetch the RSS bucket id for the given indirection
+ * entry. Cap it at the number of configured buckets
+ * (which is num_rx_queues.)
+ */
+ queue_id = rss_get_indirection_to_bucket(i);
+ queue_id = queue_id % adapter->num_rx_queues;
+ } else
+ queue_id = (j * index_mult);
- hw->mbx.ops.init_params(hw);
- pf_schema = pci_iov_schema_alloc_node();
- vf_schema = pci_iov_schema_alloc_node();
- pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL);
- pci_iov_schema_add_bool(vf_schema, "mac-anti-spoof",
- IOV_SCHEMA_HASDEFAULT, TRUE);
- pci_iov_schema_add_bool(vf_schema, "allow-set-mac",
- IOV_SCHEMA_HASDEFAULT, FALSE);
- pci_iov_schema_add_bool(vf_schema, "allow-promisc",
- IOV_SCHEMA_HASDEFAULT, FALSE);
- error = pci_iov_attach(dev, pf_schema, vf_schema);
- if (error != 0) {
- device_printf(dev,
- "Error %d setting up SR-IOV\n", error);
+ /*
+ * The low 8 bits are for hash value (n+0);
+ * The next 8 bits are for hash value (n+1), etc.
+ */
+ reta = reta >> 8;
+ reta = reta | (((uint32_t)queue_id) << 24);
+ if ((i & 3) == 3) {
+ if (i < 128)
+ IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
+ else
+ IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
+ reta);
+ reta = 0;
}
}
-#endif /* PCI_IOV */
-
- /* Check for certain supported features */
- ixgbe_check_wol_support(adapter);
- /* Add sysctls */
- ixgbe_add_device_sysctls(adapter);
- ixgbe_add_hw_stats(adapter);
-
- /* let hardware know driver is loaded */
- ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
- ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
- IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
+ /* Now fill our hash function seeds */
+ for (i = 0; i < 10; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
-#ifdef DEV_NETMAP
- ixgbe_netmap_attach(adapter);
-#endif /* DEV_NETMAP */
- INIT_DEBUGOUT("ixgbe_attach: end");
- return (0);
+ /* Perform hash on these packet types */
+ if (adapter->feat_en & IXGBE_FEATURE_RSS)
+ rss_hash_config = rss_gethashconfig();
+ else {
+ /*
+ * Disable UDP - IP fragments aren't currently being handled
+ * and so we end up with a mix of 2-tuple and 4-tuple
+ * traffic.
+ */
+ rss_hash_config = RSS_HASHTYPE_RSS_IPV4
+ | RSS_HASHTYPE_RSS_TCP_IPV4
+ | RSS_HASHTYPE_RSS_IPV6
+ | RSS_HASHTYPE_RSS_TCP_IPV6
+ | RSS_HASHTYPE_RSS_IPV6_EX
+ | RSS_HASHTYPE_RSS_TCP_IPV6_EX;
+ }
-err_late:
- ixgbe_free_transmit_structures(adapter);
- ixgbe_free_receive_structures(adapter);
-err_out:
- if (adapter->ifp != NULL)
- if_free(adapter->ifp);
- ixgbe_free_pci_resources(adapter);
- free(adapter->mta, M_DEVBUF);
- return (error);
+ mrqc = IXGBE_MRQC_RSSEN;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
+ device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, but not supported\n",
+ __func__);
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
+ mrqc |= ixgbe_get_mrqc(adapter->iov_mode);
+ IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
}
+
/*********************************************************************
- * Device removal routine
*
- * The detach entry point is called when the driver is being removed.
- * This routine stops the adapter and deallocates all the resources
- * that were allocated for driver operation.
+ * Setup receive registers and features.
*
- * return 0 on success, positive on failure
- *********************************************************************/
+ **********************************************************************/
+#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
-static int
-ixgbe_detach(device_t dev)
-{
- struct adapter *adapter = device_get_softc(dev);
- struct ix_queue *que = adapter->queues;
- struct tx_ring *txr = adapter->tx_rings;
- u32 ctrl_ext;
+#define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
- INIT_DEBUGOUT("ixgbe_detach: begin");
+static void
+ixgbe_initialize_receive_units(if_ctx_t ctx)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx = adapter->shared;
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ifnet *ifp = iflib_get_ifp(ctx);
- /* Make sure VLANS are not using driver */
- if (adapter->ifp->if_vlantrunk != NULL) {
- device_printf(dev,"Vlan in use, detach first\n");
- return (EBUSY);
- }
+ struct ix_rx_queue *que;
+ u32 bufsz, fctrl, srrctl, rxcsum;
+ u32 hlreg;
+ int i;
-#ifdef PCI_IOV
- if (pci_iov_detach(dev) != 0) {
- device_printf(dev, "SR-IOV in use; detach first.\n");
- return (EBUSY);
- }
-#endif /* PCI_IOV */
-
- ether_ifdetach(adapter->ifp);
- /* Stop the adapter */
- IXGBE_CORE_LOCK(adapter);
- ixgbe_setup_low_power_mode(adapter);
- IXGBE_CORE_UNLOCK(adapter);
-
- for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
- if (que->tq) {
-#ifndef IXGBE_LEGACY_TX
- taskqueue_drain(que->tq, &txr->txq_task);
-#endif
- taskqueue_drain(que->tq, &que->que_task);
- taskqueue_free(que->tq);
- }
- }
+ /*
+ * Make sure receives are disabled while
+ * setting up the descriptor ring
+ */
+ ixgbe_disable_rx(hw);
- /* Drain the Link queue */
- if (adapter->tq) {
- taskqueue_drain(adapter->tq, &adapter->link_task);
- taskqueue_drain(adapter->tq, &adapter->mod_task);
- taskqueue_drain(adapter->tq, &adapter->msf_task);
-#ifdef PCI_IOV
- taskqueue_drain(adapter->tq, &adapter->mbx_task);
-#endif
- taskqueue_drain(adapter->tq, &adapter->phy_task);
-#ifdef IXGBE_FDIR
- taskqueue_drain(adapter->tq, &adapter->fdir_task);
-#endif
- taskqueue_free(adapter->tq);
+ /* Enable broadcasts */
+ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ fctrl |= IXGBE_FCTRL_BAM;
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+ fctrl |= IXGBE_FCTRL_DPF;
+ fctrl |= IXGBE_FCTRL_PMCF;
}
+ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
- /* let hardware know driver is unloading */
- ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
- ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
-
- /* Unregister VLAN events */
- if (adapter->vlan_attach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
- if (adapter->vlan_detach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
-
- callout_drain(&adapter->timer);
-#ifdef DEV_NETMAP
- netmap_detach(adapter->ifp);
-#endif /* DEV_NETMAP */
- ixgbe_free_pci_resources(adapter);
- bus_generic_detach(dev);
- if_free(adapter->ifp);
-
- ixgbe_free_transmit_structures(adapter);
- ixgbe_free_receive_structures(adapter);
- free(adapter->mta, M_DEVBUF);
-
- IXGBE_CORE_LOCK_DESTROY(adapter);
- return (0);
-}
-
-/*********************************************************************
- *
- * Shutdown entry point
- *
- **********************************************************************/
-
-static int
-ixgbe_shutdown(device_t dev)
-{
- struct adapter *adapter = device_get_softc(dev);
- int error = 0;
-
- INIT_DEBUGOUT("ixgbe_shutdown: begin");
+ /* Set for Jumbo Frames? */
+ hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+ if (ifp->if_mtu > ETHERMTU)
+ hlreg |= IXGBE_HLREG0_JUMBOEN;
+ else
+ hlreg &= ~IXGBE_HLREG0_JUMBOEN;
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
- IXGBE_CORE_LOCK(adapter);
- error = ixgbe_setup_low_power_mode(adapter);
- IXGBE_CORE_UNLOCK(adapter);
+ bufsz = (adapter->rx_mbuf_sz +
+ BSIZEPKT_ROUNDUP) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- return (error);
-}
+ /* Setup the Base and Length of the Rx Descriptor Ring */
+ for (i = 0, que = adapter->rx_queues; i < adapter->num_rx_queues; i++, que++) {
+ struct rx_ring *rxr = &que->rxr;
+ u64 rdba = rxr->rx_paddr;
+ int j = rxr->me;
-/**
- * Methods for going from:
- * D0 -> D3: ixgbe_suspend
- * D3 -> D0: ixgbe_resume
- */
-static int
-ixgbe_suspend(device_t dev)
-{
- struct adapter *adapter = device_get_softc(dev);
- int error = 0;
+ /* Setup the Base and Length of the Rx Descriptor Ring */
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j),
+ (rdba & 0x00000000ffffffffULL));
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
+ IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j),
+ scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc));
- INIT_DEBUGOUT("ixgbe_suspend: begin");
+ /* Set up the SRRCTL register */
+ srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j));
+ srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
+ srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
+ srrctl |= bufsz;
+ srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
- IXGBE_CORE_LOCK(adapter);
+ /*
+ * Set DROP_EN iff we have no flow control and >1 queue.
+ * Note that srrctl was cleared shortly before during reset,
+ * so we do not need to clear the bit, but do it just in case
+ * this code is moved elsewhere.
+ */
+ if (adapter->num_rx_queues > 1 &&
+ adapter->hw.fc.requested_mode == ixgbe_fc_none) {
+ srrctl |= IXGBE_SRRCTL_DROP_EN;
+ } else {
+ srrctl &= ~IXGBE_SRRCTL_DROP_EN;
+ }
- error = ixgbe_setup_low_power_mode(adapter);
+ IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
- IXGBE_CORE_UNLOCK(adapter);
+ /* Setup the HW Rx Head and Tail Descriptor Pointers */
+ IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
- return (error);
-}
+ /* Set the driver rx tail address */
+ rxr->tail = IXGBE_RDT(rxr->me);
+ }
-static int
-ixgbe_resume(device_t dev)
-{
- struct adapter *adapter = device_get_softc(dev);
- struct ifnet *ifp = adapter->ifp;
- struct ixgbe_hw *hw = &adapter->hw;
- u32 wus;
+ if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
+ u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
+ IXGBE_PSRTYPE_UDPHDR |
+ IXGBE_PSRTYPE_IPV4HDR |
+ IXGBE_PSRTYPE_IPV6HDR;
+ IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
+ }
- INIT_DEBUGOUT("ixgbe_resume: begin");
+ rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
- IXGBE_CORE_LOCK(adapter);
+ ixgbe_initialize_rss_mapping(adapter);
- /* Read & clear WUS register */
- wus = IXGBE_READ_REG(hw, IXGBE_WUS);
- if (wus)
- device_printf(dev, "Woken up by (WUS): %#010x\n",
- IXGBE_READ_REG(hw, IXGBE_WUS));
- IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
- /* And clear WUFC until next low-power transition */
- IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
+ if (adapter->num_rx_queues > 1) {
+ /* RSS and RX IPP Checksum are mutually exclusive */
+ rxcsum |= IXGBE_RXCSUM_PCSD;
+ }
- /*
- * Required after D3->D0 transition;
- * will re-advertise all previous advertised speeds
- */
- if (ifp->if_flags & IFF_UP)
- ixgbe_init_locked(adapter);
+ if (ifp->if_capenable & IFCAP_RXCSUM)
+ rxcsum |= IXGBE_RXCSUM_PCSD;
- IXGBE_CORE_UNLOCK(adapter);
+ if (!(rxcsum & IXGBE_RXCSUM_PCSD))
+ rxcsum |= IXGBE_RXCSUM_IPPCSE;
- return (0);
+ IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
}
+
/*********************************************************************
- * Ioctl entry point
*
- * ixgbe_ioctl is called when the user wants to configure the
- * interface.
+ * Enable transmit units.
*
- * return 0 on success, positive on failure
**********************************************************************/
-
-static int
-ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
+static void
+ixgbe_initialize_transmit_units(if_ctx_t ctx)
{
- struct adapter *adapter = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *) data;
-#if defined(INET) || defined(INET6)
- struct ifaddr *ifa = (struct ifaddr *)data;
-#endif
- int error = 0;
- bool avoid_reset = FALSE;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx = adapter->shared;
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ix_tx_queue *que;
+ int i;
- switch (command) {
+ /* Setup the Base and Length of the Tx Descriptor Ring */
+ for (i = 0, que = adapter->tx_queues; i < adapter->num_tx_queues;
+ i++, que++) {
+ struct tx_ring *txr = &que->txr;
+ u64 tdba = txr->tx_paddr;
+ u32 txctrl = 0;
+ int j = txr->me;
- case SIOCSIFADDR:
-#ifdef INET
- if (ifa->ifa_addr->sa_family == AF_INET)
- avoid_reset = TRUE;
-#endif
-#ifdef INET6
- if (ifa->ifa_addr->sa_family == AF_INET6)
- avoid_reset = TRUE;
-#endif
- /*
- ** Calling init results in link renegotiation,
- ** so we avoid doing it when possible.
- */
- if (avoid_reset) {
- ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- ixgbe_init(adapter);
-#ifdef INET
- if (!(ifp->if_flags & IFF_NOARP))
- arp_ifinit(ifp, ifa);
-#endif
- } else
- error = ether_ioctl(ifp, command, data);
- break;
- case SIOCSIFMTU:
- IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
- if (ifr->ifr_mtu > IXGBE_MAX_MTU) {
- error = EINVAL;
- } else {
- IXGBE_CORE_LOCK(adapter);
- ifp->if_mtu = ifr->ifr_mtu;
- adapter->max_frame_size =
- ifp->if_mtu + IXGBE_MTU_HDR;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixgbe_init_locked(adapter);
-#ifdef PCI_IOV
- ixgbe_recalculate_max_frame(adapter);
-#endif
- IXGBE_CORE_UNLOCK(adapter);
- }
- break;
- case SIOCSIFFLAGS:
- IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
- IXGBE_CORE_LOCK(adapter);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- if ((ifp->if_flags ^ adapter->if_flags) &
- (IFF_PROMISC | IFF_ALLMULTI)) {
- ixgbe_set_promisc(adapter);
- }
- } else
- ixgbe_init_locked(adapter);
- } else
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixgbe_stop(adapter);
- adapter->if_flags = ifp->if_flags;
- IXGBE_CORE_UNLOCK(adapter);
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_CORE_LOCK(adapter);
- ixgbe_disable_intr(adapter);
- ixgbe_set_multi(adapter);
- ixgbe_enable_intr(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- }
- break;
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
- IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
- error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
- break;
- case SIOCSIFCAP:
- {
- IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
+ IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
+ (tdba & 0x00000000ffffffffULL));
+ IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
+ IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
+ scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc));
- int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- if (!mask)
- break;
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+ IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
- /* HW cannot turn these on/off separately */
- if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
- ifp->if_capenable ^= IFCAP_RXCSUM;
- ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
- }
- if (mask & IFCAP_TXCSUM)
- ifp->if_capenable ^= IFCAP_TXCSUM;
- if (mask & IFCAP_TXCSUM_IPV6)
- ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
- if (mask & IFCAP_TSO4)
- ifp->if_capenable ^= IFCAP_TSO4;
- if (mask & IFCAP_TSO6)
- ifp->if_capenable ^= IFCAP_TSO6;
- if (mask & IFCAP_LRO)
- ifp->if_capenable ^= IFCAP_LRO;
- if (mask & IFCAP_VLAN_HWTAGGING)
- ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (mask & IFCAP_VLAN_HWFILTER)
- ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
- if (mask & IFCAP_VLAN_HWTSO)
- ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_CORE_LOCK(adapter);
- ixgbe_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- }
- VLAN_CAPABILITIES(ifp);
- break;
- }
-#if __FreeBSD_version >= 1100036
- case SIOCGI2C:
- {
- struct ixgbe_hw *hw = &adapter->hw;
- struct ifi2creq i2c;
- int i;
- IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");
- error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
- if (error != 0)
+ txr->tx_rs_cidx = txr->tx_rs_pidx = txr->tx_cidx_processed = 0;
+ for (int k = 0; k < scctx->isc_ntxd[0]; k++)
+ txr->tx_rsq[k] = QIDX_INVALID;
+
+ /*
+ * Note: for X550 series devices, these registers are actually
+ * prefixed with TPH_ isntead of DCA_, but the addresses and
+ * fields remain the same.
+ */
+ /* Disable Head Writeback */
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
break;
- if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) {
- error = EINVAL;
+ default:
+ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
break;
}
- if (i2c.len > sizeof(i2c.data)) {
- error = EINVAL;
+ txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
+ break;
+ default:
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
break;
}
- for (i = 0; i < i2c.len; i++)
- hw->phy.ops.read_i2c_byte(hw, i2c.offset + i,
- i2c.dev_addr, &i2c.data[i]);
- error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
- break;
- }
-#endif
- default:
- IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
- error = ether_ioctl(ifp, command, data);
- break;
}
- return (error);
+ if (hw->mac.type != ixgbe_mac_82598EB) {
+ u32 dmatxctl, rttdcs;
+
+ dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
+ dmatxctl |= IXGBE_DMATXCTL_TE;
+ IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
+ /* Disable arbiter to set MTQC */
+ rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
+ rttdcs |= IXGBE_RTTDCS_ARBDIS;
+ IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+ IXGBE_WRITE_REG(hw, IXGBE_MTQC,
+ ixgbe_get_mtqc(adapter->iov_mode));
+ rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
+ IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+ }
}
-/*
- * Set the various hardware offload abilities.
- *
- * This takes the ifnet's if_capenable flags (e.g. set by the user using
- * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what
- * mbuf offload flags the driver will understand.
- */
-static void
-ixgbe_set_if_hwassist(struct adapter *adapter)
-{
- struct ifnet *ifp = adapter->ifp;
- struct ixgbe_hw *hw = &adapter->hw;
- ifp->if_hwassist = 0;
-#if __FreeBSD_version >= 1000000
- if (ifp->if_capenable & IFCAP_TSO4)
- ifp->if_hwassist |= CSUM_IP_TSO;
- if (ifp->if_capenable & IFCAP_TSO6)
- ifp->if_hwassist |= CSUM_IP6_TSO;
- if (ifp->if_capenable & IFCAP_TXCSUM) {
- ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP);
- if (hw->mac.type != ixgbe_mac_82598EB)
- ifp->if_hwassist |= CSUM_IP_SCTP;
- }
- if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) {
- ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP);
- if (hw->mac.type != ixgbe_mac_82598EB)
- ifp->if_hwassist |= CSUM_IP6_SCTP;
- }
-#else
- if (ifp->if_capenable & IFCAP_TSO)
- ifp->if_hwassist |= CSUM_TSO;
- if (ifp->if_capenable & IFCAP_TXCSUM) {
- ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
- if (hw->mac.type != ixgbe_mac_82598EB)
- ifp->if_hwassist |= CSUM_SCTP;
- }
-#endif
+static void *
+ixgbe_register(device_t dev)
+{
+ return (ixgbe_sctx);
}
-/*********************************************************************
- * Init entry point
+ /*********************************************************************
+ * ixgbe_if_attach_pre - Device initialization routine, part 1
*
- * This routine is used in two ways. It is used by the stack as
- * init entry point in network interface structure. It is also used
- * by the driver as a hw/sw initialization routine to get to a
- * consistent state.
+ * Called when the driver is being loaded.
+ * Identifies the type of hardware, initializes the hardware,
+ * and initializes iflib structures.
*
- * return 0 on success, positive on failure
- **********************************************************************/
-#define IXGBE_MHADD_MFS_SHIFT 16
-
-static void
-ixgbe_init_locked(struct adapter *adapter)
+ * return 0 on success, positive on failure
+ *********************************************************************/
+static int
+ixgbe_if_attach_pre(if_ctx_t ctx)
{
- struct ifnet *ifp = adapter->ifp;
- device_t dev = adapter->dev;
- struct ixgbe_hw *hw = &adapter->hw;
- struct tx_ring *txr;
- struct rx_ring *rxr;
- u32 txdctl, mhadd;
- u32 rxdctl, rxctrl;
- int err = 0;
-#ifdef PCI_IOV
- enum ixgbe_iov_mode mode;
-#endif
+ device_t dev;
+ struct adapter *adapter;
+ if_softc_ctx_t scctx;
+ struct ixgbe_hw *hw;
+ int error = 0;
+ u32 ctrl_ext;
- mtx_assert(&adapter->core_mtx, MA_OWNED);
- INIT_DEBUGOUT("ixgbe_init_locked: begin");
+ INIT_DEBUGOUT("ixgbe_attach: begin");
- hw->adapter_stopped = FALSE;
- ixgbe_stop_adapter(hw);
- callout_stop(&adapter->timer);
+ /* Allocate, clear, and link in our adapter structure */
+ dev = iflib_get_dev(ctx);
+ adapter = iflib_get_softc(ctx);
+ adapter->hw.back = adapter;
+ adapter->ctx = ctx;
+ adapter->dev = dev;
+ scctx = adapter->shared = iflib_get_softc_ctx(ctx);
+ adapter->media = iflib_get_media(ctx);
+ hw = &adapter->hw;
-#ifdef PCI_IOV
- mode = ixgbe_get_iov_mode(adapter);
- adapter->pool = ixgbe_max_vfs(mode);
- /* Queue indices may change with IOV mode */
- for (int i = 0; i < adapter->num_queues; i++) {
- adapter->rx_rings[i].me = ixgbe_pf_que_index(mode, i);
- adapter->tx_rings[i].me = ixgbe_pf_que_index(mode, i);
+ /* Save off the information about this board */
+ hw->vendor_id = pci_get_vendor(dev);
+ hw->device_id = pci_get_device(dev);
+ hw->revision_id = pci_get_revid(dev);
+ hw->subsystem_vendor_id = pci_get_subvendor(dev);
+ hw->subsystem_device_id = pci_get_subdevice(dev);
+
+ /* Do base PCI setup - map BAR0 */
+ if (ixgbe_allocate_pci_resources(ctx)) {
+ device_printf(dev, "Allocation of PCI resources failed\n");
+ return (ENXIO);
}
-#endif
- /* reprogram the RAR[0] in case user changed it. */
- ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV);
- /* Get the latest mac address, User can use a LAA */
- bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
- ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
- hw->addr_ctrl.rar_used_count = 1;
-
- /* Set hardware offload abilities from ifnet flags */
- ixgbe_set_if_hwassist(adapter);
+ /* let hardware know driver is loaded */
+ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
+ ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
- /* Prepare transmit descriptors and buffers */
- if (ixgbe_setup_transmit_structures(adapter)) {
- device_printf(dev, "Could not setup transmit structures\n");
- ixgbe_stop(adapter);
- return;
+ /* Initialize the shared code */
+ if (ixgbe_init_shared_code(hw) != 0) {
+ device_printf(dev, "Unable to initialize the shared code\n");
+ error = ENXIO;
+ goto err_pci;
}
- ixgbe_init_hw(hw);
-#ifdef PCI_IOV
- ixgbe_initialize_iov(adapter);
-#endif
- ixgbe_initialize_transmit_units(adapter);
+ if (hw->mbx.ops.init_params)
+ hw->mbx.ops.init_params(hw);
- /* Setup Multicast table */
- ixgbe_set_multi(adapter);
+ hw->allow_unsupported_sfp = allow_unsupported_sfp;
- /* Determine the correct mbuf pool, based on frame size */
- if (adapter->max_frame_size <= MCLBYTES)
- adapter->rx_mbuf_sz = MCLBYTES;
- else
- adapter->rx_mbuf_sz = MJUMPAGESIZE;
+ if (adapter->hw.mac.type != ixgbe_mac_82598EB)
+ hw->phy.smart_speed = ixgbe_smart_speed;
- /* Prepare receive descriptors and buffers */
- if (ixgbe_setup_receive_structures(adapter)) {
- device_printf(dev, "Could not setup receive structures\n");
- ixgbe_stop(adapter);
- return;
+ ixgbe_init_device_features(adapter);
+
+ /* Enable WoL (if supported) */
+ ixgbe_check_wol_support(adapter);
+
+ /* Verify adapter fan is still functional (if applicable) */
+ if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
+ u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ ixgbe_check_fan_failure(adapter, esdp, FALSE);
}
- /* Configure RX settings */
- ixgbe_initialize_receive_units(adapter);
+ /* Put the semaphore in a known state (released) */
+ ixgbe_init_swfw_semaphore(hw);
- /* Enable SDP & MSIX interrupts based on adapter */
- ixgbe_config_gpie(adapter);
+ /* Set an initial default flow control value */
+ hw->fc.requested_mode = ixgbe_flow_control;
- /* Set MTU size */
- if (ifp->if_mtu > ETHERMTU) {
- /* aka IXGBE_MAXFRS on 82599 and newer */
- mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
- mhadd &= ~IXGBE_MHADD_MFS_MASK;
- mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
- IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
- }
-
- /* Now enable all the queues */
- for (int i = 0; i < adapter->num_queues; i++) {
- txr = &adapter->tx_rings[i];
- txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me));
- txdctl |= IXGBE_TXDCTL_ENABLE;
- /* Set WTHRESH to 8, burst writeback */
- txdctl |= (8 << 16);
+ hw->phy.reset_if_overtemp = TRUE;
+ error = ixgbe_reset_hw(hw);
+ hw->phy.reset_if_overtemp = FALSE;
+ if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
/*
- * When the internal queue falls below PTHRESH (32),
- * start prefetching as long as there are at least
- * HTHRESH (1) buffers ready. The values are taken
- * from the Intel linux driver 3.8.21.
- * Prefetching enables tx line rate even with 1 queue.
+ * No optics in this port, set up
+ * so the timer routine will probe
+ * for later insertion.
*/
- txdctl |= (32 << 0) | (1 << 8);
- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl);
+ adapter->sfp_probe = TRUE;
+ error = 0;
+ } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev, "Unsupported SFP+ module detected!\n");
+ error = EIO;
+ goto err_pci;
+ } else if (error) {
+ device_printf(dev, "Hardware initialization failed\n");
+ error = EIO;
+ goto err_pci;
}
- for (int i = 0, j = 0; i < adapter->num_queues; i++) {
- rxr = &adapter->rx_rings[i];
- rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
- if (hw->mac.type == ixgbe_mac_82598EB) {
- /*
- ** PTHRESH = 21
- ** HTHRESH = 4
- ** WTHRESH = 8
- */
- rxdctl &= ~0x3FFFFF;
- rxdctl |= 0x080420;
- }
- rxdctl |= IXGBE_RXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl);
- for (; j < 10; j++) {
- if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) &
- IXGBE_RXDCTL_ENABLE)
- break;
- else
- msec_delay(1);
- }
- wmb();
-#ifdef DEV_NETMAP
- /*
- * In netmap mode, we must preserve the buffers made
- * available to userspace before the if_init()
- * (this is true by default on the TX side, because
- * init makes all buffers available to userspace).
- *
- * netmap_reset() and the device specific routines
- * (e.g. ixgbe_setup_receive_rings()) map these
- * buffers at the end of the NIC ring, so here we
- * must set the RDT (tail) register to make sure
- * they are not overwritten.
- *
- * In this driver the NIC ring starts at RDH = 0,
- * RDT points to the last slot available for reception (?),
- * so RDT = num_rx_desc - 1 means the whole ring is available.
- */
- if (ifp->if_capenable & IFCAP_NETMAP) {
- struct netmap_adapter *na = NA(adapter->ifp);
- struct netmap_kring *kring = &na->rx_rings[i];
- int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
-
- IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t);
- } else
-#endif /* DEV_NETMAP */
- IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), adapter->num_rx_desc - 1);
+ /* Make sure we have a good EEPROM before we read from it */
+ if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) {
+ device_printf(dev, "The EEPROM Checksum Is Not Valid\n");
+ error = EIO;
+ goto err_pci;
}
- /* Enable Receive engine */
- rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
- if (hw->mac.type == ixgbe_mac_82598EB)
- rxctrl |= IXGBE_RXCTRL_DMBYPS;
- rxctrl |= IXGBE_RXCTRL_RXEN;
- ixgbe_enable_rx_dma(hw, rxctrl);
+ error = ixgbe_start_hw(hw);
+ switch (error) {
+ case IXGBE_ERR_EEPROM_VERSION:
+ device_printf(dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues associated with your hardware.\n If you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n");
+ break;
+ case IXGBE_ERR_SFP_NOT_SUPPORTED:
+ device_printf(dev, "Unsupported SFP+ Module\n");
+ error = EIO;
+ goto err_pci;
+ case IXGBE_ERR_SFP_NOT_PRESENT:
+ device_printf(dev, "No SFP+ Module found\n");
+ /* falls thru */
+ default:
+ break;
+ }
- callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
+ /* Most of the iflib initialization... */
- /* Set up MSI/X routing */
- if (ixgbe_enable_msix) {
- ixgbe_configure_ivars(adapter);
- /* Set up auto-mask */
- if (hw->mac.type == ixgbe_mac_82598EB)
- IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
- else {
- IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
- IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
- }
- } else { /* Simple settings for Legacy/MSI */
- ixgbe_set_ivar(adapter, 0, 0, 0);
- ixgbe_set_ivar(adapter, 0, 0, 1);
- IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
+ iflib_set_mac(ctx, hw->mac.addr);
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ scctx->isc_rss_table_size = 512;
+ break;
+ default:
+ scctx->isc_rss_table_size = 128;
}
-#ifdef IXGBE_FDIR
- /* Init Flow director */
- if (hw->mac.type != ixgbe_mac_82598EB) {
- u32 hdrm = 32 << fdir_pballoc;
+ /* Allow legacy interrupts */
+ ixgbe_txrx.ift_legacy_intr = ixgbe_intr;
- hw->mac.ops.setup_rxpba(hw, 0, hdrm, PBA_STRATEGY_EQUAL);
- ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
- }
-#endif
+ scctx->isc_txqsizes[0] =
+ roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) +
+ sizeof(u32), DBA_ALIGN),
+ scctx->isc_rxqsizes[0] =
+ roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc),
+ DBA_ALIGN);
- /*
- * Check on any SFP devices that
- * need to be kick-started
- */
- if (hw->phy.type == ixgbe_phy_none) {
- err = hw->phy.ops.identify(hw);
- if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,
- "Unsupported SFP+ module type was detected.\n");
- return;
- }
+ /* XXX */
+ scctx->isc_max_txqsets = scctx->isc_max_rxqsets = 32;
+ scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO;
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+ scctx->isc_tx_nsegments = IXGBE_82598_SCATTER;
+ scctx->isc_msix_bar = PCIR_BAR(MSIX_82598_BAR);
+ } else {
+ scctx->isc_tx_csum_flags |= CSUM_SCTP |CSUM_IP6_SCTP;
+ scctx->isc_tx_nsegments = IXGBE_82599_SCATTER;
+ scctx->isc_msix_bar = PCIR_BAR(MSIX_82599_BAR);
}
+ scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments;
+ scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE;
+ scctx->isc_tx_tso_segsize_max = PAGE_SIZE;
- /* Set moderation on the Link interrupt */
- IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
+ scctx->isc_txrx = &ixgbe_txrx;
- /* Configure Energy Efficient Ethernet for supported devices */
- if (hw->mac.ops.setup_eee) {
- err = hw->mac.ops.setup_eee(hw, adapter->eee_enabled);
- if (err)
- device_printf(dev, "Error setting up EEE: %d\n", err);
- }
+ scctx->isc_capenable = IXGBE_CAPS;
- /* Enable power to the phy. */
- ixgbe_set_phy_power(hw, TRUE);
+ return (0);
- /* Config/Enable Link */
- ixgbe_config_link(adapter);
+err_pci:
+ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
+ ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
+ ixgbe_free_pci_resources(ctx);
- /* Hardware Packet Buffer & Flow Control setup */
- ixgbe_config_delay_values(adapter);
+ return (error);
+}
- /* Initialize the FC settings */
- ixgbe_start_hw(hw);
+ /*********************************************************************
+ * ixgbe_if_attach_post - Device initialization routine, part 2
+ *
+ * Called during driver load, but after interrupts and
+ * resources have been allocated and configured.
+ * Sets up some data structures not relevant to iflib.
+ *
+ * return 0 on success, positive on failure
+ *********************************************************************/
+static int
+ixgbe_if_attach_post(if_ctx_t ctx)
+{
+ device_t dev;
+ struct adapter *adapter;
+ struct ixgbe_hw *hw;
+ int error = 0;
- /* Set up VLAN support and filter */
- ixgbe_setup_vlan_hw_support(adapter);
+ dev = iflib_get_dev(ctx);
+ adapter = iflib_get_softc(ctx);
+ hw = &adapter->hw;
- /* Setup DMA Coalescing */
- ixgbe_config_dmac(adapter);
- /* And now turn on interrupts */
- ixgbe_enable_intr(adapter);
+ /* Sysctls for limiting the amount of work done in the taskqueues */
+ ixgbe_set_sysctl_value(adapter, "rx_processing_limit",
+ "max number of rx packets to process",
+ &adapter->rx_process_limit, ixgbe_rx_process_limit);
-#ifdef PCI_IOV
- /* Enable the use of the MBX by the VF's */
- {
- u32 reg = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
- reg |= IXGBE_CTRL_EXT_PFRSTD;
- IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, reg);
+ ixgbe_set_sysctl_value(adapter, "tx_processing_limit",
+ "max number of tx packets to process",
+ &adapter->tx_process_limit, ixgbe_tx_process_limit);
+
+ /* Allocate multicast array memory. */
+ adapter->mta = malloc(sizeof(*adapter->mta) *
+ MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT);
+ if (adapter->mta == NULL) {
+ device_printf(dev, "Can not allocate multicast setup array\n");
+ error = ENOMEM;
+ goto err;
}
-#endif
- /* Now inform the stack we're ready */
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ /* hw.ix defaults init */
+ ixgbe_set_advertise(adapter, ixgbe_advertise_speed);
+ adapter->enable_aim = ixgbe_enable_aim;
- return;
-}
+ /* Enable the optics for 82599 SFP+ fiber */
+ ixgbe_enable_tx_laser(hw);
-static void
-ixgbe_init(void *arg)
-{
- struct adapter *adapter = arg;
+ /* Enable power to the phy. */
+ ixgbe_set_phy_power(hw, TRUE);
- IXGBE_CORE_LOCK(adapter);
- ixgbe_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- return;
-}
+ ixgbe_initialize_iov(adapter);
-static void
-ixgbe_config_gpie(struct adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- u32 gpie;
+ error = ixgbe_setup_interface(ctx);
+ if (error) {
+ device_printf(dev, "Interface setup failed: %d\n", error);
+ goto err;
+ }
- gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+ /* Initialize statistics */
+ ixgbe_update_stats_counters(adapter);
+ ixgbe_add_hw_stats(adapter);
- /* Fan Failure Interrupt */
- if (hw->device_id == IXGBE_DEV_ID_82598AT)
- gpie |= IXGBE_SDP1_GPIEN;
+ /* Check PCIE slot type/speed/width */
+ ixgbe_get_slot_info(adapter);
/*
- * Module detection (SDP2)
- * Media ready (SDP1)
+ * Do time init and sysctl init here, but
+ * only on the first port of a bypass adapter.
*/
- if (hw->mac.type == ixgbe_mac_82599EB) {
- gpie |= IXGBE_SDP2_GPIEN;
- if (hw->device_id != IXGBE_DEV_ID_82599_QSFP_SF_QP)
- gpie |= IXGBE_SDP1_GPIEN;
- }
+ ixgbe_bypass_init(adapter);
- /*
- * Thermal Failure Detection (X540)
- * Link Detection (X552 SFP+, X552/X557-AT)
- */
- if (hw->mac.type == ixgbe_mac_X540 ||
- hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
- hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
- gpie |= IXGBE_SDP0_GPIEN_X540;
+ /* Set an initial dmac value */
+ adapter->dmac = 0;
+ adapter->eee_enabled = 0;
- if (adapter->msix > 1) {
- /* Enable Enhanced MSIX mode */
- gpie |= IXGBE_GPIE_MSIX_MODE;
- gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
- IXGBE_GPIE_OCD;
- }
+ if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
+ ixgbe_define_iov_schemas(dev, &error);
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
- return;
+ /* Sysctls */
+ ixgbe_add_device_sysctls(ctx);
+
+ return (0);
+err:
+ ixgbe_if_detach(ctx);
+ return (error);
}
/*
- * Requires adapter->max_frame_size to be set.
+ * Checks whether the adapter's ports are capable of
+ * Wake On LAN by reading the adapter's NVM.
+ *
+ * Sets each port's hw->wol_enabled value depending
+ * on the value read here.
*/
static void
-ixgbe_config_delay_values(struct adapter *adapter)
+ixgbe_check_wol_support(struct adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- u32 rxpb, frame, size, tmp;
+ u16 dev_caps = 0;
- frame = adapter->max_frame_size;
+ /* Find out WoL support for port */
+ adapter->wol_support = hw->wol_enabled = 0;
+ ixgbe_get_device_caps(hw, &dev_caps);
+ if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
+ ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
+ hw->bus.func == 0))
+ adapter->wol_support = hw->wol_enabled = 1;
- /* Calculate High Water */
- switch (hw->mac.type) {
- case ixgbe_mac_X540:
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- tmp = IXGBE_DV_X540(frame, frame);
- break;
- default:
- tmp = IXGBE_DV(frame, frame);
- break;
- }
- size = IXGBE_BT2KB(tmp);
- rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
- hw->fc.high_water[0] = rxpb - size;
-
- /* Now calculate Low Water */
- switch (hw->mac.type) {
- case ixgbe_mac_X540:
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- tmp = IXGBE_LOW_DV_X540(frame);
- break;
- default:
- tmp = IXGBE_LOW_DV(frame);
- break;
- }
- hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
-
- hw->fc.requested_mode = adapter->fc;
- hw->fc.pause_time = IXGBE_FC_PAUSE;
- hw->fc.send_xon = TRUE;
-}
-
-/*
-**
-** MSIX Interrupt Handlers and Tasklets
-**
-*/
-
-static inline void
-ixgbe_enable_queue(struct adapter *adapter, u32 vector)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- u64 queue = (u64)(1 << vector);
- u32 mask;
-
- if (hw->mac.type == ixgbe_mac_82598EB) {
- mask = (IXGBE_EIMS_RTX_QUEUE & queue);
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
- } else {
- mask = (queue & 0xFFFFFFFF);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
- mask = (queue >> 32);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
- }
-}
-
-static inline void
-ixgbe_disable_queue(struct adapter *adapter, u32 vector)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- u64 queue = (u64)(1 << vector);
- u32 mask;
-
- if (hw->mac.type == ixgbe_mac_82598EB) {
- mask = (IXGBE_EIMS_RTX_QUEUE & queue);
- IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
- } else {
- mask = (queue & 0xFFFFFFFF);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
- mask = (queue >> 32);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
- }
-}
-
-static void
-ixgbe_handle_que(void *context, int pending)
-{
- struct ix_queue *que = context;
- struct adapter *adapter = que->adapter;
- struct tx_ring *txr = que->txr;
- struct ifnet *ifp = adapter->ifp;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- ixgbe_rxeof(que);
- IXGBE_TX_LOCK(txr);
- ixgbe_txeof(txr);
-#ifndef IXGBE_LEGACY_TX
- if (!drbr_empty(ifp, txr->br))
- ixgbe_mq_start_locked(ifp, txr);
-#else
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- ixgbe_start_locked(txr, ifp);
-#endif
- IXGBE_TX_UNLOCK(txr);
- }
+ /* Save initial wake up filter configuration */
+ adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
- /* Reenable this interrupt */
- if (que->res != NULL)
- ixgbe_enable_queue(adapter, que->msix);
- else
- ixgbe_enable_intr(adapter);
return;
}
-
/*********************************************************************
*
- * Legacy Interrupt Service routine
+ * Setup networking device structure and register an interface.
*
**********************************************************************/
-
-static void
-ixgbe_legacy_irq(void *arg)
+static int
+ixgbe_setup_interface(if_ctx_t ctx)
{
- struct ix_queue *que = arg;
- struct adapter *adapter = que->adapter;
- struct ixgbe_hw *hw = &adapter->hw;
- struct ifnet *ifp = adapter->ifp;
- struct tx_ring *txr = adapter->tx_rings;
- bool more;
- u32 reg_eicr;
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ struct adapter *adapter = iflib_get_softc(ctx);
+ INIT_DEBUGOUT("ixgbe_setup_interface: begin");
- reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+ if_setifheaderlen(ifp, sizeof(struct ether_vlan_header));
+ if_setbaudrate(ifp, IF_Gbps(10));
- ++que->irqs;
- if (reg_eicr == 0) {
- ixgbe_enable_intr(adapter);
- return;
- }
+ adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
- more = ixgbe_rxeof(que);
+ /*
+ * Don't turn this on by default, if vlans are
+ * created on another pseudo device (eg. lagg)
+ * then vlan events are not passed thru, breaking
+ * operation, but with HW FILTER off it works. If
+ * using vlans directly on the ixgbe driver you can
+ * enable this and get full hardware tag filtering.
+ */
+ if_setcapenablebit(ifp, 0, IFCAP_VLAN_HWFILTER);
+ adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
- IXGBE_TX_LOCK(txr);
- ixgbe_txeof(txr);
-#ifdef IXGBE_LEGACY_TX
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- ixgbe_start_locked(txr, ifp);
-#else
- if (!drbr_empty(ifp, txr->br))
- ixgbe_mq_start_locked(ifp, txr);
-#endif
- IXGBE_TX_UNLOCK(txr);
+ ixgbe_add_media_types(ctx);
- /* Check for fan failure */
- if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
- (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
- device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
- "REPLACE IMMEDIATELY!!\n");
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
- }
+ /* Autoselect media by default */
+ ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO);
- /* Link status change */
- if (reg_eicr & IXGBE_EICR_LSC)
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ return (0);
+}
- /* External PHY interrupt */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
- (reg_eicr & IXGBE_EICR_GPI_SDP0_X540))
- taskqueue_enqueue(adapter->tq, &adapter->phy_task);
+static uint64_t
+ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_t ifp = iflib_get_ifp(ctx);
- if (more)
- taskqueue_enqueue(que->tq, &que->que_task);
- else
- ixgbe_enable_intr(adapter);
- return;
+ switch (cnt) {
+ case IFCOUNTER_IPACKETS:
+ return (adapter->ipackets);
+ case IFCOUNTER_OPACKETS:
+ return (adapter->opackets);
+ case IFCOUNTER_IBYTES:
+ return (adapter->ibytes);
+ case IFCOUNTER_OBYTES:
+ return (adapter->obytes);
+ case IFCOUNTER_IMCASTS:
+ return (adapter->imcasts);
+ case IFCOUNTER_OMCASTS:
+ return (adapter->omcasts);
+ case IFCOUNTER_COLLISIONS:
+ return (0);
+ case IFCOUNTER_IQDROPS:
+ return (adapter->iqdrops);
+ case IFCOUNTER_OQDROPS:
+ return (0);
+ case IFCOUNTER_IERRORS:
+ return (adapter->ierrors);
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
}
-
-/*********************************************************************
- *
- * MSIX Queue Interrupt Service routine
- *
- **********************************************************************/
-void
-ixgbe_msix_que(void *arg)
+static void
+ixgbe_add_media_types(if_ctx_t ctx)
{
- struct ix_queue *que = arg;
- struct adapter *adapter = que->adapter;
- struct ifnet *ifp = adapter->ifp;
- struct tx_ring *txr = que->txr;
- struct rx_ring *rxr = que->rxr;
- bool more;
- u32 newitr = 0;
-
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ device_t dev = iflib_get_dev(ctx);
+ u64 layer;
- /* Protect against spurious interrupts */
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
+ layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
- ixgbe_disable_queue(adapter, que->msix);
- ++que->irqs;
+ /* Media types with matching FreeBSD media defines */
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T, 0, NULL);
- more = ixgbe_rxeof(que);
+ if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
+ layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
- IXGBE_TX_LOCK(txr);
- ixgbe_txeof(txr);
-#ifdef IXGBE_LEGACY_TX
- if (!IFQ_DRV_IS_EMPTY(ifp->if_snd))
- ixgbe_start_locked(txr, ifp);
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+ if (hw->phy.multispeed_fiber)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
+ } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
+#ifdef IFM_ETH_XTYPE
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4)
+ ifmedia_add( adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX)
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_KX, 0, NULL);
#else
- if (!drbr_empty(ifp, txr->br))
- ixgbe_mq_start_locked(ifp, txr);
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
+ device_printf(dev, "Media supported: 10GbaseKR\n");
+ device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
+ device_printf(dev, "Media supported: 10GbaseKX4\n");
+ device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n");
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
+ device_printf(dev, "Media supported: 1000baseKX\n");
+ device_printf(dev, "1000baseKX mapped to 1000baseCX\n");
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
+ }
#endif
- IXGBE_TX_UNLOCK(txr);
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) {
+ /* Someday, someone will care about you... */
+ device_printf(dev, "Media supported: 1000baseBX\n");
+ }
- /* Do AIM now? */
+ if (hw->device_id == IXGBE_DEV_ID_82598AT) {
+ ifmedia_add(adapter->media,
+ IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
+ ifmedia_add(adapter->media,
+ IFM_ETHER | IFM_1000_T, 0, NULL);
+ }
- if (adapter->enable_aim == FALSE)
- goto no_calc;
- /*
- ** Do Adaptive Interrupt Moderation:
- ** - Write out last calculated setting
- ** - Calculate based on average size over
- ** the last interval.
- */
- if (que->eitr_setting)
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(que->msix), que->eitr_setting);
-
- que->eitr_setting = 0;
-
- /* Idle, do nothing */
- if ((txr->bytes == 0) && (rxr->bytes == 0))
- goto no_calc;
-
- if ((txr->bytes) && (txr->packets))
- newitr = txr->bytes/txr->packets;
- if ((rxr->bytes) && (rxr->packets))
- newitr = max(newitr,
- (rxr->bytes / rxr->packets));
- newitr += 24; /* account for hardware frame, crc */
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+}
- /* set an upper boundary */
- newitr = min(newitr, 3000);
+/************************************************************************
+ * ixgbe_is_sfp
+ ************************************************************************/
+static inline bool
+ixgbe_is_sfp(struct ixgbe_hw *hw)
+{
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ if (hw->phy.type == ixgbe_phy_nl)
+ return (TRUE);
+ return (FALSE);
+ case ixgbe_mac_82599EB:
+ switch (hw->mac.ops.get_media_type(hw)) {
+ case ixgbe_media_type_fiber:
+ case ixgbe_media_type_fiber_qsfp:
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
+ return (TRUE);
+ return (FALSE);
+ default:
+ return (FALSE);
+ }
+} /* ixgbe_is_sfp */
- /* Be nice to the mid range */
- if ((newitr > 300) && (newitr < 1200))
- newitr = (newitr / 3);
- else
- newitr = (newitr / 2);
+static void
+ixgbe_config_link(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 autoneg, err = 0;
+ bool sfp, negotiate;
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
- newitr |= newitr << 16;
- else
- newitr |= IXGBE_EITR_CNT_WDIS;
-
- /* save for next interrupt */
- que->eitr_setting = newitr;
+ sfp = ixgbe_is_sfp(hw);
- /* Reset state */
- txr->bytes = 0;
- txr->packets = 0;
- rxr->bytes = 0;
- rxr->packets = 0;
+ if (sfp) {
+ GROUPTASK_ENQUEUE(&adapter->mod_task);
+ } else {
+ if (hw->mac.ops.check_link)
+ err = ixgbe_check_link(hw, &adapter->link_speed,
+ &adapter->link_up, FALSE);
+ if (err)
+ return;
+ autoneg = hw->phy.autoneg_advertised;
+ if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
+ err = hw->mac.ops.get_link_capabilities(hw,
+ &autoneg, &negotiate);
+ if (err)
+ return;
+ if (hw->mac.ops.setup_link)
+ err = hw->mac.ops.setup_link(hw,
+ autoneg, adapter->link_up);
+ }
-no_calc:
- if (more)
- taskqueue_enqueue(que->tq, &que->que_task);
- else
- ixgbe_enable_queue(adapter, que->msix);
- return;
}
+/**********************************************************************
+ *
+ * Update the board statistics counters.
+ *
+ **********************************************************************/
static void
-ixgbe_msix_link(void *arg)
+ixgbe_update_stats_counters(struct adapter *adapter)
{
- struct adapter *adapter = arg;
struct ixgbe_hw *hw = &adapter->hw;
- u32 reg_eicr, mod_mask;
-
- ++adapter->link_irq;
-
- /* Pause other interrupts */
- IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
+ u32 missed_rx = 0, bprc, lxon, lxoff, total;
+ u64 total_missed_rx = 0;
- /* First get the cause */
- reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
- /* Be sure the queue bits are not cleared */
- reg_eicr &= ~IXGBE_EICR_RTX_QUEUE;
- /* Clear interrupt with write */
- IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
+ adapter->stats.pf.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
+ adapter->stats.pf.illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
+ adapter->stats.pf.errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC);
+ adapter->stats.pf.mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC);
- /* Link status change */
- if (reg_eicr & IXGBE_EICR_LSC) {
- IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ for (int i = 0; i < 16; i++) {
+ adapter->stats.pf.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+ adapter->stats.pf.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+ adapter->stats.pf.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
}
+ adapter->stats.pf.mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC);
+ adapter->stats.pf.mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC);
+ adapter->stats.pf.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
- if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
-#ifdef IXGBE_FDIR
- if (reg_eicr & IXGBE_EICR_FLOW_DIR) {
- /* This is probably overkill :) */
- if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
- return;
- /* Disable the interrupt */
- IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
- taskqueue_enqueue(adapter->tq, &adapter->fdir_task);
- } else
-#endif
- if (reg_eicr & IXGBE_EICR_ECC) {
- device_printf(adapter->dev, "CRITICAL: ECC ERROR!! "
- "Please Reboot!!\n");
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
- }
-
- /* Check for over temp condition */
- if (reg_eicr & IXGBE_EICR_TS) {
- device_printf(adapter->dev, "CRITICAL: OVER TEMP!! "
- "PHY IS SHUT DOWN!!\n");
- device_printf(adapter->dev, "System shutdown required!\n");
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
- }
-#ifdef PCI_IOV
- if (reg_eicr & IXGBE_EICR_MAILBOX)
- taskqueue_enqueue(adapter->tq, &adapter->mbx_task);
-#endif
- }
-
- /* Pluggable optics-related interrupt */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
- mod_mask = IXGBE_EICR_GPI_SDP0_X540;
- else
- mod_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
-
- if (ixgbe_is_sfp(hw)) {
- if (reg_eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw)) {
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
- taskqueue_enqueue(adapter->tq, &adapter->msf_task);
- } else if (reg_eicr & mod_mask) {
- IXGBE_WRITE_REG(hw, IXGBE_EICR, mod_mask);
- taskqueue_enqueue(adapter->tq, &adapter->mod_task);
- }
- }
-
- /* Check for fan failure */
- if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
- (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
- device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
- "REPLACE IMMEDIATELY!!\n");
- }
-
- /* External PHY interrupt */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
- (reg_eicr & IXGBE_EICR_GPI_SDP0_X540)) {
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
- taskqueue_enqueue(adapter->tq, &adapter->phy_task);
- }
-
- /* Re-enable other interrupts */
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
- return;
-}
-
-/*********************************************************************
- *
- * Media Ioctl callback
- *
- * This routine is called whenever the user queries the status of
- * the interface using ifconfig.
- *
- **********************************************************************/
-static void
-ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
-{
- struct adapter *adapter = ifp->if_softc;
- struct ixgbe_hw *hw = &adapter->hw;
- int layer;
-
- INIT_DEBUGOUT("ixgbe_media_status: begin");
- IXGBE_CORE_LOCK(adapter);
- ixgbe_update_link_status(adapter);
-
- ifmr->ifm_status = IFM_AVALID;
- ifmr->ifm_active = IFM_ETHER;
-
- if (!adapter->link_active) {
- IXGBE_CORE_UNLOCK(adapter);
- return;
- }
-
- ifmr->ifm_status |= IFM_ACTIVE;
- layer = adapter->phy_layer;
-
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T ||
- layer & IXGBE_PHYSICAL_LAYER_1000BASE_T ||
- layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_100_FULL:
- ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
- break;
- }
- if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
- layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
- break;
- }
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
- break;
- }
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
- break;
- }
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR ||
- layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
- break;
- }
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
- break;
- }
- /*
- ** XXX: These need to use the proper media types once
- ** they're added.
- */
-#ifndef IFM_ETH_XTYPE
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_2_5GB_FULL:
- ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
- break;
- }
- else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4
- || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_2_5GB_FULL:
- ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
- break;
- }
-#else
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_2_5GB_FULL:
- ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
- break;
- }
- else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4
- || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
- switch (adapter->link_speed) {
- case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_2_5GB_FULL:
- ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
- break;
- case IXGBE_LINK_SPEED_1GB_FULL:
- ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
- break;
- }
-#endif
-
- /* If nothing is recognized... */
- if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
- ifmr->ifm_active |= IFM_UNKNOWN;
-
-#if __FreeBSD_version >= 900025
- /* Display current flow control setting used on link */
- if (hw->fc.current_mode == ixgbe_fc_rx_pause ||
- hw->fc.current_mode == ixgbe_fc_full)
- ifmr->ifm_active |= IFM_ETH_RXPAUSE;
- if (hw->fc.current_mode == ixgbe_fc_tx_pause ||
- hw->fc.current_mode == ixgbe_fc_full)
- ifmr->ifm_active |= IFM_ETH_TXPAUSE;
-#endif
-
- IXGBE_CORE_UNLOCK(adapter);
-
- return;
-}
-
-/*********************************************************************
- *
- * Media Ioctl callback
- *
- * This routine is called when the user changes speed/duplex using
- * media/mediopt option with ifconfig.
- *
- **********************************************************************/
-static int
-ixgbe_media_change(struct ifnet * ifp)
-{
- struct adapter *adapter = ifp->if_softc;
- struct ifmedia *ifm = &adapter->media;
- struct ixgbe_hw *hw = &adapter->hw;
- ixgbe_link_speed speed = 0;
-
- INIT_DEBUGOUT("ixgbe_media_change: begin");
-
- if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
- return (EINVAL);
-
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- return (ENODEV);
-
- /*
- ** We don't actually need to check against the supported
- ** media types of the adapter; ifmedia will take care of
- ** that for us.
- */
-#ifndef IFM_ETH_XTYPE
- switch (IFM_SUBTYPE(ifm->ifm_media)) {
- case IFM_AUTO:
- case IFM_10G_T:
- speed |= IXGBE_LINK_SPEED_100_FULL;
- case IFM_10G_LRM:
- case IFM_10G_SR: /* KR, too */
- case IFM_10G_LR:
- case IFM_10G_CX4: /* KX4 */
- speed |= IXGBE_LINK_SPEED_1GB_FULL;
- case IFM_10G_TWINAX:
- speed |= IXGBE_LINK_SPEED_10GB_FULL;
- break;
- case IFM_1000_T:
- speed |= IXGBE_LINK_SPEED_100_FULL;
- case IFM_1000_LX:
- case IFM_1000_SX:
- case IFM_1000_CX: /* KX */
- speed |= IXGBE_LINK_SPEED_1GB_FULL;
- break;
- case IFM_100_TX:
- speed |= IXGBE_LINK_SPEED_100_FULL;
- break;
- default:
- goto invalid;
- }
-#else
- switch (IFM_SUBTYPE(ifm->ifm_media)) {
- case IFM_AUTO:
- case IFM_10G_T:
- speed |= IXGBE_LINK_SPEED_100_FULL;
- case IFM_10G_LRM:
- case IFM_10G_KR:
- case IFM_10G_LR:
- case IFM_10G_KX4:
- speed |= IXGBE_LINK_SPEED_1GB_FULL;
- case IFM_10G_TWINAX:
- speed |= IXGBE_LINK_SPEED_10GB_FULL;
- break;
- case IFM_1000_T:
- speed |= IXGBE_LINK_SPEED_100_FULL;
- case IFM_1000_LX:
- case IFM_1000_SX:
- case IFM_1000_KX:
- speed |= IXGBE_LINK_SPEED_1GB_FULL;
- break;
- case IFM_100_TX:
- speed |= IXGBE_LINK_SPEED_100_FULL;
- break;
- default:
- goto invalid;
- }
-#endif
-
- hw->mac.autotry_restart = TRUE;
- hw->mac.ops.setup_link(hw, speed, TRUE);
- if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
- adapter->advertise = 0;
- } else {
- if ((speed & IXGBE_LINK_SPEED_10GB_FULL) != 0)
- adapter->advertise |= 1 << 2;
- if ((speed & IXGBE_LINK_SPEED_1GB_FULL) != 0)
- adapter->advertise |= 1 << 1;
- if ((speed & IXGBE_LINK_SPEED_100_FULL) != 0)
- adapter->advertise |= 1 << 0;
- }
-
- return (0);
-
-invalid:
- device_printf(adapter->dev, "Invalid media type!\n");
- return (EINVAL);
-}
-
-static void
-ixgbe_set_promisc(struct adapter *adapter)
-{
- u_int32_t reg_rctl;
- struct ifnet *ifp = adapter->ifp;
- int mcnt = 0;
-
- reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
- reg_rctl &= (~IXGBE_FCTRL_UPE);
- if (ifp->if_flags & IFF_ALLMULTI)
- mcnt = MAX_NUM_MULTICAST_ADDRESSES;
- else {
- struct ifmultiaddr *ifma;
-#if __FreeBSD_version < 800000
- IF_ADDR_LOCK(ifp);
-#else
- if_maddr_rlock(ifp);
-#endif
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
- break;
- mcnt++;
- }
-#if __FreeBSD_version < 800000
- IF_ADDR_UNLOCK(ifp);
-#else
- if_maddr_runlock(ifp);
-#endif
- }
- if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
- reg_rctl &= (~IXGBE_FCTRL_MPE);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
-
- if (ifp->if_flags & IFF_PROMISC) {
- reg_rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
- } else if (ifp->if_flags & IFF_ALLMULTI) {
- reg_rctl |= IXGBE_FCTRL_MPE;
- reg_rctl &= ~IXGBE_FCTRL_UPE;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
- }
- return;
-}
-
-
-/*********************************************************************
- * Multicast Update
- *
- * This routine is called whenever multicast address list is updated.
- *
- **********************************************************************/
-#define IXGBE_RAR_ENTRIES 16
-
-static void
-ixgbe_set_multi(struct adapter *adapter)
-{
- u32 fctrl;
- u8 *update_ptr;
- struct ifmultiaddr *ifma;
- struct ixgbe_mc_addr *mta;
- int mcnt = 0;
- struct ifnet *ifp = adapter->ifp;
-
- IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
-
- mta = adapter->mta;
- bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
-
-#if __FreeBSD_version < 800000
- IF_ADDR_LOCK(ifp);
-#else
- if_maddr_rlock(ifp);
-#endif
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
- break;
- bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
- mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
- mta[mcnt].vmdq = adapter->pool;
- mcnt++;
- }
-#if __FreeBSD_version < 800000
- IF_ADDR_UNLOCK(ifp);
-#else
- if_maddr_runlock(ifp);
-#endif
-
- fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
- fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
- if (ifp->if_flags & IFF_PROMISC)
- fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
- else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES ||
- ifp->if_flags & IFF_ALLMULTI) {
- fctrl |= IXGBE_FCTRL_MPE;
- fctrl &= ~IXGBE_FCTRL_UPE;
- } else
- fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
-
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
-
- if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) {
- update_ptr = (u8 *)mta;
- ixgbe_update_mc_addr_list(&adapter->hw,
- update_ptr, mcnt, ixgbe_mc_array_itr, TRUE);
- }
-
- return;
-}
-
-/*
- * This is an iterator function now needed by the multicast
- * shared code. It simply feeds the shared code routine the
- * addresses in the array of ixgbe_set_multi() one by one.
- */
-static u8 *
-ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
-{
- struct ixgbe_mc_addr *mta;
-
- mta = (struct ixgbe_mc_addr *)*update_ptr;
- *vmdq = mta->vmdq;
-
- *update_ptr = (u8*)(mta + 1);
- return (mta->addr);
-}
-
-
-/*********************************************************************
- * Timer routine
- *
- * This routine checks for link status,updates statistics,
- * and runs the watchdog check.
- *
- **********************************************************************/
-
-static void
-ixgbe_local_timer(void *arg)
-{
- struct adapter *adapter = arg;
- device_t dev = adapter->dev;
- struct ix_queue *que = adapter->queues;
- u64 queues = 0;
- int hung = 0;
-
- mtx_assert(&adapter->core_mtx, MA_OWNED);
-
- /* Check for pluggable optics */
- if (adapter->sfp_probe)
- if (!ixgbe_sfp_probe(adapter))
- goto out; /* Nothing to do */
-
- ixgbe_update_link_status(adapter);
- ixgbe_update_stats_counters(adapter);
-
- /*
- ** Check the TX queues status
- ** - mark hung queues so we don't schedule on them
- ** - watchdog only if all queues show hung
- */
- for (int i = 0; i < adapter->num_queues; i++, que++) {
- /* Keep track of queues with work for soft irq */
- if (que->txr->busy)
- queues |= ((u64)1 << que->me);
- /*
- ** Each time txeof runs without cleaning, but there
- ** are uncleaned descriptors it increments busy. If
- ** we get to the MAX we declare it hung.
- */
- if (que->busy == IXGBE_QUEUE_HUNG) {
- ++hung;
- /* Mark the queue as inactive */
- adapter->active_queues &= ~((u64)1 << que->me);
- continue;
- } else {
- /* Check if we've come back from hung */
- if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
- adapter->active_queues |= ((u64)1 << que->me);
- }
- if (que->busy >= IXGBE_MAX_TX_BUSY) {
- device_printf(dev,"Warning queue %d "
- "appears to be hung!\n", i);
- que->txr->busy = IXGBE_QUEUE_HUNG;
- ++hung;
- }
-
- }
-
- /* Only truly watchdog if all queues show hung */
- if (hung == adapter->num_queues)
- goto watchdog;
- else if (queues != 0) { /* Force an IRQ on queues with work */
- ixgbe_rearm_queues(adapter, queues);
- }
-
-out:
- callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
- return;
-
-watchdog:
- device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
- adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- adapter->watchdog_events++;
- ixgbe_init_locked(adapter);
-}
-
-
-/*
-** Note: this routine updates the OS on the link state
-** the real check of the hardware only happens with
-** a link interrupt.
-*/
-static void
-ixgbe_update_link_status(struct adapter *adapter)
-{
- struct ifnet *ifp = adapter->ifp;
- device_t dev = adapter->dev;
-
- if (adapter->link_up){
- if (adapter->link_active == FALSE) {
- if (bootverbose)
- device_printf(dev,"Link is up %d Gbps %s \n",
- ((adapter->link_speed == 128)? 10:1),
- "Full Duplex");
- adapter->link_active = TRUE;
- /* Update any Flow Control changes */
- ixgbe_fc_enable(&adapter->hw);
- /* Update DMA coalescing config */
- ixgbe_config_dmac(adapter);
- if_link_state_change(ifp, LINK_STATE_UP);
-#ifdef PCI_IOV
- ixgbe_ping_all_vfs(adapter);
-#endif
- }
- } else { /* Link down */
- if (adapter->link_active == TRUE) {
- if (bootverbose)
- device_printf(dev,"Link is Down\n");
- if_link_state_change(ifp, LINK_STATE_DOWN);
- adapter->link_active = FALSE;
-#ifdef PCI_IOV
- ixgbe_ping_all_vfs(adapter);
-#endif
- }
- }
-
- return;
-}
-
-
-/*********************************************************************
- *
- * This routine disables all traffic on the adapter by issuing a
- * global reset on the MAC and deallocates TX/RX buffers.
- *
- **********************************************************************/
-
-static void
-ixgbe_stop(void *arg)
-{
- struct ifnet *ifp;
- struct adapter *adapter = arg;
- struct ixgbe_hw *hw = &adapter->hw;
- ifp = adapter->ifp;
-
- mtx_assert(&adapter->core_mtx, MA_OWNED);
-
- INIT_DEBUGOUT("ixgbe_stop: begin\n");
- ixgbe_disable_intr(adapter);
- callout_stop(&adapter->timer);
-
- /* Let the stack know...*/
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-
- ixgbe_reset_hw(hw);
- hw->adapter_stopped = FALSE;
- ixgbe_stop_adapter(hw);
- if (hw->mac.type == ixgbe_mac_82599EB)
- ixgbe_stop_mac_link_on_d3_82599(hw);
- /* Turn off the laser - noop with no optics */
- ixgbe_disable_tx_laser(hw);
-
- /* Update the stack */
- adapter->link_up = FALSE;
- ixgbe_update_link_status(adapter);
-
- /* reprogram the RAR[0] in case user changed it. */
- ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
-
- return;
-}
-
-
-/*********************************************************************
- *
- * Determine hardware revision.
- *
- **********************************************************************/
-static void
-ixgbe_identify_hardware(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- struct ixgbe_hw *hw = &adapter->hw;
-
- /* Save off the information about this board */
- hw->vendor_id = pci_get_vendor(dev);
- hw->device_id = pci_get_device(dev);
- hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
- hw->subsystem_vendor_id =
- pci_read_config(dev, PCIR_SUBVEND_0, 2);
- hw->subsystem_device_id =
- pci_read_config(dev, PCIR_SUBDEV_0, 2);
-
- /*
- ** Make sure BUSMASTER is set
- */
- pci_enable_busmaster(dev);
-
- /* We need this here to set the num_segs below */
- ixgbe_set_mac_type(hw);
+ /* Hardware workaround, gprc counts missed packets */
+ adapter->stats.pf.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
+ adapter->stats.pf.gprc -= missed_rx;
- /* Pick up the 82599 settings */
if (hw->mac.type != ixgbe_mac_82598EB) {
- hw->phy.smart_speed = ixgbe_smart_speed;
- adapter->num_segs = IXGBE_82599_SCATTER;
- } else
- adapter->num_segs = IXGBE_82598_SCATTER;
-
- return;
-}
-
-/*********************************************************************
- *
- * Determine optic type
- *
- **********************************************************************/
-static void
-ixgbe_setup_optics(struct adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- int layer;
-
- layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
-
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
- adapter->optics = IFM_10G_T;
- return;
- }
-
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
- adapter->optics = IFM_1000_T;
- return;
- }
-
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
- adapter->optics = IFM_1000_SX;
- return;
- }
-
- if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_LR |
- IXGBE_PHYSICAL_LAYER_10GBASE_LRM)) {
- adapter->optics = IFM_10G_LR;
- return;
- }
-
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
- adapter->optics = IFM_10G_SR;
- return;
- }
-
- if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) {
- adapter->optics = IFM_10G_TWINAX;
- return;
- }
-
- if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
- IXGBE_PHYSICAL_LAYER_10GBASE_CX4)) {
- adapter->optics = IFM_10G_CX4;
- return;
- }
-
- /* If we get here just set the default */
- adapter->optics = IFM_ETHER | IFM_AUTO;
- return;
-}
-
-/*********************************************************************
- *
- * Setup the Legacy or MSI Interrupt handler
- *
- **********************************************************************/
-static int
-ixgbe_allocate_legacy(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- struct ix_queue *que = adapter->queues;
-#ifndef IXGBE_LEGACY_TX
- struct tx_ring *txr = adapter->tx_rings;
-#endif
- int error, rid = 0;
-
- /* MSI RID at 1 */
- if (adapter->msix == 1)
- rid = 1;
-
- /* We allocate a single interrupt resource */
- adapter->res = bus_alloc_resource_any(dev,
- SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
- if (adapter->res == NULL) {
- device_printf(dev, "Unable to allocate bus resource: "
- "interrupt\n");
- return (ENXIO);
- }
-
- /*
- * Try allocating a fast interrupt and the associated deferred
- * processing contexts.
- */
-#ifndef IXGBE_LEGACY_TX
- TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
-#endif
- TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
- que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
- taskqueue_thread_enqueue, &que->tq);
- taskqueue_start_threads(&que->tq, 1, PI_NET, "%s ixq",
- device_get_nameunit(adapter->dev));
-
- /* Tasklets for Link, SFP and Multispeed Fiber */
- TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
- TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
- TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
- TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter);
-#ifdef IXGBE_FDIR
- TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter);
-#endif
- adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
- taskqueue_thread_enqueue, &adapter->tq);
- taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
- device_get_nameunit(adapter->dev));
-
- if ((error = bus_setup_intr(dev, adapter->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq,
- que, &adapter->tag)) != 0) {
- device_printf(dev, "Failed to register fast interrupt "
- "handler: %d\n", error);
- taskqueue_free(que->tq);
- taskqueue_free(adapter->tq);
- que->tq = NULL;
- adapter->tq = NULL;
- return (error);
+ adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) +
+ ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
+ adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
+ ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32);
+ adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORL) +
+ ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
+ adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+ adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+ } else {
+ adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+ adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+ /* 82598 only has a counter in the high register */
+ adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
+ adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
+ adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
}
- /* For simplicity in the handlers */
- adapter->active_queues = IXGBE_EIMS_ENABLE_MASK;
-
- return (0);
-}
-
-
-/*********************************************************************
- *
- * Setup MSIX Interrupt resources and handlers
- *
- **********************************************************************/
-static int
-ixgbe_allocate_msix(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- struct ix_queue *que = adapter->queues;
- struct tx_ring *txr = adapter->tx_rings;
- int error, rid, vector = 0;
- int cpu_id = 0;
-#ifdef RSS
- cpuset_t cpu_mask;
-#endif
-#ifdef RSS
/*
- * If we're doing RSS, the number of queues needs to
- * match the number of RSS buckets that are configured.
- *
- * + If there's more queues than RSS buckets, we'll end
- * up with queues that get no traffic.
- *
- * + If there's more RSS buckets than queues, we'll end
- * up having multiple RSS buckets map to the same queue,
- * so there'll be some contention.
+ * Workaround: mprc hardware is incorrectly counting
+ * broadcasts, so for now we subtract those.
*/
- if (adapter->num_queues != rss_getnumbuckets()) {
- device_printf(dev,
- "%s: number of queues (%d) != number of RSS buckets (%d)"
- "; performance will be impacted.\n",
- __func__,
- adapter->num_queues,
- rss_getnumbuckets());
- }
-#endif
+ bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
+ adapter->stats.pf.bprc += bprc;
+ adapter->stats.pf.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ adapter->stats.pf.mprc -= bprc;
- for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
- rid = vector + 1;
- que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (que->res == NULL) {
- device_printf(dev,"Unable to allocate"
- " bus resource: que interrupt [%d]\n", vector);
- return (ENXIO);
- }
- /* Set the handler function */
- error = bus_setup_intr(dev, que->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixgbe_msix_que, que, &que->tag);
- if (error) {
- que->res = NULL;
- device_printf(dev, "Failed to register QUE handler");
- return (error);
- }
-#if __FreeBSD_version >= 800504
- bus_describe_intr(dev, que->res, que->tag, "q%d", i);
-#endif
- que->msix = vector;
- adapter->active_queues |= (u64)(1 << que->msix);
-#ifdef RSS
- /*
- * The queue ID is used as the RSS layer bucket ID.
- * We look up the queue ID -> RSS CPU ID and select
- * that.
- */
- cpu_id = rss_getcpu(i % rss_getnumbuckets());
-#else
- /*
- * Bind the msix vector, and thus the
- * rings to the corresponding cpu.
- *
- * This just happens to match the default RSS round-robin
- * bucket -> queue -> CPU allocation.
- */
- if (adapter->num_queues > 1)
- cpu_id = i;
-#endif
- if (adapter->num_queues > 1)
- bus_bind_intr(dev, que->res, cpu_id);
-#ifdef IXGBE_DEBUG
-#ifdef RSS
- device_printf(dev,
- "Bound RSS bucket %d to CPU %d\n",
- i, cpu_id);
-#else
- device_printf(dev,
- "Bound queue %d to cpu %d\n",
- i, cpu_id);
-#endif
-#endif /* IXGBE_DEBUG */
+ adapter->stats.pf.prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
+ adapter->stats.pf.prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
+ adapter->stats.pf.prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
+ adapter->stats.pf.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
+ adapter->stats.pf.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
+ adapter->stats.pf.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
+ lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
+ adapter->stats.pf.lxontxc += lxon;
+ lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
+ adapter->stats.pf.lxofftxc += lxoff;
+ total = lxon + lxoff;
-#ifndef IXGBE_LEGACY_TX
- TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
-#endif
- TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
- que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
- taskqueue_thread_enqueue, &que->tq);
-#ifdef RSS
- CPU_SETOF(cpu_id, &cpu_mask);
- taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
- &cpu_mask,
- "%s (bucket %d)",
- device_get_nameunit(adapter->dev),
- cpu_id);
-#else
- taskqueue_start_threads(&que->tq, 1, PI_NET, "%s:q%d",
- device_get_nameunit(adapter->dev), i);
-#endif
- }
+ adapter->stats.pf.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
+ adapter->stats.pf.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
+ adapter->stats.pf.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
+ adapter->stats.pf.gptc -= total;
+ adapter->stats.pf.mptc -= total;
+ adapter->stats.pf.ptc64 -= total;
+ adapter->stats.pf.gotc -= total * ETHER_MIN_LEN;
- /* and Link */
- rid = vector + 1;
- adapter->res = bus_alloc_resource_any(dev,
- SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
- if (!adapter->res) {
- device_printf(dev,"Unable to allocate"
- " bus resource: Link interrupt [%d]\n", rid);
- return (ENXIO);
- }
- /* Set the link handler function */
- error = bus_setup_intr(dev, adapter->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixgbe_msix_link, adapter, &adapter->tag);
- if (error) {
- adapter->res = NULL;
- device_printf(dev, "Failed to register LINK handler");
- return (error);
+ adapter->stats.pf.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
+ adapter->stats.pf.rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
+ adapter->stats.pf.roc += IXGBE_READ_REG(hw, IXGBE_ROC);
+ adapter->stats.pf.rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
+ adapter->stats.pf.mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
+ adapter->stats.pf.mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
+ adapter->stats.pf.mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
+ adapter->stats.pf.tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
+ adapter->stats.pf.tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
+ adapter->stats.pf.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
+ adapter->stats.pf.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
+ adapter->stats.pf.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
+ adapter->stats.pf.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
+ adapter->stats.pf.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
+ adapter->stats.pf.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
+ adapter->stats.pf.xec += IXGBE_READ_REG(hw, IXGBE_XEC);
+ adapter->stats.pf.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
+ adapter->stats.pf.fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
+ /* Only read FCOE on 82599 */
+ if (hw->mac.type != ixgbe_mac_82598EB) {
+ adapter->stats.pf.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
+ adapter->stats.pf.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
+ adapter->stats.pf.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
+ adapter->stats.pf.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
+ adapter->stats.pf.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
}
-#if __FreeBSD_version >= 800504
- bus_describe_intr(dev, adapter->res, adapter->tag, "link");
-#endif
- adapter->vector = vector;
- /* Tasklets for Link, SFP and Multispeed Fiber */
- TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
- TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
- TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
-#ifdef PCI_IOV
- TASK_INIT(&adapter->mbx_task, 0, ixgbe_handle_mbx, adapter);
-#endif
- TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter);
-#ifdef IXGBE_FDIR
- TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter);
-#endif
- adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
- taskqueue_thread_enqueue, &adapter->tq);
- taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
- device_get_nameunit(adapter->dev));
- return (0);
+ /* Fill out the OS statistics structure */
+ IXGBE_SET_IPACKETS(adapter, adapter->stats.pf.gprc);
+ IXGBE_SET_OPACKETS(adapter, adapter->stats.pf.gptc);
+ IXGBE_SET_IBYTES(adapter, adapter->stats.pf.gorc);
+ IXGBE_SET_OBYTES(adapter, adapter->stats.pf.gotc);
+ IXGBE_SET_IMCASTS(adapter, adapter->stats.pf.mprc);
+ IXGBE_SET_OMCASTS(adapter, adapter->stats.pf.mptc);
+ IXGBE_SET_COLLISIONS(adapter, 0);
+ IXGBE_SET_IQDROPS(adapter, total_missed_rx);
+ IXGBE_SET_IERRORS(adapter, adapter->stats.pf.crcerrs
+ + adapter->stats.pf.rlec);
}
/*
- * Setup Either MSI/X or MSI
+ * Add sysctl variables, one per statistic, to the system.
*/
-static int
-ixgbe_setup_msix(struct adapter *adapter)
+static void
+ixgbe_add_hw_stats(struct adapter *adapter)
{
- device_t dev = adapter->dev;
- int rid, want, queues, msgs;
-
- /* Override by tuneable */
- if (ixgbe_enable_msix == 0)
- goto msi;
-
- /* First try MSI/X */
- msgs = pci_msix_count(dev);
- if (msgs == 0)
- goto msi;
- rid = PCIR_BAR(MSIX_82598_BAR);
- adapter->msix_mem = bus_alloc_resource_any(dev,
- SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (adapter->msix_mem == NULL) {
- rid += 4; /* 82599 maps in higher BAR */
- adapter->msix_mem = bus_alloc_resource_any(dev,
- SYS_RES_MEMORY, &rid, RF_ACTIVE);
- }
- if (adapter->msix_mem == NULL) {
- /* May not be enabled */
- device_printf(adapter->dev,
- "Unable to map MSIX table \n");
- goto msi;
- }
+ device_t dev = iflib_get_dev(adapter->ctx);
+ struct ix_rx_queue *rx_que;
+ struct ix_tx_queue *tx_que;
+ int i;
- /* Figure out a reasonable auto config value */
- queues = (mp_ncpus > (msgs - 1)) ? (msgs - 1) : mp_ncpus;
+ struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
+ struct sysctl_oid *tree = device_get_sysctl_tree(dev);
+ struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
+ struct ixgbe_hw_stats *stats = &adapter->stats.pf;
-#ifdef RSS
- /* If we're doing RSS, clamp at the number of RSS buckets */
- if (queues > rss_getnumbuckets())
- queues = rss_getnumbuckets();
-#endif
+ struct sysctl_oid *stat_node, *queue_node;
+ struct sysctl_oid_list *stat_list, *queue_list;
- if (ixgbe_num_queues != 0)
- queues = ixgbe_num_queues;
- /* Set max queues to 8 when autoconfiguring */
- else if ((ixgbe_num_queues == 0) && (queues > 8))
- queues = 8;
+#define QUEUE_NAME_LEN 32
+ char namebuf[QUEUE_NAME_LEN];
- /* reflect correct sysctl value */
- ixgbe_num_queues = queues;
+ /* Driver Statistics */
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
+ CTLFLAG_RD, &adapter->watchdog_events,
+ "Watchdog timeouts");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
+ CTLFLAG_RD, &adapter->link_irq,
+ "Link MSIX IRQ Handled");
- /*
- ** Want one vector (RX/TX pair) per queue
- ** plus an additional for Link.
- */
- want = queues + 1;
- if (msgs >= want)
- msgs = want;
- else {
- device_printf(adapter->dev,
- "MSIX Configuration Problem, "
- "%d vectors but %d queues wanted!\n",
- msgs, want);
- goto msi;
- }
- if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) {
- device_printf(adapter->dev,
- "Using MSIX interrupts with %d vectors\n", msgs);
- adapter->num_queues = queues;
- return (msgs);
+ for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) {
+ struct tx_ring *txr = &tx_que->txr;
+ snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
+ queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
+ CTLFLAG_RD, NULL, "Queue Name");
+ queue_list = SYSCTL_CHILDREN(queue_node);
+ SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head",
+ CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
+ ixgbe_sysctl_tdh_handler, "IU",
+ "Transmit Descriptor Head");
+ SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail",
+ CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
+ ixgbe_sysctl_tdt_handler, "IU",
+ "Transmit Descriptor Tail");
+ SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tso_tx",
+ CTLFLAG_RD, &txr->tso_tx,
+ "TSO");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
+ CTLFLAG_RD, &txr->total_packets,
+ "Queue Packets Transmitted");
}
- /*
- ** If MSIX alloc failed or provided us with
- ** less than needed, free and fall through to MSI
- */
- pci_release_msi(dev);
-msi:
- if (adapter->msix_mem != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY,
- rid, adapter->msix_mem);
- adapter->msix_mem = NULL;
- }
- msgs = 1;
- if (pci_alloc_msi(dev, &msgs) == 0) {
- device_printf(adapter->dev, "Using an MSI interrupt\n");
- return (msgs);
- }
- device_printf(adapter->dev, "Using a Legacy interrupt\n");
- return (0);
-}
+ for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) {
+ struct rx_ring *rxr = &rx_que->rxr;
+ snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
+ queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
+ CTLFLAG_RD, NULL, "Queue Name");
+ queue_list = SYSCTL_CHILDREN(queue_node);
+ SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate",
+ CTLTYPE_UINT | CTLFLAG_RW, &adapter->rx_queues[i],
+ sizeof(&adapter->rx_queues[i]),
+ ixgbe_sysctl_interrupt_rate_handler, "IU",
+ "Interrupt Rate");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
+ CTLFLAG_RD, &(adapter->rx_queues[i].irqs),
+ "irqs on this queue");
+ SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head",
+ CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
+ ixgbe_sysctl_rdh_handler, "IU",
+ "Receive Descriptor Head");
+ SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail",
+ CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
+ ixgbe_sysctl_rdt_handler, "IU",
+ "Receive Descriptor Tail");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
+ CTLFLAG_RD, &rxr->rx_packets,
+ "Queue Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
+ CTLFLAG_RD, &rxr->rx_bytes,
+ "Queue Bytes Received");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies",
+ CTLFLAG_RD, &rxr->rx_copies,
+ "Copied RX Frames");
+ }
-static int
-ixgbe_allocate_pci_resources(struct adapter *adapter)
-{
- int rid;
- device_t dev = adapter->dev;
+ /* MAC stats get the own sub node */
- rid = PCIR_BAR(0);
- adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &rid, RF_ACTIVE);
+ stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
+ CTLFLAG_RD, NULL, "MAC Statistics");
+ stat_list = SYSCTL_CHILDREN(stat_node);
- if (!(adapter->pci_mem)) {
- device_printf(dev, "Unable to allocate bus resource: memory\n");
- return (ENXIO);
- }
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
+ CTLFLAG_RD, &stats->crcerrs,
+ "CRC Errors");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs",
+ CTLFLAG_RD, &stats->illerrc,
+ "Illegal Byte Errors");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs",
+ CTLFLAG_RD, &stats->errbc,
+ "Byte Errors");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards",
+ CTLFLAG_RD, &stats->mspdc,
+ "MAC Short Packets Discarded");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults",
+ CTLFLAG_RD, &stats->mlfc,
+ "MAC Local Faults");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults",
+ CTLFLAG_RD, &stats->mrfc,
+ "MAC Remote Faults");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs",
+ CTLFLAG_RD, &stats->rlec,
+ "Receive Length Errors");
- /* Save bus_space values for READ/WRITE_REG macros */
- adapter->osdep.mem_bus_space_tag =
- rman_get_bustag(adapter->pci_mem);
- adapter->osdep.mem_bus_space_handle =
- rman_get_bushandle(adapter->pci_mem);
- /* Set hw values for shared code */
- adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle;
- adapter->hw.back = adapter;
+ /* Flow Control stats */
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
+ CTLFLAG_RD, &stats->lxontxc,
+ "Link XON Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
+ CTLFLAG_RD, &stats->lxonrxc,
+ "Link XON Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
+ CTLFLAG_RD, &stats->lxofftxc,
+ "Link XOFF Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
+ CTLFLAG_RD, &stats->lxoffrxc,
+ "Link XOFF Received");
- /* Default to 1 queue if MSI-X setup fails */
- adapter->num_queues = 1;
+ /* Packet Reception Stats */
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd",
+ CTLFLAG_RD, &stats->tor,
+ "Total Octets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
+ CTLFLAG_RD, &stats->gorc,
+ "Good Octets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd",
+ CTLFLAG_RD, &stats->tpr,
+ "Total Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
+ CTLFLAG_RD, &stats->gprc,
+ "Good Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
+ CTLFLAG_RD, &stats->mprc,
+ "Multicast Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd",
+ CTLFLAG_RD, &stats->bprc,
+ "Broadcast Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
+ CTLFLAG_RD, &stats->prc64,
+ "64 byte frames received ");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
+ CTLFLAG_RD, &stats->prc127,
+ "65-127 byte frames received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
+ CTLFLAG_RD, &stats->prc255,
+ "128-255 byte frames received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
+ CTLFLAG_RD, &stats->prc511,
+ "256-511 byte frames received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
+ CTLFLAG_RD, &stats->prc1023,
+ "512-1023 byte frames received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
+ CTLFLAG_RD, &stats->prc1522,
+ "1023-1522 byte frames received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized",
+ CTLFLAG_RD, &stats->ruc,
+ "Receive Undersized");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
+ CTLFLAG_RD, &stats->rfc,
+ "Fragmented Packets Received ");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized",
+ CTLFLAG_RD, &stats->roc,
+ "Oversized Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd",
+ CTLFLAG_RD, &stats->rjc,
+ "Received Jabber");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd",
+ CTLFLAG_RD, &stats->mngprc,
+ "Management Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd",
+ CTLFLAG_RD, &stats->mngptc,
+ "Management Packets Dropped");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs",
+ CTLFLAG_RD, &stats->xec,
+ "Checksum Errors");
- /*
- ** Now setup MSI or MSI-X, should
- ** return us the number of supported
- ** vectors. (Will be 1 for MSI)
- */
- adapter->msix = ixgbe_setup_msix(adapter);
- return (0);
+ /* Packet Transmission Stats */
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
+ CTLFLAG_RD, &stats->gotc,
+ "Good Octets Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
+ CTLFLAG_RD, &stats->tpt,
+ "Total Packets Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
+ CTLFLAG_RD, &stats->gptc,
+ "Good Packets Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
+ CTLFLAG_RD, &stats->bptc,
+ "Broadcast Packets Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
+ CTLFLAG_RD, &stats->mptc,
+ "Multicast Packets Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd",
+ CTLFLAG_RD, &stats->mngptc,
+ "Management Packets Transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
+ CTLFLAG_RD, &stats->ptc64,
+ "64 byte frames transmitted ");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
+ CTLFLAG_RD, &stats->ptc127,
+ "65-127 byte frames transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
+ CTLFLAG_RD, &stats->ptc255,
+ "128-255 byte frames transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
+ CTLFLAG_RD, &stats->ptc511,
+ "256-511 byte frames transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
+ CTLFLAG_RD, &stats->ptc1023,
+ "512-1023 byte frames transmitted");
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
+ CTLFLAG_RD, &stats->ptc1522,
+ "1024-1522 byte frames transmitted");
}
-static void
-ixgbe_free_pci_resources(struct adapter * adapter)
+/** ixgbe_sysctl_tdh_handler - Handler function
+ * Retrieves the TDH value from the hardware
+ */
+static int
+ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS)
{
- struct ix_queue *que = adapter->queues;
- device_t dev = adapter->dev;
- int rid, memrid;
-
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
- memrid = PCIR_BAR(MSIX_82598_BAR);
- else
- memrid = PCIR_BAR(MSIX_82599_BAR);
-
- /*
- ** There is a slight possibility of a failure mode
- ** in attach that will result in entering this function
- ** before interrupt resources have been initialized, and
- ** in that case we do not want to execute the loops below
- ** We can detect this reliably by the state of the adapter
- ** res pointer.
- */
- if (adapter->res == NULL)
- goto mem;
-
- /*
- ** Release all msix queue resources:
- */
- for (int i = 0; i < adapter->num_queues; i++, que++) {
- rid = que->msix + 1;
- if (que->tag != NULL) {
- bus_teardown_intr(dev, que->res, que->tag);
- que->tag = NULL;
- }
- if (que->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
- }
-
-
- /* Clean the Legacy or Link interrupt last */
- if (adapter->vector) /* we are doing MSIX */
- rid = adapter->vector + 1;
- else
- (adapter->msix != 0) ? (rid = 1):(rid = 0);
-
- if (adapter->tag != NULL) {
- bus_teardown_intr(dev, adapter->res, adapter->tag);
- adapter->tag = NULL;
- }
- if (adapter->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res);
-
-mem:
- if (adapter->msix)
- pci_release_msi(dev);
-
- if (adapter->msix_mem != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- memrid, adapter->msix_mem);
+ int error;
- if (adapter->pci_mem != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- PCIR_BAR(0), adapter->pci_mem);
+ struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
+ if (!txr)
+ return 0;
- return;
+ unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error || !req->newptr)
+ return error;
+ return 0;
}
-/*********************************************************************
- *
- * Setup networking device structure and register an interface.
- *
- **********************************************************************/
+/** ixgbe_sysctl_tdt_handler - Handler function
+ * Retrieves the TDT value from the hardware
+ */
static int
-ixgbe_setup_interface(device_t dev, struct adapter *adapter)
+ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS)
{
- struct ifnet *ifp;
-
- INIT_DEBUGOUT("ixgbe_setup_interface: begin");
-
- ifp = adapter->ifp = if_alloc(IFT_ETHER);
- if (ifp == NULL) {
- device_printf(dev, "can not allocate ifnet structure\n");
- return (-1);
- }
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_baudrate = IF_Gbps(10);
- ifp->if_init = ixgbe_init;
- ifp->if_softc = adapter;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = ixgbe_ioctl;
-#if __FreeBSD_version >= 1100036
- if_setgetcounterfn(ifp, ixgbe_get_counter);
-#endif
-#if __FreeBSD_version >= 1100045
- /* TSO parameters */
- ifp->if_hw_tsomax = 65518;
- ifp->if_hw_tsomaxsegcount = IXGBE_82599_SCATTER;
- ifp->if_hw_tsomaxsegsize = 2048;
-#endif
-#ifndef IXGBE_LEGACY_TX
- ifp->if_transmit = ixgbe_mq_start;
- ifp->if_qflush = ixgbe_qflush;
-#else
- ifp->if_start = ixgbe_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
- ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 2;
- IFQ_SET_READY(&ifp->if_snd);
-#endif
+ int error;
- ether_ifattach(ifp, adapter->hw.mac.addr);
+ struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
+ if (!txr)
+ return 0;
- adapter->max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error || !req->newptr)
+ return error;
+ return 0;
+}
- /*
- * Tell the upper layer(s) we support long frames.
- */
- ifp->if_hdrlen = sizeof(struct ether_vlan_header);
-
- /* Set capability flags */
- ifp->if_capabilities |= IFCAP_RXCSUM
- | IFCAP_TXCSUM
- | IFCAP_RXCSUM_IPV6
- | IFCAP_TXCSUM_IPV6
- | IFCAP_TSO4
- | IFCAP_TSO6
- | IFCAP_LRO
- | IFCAP_VLAN_HWTAGGING
- | IFCAP_VLAN_HWTSO
- | IFCAP_VLAN_HWCSUM
- | IFCAP_JUMBO_MTU
- | IFCAP_VLAN_MTU
- | IFCAP_HWSTATS;
-
- /* Enable the above capabilities by default */
- ifp->if_capenable = ifp->if_capabilities;
+/** ixgbe_sysctl_rdh_handler - Handler function
+ * Retrieves the RDH value from the hardware
+ */
+static int
+ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS)
+{
+ int error;
- /*
- ** Don't turn this on by default, if vlans are
- ** created on another pseudo device (eg. lagg)
- ** then vlan events are not passed thru, breaking
- ** operation, but with HW FILTER off it works. If
- ** using vlans directly on the ixgbe driver you can
- ** enable this and get full hardware tag filtering.
- */
- ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
+ struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
+ if (!rxr)
+ return 0;
- /*
- * Specify the media types supported by this adapter and register
- * callbacks to update media and link information
- */
- ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change,
- ixgbe_media_status);
+ unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error || !req->newptr)
+ return error;
+ return 0;
+}
- adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
- ixgbe_add_media_types(adapter);
+/** ixgbe_sysctl_rdt_handler - Handler function
+ * Retrieves the RDT value from the hardware
+ */
+static int
+ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS)
+{
+ int error;
- /* Set autoselect media by default */
- ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
+ struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
+ if (!rxr)
+ return 0;
- return (0);
+ unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error || !req->newptr)
+ return error;
+ return 0;
}
+/*
+** This routine is run via a vlan config EVENT,
+** it enables us to use the HW Filter table since
+** we can get the vlan id. This just creates the
+** entry in the soft version of the VFTA, init will
+** repopulate the real table.
+*/
static void
-ixgbe_add_media_types(struct adapter *adapter)
+ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag)
{
- struct ixgbe_hw *hw = &adapter->hw;
- device_t dev = adapter->dev;
- int layer;
-
- layer = adapter->phy_layer;
-
- /* Media types with matching FreeBSD media defines */
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL);
-
- if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
- layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
-
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
- if (hw->phy.multispeed_fiber)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0, NULL);
- }
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
- if (hw->phy.multispeed_fiber)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
- } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
-
-#ifdef IFM_ETH_XTYPE
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
-#else
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
- device_printf(dev, "Media supported: 10GbaseKR\n");
- device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
- }
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
- device_printf(dev, "Media supported: 10GbaseKX4\n");
- device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n");
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
- }
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
- device_printf(dev, "Media supported: 1000baseKX\n");
- device_printf(dev, "1000baseKX mapped to 1000baseCX\n");
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
- }
-#endif
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
- device_printf(dev, "Media supported: 1000baseBX\n");
-
- if (hw->device_id == IXGBE_DEV_ID_82598AT) {
- ifmedia_add(&adapter->media,
- IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
- ifmedia_add(&adapter->media,
- IFM_ETHER | IFM_1000_T, 0, NULL);
- }
+ struct adapter *adapter = iflib_get_softc(ctx);
+ u16 index, bit;
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ index = (vtag >> 5) & 0x7F;
+ bit = vtag & 0x1F;
+ adapter->shadow_vfta[index] |= (1 << bit);
+ ++adapter->num_vlans;
+ ixgbe_setup_vlan_hw_support(ctx);
}
+/*
+** This routine is run via a vlan
+** unconfig EVENT, remove our entry
+** in the soft vfta.
+*/
static void
-ixgbe_config_link(struct adapter *adapter)
+ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag)
{
- struct ixgbe_hw *hw = &adapter->hw;
- u32 autoneg, err = 0;
- bool sfp, negotiate;
-
- sfp = ixgbe_is_sfp(hw);
+ struct adapter *adapter = iflib_get_softc(ctx);
+ u16 index, bit;
- if (sfp) {
- taskqueue_enqueue(adapter->tq, &adapter->mod_task);
- } else {
- if (hw->mac.ops.check_link)
- err = ixgbe_check_link(hw, &adapter->link_speed,
- &adapter->link_up, FALSE);
- if (err)
- goto out;
- autoneg = hw->phy.autoneg_advertised;
- if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
- err = hw->mac.ops.get_link_capabilities(hw,
- &autoneg, &negotiate);
- if (err)
- goto out;
- if (hw->mac.ops.setup_link)
- err = hw->mac.ops.setup_link(hw,
- autoneg, adapter->link_up);
- }
-out:
- return;
+ index = (vtag >> 5) & 0x7F;
+ bit = vtag & 0x1F;
+ adapter->shadow_vfta[index] &= ~(1 << bit);
+ --adapter->num_vlans;
+ /* Re-init to load the changes */
+ ixgbe_setup_vlan_hw_support(ctx);
}
-
-/*********************************************************************
- *
- * Enable transmit units.
- *
- **********************************************************************/
static void
-ixgbe_initialize_transmit_units(struct adapter *adapter)
+ixgbe_setup_vlan_hw_support(if_ctx_t ctx)
{
- struct tx_ring *txr = adapter->tx_rings;
- struct ixgbe_hw *hw = &adapter->hw;
-
- /* Setup the Base and Length of the Tx Descriptor Ring */
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- u64 tdba = txr->txdma.dma_paddr;
- u32 txctrl = 0;
- int j = txr->me;
-
- IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
- (tdba & 0x00000000ffffffffULL));
- IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
- IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
- adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc));
-
- /* Setup the HW Tx Head and Tail descriptor pointers */
- IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
- IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
-
- /* Cache the tail address */
- txr->tail = IXGBE_TDT(j);
-
- /* Disable Head Writeback */
- /*
- * Note: for X550 series devices, these registers are actually
- * prefixed with TPH_ isntead of DCA_, but the addresses and
- * fields remain the same.
- */
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB:
- txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
- break;
- default:
- txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
- break;
- }
- txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB:
- IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
- break;
- default:
- IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
- break;
- }
-
- }
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ struct rx_ring *rxr;
+ u32 ctrl;
- if (hw->mac.type != ixgbe_mac_82598EB) {
- u32 dmatxctl, rttdcs;
-#ifdef PCI_IOV
- enum ixgbe_iov_mode mode = ixgbe_get_iov_mode(adapter);
-#endif
- dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
- dmatxctl |= IXGBE_DMATXCTL_TE;
- IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
- /* Disable arbiter to set MTQC */
- rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
- rttdcs |= IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
-#ifdef PCI_IOV
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, ixgbe_get_mtqc(mode));
-#else
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
-#endif
- rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+ /* We get here thru init_locked, meaning
+ ** a soft reset, this has already cleared
+ ** the VFTA and other state, so if there
+ ** have been no vlan's registered do nothing.
+ */
+ if (adapter->num_vlans == 0)
+ return;
+
+ /* Setup the queues for vlans */
+ for (int i = 0; i < adapter->num_rx_queues; i++) {
+ rxr = &adapter->rx_queues[i].rxr;
+ /* On 82599 the VLAN enable is per/queue in RXDCTL */
+ if (hw->mac.type != ixgbe_mac_82598EB) {
+ ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
+ ctrl |= IXGBE_RXDCTL_VME;
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl);
+ }
+ rxr->vtag_strip = TRUE;
}
- return;
+ if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
+ return;
+
+ /* A soft reset zero's out the VFTA, so
+ ** we need to repopulate it now.
+ */
+ for (int i = 0; i < IXGBE_VFTA_SIZE; i++)
+ if (adapter->shadow_vfta[i] != 0)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
+ adapter->shadow_vfta[i]);
+
+ ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ /* Enable the Filter Table if enabled */
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
+ ctrl &= ~IXGBE_VLNCTRL_CFIEN;
+ ctrl |= IXGBE_VLNCTRL_VFE;
+ }
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ctrl |= IXGBE_VLNCTRL_VME;
+ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
}
+/*
+** Get the width and transaction speed of
+** the slot this adapter is plugged into.
+*/
static void
-ixgbe_initialize_rss_mapping(struct adapter *adapter)
+ixgbe_get_slot_info(struct adapter *adapter)
{
- struct ixgbe_hw *hw = &adapter->hw;
- u32 reta = 0, mrqc, rss_key[10];
- int queue_id, table_size, index_mult;
-#ifdef RSS
- u32 rss_hash_config;
-#endif
-#ifdef PCI_IOV
- enum ixgbe_iov_mode mode;
-#endif
-
-#ifdef RSS
- /* Fetch the configured RSS key */
- rss_getkey((uint8_t *) &rss_key);
-#else
- /* set up random bits */
- arc4rand(&rss_key, sizeof(rss_key), 0);
-#endif
+ device_t dev = iflib_get_dev(adapter->ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u16 link;
+ u32 offset;
+ int bus_info_valid = TRUE;
- /* Set multiplier for RETA setup and table size based on MAC */
- index_mult = 0x1;
- table_size = 128;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82598EB:
- index_mult = 0x11;
- break;
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- table_size = 512;
- break;
- default:
- break;
+ MPASS(hw->back != NULL);
+ /* For most devices simply call the shared code routine */
+ if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) {
+ ixgbe_get_bus_info(hw);
+ /* These devices don't use PCI-E */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ return;
+ default:
+ goto display;
+ }
}
-
- /* Set up the redirection table */
- for (int i = 0, j = 0; i < table_size; i++, j++) {
- if (j == adapter->num_queues) j = 0;
-#ifdef RSS
- /*
- * Fetch the RSS bucket id for the given indirection entry.
- * Cap it at the number of configured buckets (which is
- * num_queues.)
- */
- queue_id = rss_get_indirection_to_bucket(i);
- queue_id = queue_id % adapter->num_queues;
-#else
- queue_id = (j * index_mult);
+ /*
+ ** For the Quad port adapter we need to parse back
+ ** up the PCI tree to find the speed of the expansion
+ ** slot into which this adapter is plugged. A bit more work.
+ */
+ dev = device_get_parent(device_get_parent(dev));
+#ifdef IXGBE_DEBUG
+ device_printf(dev, "parent pcib = %x,%x,%x\n",
+ pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
+#endif
+ dev = device_get_parent(device_get_parent(dev));
+#ifdef IXGBE_DEBUG
+ device_printf(dev, "slot pcib = %x,%x,%x\n",
+ pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
#endif
+ /* Now get the PCI Express Capabilities offset */
+ if (pci_find_cap(dev, PCIY_EXPRESS, &offset)) {
/*
- * The low 8 bits are for hash value (n+0);
- * The next 8 bits are for hash value (n+1), etc.
+ * Hmm...can't get PCI-Express capabilities.
+ * Falling back to default method.
*/
- reta = reta >> 8;
- reta = reta | ( ((uint32_t) queue_id) << 24);
- if ((i & 3) == 3) {
- if (i < 128)
- IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
- else
- IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), reta);
- reta = 0;
- }
+ bus_info_valid = FALSE;
+ ixgbe_get_bus_info(hw);
+ goto display;
}
+ /* ...and read the Link Status Register */
+ link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
+ ixgbe_set_pci_config_data_generic(hw, link);
- /* Now fill our hash function seeds */
- for (int i = 0; i < 10; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
+display:
+ device_printf(dev, "PCI Express Bus: Speed %s %s\n",
+ ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s" :
+ (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s" :
+ (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s" : "Unknown"),
+ ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
+ (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
+ (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
+ "Unknown"));
+
+ if (bus_info_valid) {
+ if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
+ ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
+ (hw->bus.speed == ixgbe_bus_speed_2500))) {
+ device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n");
+ device_printf(dev, "For optimal performance a x8 PCIE, or x4 PCIE Gen2 slot is required.\n");
+ }
+ if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
+ ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
+ (hw->bus.speed < ixgbe_bus_speed_8000))) {
+ device_printf(dev, "PCI-Express bandwidth available for this card\n is not sufficient for optimal performance.\n");
+ device_printf(dev, "For optimal performance a x8 PCIE Gen3 slot is required.\n");
+ }
+ } else
+ device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n");
- /* Perform hash on these packet types */
-#ifdef RSS
- mrqc = IXGBE_MRQC_RSSEN;
- rss_hash_config = rss_gethashconfig();
- if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
- if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
- if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
- if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
- if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
- if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
- if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
- if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
- device_printf(adapter->dev,
- "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, "
- "but not supported\n", __func__);
- if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
- if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
-#else
- /*
- * Disable UDP - IP fragments aren't currently being handled
- * and so we end up with a mix of 2-tuple and 4-tuple
- * traffic.
- */
- mrqc = IXGBE_MRQC_RSSEN
- | IXGBE_MRQC_RSS_FIELD_IPV4
- | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
- | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP
- | IXGBE_MRQC_RSS_FIELD_IPV6_EX
- | IXGBE_MRQC_RSS_FIELD_IPV6
- | IXGBE_MRQC_RSS_FIELD_IPV6_TCP
- ;
-#endif /* RSS */
-#ifdef PCI_IOV
- mode = ixgbe_get_iov_mode(adapter);
- mrqc |= ixgbe_get_mrqc(mode);
-#endif
- IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+ return;
}
-
/*********************************************************************
*
- * Setup receive registers and features.
+ * Setup MSIX Interrupt resources and handlers
*
**********************************************************************/
-#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
-
-#define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
-
-static void
-ixgbe_initialize_receive_units(struct adapter *adapter)
+static int
+ixgbe_if_msix_intr_assign(if_ctx_t ctx, int msix)
{
- struct rx_ring *rxr = adapter->rx_rings;
- struct ixgbe_hw *hw = &adapter->hw;
- struct ifnet *ifp = adapter->ifp;
- u32 bufsz, fctrl, srrctl, rxcsum;
- u32 hlreg;
-
- /*
- * Make sure receives are disabled while
- * setting up the descriptor ring
- */
- ixgbe_disable_rx(hw);
-
- /* Enable broadcasts */
- fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
- fctrl |= IXGBE_FCTRL_BAM;
- if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
- fctrl |= IXGBE_FCTRL_DPF;
- fctrl |= IXGBE_FCTRL_PMCF;
- }
- IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
-
- /* Set for Jumbo Frames? */
- hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
- if (ifp->if_mtu > ETHERMTU)
- hlreg |= IXGBE_HLREG0_JUMBOEN;
- else
- hlreg &= ~IXGBE_HLREG0_JUMBOEN;
-#ifdef DEV_NETMAP
- /* crcstrip is conditional in netmap (in RDRXCTL too ?) */
- if (ifp->if_capenable & IFCAP_NETMAP && !ix_crcstrip)
- hlreg &= ~IXGBE_HLREG0_RXCRCSTRP;
- else
- hlreg |= IXGBE_HLREG0_RXCRCSTRP;
-#endif /* DEV_NETMAP */
- IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
-
- bufsz = (adapter->rx_mbuf_sz +
- BSIZEPKT_ROUNDUP) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_rx_queue *rx_que = adapter->rx_queues;
+ struct ix_tx_queue *tx_que;
+ int error, rid, vector = 0;
+ int cpu_id = 0;
+ char buf[16];
- for (int i = 0; i < adapter->num_queues; i++, rxr++) {
- u64 rdba = rxr->rxdma.dma_paddr;
- int j = rxr->me;
+ /* Admin Que is vector 0*/
+ rid = vector + 1;
+ for (int i = 0; i < adapter->num_rx_queues; i++, vector++, rx_que++) {
+ rid = vector + 1;
- /* Setup the Base and Length of the Rx Descriptor Ring */
- IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j),
- (rdba & 0x00000000ffffffffULL));
- IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
- IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j),
- adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
+ snprintf(buf, sizeof(buf), "rxq%d", i);
+ error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid,
+ IFLIB_INTR_RX, ixgbe_msix_que, rx_que, rx_que->rxr.me, buf);
- /* Set up the SRRCTL register */
- srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j));
- srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
- srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
- srrctl |= bufsz;
- srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
+ if (error) {
+ device_printf(iflib_get_dev(ctx),
+ "Failed to allocate que int %d err: %d", i, error);
+ adapter->num_rx_queues = i + 1;
+ goto fail;
+ }
- /*
- * Set DROP_EN iff we have no flow control and >1 queue.
- * Note that srrctl was cleared shortly before during reset,
- * so we do not need to clear the bit, but do it just in case
- * this code is moved elsewhere.
- */
- if (adapter->num_queues > 1 &&
- adapter->hw.fc.requested_mode == ixgbe_fc_none) {
- srrctl |= IXGBE_SRRCTL_DROP_EN;
+ rx_que->msix = vector;
+ adapter->active_queues |= (u64)(1 << rx_que->msix);
+ if (adapter->feat_en & IXGBE_FEATURE_RSS) {
+ /*
+ * The queue ID is used as the RSS layer bucket ID.
+ * We look up the queue ID -> RSS CPU ID and select
+ * that.
+ */
+ cpu_id = rss_getcpu(i % rss_getnumbuckets());
} else {
- srrctl &= ~IXGBE_SRRCTL_DROP_EN;
+ /*
+ * Bind the msix vector, and thus the
+ * rings to the corresponding cpu.
+ *
+ * This just happens to match the default RSS
+ * round-robin bucket -> queue -> CPU allocation.
+ */
+ if (adapter->num_rx_queues > 1)
+ cpu_id = i;
}
- IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
+ }
+ for (int i = 0; i < adapter->num_tx_queues; i++) {
+ snprintf(buf, sizeof(buf), "txq%d", i);
+ tx_que = &adapter->tx_queues[i];
+ tx_que->msix = i % adapter->num_rx_queues;
+ iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_TX, tx_que,
+ tx_que->txr.me, buf);
+ }
+ rid = vector + 1;
+ error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid,
+ IFLIB_INTR_ADMIN, ixgbe_msix_link, adapter, 0, "aq");
+ if (error) {
+ device_printf(iflib_get_dev(ctx),
+ "Failed to register admin handler");
+ return (error);
+ }
- /* Setup the HW Rx Head and Tail Descriptor Pointers */
- IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
- /* Set the driver rx tail address */
- rxr->tail = IXGBE_RDT(rxr->me);
- }
+ adapter->vector = vector;
+ return (0);
+fail:
+ iflib_irq_free(ctx, &adapter->irq);
+ rx_que = adapter->rx_queues;
+ for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++)
+ iflib_irq_free(ctx, &rx_que->que_irq);
+ return (error);
+}
- if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
- u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
- IXGBE_PSRTYPE_UDPHDR |
- IXGBE_PSRTYPE_IPV4HDR |
- IXGBE_PSRTYPE_IPV6HDR;
- IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
- }
+/*********************************************************************
+ *
+ * MSIX Queue Interrupt Service routine
+ *
+ **********************************************************************/
+static int
+ixgbe_msix_que(void *arg)
+{
+ struct ix_rx_queue *que = arg;
+ struct adapter *adapter = que->adapter;
+#ifdef notyet
+ struct tx_ring *txr = &que->txr;
+#endif
+ struct rx_ring *rxr = &que->rxr;
+ struct ifnet *ifp = iflib_get_ifp(que->adapter->ctx);
+ u32 newitr = 0;
- rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+ /* Protect against spurious interrupts */
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return 0;
- ixgbe_initialize_rss_mapping(adapter);
+ ixgbe_disable_queue(adapter, que->msix);
+ ++que->irqs;
- if (adapter->num_queues > 1) {
- /* RSS and RX IPP Checksum are mutually exclusive */
- rxcsum |= IXGBE_RXCSUM_PCSD;
+ if (ixgbe_enable_aim == FALSE)
+ goto no_calc;
+ /*
+ * Do Adaptive Interrupt Moderation:
+ * - Write out last calculated setting
+ * - Calculate based on average size over
+ * the last interval.
+ */
+ if (que->eitr_setting) {
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix),
+ que->eitr_setting);
}
- if (ifp->if_capenable & IFCAP_RXCSUM)
- rxcsum |= IXGBE_RXCSUM_PCSD;
-
- /* This is useful for calculating UDP/IP fragment checksums */
- if (!(rxcsum & IXGBE_RXCSUM_PCSD))
- rxcsum |= IXGBE_RXCSUM_IPPCSE;
+ que->eitr_setting = 0;
- IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+ /* Idle, do nothing */
+#ifdef notyet
+ if ((txr->bytes) && (txr->packets))
+ newitr = txr->bytes/txr->packets;
+#endif
+ if ((rxr->bytes) && (rxr->packets))
+ newitr = max(newitr, (rxr->bytes / rxr->packets));
+ newitr += 24; /* account for hardware frame, crc */
- return;
-}
+ /* set an upper boundary */
+ newitr = min(newitr, 3000);
+ /* Be nice to the mid range */
+ if ((newitr > 300) && (newitr < 1200))
+ newitr = (newitr / 3);
+ else
+ newitr = (newitr / 2);
-/*
-** This routine is run via an vlan config EVENT,
-** it enables us to use the HW Filter table since
-** we can get the vlan id. This just creates the
-** entry in the soft version of the VFTA, init will
-** repopulate the real table.
-*/
-static void
-ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
-{
- struct adapter *adapter = ifp->if_softc;
- u16 index, bit;
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ newitr |= newitr << 16;
+ else
+ newitr |= IXGBE_EITR_CNT_WDIS;
- if (ifp->if_softc != arg) /* Not our event */
- return;
+ /* save for next interrupt */
+ que->eitr_setting = newitr;
- if ((vtag == 0) || (vtag > 4095)) /* Invalid */
- return;
+ /* Reset state */
+#ifdef notyet
+ txr->bytes = 0;
+ txr->packets = 0;
+#endif
+ rxr->bytes = 0;
+ rxr->packets = 0;
- IXGBE_CORE_LOCK(adapter);
- index = (vtag >> 5) & 0x7F;
- bit = vtag & 0x1F;
- adapter->shadow_vfta[index] |= (1 << bit);
- ++adapter->num_vlans;
- ixgbe_setup_vlan_hw_support(adapter);
- IXGBE_CORE_UNLOCK(adapter);
+no_calc:
+ return (FILTER_SCHEDULE_THREAD);
}
-/*
-** This routine is run via an vlan
-** unconfig EVENT, remove our entry
-** in the soft vfta.
-*/
+/*********************************************************************
+ *
+ * Media Ioctl callback
+ *
+ * This routine is called whenever the user queries the status of
+ * the interface using ifconfig.
+ *
+ **********************************************************************/
static void
-ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
+ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
{
- struct adapter *adapter = ifp->if_softc;
- u16 index, bit;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ int layer;
- if (ifp->if_softc != arg)
- return;
+ INIT_DEBUGOUT("ixgbe_if_media_status: begin");
+ ixgbe_if_update_admin_status(ctx);
+
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_active = IFM_ETHER;
- if ((vtag == 0) || (vtag > 4095)) /* Invalid */
+ if (!adapter->link_active) {
return;
+ }
- IXGBE_CORE_LOCK(adapter);
- index = (vtag >> 5) & 0x7F;
- bit = vtag & 0x1F;
- adapter->shadow_vfta[index] &= ~(1 << bit);
- --adapter->num_vlans;
- /* Re-init to load the changes */
- ixgbe_setup_vlan_hw_support(adapter);
- IXGBE_CORE_UNLOCK(adapter);
+ ifmr->ifm_status |= IFM_ACTIVE;
+ layer = adapter->phy_layer;
+
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T ||
+ layer & IXGBE_PHYSICAL_LAYER_1000BASE_T ||
+ layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_100_FULL:
+ ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
+ break;
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
+ layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
+ break;
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
+ break;
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
+ break;
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR ||
+ layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
+ break;
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
+ break;
+ }
+ /*
+ ** XXX: These need to use the proper media types once
+ ** they're added.
+ */
+#ifndef IFM_ETH_XTYPE
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_2_5GB_FULL:
+ ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
+ break;
+ }
+ else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
+ layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
+ layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_2_5GB_FULL:
+ ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
+ break;
+ }
+#else
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_2_5GB_FULL:
+ ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
+ break;
+ }
+ else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
+ layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
+ layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_2_5GB_FULL:
+ ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
+ break;
+ }
+#endif
+ /* If nothing is recognized... */
+ if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
+ ifmr->ifm_active |= IFM_UNKNOWN;
+
+ /* Display current flow control setting used on link */
+ if (hw->fc.current_mode == ixgbe_fc_rx_pause ||
+ hw->fc.current_mode == ixgbe_fc_full)
+ ifmr->ifm_active |= IFM_ETH_RXPAUSE;
+ if (hw->fc.current_mode == ixgbe_fc_tx_pause ||
+ hw->fc.current_mode == ixgbe_fc_full)
+ ifmr->ifm_active |= IFM_ETH_TXPAUSE;
}
-static void
-ixgbe_setup_vlan_hw_support(struct adapter *adapter)
+/*********************************************************************
+ *
+ * Media Ioctl callback
+ *
+ * This routine is called when the user changes speed/duplex using
+ * media/mediopt option with ifconfig.
+ *
+ **********************************************************************/
+static int
+ixgbe_if_media_change(if_ctx_t ctx)
{
- struct ifnet *ifp = adapter->ifp;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ifmedia *ifm = iflib_get_media(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- struct rx_ring *rxr;
- u32 ctrl;
+ ixgbe_link_speed speed = 0;
+
+ INIT_DEBUGOUT("ixgbe_if_media_change: begin");
+
+ if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
+ return (EINVAL);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ return (EPERM);
/*
- ** We get here thru init_locked, meaning
- ** a soft reset, this has already cleared
- ** the VFTA and other state, so if there
- ** have been no vlan's registered do nothing.
+ ** We don't actually need to check against the supported
+ ** media types of the adapter; ifmedia will take care of
+ ** that for us.
*/
- if (adapter->num_vlans == 0)
- return;
+#ifndef IFM_ETH_XTYPE
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ case IFM_10G_T:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ case IFM_10G_LRM:
+ case IFM_10G_SR: /* KR, too */
+ case IFM_10G_LR:
+ case IFM_10G_CX4: /* KX4 */
+ speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ case IFM_10G_TWINAX:
+ speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ break;
+ case IFM_1000_T:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ case IFM_1000_LX:
+ case IFM_1000_SX:
+ case IFM_1000_CX: /* KX */
+ speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ case IFM_2500_SX:
+ speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
+ break;
+ case IFM_100_TX:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ break;
+ default:
+ goto invalid;
+ }
+#else
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ case IFM_10G_T:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ case IFM_10G_LRM:
+ case IFM_10G_KR:
+ case IFM_10G_LR:
+ case IFM_10G_KX4:
+ speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ case IFM_10G_TWINAX:
+ speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ break;
+ case IFM_1000_T:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ case IFM_1000_LX:
+ case IFM_1000_SX:
+ case IFM_1000_KX:
+ speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ case IFM_2500_KX:
+ speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
+ break;
+ case IFM_100_TX:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ break;
+ default:
+ goto invalid;
+ }
+#endif
+ hw->mac.autotry_restart = TRUE;
+ hw->mac.ops.setup_link(hw, speed, TRUE);
+ adapter->advertise =
+ ((speed & IXGBE_LINK_SPEED_10GB_FULL) << 2) |
+ ((speed & IXGBE_LINK_SPEED_1GB_FULL) << 1) |
+ ((speed & IXGBE_LINK_SPEED_100_FULL) << 0);
+
+ return (0);
+
+invalid:
+ device_printf(iflib_get_dev(ctx), "Invalid media type!\n");
+ return (EINVAL);
+}
+
+static int
+ixgbe_if_promisc_set(if_ctx_t ctx, int flags)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ u_int32_t reg_rctl;
+ int mcnt = 0;
- /* Setup the queues for vlans */
- for (int i = 0; i < adapter->num_queues; i++) {
- rxr = &adapter->rx_rings[i];
- /* On 82599 the VLAN enable is per/queue in RXDCTL */
- if (hw->mac.type != ixgbe_mac_82598EB) {
- ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
- ctrl |= IXGBE_RXDCTL_VME;
- IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl);
- }
- rxr->vtag_strip = TRUE;
+ reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+ reg_rctl &= (~IXGBE_FCTRL_UPE);
+ if (ifp->if_flags & IFF_ALLMULTI)
+ mcnt = MAX_NUM_MULTICAST_ADDRESSES;
+ else {
+ mcnt = if_multiaddr_count(ifp, MAX_NUM_MULTICAST_ADDRESSES);
}
+ if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
+ reg_rctl &= (~IXGBE_FCTRL_MPE);
- if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
- return;
- /*
- ** A soft reset zero's out the VFTA, so
- ** we need to repopulate it now.
- */
- for (int i = 0; i < IXGBE_VFTA_SIZE; i++)
- if (adapter->shadow_vfta[i] != 0)
- IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
- adapter->shadow_vfta[i]);
+ /* clear promiscuous mode and multicast filters before enabling */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
- ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
- /* Enable the Filter Table if enabled */
- if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
- ctrl &= ~IXGBE_VLNCTRL_CFIEN;
- ctrl |= IXGBE_VLNCTRL_VFE;
+ if (ifp->if_flags & IFF_PROMISC) {
+ reg_rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
+ } else if (ifp->if_flags & IFF_ALLMULTI) {
+ reg_rctl |= IXGBE_FCTRL_MPE;
+ reg_rctl &= ~IXGBE_FCTRL_UPE;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
}
- if (hw->mac.type == ixgbe_mac_82598EB)
- ctrl |= IXGBE_VLNCTRL_VME;
- IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
+
+ return (0);
}
-static void
-ixgbe_enable_intr(struct adapter *adapter)
+static int
+ixgbe_msix_link(void *arg)
{
- struct ixgbe_hw *hw = &adapter->hw;
- struct ix_queue *que = adapter->queues;
- u32 mask, fwsm;
+ struct adapter *adapter = arg;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 eicr, eicr_mask;
+ s32 retval;
- mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
- /* Enable Fan Failure detection */
- if (hw->device_id == IXGBE_DEV_ID_82598AT)
- mask |= IXGBE_EIMS_GPI_SDP1;
+ ++adapter->link_irq;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- mask |= IXGBE_EIMS_ECC;
- /* Temperature sensor on some adapters */
- mask |= IXGBE_EIMS_GPI_SDP0;
- /* SFP+ (RX_LOS_N & MOD_ABS_N) */
- mask |= IXGBE_EIMS_GPI_SDP1;
- mask |= IXGBE_EIMS_GPI_SDP2;
-#ifdef IXGBE_FDIR
- mask |= IXGBE_EIMS_FLOW_DIR;
-#endif
-#ifdef PCI_IOV
- mask |= IXGBE_EIMS_MAILBOX;
-#endif
- break;
- case ixgbe_mac_X540:
- /* Detect if Thermal Sensor is enabled */
- fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
- if (fwsm & IXGBE_FWSM_TS_ENABLED)
- mask |= IXGBE_EIMS_TS;
- mask |= IXGBE_EIMS_ECC;
-#ifdef IXGBE_FDIR
- mask |= IXGBE_EIMS_FLOW_DIR;
-#endif
- break;
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- /* MAC thermal sensor is automatically enabled */
- mask |= IXGBE_EIMS_TS;
- /* Some devices use SDP0 for important information */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
- hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
- mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
- mask |= IXGBE_EIMS_ECC;
-#ifdef IXGBE_FDIR
- mask |= IXGBE_EIMS_FLOW_DIR;
-#endif
-#ifdef PCI_IOV
- mask |= IXGBE_EIMS_MAILBOX;
-#endif
- /* falls through */
- default:
- break;
- }
+ /* Pause other interrupts */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
+ /* First get the cause */
+ eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
+ /* Be sure the queue bits are not cleared */
+ eicr &= ~IXGBE_EICR_RTX_QUEUE;
+ /* Clear interrupt with write */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
- /* With MSI-X we use auto clear */
- if (adapter->msix_mem) {
- mask = IXGBE_EIMS_ENABLE_MASK;
- /* Don't autoclear Link */
- mask &= ~IXGBE_EIMS_OTHER;
- mask &= ~IXGBE_EIMS_LSC;
-#ifdef PCI_IOV
- mask &= ~IXGBE_EIMS_MAILBOX;
-#endif
- IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
+ /* Link status change */
+ if (eicr & IXGBE_EICR_LSC) {
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
+ iflib_admin_intr_deferred(adapter->ctx);
}
- /*
- ** Now enable all queues, this is done separately to
- ** allow for handling the extended (beyond 32) MSIX
- ** vectors that can be used by 82599
- */
- for (int i = 0; i < adapter->num_queues; i++, que++)
- ixgbe_enable_queue(adapter, que->msix);
-
- IXGBE_WRITE_FLUSH(hw);
+ if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
+ if ((adapter->feat_en & IXGBE_FEATURE_FDIR) &&
+ (eicr & IXGBE_EICR_FLOW_DIR)) {
+ /* This is probably overkill :) */
+ if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
+ return (FILTER_HANDLED);
+ /* Disable the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
+ GROUPTASK_ENQUEUE(&adapter->fdir_task);
+ } else
+ if (eicr & IXGBE_EICR_ECC) {
+ device_printf(iflib_get_dev(adapter->ctx),
+ "\nCRITICAL: ECC ERROR!! Please Reboot!!\n");
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
+ }
- return;
-}
+ /* Check for over temp condition */
+ if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) {
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X550EM_a:
+ if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a))
+ break;
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC,
+ IXGBE_EICR_GPI_SDP0_X550EM_a);
+ IXGBE_WRITE_REG(hw, IXGBE_EICR,
+ IXGBE_EICR_GPI_SDP0_X550EM_a);
+ retval = hw->phy.ops.check_overtemp(hw);
+ if (retval != IXGBE_ERR_OVERTEMP)
+ break;
+ device_printf(iflib_get_dev(adapter->ctx),
+ "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
+ device_printf(iflib_get_dev(adapter->ctx),
+ "System shutdown required!\n");
+ break;
+ default:
+ if (!(eicr & IXGBE_EICR_TS))
+ break;
+ retval = hw->phy.ops.check_overtemp(hw);
+ if (retval != IXGBE_ERR_OVERTEMP)
+ break;
+ device_printf(iflib_get_dev(adapter->ctx),
+ "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
+ device_printf(iflib_get_dev(adapter->ctx),
+ "System shutdown required!\n");
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
+ break;
+ }
+ }
-static void
-ixgbe_disable_intr(struct adapter *adapter)
-{
- if (adapter->msix_mem)
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
- if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
- } else {
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
+ /* Check for VF message */
+ if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) &&
+ (eicr & IXGBE_EICR_MAILBOX))
+ GROUPTASK_ENQUEUE(&adapter->mbx_task);
}
- IXGBE_WRITE_FLUSH(&adapter->hw);
- return;
-}
-/*
-** Get the width and transaction speed of
-** the slot this adapter is plugged into.
-*/
-static void
-ixgbe_get_slot_info(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- struct ixgbe_hw *hw = &adapter->hw;
- struct ixgbe_mac_info *mac = &hw->mac;
- u16 link;
- u32 offset;
+ if (ixgbe_is_sfp(hw)) {
+ /* Pluggable optics-related interrupt */
+ if (hw->device_id >= ixgbe_mac_X540)
+ eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
+ else
+ eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
- /* For most devices simply call the shared code routine */
- if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) {
- ixgbe_get_bus_info(hw);
- /* These devices don't use PCI-E */
- switch (hw->mac.type) {
- case ixgbe_mac_X550EM_x:
- return;
- default:
- goto display;
+ if (eicr & eicr_mask) {
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
+ GROUPTASK_ENQUEUE(&adapter->mod_task);
+ }
+ if ((hw->mac.type == ixgbe_mac_82599EB) &&
+ (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
+ IXGBE_WRITE_REG(hw, IXGBE_EICR,
+ IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
+ GROUPTASK_ENQUEUE(&adapter->msf_task);
}
}
- /*
- ** For the Quad port adapter we need to parse back
- ** up the PCI tree to find the speed of the expansion
- ** slot into which this adapter is plugged. A bit more work.
- */
- dev = device_get_parent(device_get_parent(dev));
-#ifdef IXGBE_DEBUG
- device_printf(dev, "parent pcib = %x,%x,%x\n",
- pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
-#endif
- dev = device_get_parent(device_get_parent(dev));
-#ifdef IXGBE_DEBUG
- device_printf(dev, "slot pcib = %x,%x,%x\n",
- pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
-#endif
- /* Now get the PCI Express Capabilities offset */
- pci_find_cap(dev, PCIY_EXPRESS, &offset);
- /* ...and read the Link Status Register */
- link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
- switch (link & IXGBE_PCI_LINK_WIDTH) {
- case IXGBE_PCI_LINK_WIDTH_1:
- hw->bus.width = ixgbe_bus_width_pcie_x1;
- break;
- case IXGBE_PCI_LINK_WIDTH_2:
- hw->bus.width = ixgbe_bus_width_pcie_x2;
- break;
- case IXGBE_PCI_LINK_WIDTH_4:
- hw->bus.width = ixgbe_bus_width_pcie_x4;
- break;
- case IXGBE_PCI_LINK_WIDTH_8:
- hw->bus.width = ixgbe_bus_width_pcie_x8;
- break;
- default:
- hw->bus.width = ixgbe_bus_width_unknown;
- break;
+ /* Check for fan failure */
+ if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
+ ixgbe_check_fan_failure(adapter, eicr, TRUE);
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
}
- switch (link & IXGBE_PCI_LINK_SPEED) {
- case IXGBE_PCI_LINK_SPEED_2500:
- hw->bus.speed = ixgbe_bus_speed_2500;
- break;
- case IXGBE_PCI_LINK_SPEED_5000:
- hw->bus.speed = ixgbe_bus_speed_5000;
- break;
- case IXGBE_PCI_LINK_SPEED_8000:
- hw->bus.speed = ixgbe_bus_speed_8000;
- break;
- default:
- hw->bus.speed = ixgbe_bus_speed_unknown;
- break;
+ /* External PHY interrupt */
+ if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
+ (eicr & IXGBE_EICR_GPI_SDP0_X540)) {
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
+ GROUPTASK_ENQUEUE(&adapter->phy_task);
}
- mac->ops.set_lan_id(hw);
-
-display:
- device_printf(dev,"PCI Express Bus: Speed %s %s\n",
- ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s":
- (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s":
- (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s":"Unknown"),
- (hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
- (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
- (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
- ("Unknown"));
-
- if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
- ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
- (hw->bus.speed == ixgbe_bus_speed_2500))) {
- device_printf(dev, "PCI-Express bandwidth available"
- " for this card\n is not sufficient for"
- " optimal performance.\n");
- device_printf(dev, "For optimal performance a x8 "
- "PCIE, or x4 PCIE Gen2 slot is required.\n");
- }
- if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
- ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
- (hw->bus.speed < ixgbe_bus_speed_8000))) {
- device_printf(dev, "PCI-Express bandwidth available"
- " for this card\n is not sufficient for"
- " optimal performance.\n");
- device_printf(dev, "For optimal performance a x8 "
- "PCIE Gen3 slot is required.\n");
- }
+ /* Re-enable other interrupts */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
- return;
+ return (FILTER_HANDLED);
}
+static int
+ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1);
+ unsigned int reg, usec, rate;
+
+ reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
+ usec = ((reg & 0x0FF8) >> 3);
+ if (usec > 0)
+ rate = 500000 / usec;
+ else
+ rate = 0;
+ error = sysctl_handle_int(oidp, &rate, 0, req);
+ if (error || !req->newptr)
+ return error;
+ reg &= ~0xfff; /* default, no limitation */
+ ixgbe_max_interrupt_rate = 0;
+ if (rate > 0 && rate < 500000) {
+ if (rate < 1000)
+ rate = 1000;
+ ixgbe_max_interrupt_rate = rate;
+ reg |= ((4000000/rate) & 0xff8 );
+ }
+ IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg);
+ return 0;
+}
-/*
-** Setup the correct IVAR register for a particular MSIX interrupt
-** (yes this is all very magic and confusing :)
-** - entry is the register array entry
-** - vector is the MSIX vector for this queue
-** - type is RX/TX/MISC
-*/
static void
-ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
+ixgbe_add_device_sysctls(if_ctx_t ctx)
{
+ device_t dev = iflib_get_dev(ctx);
+ struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- u32 ivar, index;
+ struct sysctl_oid_list *child;
+ struct sysctl_ctx_list *ctx_list;
- vector |= IXGBE_IVAR_ALLOC_VAL;
+ ctx_list = device_get_sysctl_ctx(dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
- switch (hw->mac.type) {
+ /* Sysctls for all devices */
+ SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC);
- case ixgbe_mac_82598EB:
- if (type == -1)
- entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
- else
- entry += (type * 64);
- index = (entry >> 2) & 0x1F;
- ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
- ivar &= ~(0xFF << (8 * (entry & 0x3)));
- ivar |= (vector << (8 * (entry & 0x3)));
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
- break;
+ SYSCTL_ADD_INT(ctx_list, child, OID_AUTO, "enable_aim", CTLFLAG_RW,
+ &ixgbe_enable_aim, 1, "Interrupt Moderation");
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- if (type == -1) { /* MISC IVAR */
- index = (entry & 1) * 8;
- ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
- ivar &= ~(0xFF << index);
- ivar |= (vector << index);
- IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
- } else { /* RX/TX IVARS */
- index = (16 * (entry & 1)) + (8 * type);
- ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
- ivar &= ~(0xFF << index);
- ivar |= (vector << index);
- IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
- }
+ SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "advertise_speed",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_advertise, "I",
+ IXGBE_SYSCTL_DESC_ADV_SPEED);
- default:
- break;
- }
-}
+ SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "thermal_test",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_thermal_test, "I", "Thermal Test");
+
+ SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "reg_dump",
+ CTLTYPE_STRING | CTLFLAG_RD, adapter, 0,
+ ixgbe_get_regs, "A", "Dump Registers");
+
+#ifdef IXGBE_DEBUG
+ /* testing sysctls (for all devices) */
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_power_state, "I", "PCI Power State");
+
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config",
+ CTLTYPE_STRING | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration");
+#endif
+ /* for X550 series devices */
+ if (hw->mac.type >= ixgbe_mac_X550)
+ SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "dmac",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_dmac, "I", "DMA Coalesce");
-static void
-ixgbe_configure_ivars(struct adapter *adapter)
-{
- struct ix_queue *que = adapter->queues;
- u32 newitr;
+ /* for X552 backplane devices */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
+ struct sysctl_oid *eee_node;
+ struct sysctl_oid_list *eee_list;
- if (ixgbe_max_interrupt_rate > 0)
- newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
- else {
- /*
- ** Disable DMA coalescing if interrupt moderation is
- ** disabled.
- */
- adapter->dmac = 0;
- newitr = 0;
- }
+ eee_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "eee",
+ CTLFLAG_RD, NULL,
+ "Energy Efficient Ethernet sysctls");
+ eee_list = SYSCTL_CHILDREN(eee_node);
- for (int i = 0; i < adapter->num_queues; i++, que++) {
- struct rx_ring *rxr = &adapter->rx_rings[i];
- struct tx_ring *txr = &adapter->tx_rings[i];
- /* First the RX queue entry */
- ixgbe_set_ivar(adapter, rxr->me, que->msix, 0);
- /* ... and the TX */
- ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
- /* Set an Initial EITR value */
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(que->msix), newitr);
+ SYSCTL_ADD_PROC(ctx_list, eee_list, OID_AUTO, "enable",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_eee_enable, "I",
+ "Enable or Disable EEE");
+
+ SYSCTL_ADD_PROC(ctx_list, eee_list, OID_AUTO, "negotiated",
+ CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_eee_negotiated, "I",
+ "EEE negotiated on link");
+
+ SYSCTL_ADD_PROC(ctx_list, eee_list, OID_AUTO, "tx_lpi_status",
+ CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_eee_tx_lpi_status, "I",
+ "Whether or not TX link is in LPI state");
+
+ SYSCTL_ADD_PROC(ctx_list, eee_list, OID_AUTO, "rx_lpi_status",
+ CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_eee_rx_lpi_status, "I",
+ "Whether or not RX link is in LPI state");
+ SYSCTL_ADD_PROC(ctx_list, eee_list, OID_AUTO, "tx_lpi_delay",
+ CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_eee_tx_lpi_delay, "I",
+ "TX LPI entry delay in microseconds");
}
- /* For the Link interrupt */
- ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
-}
-
-/*
-** ixgbe_sfp_probe - called in the local timer to
-** determine if a port had optics inserted.
-*/
-static bool
-ixgbe_sfp_probe(struct adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- device_t dev = adapter->dev;
- bool result = FALSE;
+ /* for WoL-capable devices */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+ SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_wol_enable, "I",
+ "Enable/Disable Wake on LAN");
- if ((hw->phy.type == ixgbe_phy_nl) &&
- (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
- s32 ret = hw->phy.ops.identify_sfp(hw);
- if (ret)
- goto out;
- ret = hw->phy.ops.reset(hw);
- if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev, "Unsupported SFP+ module detected!");
- device_printf(dev, "Reload driver with supported module.\n");
- adapter->sfp_probe = FALSE;
- goto out;
- } else
- device_printf(dev, "SFP+ module detected!\n");
- /* We now have supported optics */
- adapter->sfp_probe = FALSE;
- /* Set the optics type so system reports correctly */
- ixgbe_setup_optics(adapter);
- result = TRUE;
+ SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_wufc, "I",
+ "Enable/Disable Wake Up Filters");
}
-out:
- return (result);
-}
+ /* for X550EM 10GBaseT devices */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+ struct sysctl_oid *phy_node;
+ struct sysctl_oid_list *phy_list;
-/*
-** Tasklet handler for MSIX Link interrupts
-** - do outside interrupt since it might sleep
-*/
-static void
-ixgbe_handle_link(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ixgbe_hw *hw = &adapter->hw;
+ phy_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "phy",
+ CTLFLAG_RD, NULL,
+ "External PHY sysctls");
+ phy_list = SYSCTL_CHILDREN(phy_node);
- ixgbe_check_link(hw,
- &adapter->link_speed, &adapter->link_up, 0);
- ixgbe_update_link_status(adapter);
+ SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, "temp",
+ CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_phy_temp, "I",
+ "Current External PHY Temperature (Celsius)");
- /* Re-enable link interrupts */
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
+ SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO,
+ "overtemp_occurred",
+ CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_phy_overtemp_occurred, "I",
+ "External PHY High Temperature Event Occurred");
+ }
}
-/*
-** Tasklet for handling SFP module interrupts
-*/
+/*********************************************************************
+ *
+ * Determine optic type
+ *
+ **********************************************************************/
static void
-ixgbe_handle_mod(void *context, int pending)
+ixgbe_setup_optics(struct adapter *adapter)
{
- struct adapter *adapter = context;
struct ixgbe_hw *hw = &adapter->hw;
- enum ixgbe_phy_type orig_type = hw->phy.type;
- device_t dev = adapter->dev;
- u32 err;
+ int layer;
- IXGBE_CORE_LOCK(adapter);
+ layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
- /* Check to see if the PHY type changed */
- if (hw->phy.ops.identify) {
- hw->phy.type = ixgbe_phy_unknown;
- hw->phy.ops.identify(hw);
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
+ adapter->optics = IFM_10G_T;
+ return;
}
- if (hw->phy.type != orig_type) {
- device_printf(dev, "Detected phy_type %d\n", hw->phy.type);
-
- if (hw->phy.type == ixgbe_phy_none) {
- hw->phy.sfp_type = ixgbe_sfp_type_unknown;
- goto out;
- }
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
+ adapter->optics = IFM_1000_T;
+ return;
- /* Try to do the initialization that was skipped before */
- if (hw->phy.ops.init)
- hw->phy.ops.init(hw);
- if (hw->phy.ops.reset)
- hw->phy.ops.reset(hw);
}
- err = hw->phy.ops.identify_sfp(hw);
- if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,
- "Unsupported SFP+ module type was detected.\n");
- goto out;
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
+ adapter->optics = IFM_1000_SX;
+ return;
}
- err = hw->mac.ops.setup_sfp(hw);
- if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,
- "Setup failure - unsupported SFP+ module type.\n");
- goto out;
- }
- if (hw->phy.multispeed_fiber)
- taskqueue_enqueue(adapter->tq, &adapter->msf_task);
-out:
- /* Update media type */
- switch (hw->mac.ops.get_media_type(hw)) {
- case ixgbe_media_type_fiber:
- adapter->optics = IFM_10G_SR;
- break;
- case ixgbe_media_type_copper:
- adapter->optics = IFM_10G_TWINAX;
- break;
- case ixgbe_media_type_cx4:
- adapter->optics = IFM_10G_CX4;
- break;
- default:
- adapter->optics = 0;
- break;
+ if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_LR |
+ IXGBE_PHYSICAL_LAYER_10GBASE_LRM)) {
+ adapter->optics = IFM_10G_LR;
+ return;
}
- IXGBE_CORE_UNLOCK(adapter);
- return;
-}
-
-
-/*
-** Tasklet for handling MSF (multispeed fiber) interrupts
-*/
-static void
-ixgbe_handle_msf(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ixgbe_hw *hw = &adapter->hw;
- u32 autoneg;
- bool negotiate;
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
+ adapter->optics = IFM_10G_SR;
+ return;
+ }
- IXGBE_CORE_LOCK(adapter);
- /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
- adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
+ if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) {
+ adapter->optics = IFM_10G_TWINAX;
+ return;
+ }
- autoneg = hw->phy.autoneg_advertised;
- if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
- hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
- if (hw->mac.ops.setup_link)
- hw->mac.ops.setup_link(hw, autoneg, TRUE);
+ if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
+ IXGBE_PHYSICAL_LAYER_10GBASE_CX4)) {
+ adapter->optics = IFM_10G_CX4;
+ return;
+ }
- /* Adjust media types shown in ifconfig */
- ifmedia_removeall(&adapter->media);
- ixgbe_add_media_types(adapter);
- ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
- IXGBE_CORE_UNLOCK(adapter);
- return;
+ /* If we get here just set the default */
+ adapter->optics = IFM_ETHER | IFM_AUTO;
}
-/*
-** Tasklet for handling interrupts from an external PHY
-*/
-static void
-ixgbe_handle_phy(void *context, int pending)
+static int
+ixgbe_allocate_pci_resources(if_ctx_t ctx)
{
- struct adapter *adapter = context;
- struct ixgbe_hw *hw = &adapter->hw;
- int error;
+ int rid;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ device_t dev = iflib_get_dev(ctx);
- error = hw->phy.ops.handle_lasi(hw);
- if (error == IXGBE_ERR_OVERTEMP)
- device_printf(adapter->dev,
- "CRITICAL: EXTERNAL PHY OVER TEMP!! "
- " PHY will downshift to lower power state!\n");
- else if (error)
- device_printf(adapter->dev,
- "Error handling LASI interrupt: %d\n",
- error);
- return;
-}
+ rid = PCIR_BAR(0);
+ adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE);
-#ifdef IXGBE_FDIR
-/*
-** Tasklet for reinitializing the Flow Director filter table
-*/
-static void
-ixgbe_reinit_fdir(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp = adapter->ifp;
+ if (!(adapter->pci_mem)) {
+ device_printf(dev, "Unable to allocate bus resource: memory\n");
+ return (ENXIO);
+ }
- if (adapter->fdir_reinit != 1) /* Shouldn't happen */
- return;
- ixgbe_reinit_fdir_tables_82599(&adapter->hw);
- adapter->fdir_reinit = 0;
- /* re-enable flow director interrupts */
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
- /* Restart the interface */
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- return;
+ adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem);
+ adapter->osdep.mem_bus_space_handle =
+ rman_get_bushandle(adapter->pci_mem);
+ adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle;
+
+ return (0);
}
-#endif
/*********************************************************************
+ * Device removal routine
*
- * Configure DMA Coalescing
+ * The detach entry point is called when the driver is being removed.
+ * This routine stops the adapter and deallocates all the resources
+ * that were allocated for driver operation.
*
- **********************************************************************/
-static void
-ixgbe_config_dmac(struct adapter *adapter)
+ * return 0 on success, positive on failure
+ *********************************************************************/
+static int
+ixgbe_if_detach(if_ctx_t ctx)
{
- struct ixgbe_hw *hw = &adapter->hw;
- struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
-
- if (hw->mac.type < ixgbe_mac_X550 ||
- !hw->mac.ops.dmac_config)
- return;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ u32 ctrl_ext;
+ device_t dev = iflib_get_dev(ctx);
- if (dcfg->watchdog_timer ^ adapter->dmac ||
- dcfg->link_speed ^ adapter->link_speed) {
- dcfg->watchdog_timer = adapter->dmac;
- dcfg->fcoe_en = false;
- dcfg->link_speed = adapter->link_speed;
- dcfg->num_tcs = 1;
-
- INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n",
- dcfg->watchdog_timer, dcfg->link_speed);
+ INIT_DEBUGOUT("ixgbe_detach: begin");
- hw->mac.ops.dmac_config(hw);
+ if (ixgbe_pci_iov_detach(dev) != 0) {
+ device_printf(dev, "SR-IOV in use; detach first.\n");
+ return (EBUSY);
}
-}
-/*
- * Checks whether the adapter's ports are capable of
- * Wake On LAN by reading the adapter's NVM.
- *
- * Sets each port's hw->wol_enabled value depending
- * on the value read here.
- */
-static void
-ixgbe_check_wol_support(struct adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- u16 dev_caps = 0;
+ iflib_config_gtask_deinit(&adapter->mod_task);
+ iflib_config_gtask_deinit(&adapter->msf_task);
+ iflib_config_gtask_deinit(&adapter->phy_task);
+ if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
+ iflib_config_gtask_deinit(&adapter->mbx_task);
- /* Find out WoL support for port */
- adapter->wol_support = hw->wol_enabled = 0;
- ixgbe_get_device_caps(hw, &dev_caps);
- if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
- ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
- hw->bus.func == 0))
- adapter->wol_support = hw->wol_enabled = 1;
+ ixgbe_setup_low_power_mode(ctx);
- /* Save initial wake up filter configuration */
- adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
+ /* let hardware know driver is unloading */
+ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
+ ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
- return;
-}
+ ixgbe_free_pci_resources(ctx);
+ free(adapter->mta, M_IXGBE);
+
+ return (0);
+}
-/*
- * Prepare the adapter/port for LPLU and/or WoL
- */
static int
-ixgbe_setup_low_power_mode(struct adapter *adapter)
+ixgbe_setup_low_power_mode(if_ctx_t ctx)
{
+ struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- device_t dev = adapter->dev;
+ device_t dev = iflib_get_dev(ctx);
s32 error = 0;
- mtx_assert(&adapter->core_mtx, MA_OWNED);
-
if (!hw->wol_enabled)
ixgbe_set_phy_power(hw, FALSE);
/* Limit power management flow to X550EM baseT */
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T
- && hw->phy.ops.enter_lplu) {
+ && hw->phy.ops.enter_lplu) {
/* Turn off support for APM wakeup. (Using ACPI instead) */
IXGBE_WRITE_REG(hw, IXGBE_GRC,
IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2);
@@ -4019,1984 +2830,1835 @@
/* Enable wakeups and power management in Wakeup Control */
IXGBE_WRITE_REG(hw, IXGBE_WUC,
- IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
+ IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
/* X550EM baseT adapters need a special LPLU flow */
- hw->phy.reset_disable = true;
- ixgbe_stop(adapter);
+ hw->phy.reset_disable = TRUE;
error = hw->phy.ops.enter_lplu(hw);
if (error)
- device_printf(dev,
- "Error entering LPLU: %d\n", error);
- hw->phy.reset_disable = false;
- } else {
- /* Just stop for other adapters */
- ixgbe_stop(adapter);
+ device_printf(dev, "Error entering LPLU: %d\n", error);
+ hw->phy.reset_disable = FALSE;
}
return error;
}
-/**********************************************************************
+/*********************************************************************
*
- * Update the board statistics counters.
+ * Shutdown entry point
*
**********************************************************************/
-static void
-ixgbe_update_stats_counters(struct adapter *adapter)
+static int
+ixgbe_if_shutdown(if_ctx_t ctx)
{
- struct ixgbe_hw *hw = &adapter->hw;
- u32 missed_rx = 0, bprc, lxon, lxoff, total;
- u64 total_missed_rx = 0;
-
- adapter->stats.pf.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
- adapter->stats.pf.illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
- adapter->stats.pf.errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC);
- adapter->stats.pf.mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC);
-
- for (int i = 0; i < 16; i++) {
- adapter->stats.pf.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
- adapter->stats.pf.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
- adapter->stats.pf.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
- }
- adapter->stats.pf.mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC);
- adapter->stats.pf.mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC);
- adapter->stats.pf.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
-
- /* Hardware workaround, gprc counts missed packets */
- adapter->stats.pf.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
- adapter->stats.pf.gprc -= missed_rx;
-
- if (hw->mac.type != ixgbe_mac_82598EB) {
- adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) +
- ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
- adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
- ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32);
- adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORL) +
- ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
- adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
- adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
- } else {
- adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
- adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
- /* 82598 only has a counter in the high register */
- adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
- adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
- adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
- }
-
- /*
- * Workaround: mprc hardware is incorrectly counting
- * broadcasts, so for now we subtract those.
- */
- bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
- adapter->stats.pf.bprc += bprc;
- adapter->stats.pf.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
- if (hw->mac.type == ixgbe_mac_82598EB)
- adapter->stats.pf.mprc -= bprc;
-
- adapter->stats.pf.prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
- adapter->stats.pf.prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
- adapter->stats.pf.prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
- adapter->stats.pf.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
- adapter->stats.pf.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
- adapter->stats.pf.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
-
- lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
- adapter->stats.pf.lxontxc += lxon;
- lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
- adapter->stats.pf.lxofftxc += lxoff;
- total = lxon + lxoff;
-
- adapter->stats.pf.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
- adapter->stats.pf.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
- adapter->stats.pf.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
- adapter->stats.pf.gptc -= total;
- adapter->stats.pf.mptc -= total;
- adapter->stats.pf.ptc64 -= total;
- adapter->stats.pf.gotc -= total * ETHER_MIN_LEN;
+ int error = 0;
- adapter->stats.pf.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
- adapter->stats.pf.rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
- adapter->stats.pf.roc += IXGBE_READ_REG(hw, IXGBE_ROC);
- adapter->stats.pf.rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
- adapter->stats.pf.mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
- adapter->stats.pf.mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
- adapter->stats.pf.mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
- adapter->stats.pf.tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
- adapter->stats.pf.tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
- adapter->stats.pf.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
- adapter->stats.pf.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
- adapter->stats.pf.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
- adapter->stats.pf.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
- adapter->stats.pf.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
- adapter->stats.pf.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
- adapter->stats.pf.xec += IXGBE_READ_REG(hw, IXGBE_XEC);
- adapter->stats.pf.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
- adapter->stats.pf.fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
- /* Only read FCOE on 82599 */
- if (hw->mac.type != ixgbe_mac_82598EB) {
- adapter->stats.pf.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
- adapter->stats.pf.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
- adapter->stats.pf.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
- adapter->stats.pf.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
- adapter->stats.pf.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
- }
+ INIT_DEBUGOUT("ixgbe_shutdown: begin");
- /* Fill out the OS statistics structure */
- IXGBE_SET_IPACKETS(adapter, adapter->stats.pf.gprc);
- IXGBE_SET_OPACKETS(adapter, adapter->stats.pf.gptc);
- IXGBE_SET_IBYTES(adapter, adapter->stats.pf.gorc);
- IXGBE_SET_OBYTES(adapter, adapter->stats.pf.gotc);
- IXGBE_SET_IMCASTS(adapter, adapter->stats.pf.mprc);
- IXGBE_SET_OMCASTS(adapter, adapter->stats.pf.mptc);
- IXGBE_SET_COLLISIONS(adapter, 0);
- IXGBE_SET_IQDROPS(adapter, total_missed_rx);
- IXGBE_SET_IERRORS(adapter, adapter->stats.pf.crcerrs
- + adapter->stats.pf.rlec);
+ error = ixgbe_setup_low_power_mode(ctx);
+ return (error);
}
-#if __FreeBSD_version >= 1100036
-static uint64_t
-ixgbe_get_counter(struct ifnet *ifp, ift_counter cnt)
+static int
+ixgbe_if_suspend(if_ctx_t ctx)
{
- struct adapter *adapter;
- struct tx_ring *txr;
- uint64_t rv;
-
- adapter = if_getsoftc(ifp);
-
- switch (cnt) {
- case IFCOUNTER_IPACKETS:
- return (adapter->ipackets);
- case IFCOUNTER_OPACKETS:
- return (adapter->opackets);
- case IFCOUNTER_IBYTES:
- return (adapter->ibytes);
- case IFCOUNTER_OBYTES:
- return (adapter->obytes);
- case IFCOUNTER_IMCASTS:
- return (adapter->imcasts);
- case IFCOUNTER_OMCASTS:
- return (adapter->omcasts);
- case IFCOUNTER_COLLISIONS:
- return (0);
- case IFCOUNTER_IQDROPS:
- return (adapter->iqdrops);
- case IFCOUNTER_OQDROPS:
- rv = 0;
- txr = adapter->tx_rings;
- for (int i = 0; i < adapter->num_queues; i++, txr++)
- rv += txr->br->br_drops;
- return (rv);
- case IFCOUNTER_IERRORS:
- return (adapter->ierrors);
- default:
- return (if_get_counter_default(ifp, cnt));
- }
-}
-#endif
+ int error = 0;
-/** ixgbe_sysctl_tdh_handler - Handler function
- * Retrieves the TDH value from the hardware
- */
-static int
-ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS)
-{
- int error;
+ INIT_DEBUGOUT("ixgbe_suspend: begin");
- struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
- if (!txr) return 0;
+ error = ixgbe_setup_low_power_mode(ctx);
- unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
- error = sysctl_handle_int(oidp, &val, 0, req);
- if (error || !req->newptr)
- return error;
- return 0;
+ return (error);
}
-/** ixgbe_sysctl_tdt_handler - Handler function
- * Retrieves the TDT value from the hardware
- */
-static int
-ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS)
+static int
+ixgbe_if_resume(if_ctx_t ctx)
{
- int error;
-
- struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
- if (!txr) return 0;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ device_t dev = iflib_get_dev(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 wus;
- unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
- error = sysctl_handle_int(oidp, &val, 0, req);
- if (error || !req->newptr)
- return error;
- return 0;
-}
+ INIT_DEBUGOUT("ixgbe_resume: begin");
-/** ixgbe_sysctl_rdh_handler - Handler function
- * Retrieves the RDH value from the hardware
- */
-static int
-ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS)
-{
- int error;
+ /* Read & clear WUS register */
+ wus = IXGBE_READ_REG(hw, IXGBE_WUS);
+ if (wus)
+ device_printf(dev, "Woken up by (WUS): %#010x\n",
+ IXGBE_READ_REG(hw, IXGBE_WUS));
+ IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
+ /* And clear WUFC until next low-power transition */
+ IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
- struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
- if (!rxr) return 0;
+ /*
+ * Required after D3->D0 transition;
+ * will re-advertise all previous advertised speeds
+ */
+ if (ifp->if_flags & IFF_UP)
+ ixgbe_if_init(ctx);
- unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
- error = sysctl_handle_int(oidp, &val, 0, req);
- if (error || !req->newptr)
- return error;
- return 0;
+ INIT_DEBUGOUT("ixgbe_resume: end");
+ return (0);
}
-/** ixgbe_sysctl_rdt_handler - Handler function
- * Retrieves the RDT value from the hardware
- */
-static int
-ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS)
+/*********************************************************************
+ * Ioctl mtu entry point
+ *
+ *
+ * return 0 on success, EINVAL on failure
+ **********************************************************************/
+static int
+ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
{
- int error;
+ int error = 0;
+ struct adapter *adapter = iflib_get_softc(ctx);
- struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
- if (!rxr) return 0;
+ IOCTL_DEBUGOUT("ioctl: SIOCIFMTU (Set Interface MTU)");
- unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
- error = sysctl_handle_int(oidp, &val, 0, req);
- if (error || !req->newptr)
- return error;
- return 0;
+ if (mtu > IXGBE_MAX_MTU) {
+ error = EINVAL;
+ } else {
+ adapter->max_frame_size = mtu + IXGBE_MTU_HDR;
+ }
+
+ return error;
}
-static int
-ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
-{
- int error;
- struct ix_queue *que = ((struct ix_queue *)oidp->oid_arg1);
- unsigned int reg, usec, rate;
- reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
- usec = ((reg & 0x0FF8) >> 3);
- if (usec > 0)
- rate = 500000 / usec;
- else
- rate = 0;
- error = sysctl_handle_int(oidp, &rate, 0, req);
- if (error || !req->newptr)
- return error;
- reg &= ~0xfff; /* default, no limitation */
- ixgbe_max_interrupt_rate = 0;
- if (rate > 0 && rate < 500000) {
- if (rate < 1000)
- rate = 1000;
- ixgbe_max_interrupt_rate = rate;
- reg |= ((4000000/rate) & 0xff8 );
- }
- IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg);
- return 0;
+static void
+ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int crcstrip)
+{
+ struct adapter *sc = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &sc->hw;
+ /* crc stripping is set in two places:
+ * IXGBE_HLREG0 (modified on init_locked and hw reset)
+ * IXGBE_RDRXCTL (set by the original driver in
+ * ixgbe_setup_hw_rsc() called in init_locked.
+ * We disable the setting when netmap is compiled in).
+ * We update the values here, but also in ixgbe.c because
+ * init_locked sometimes is called outside our control.
+ */
+ uint32_t hl, rxc;
+
+ hl = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+ rxc = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+#ifdef NETMAP
+ if (netmap_verbose)
+ D("%s read HLREG 0x%x rxc 0x%x",
+ onoff ? "enter" : "exit", hl, rxc);
+#endif
+ /* hw requirements ... */
+ rxc &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
+ rxc |= IXGBE_RDRXCTL_RSCACKC;
+ if (onoff && !crcstrip) {
+ /* keep the crc. Fast rx */
+ hl &= ~IXGBE_HLREG0_RXCRCSTRP;
+ rxc &= ~IXGBE_RDRXCTL_CRCSTRIP;
+ } else {
+ /* reset default mode */
+ hl |= IXGBE_HLREG0_RXCRCSTRP;
+ rxc |= IXGBE_RDRXCTL_CRCSTRIP;
+ }
+#ifdef NETMAP
+ if (netmap_verbose)
+ D("%s write HLREG 0x%x rxc 0x%x",
+ onoff ? "enter" : "exit", hl, rxc);
+#endif
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hl);
+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rxc);
}
-static void
-ixgbe_add_device_sysctls(struct adapter *adapter)
+/*********************************************************************
+ * Init entry point
+ *
+ * This routine is used in two ways. It is used by the stack as
+ * init entry point in network interface structure. It is also used
+ * by the driver as a hw/sw initialization routine to get to a
+ * consistent state.
+ *
+ * return 0 on success, positive on failure
+ **********************************************************************/
+void
+ixgbe_if_init(if_ctx_t ctx)
{
- device_t dev = adapter->dev;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ device_t dev = iflib_get_dev(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- struct sysctl_oid_list *child;
- struct sysctl_ctx_list *ctx;
+ struct ix_rx_queue *rx_que;
+ struct ix_tx_queue *tx_que;
- ctx = device_get_sysctl_ctx(dev);
- child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
+ u32 txdctl, mhadd;
+ u32 rxdctl, rxctrl;
+ int i, err;
- /* Sysctls for all devices */
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC);
+ INIT_DEBUGOUT("ixgbe_if_init: begin");
- SYSCTL_ADD_INT(ctx, child, OID_AUTO, "enable_aim",
- CTLFLAG_RW,
- &ixgbe_enable_aim, 1, "Interrupt Moderation");
+ /* Queue indices may change with IOV mode */
+ ixgbe_align_all_queue_indices(adapter);
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "advertise_speed",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_advertise, "I", IXGBE_SYSCTL_DESC_ADV_SPEED);
+ /* reprogram the RAR[0] in case user changed it. */
+ ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV);
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "thermal_test",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_thermal_test, "I", "Thermal Test");
+ /* Get the latest mac address, User can use a LAA */
+ bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
+ ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
+ hw->addr_ctrl.rar_used_count = 1;
-#ifdef IXGBE_DEBUG
- /* testing sysctls (for all devices) */
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_power_state, "I", "PCI Power State");
+ ixgbe_init_hw(hw);
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config",
- CTLTYPE_STRING | CTLFLAG_RD, adapter, 0,
- ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration");
-#endif
- /* for X550 series devices */
- if (hw->mac.type >= ixgbe_mac_X550)
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "dmac",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_dmac, "I", "DMA Coalesce");
+ ixgbe_initialize_iov(adapter);
- /* for X552 backplane devices */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
- struct sysctl_oid *eee_node;
- struct sysctl_oid_list *eee_list;
+ ixgbe_initialize_transmit_units(ctx);
- eee_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "eee",
- CTLFLAG_RD, NULL,
- "Energy Efficient Ethernet sysctls");
- eee_list = SYSCTL_CHILDREN(eee_node);
+ /* Setup Multicast table */
+ ixgbe_if_multi_set(ctx);
- SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "enable",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_eee_enable, "I",
- "Enable or Disable EEE");
+ /*
+ * Determine the correct mbuf pool
+ * for doing jumbo frames
+ */
+ if (adapter->max_frame_size <= MCLBYTES)
+ adapter->rx_mbuf_sz = MCLBYTES;
+ else
+ adapter->rx_mbuf_sz = MJUMPAGESIZE;
- SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "negotiated",
- CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
- ixgbe_sysctl_eee_negotiated, "I",
- "EEE negotiated on link");
+ /* Configure RX settings */
+ ixgbe_initialize_receive_units(ctx);
- SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_status",
- CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
- ixgbe_sysctl_eee_tx_lpi_status, "I",
- "Whether or not TX link is in LPI state");
+ /* Enable SDP & MSIX interrupts based on adapter */
+ ixgbe_config_gpie(adapter);
- SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "rx_lpi_status",
- CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
- ixgbe_sysctl_eee_rx_lpi_status, "I",
- "Whether or not RX link is in LPI state");
+ /* Set MTU size */
+ if (ifp->if_mtu > ETHERMTU) {
+ /* aka IXGBE_MAXFRS on 82599 and newer */
+ mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
+ mhadd &= ~IXGBE_MHADD_MFS_MASK;
+ mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
+ }
- SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_delay",
- CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
- ixgbe_sysctl_eee_tx_lpi_delay, "I",
- "TX LPI entry delay in microseconds");
+ /* Now enable all the queues */
+ for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) {
+ struct tx_ring *txr = &tx_que->txr;
+
+ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me));
+ txdctl |= IXGBE_TXDCTL_ENABLE;
+ /* Set WTHRESH to 8, burst writeback */
+ txdctl |= (8 << 16);
+ /*
+ * When the internal queue falls below PTHRESH (32),
+ * start prefetching as long as there are at least
+ * HTHRESH (1) buffers ready. The values are taken
+ * from the Intel linux driver 3.8.21.
+ * Prefetching enables tx line rate even with 1 queue.
+ */
+ txdctl |= (32 << 0) | (1 << 8);
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl);
}
- /* for WoL-capable devices */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wol_enable",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_wol_enable, "I",
- "Enable/Disable Wake on LAN");
+ for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) {
+ struct rx_ring *rxr = &rx_que->rxr;
+ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ /*
+ ** PTHRESH = 21
+ ** HTHRESH = 4
+ ** WTHRESH = 8
+ */
+ rxdctl &= ~0x3FFFFF;
+ rxdctl |= 0x080420;
+ }
+ rxdctl |= IXGBE_RXDCTL_ENABLE;
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl);
+ for (int j = 0; j < 10; j++) {
+ if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) &
+ IXGBE_RXDCTL_ENABLE)
+ break;
+ else
+ msec_delay(1);
+ }
+ wmb();
+ }
+
+ /* Enable Receive engine */
+ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ rxctrl |= IXGBE_RXCTRL_DMBYPS;
+ rxctrl |= IXGBE_RXCTRL_RXEN;
+ ixgbe_enable_rx_dma(hw, rxctrl);
+
+ /* Set up MSI/MSI-X routing */
+ if (ixgbe_enable_msix) {
+ ixgbe_configure_ivars(adapter);
+ /* Set up auto-mask */
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
+ else {
+ IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
+ IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
+ }
+ } else { /* Simple settings for Legacy/MSI */
+ ixgbe_set_ivar(adapter, 0, 0, 0);
+ ixgbe_set_ivar(adapter, 0, 0, 1);
+ IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
+ }
+
+ ixgbe_init_fdir(adapter);
- SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wufc",
- CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_sysctl_wufc, "I",
- "Enable/Disable Wake Up Filters");
+ /*
+ * Check on any SFP devices that
+ * need to be kick-started
+ */
+ if (hw->phy.type == ixgbe_phy_none) {
+ int err = hw->phy.ops.identify(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev,
+ "Unsupported SFP+ module type was detected.\n");
+ return;
+ }
}
- /* for X552/X557-AT devices */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
- struct sysctl_oid *phy_node;
- struct sysctl_oid_list *phy_list;
+ /* Set moderation on the Link interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
- phy_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "phy",
- CTLFLAG_RD, NULL,
- "External PHY sysctls");
- phy_list = SYSCTL_CHILDREN(phy_node);
+ /* Configure Energy Efficient Ethernet for supported devices */
+ if (hw->mac.ops.setup_eee) {
+ err = hw->mac.ops.setup_eee(hw, adapter->eee_enabled);
+ if (err)
+ device_printf(dev, "Error setting up EEE: %d\n", err);
+ }
- SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "temp",
- CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
- ixgbe_sysctl_phy_temp, "I",
- "Current External PHY Temperature (Celsius)");
+ /* Enable power to the phy. */
+ ixgbe_set_phy_power(hw, TRUE);
- SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "overtemp_occurred",
- CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
- ixgbe_sysctl_phy_overtemp_occurred, "I",
- "External PHY High Temperature Event Occurred");
+ /* Config/Enable Link */
+ ixgbe_config_link(adapter);
+
+ /* Hardware Packet Buffer & Flow Control setup */
+ ixgbe_config_delay_values(adapter);
+
+ /* Initialize the FC settings */
+ ixgbe_start_hw(hw);
+
+ /* Set up VLAN support and filter */
+ ixgbe_setup_vlan_hw_support(ctx);
+
+ /* Setup DMA Coalescing */
+ ixgbe_config_dmac(adapter);
+
+ /* And now turn on interrupts */
+ ixgbe_if_enable_intr(ctx);
+
+ /* Enable the use of the MBX by the VF's */
+ if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) {
+ u32 reg = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
+ reg |= IXGBE_CTRL_EXT_PFRSTD;
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, reg);
}
}
/*
- * Add sysctl variables, one per statistic, to the system.
- */
+** Setup the correct IVAR register for a particular MSIX interrupt
+** (yes this is all very magic and confusing :)
+** - entry is the register array entry
+** - vector is the MSIX vector for this queue
+** - type is RX/TX/MISC
+*/
static void
-ixgbe_add_hw_stats(struct adapter *adapter)
+ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
{
- device_t dev = adapter->dev;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 ivar, index;
+
+ vector |= IXGBE_IVAR_ALLOC_VAL;
- struct tx_ring *txr = adapter->tx_rings;
- struct rx_ring *rxr = adapter->rx_rings;
+ switch (hw->mac.type) {
- struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
- struct sysctl_oid *tree = device_get_sysctl_tree(dev);
- struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
- struct ixgbe_hw_stats *stats = &adapter->stats.pf;
+ case ixgbe_mac_82598EB:
+ if (type == -1)
+ entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
+ else
+ entry += (type * 64);
+ index = (entry >> 2) & 0x1F;
+ ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
+ ivar &= ~(0xFF << (8 * (entry & 0x3)));
+ ivar |= (vector << (8 * (entry & 0x3)));
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
+ break;
- struct sysctl_oid *stat_node, *queue_node;
- struct sysctl_oid_list *stat_list, *queue_list;
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ if (type == -1) { /* MISC IVAR */
+ index = (entry & 1) * 8;
+ ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
+ ivar &= ~(0xFF << index);
+ ivar |= (vector << index);
+ IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
+ } else { /* RX/TX IVARS */
+ index = (16 * (entry & 1)) + (8 * type);
+ ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
+ ivar &= ~(0xFF << index);
+ ivar |= (vector << index);
+ IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
+ }
-#define QUEUE_NAME_LEN 32
- char namebuf[QUEUE_NAME_LEN];
+ default:
+ break;
+ }
+}
- /* Driver Statistics */
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
- CTLFLAG_RD, &adapter->dropped_pkts,
- "Driver dropped packets");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_failed",
- CTLFLAG_RD, &adapter->mbuf_defrag_failed,
- "m_defrag() failed");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
- CTLFLAG_RD, &adapter->watchdog_events,
- "Watchdog timeouts");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
- CTLFLAG_RD, &adapter->link_irq,
- "Link MSIX IRQ Handled");
+static void
+ixgbe_configure_ivars(struct adapter *adapter)
+{
+ struct ix_rx_queue *rx_que = adapter->rx_queues;
+ struct ix_tx_queue *tx_que = adapter->tx_queues;
+ u32 newitr;
+
+ if (ixgbe_max_interrupt_rate > 0)
+ newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
+ else {
+ /*
+ ** Disable DMA coalescing if interrupt moderation is
+ ** disabled.
+ */
+ adapter->dmac = 0;
+ newitr = 0;
+ }
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
- queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
- CTLFLAG_RD, NULL, "Queue Name");
- queue_list = SYSCTL_CHILDREN(queue_node);
+ for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++) {
+ struct rx_ring *rxr = &rx_que->rxr;
- SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate",
- CTLTYPE_UINT | CTLFLAG_RW, &adapter->queues[i],
- sizeof(&adapter->queues[i]),
- ixgbe_sysctl_interrupt_rate_handler, "IU",
- "Interrupt Rate");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
- CTLFLAG_RD, &(adapter->queues[i].irqs),
- "irqs on this queue");
- SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head",
- CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
- ixgbe_sysctl_tdh_handler, "IU",
- "Transmit Descriptor Head");
- SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail",
- CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
- ixgbe_sysctl_tdt_handler, "IU",
- "Transmit Descriptor Tail");
- SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tso_tx",
- CTLFLAG_RD, &txr->tso_tx,
- "TSO");
- SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "no_tx_dma_setup",
- CTLFLAG_RD, &txr->no_tx_dma_setup,
- "Driver tx dma failure in xmit");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail",
- CTLFLAG_RD, &txr->no_desc_avail,
- "Queue No Descriptor Available");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
- CTLFLAG_RD, &txr->total_packets,
- "Queue Packets Transmitted");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "br_drops",
- CTLFLAG_RD, &txr->br->br_drops,
- "Packets dropped in buf_ring");
+ /* First the RX queue entry */
+ ixgbe_set_ivar(adapter, rxr->me, rx_que->msix, 0);
+
+ /* Set an Initial EITR value */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(rx_que->msix), newitr);
}
+ for (int i = 0; i < adapter->num_tx_queues; i++, tx_que++) {
+ struct tx_ring *txr = &tx_que->txr;
- for (int i = 0; i < adapter->num_queues; i++, rxr++) {
- snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
- queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
- CTLFLAG_RD, NULL, "Queue Name");
- queue_list = SYSCTL_CHILDREN(queue_node);
+ /* ... and the TX */
+ ixgbe_set_ivar(adapter, txr->me, tx_que->msix, 1);
+ }
+ /* For the Link interrupt */
+ ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
+}
- struct lro_ctrl *lro = &rxr->lro;
+static void
+ixgbe_config_gpie(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 gpie;
- snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
- queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
- CTLFLAG_RD, NULL, "Queue Name");
- queue_list = SYSCTL_CHILDREN(queue_node);
+ gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
- SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head",
- CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
- ixgbe_sysctl_rdh_handler, "IU",
- "Receive Descriptor Head");
- SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail",
- CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
- ixgbe_sysctl_rdt_handler, "IU",
- "Receive Descriptor Tail");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
- CTLFLAG_RD, &rxr->rx_packets,
- "Queue Packets Received");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
- CTLFLAG_RD, &rxr->rx_bytes,
- "Queue Bytes Received");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies",
- CTLFLAG_RD, &rxr->rx_copies,
- "Copied RX Frames");
- SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_queued",
- CTLFLAG_RD, &lro->lro_queued, 0,
- "LRO Queued");
- SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_flushed",
- CTLFLAG_RD, &lro->lro_flushed, 0,
- "LRO Flushed");
+ if (adapter->intr_type == IFLIB_INTR_MSIX) {
+ /* Enable Enhanced MSI-X mode */
+ gpie |= IXGBE_GPIE_MSIX_MODE;
+ gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
+ IXGBE_GPIE_OCD;
}
- /* MAC stats get the own sub node */
+ /* Fan Failure Interrupt */
+ if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
+ gpie |= IXGBE_SDP1_GPIEN;
- stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
- CTLFLAG_RD, NULL, "MAC Statistics");
- stat_list = SYSCTL_CHILDREN(stat_node);
+ /* Thermal Sensor Interrupt */
+ if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR)
+ gpie |= IXGBE_SDP0_GPIEN_X540;
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
- CTLFLAG_RD, &stats->crcerrs,
- "CRC Errors");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs",
- CTLFLAG_RD, &stats->illerrc,
- "Illegal Byte Errors");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs",
- CTLFLAG_RD, &stats->errbc,
- "Byte Errors");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards",
- CTLFLAG_RD, &stats->mspdc,
- "MAC Short Packets Discarded");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults",
- CTLFLAG_RD, &stats->mlfc,
- "MAC Local Faults");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults",
- CTLFLAG_RD, &stats->mrfc,
- "MAC Remote Faults");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs",
- CTLFLAG_RD, &stats->rlec,
- "Receive Length Errors");
+ /* Link detection */
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN;
+ break;
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ gpie |= IXGBE_SDP0_GPIEN_X540;
+ break;
+ default:
+ break;
+ }
- /* Flow Control stats */
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
- CTLFLAG_RD, &stats->lxontxc,
- "Link XON Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
- CTLFLAG_RD, &stats->lxonrxc,
- "Link XON Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
- CTLFLAG_RD, &stats->lxofftxc,
- "Link XOFF Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
- CTLFLAG_RD, &stats->lxoffrxc,
- "Link XOFF Received");
+ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+}
- /* Packet Reception Stats */
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd",
- CTLFLAG_RD, &stats->tor,
- "Total Octets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
- CTLFLAG_RD, &stats->gorc,
- "Good Octets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd",
- CTLFLAG_RD, &stats->tpr,
- "Total Packets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
- CTLFLAG_RD, &stats->gprc,
- "Good Packets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
- CTLFLAG_RD, &stats->mprc,
- "Multicast Packets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd",
- CTLFLAG_RD, &stats->bprc,
- "Broadcast Packets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
- CTLFLAG_RD, &stats->prc64,
- "64 byte frames received ");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
- CTLFLAG_RD, &stats->prc127,
- "65-127 byte frames received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
- CTLFLAG_RD, &stats->prc255,
- "128-255 byte frames received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
- CTLFLAG_RD, &stats->prc511,
- "256-511 byte frames received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
- CTLFLAG_RD, &stats->prc1023,
- "512-1023 byte frames received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
- CTLFLAG_RD, &stats->prc1522,
- "1023-1522 byte frames received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized",
- CTLFLAG_RD, &stats->ruc,
- "Receive Undersized");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
- CTLFLAG_RD, &stats->rfc,
- "Fragmented Packets Received ");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized",
- CTLFLAG_RD, &stats->roc,
- "Oversized Packets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd",
- CTLFLAG_RD, &stats->rjc,
- "Received Jabber");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd",
- CTLFLAG_RD, &stats->mngprc,
- "Management Packets Received");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd",
- CTLFLAG_RD, &stats->mngptc,
- "Management Packets Dropped");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs",
- CTLFLAG_RD, &stats->xec,
- "Checksum Errors");
+/*
+ * Requires adapter->max_frame_size to be set.
+ */
+static void
+ixgbe_config_delay_values(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 rxpb, frame, size, tmp;
- /* Packet Transmission Stats */
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
- CTLFLAG_RD, &stats->gotc,
- "Good Octets Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
- CTLFLAG_RD, &stats->tpt,
- "Total Packets Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
- CTLFLAG_RD, &stats->gptc,
- "Good Packets Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
- CTLFLAG_RD, &stats->bptc,
- "Broadcast Packets Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
- CTLFLAG_RD, &stats->mptc,
- "Multicast Packets Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd",
- CTLFLAG_RD, &stats->mngptc,
- "Management Packets Transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
- CTLFLAG_RD, &stats->ptc64,
- "64 byte frames transmitted ");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
- CTLFLAG_RD, &stats->ptc127,
- "65-127 byte frames transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
- CTLFLAG_RD, &stats->ptc255,
- "128-255 byte frames transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
- CTLFLAG_RD, &stats->ptc511,
- "256-511 byte frames transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
- CTLFLAG_RD, &stats->ptc1023,
- "512-1023 byte frames transmitted");
- SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
- CTLFLAG_RD, &stats->ptc1522,
- "1024-1522 byte frames transmitted");
+ frame = adapter->max_frame_size;
+
+ /* Calculate High Water */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ tmp = IXGBE_DV_X540(frame, frame);
+ break;
+ default:
+ tmp = IXGBE_DV(frame, frame);
+ break;
+ }
+ size = IXGBE_BT2KB(tmp);
+ rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
+ hw->fc.high_water[0] = rxpb - size;
+
+ /* Now calculate Low Water */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ tmp = IXGBE_LOW_DV_X540(frame);
+ break;
+ default:
+ tmp = IXGBE_LOW_DV(frame);
+ break;
+ }
+ hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
+
+ hw->fc.pause_time = IXGBE_FC_PAUSE;
+ hw->fc.send_xon = TRUE;
}
-static void
-ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
- const char *description, int *limit, int value)
+/*********************************************************************
+ * Multicast Update
+ *
+ * This routine is called whenever multicast address list is updated.
+ *
+ **********************************************************************/
+#define IXGBE_RAR_ENTRIES 16
+
+static int
+ixgbe_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count)
{
- *limit = value;
- SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
- OID_AUTO, name, CTLFLAG_RW, limit, value, description);
+ struct adapter *adapter = arg;
+ struct ixgbe_mc_addr *mta = adapter->mta;
+
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ return (0);
+ if (count == MAX_NUM_MULTICAST_ADDRESSES)
+ return (0);
+ bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
+ mta[count].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
+ mta[count].vmdq = adapter->pool;
+ return (1);
}
-/*
-** Set flow control using sysctl:
-** Flow control values:
-** 0 - off
-** 1 - rx pause
-** 2 - tx pause
-** 3 - full
-*/
-static int
-ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS)
+static void
+ixgbe_if_multi_set(if_ctx_t ctx)
{
- int error, fc;
- struct adapter *adapter;
+ u32 fctrl;
+ u8 *update_ptr;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_mc_addr *mta;
+ int mcnt = 0;
+ struct ifnet *ifp = iflib_get_ifp(ctx);
- adapter = (struct adapter *) arg1;
- fc = adapter->fc;
+ IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin");
- error = sysctl_handle_int(oidp, &fc, 0, req);
- if ((error) || (req->newptr == NULL))
- return (error);
+ mta = adapter->mta;
+ bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
- /* Don't bother if it's not changed */
- if (adapter->fc == fc)
- return (0);
+ mcnt = if_multi_apply(iflib_get_ifp(ctx), ixgbe_mc_filter_apply, adapter);
- return ixgbe_set_flowcntl(adapter, fc);
+ fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+ fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
+ if (ifp->if_flags & IFF_PROMISC)
+ fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
+ else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES ||
+ ifp->if_flags & IFF_ALLMULTI) {
+ fctrl |= IXGBE_FCTRL_MPE;
+ fctrl &= ~IXGBE_FCTRL_UPE;
+ } else
+ fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
+
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
+
+ if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) {
+ update_ptr = (u8 *)mta;
+ ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt, ixgbe_mc_array_itr, TRUE);
+ }
+
+ IOCTL_DEBUGOUT("ixgbe_if_multi_set: end");
}
+/*
+ * This is an iterator function now needed by the multicast
+ * shared code. It simply feeds the shared code routine the
+ * addresses in the array of ixgbe_if_multi_set() one by one.
+ */
+static u8 *
+ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
+{
+ struct ixgbe_mc_addr *mta;
-static int
-ixgbe_set_flowcntl(struct adapter *adapter, int fc)
+ mta = (struct ixgbe_mc_addr *)*update_ptr;
+ *vmdq = mta->vmdq;
+
+ *update_ptr = (u8*)(mta + 1);;
+ return (mta->addr);
+}
+
+/*********************************************************************
+ * Timer routine
+ *
+ * This routine checks for link status, updates statistics,
+ * and runs the watchdog check.
+ *
+ **********************************************************************/
+
+static void
+ixgbe_if_timer(if_ctx_t ctx, uint16_t qid)
{
+ struct adapter *adapter = iflib_get_softc(ctx);
- switch (fc) {
- case ixgbe_fc_rx_pause:
- case ixgbe_fc_tx_pause:
- case ixgbe_fc_full:
- adapter->hw.fc.requested_mode = adapter->fc;
- if (adapter->num_queues > 1)
- ixgbe_disable_rx_drop(adapter);
- break;
- case ixgbe_fc_none:
- adapter->hw.fc.requested_mode = ixgbe_fc_none;
- if (adapter->num_queues > 1)
- ixgbe_enable_rx_drop(adapter);
- break;
- default:
- return (EINVAL);
- }
- adapter->fc = fc;
- /* Don't autoneg if forcing a value */
- adapter->hw.fc.disable_fc_autoneg = TRUE;
- ixgbe_fc_enable(&adapter->hw);
- return (0);
+ if (qid != 0)
+ return;
+
+ /* Check for pluggable optics */
+ if (adapter->sfp_probe)
+ if (!ixgbe_sfp_probe(ctx))
+ return; /* Nothing to do */
+
+ ixgbe_check_link(&adapter->hw, &adapter->link_speed,
+ &adapter->link_up, 0);
+ ixgbe_if_update_admin_status(ctx);
+ ixgbe_update_stats_counters(adapter);
+
+ /* Fire off the adminq task */
+ iflib_admin_intr_deferred(ctx);
}
/*
-** Control advertised link speed:
-** Flags:
-** 0x1 - advertise 100 Mb
-** 0x2 - advertise 1G
-** 0x4 - advertise 10G
+** ixgbe_sfp_probe - called in the local timer to
+** determine if a port had optics inserted.
*/
-static int
-ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
+static bool
+ixgbe_sfp_probe(if_ctx_t ctx)
{
- int error, advertise;
- struct adapter *adapter;
-
- adapter = (struct adapter *) arg1;
- advertise = adapter->advertise;
-
- error = sysctl_handle_int(oidp, &advertise, 0, req);
- if ((error) || (req->newptr == NULL))
- return (error);
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ device_t dev = iflib_get_dev(ctx);
+ bool result = FALSE;
- return ixgbe_set_advertise(adapter, advertise);
+ if ((hw->phy.type == ixgbe_phy_nl) &&
+ (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
+ s32 ret = hw->phy.ops.identify_sfp(hw);
+ if (ret)
+ goto out;
+ ret = hw->phy.ops.reset(hw);
+ if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev, "Unsupported SFP+ module detected!");
+ printf(" Reload driver with supported module.\n");
+ adapter->sfp_probe = FALSE;
+ goto out;
+ } else
+ device_printf(dev, "SFP+ module detected!\n");
+ /* We now have supported optics */
+ adapter->sfp_probe = FALSE;
+ /* Set the optics type so system reports correctly */
+ ixgbe_setup_optics(adapter);
+ result = TRUE;
+ }
+out:
+ return (result);
}
-static int
-ixgbe_set_advertise(struct adapter *adapter, int advertise)
+/*************************************************************************
+ *
+ * Tasklet handler - ixgbe_handle_mod, ixgbe_handle_msf, ixgbe_handle_phy
+ *
+ *************************************************************************/
+/*
+** Tasklet for handling SFP module interrupts
+*/
+static void
+ixgbe_handle_mod(void *context)
{
- device_t dev;
- struct ixgbe_hw *hw;
- ixgbe_link_speed speed;
+ if_ctx_t ctx = context;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ enum ixgbe_phy_type orig_type = hw->phy.type;
+ device_t dev = iflib_get_dev(ctx);
+ u32 err;
- /* Checks to validate new value */
- if (adapter->advertise == advertise) /* no change */
- return (0);
+ /* Check to see if the PHY type changed */
+ if (hw->phy.ops.identify) {
+ hw->phy.type = ixgbe_phy_unknown;
+ hw->phy.ops.identify(hw);
+ }
- hw = &adapter->hw;
- dev = adapter->dev;
+ if (hw->phy.type != orig_type) {
+ device_printf(dev, "Detected phy_type %d\n", hw->phy.type);
- /* No speed changes for backplane media */
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- return (ENODEV);
+ if (hw->phy.type == ixgbe_phy_none) {
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ goto out;
+ }
- if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
- (hw->phy.multispeed_fiber))) {
- device_printf(dev,
- "Advertised speed can only be set on copper or "
- "multispeed fiber media types.\n");
- return (EINVAL);
+ /* Try to do the initialization that was skipped before */
+ if (hw->phy.ops.init)
+ hw->phy.ops.init(hw);
+ if (hw->phy.ops.reset)
+ hw->phy.ops.reset(hw);
}
- if (advertise < 0x1 || advertise > 0x7) {
+ err = hw->phy.ops.identify_sfp(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
device_printf(dev,
- "Invalid advertised speed; valid modes are 0x1 through 0x7\n");
- return (EINVAL);
+ "Unsupported SFP+ module type was detected.\n");
+ goto out;
}
- if ((advertise & 0x1)
- && (hw->mac.type != ixgbe_mac_X540)
- && (hw->mac.type != ixgbe_mac_X550)) {
- device_printf(dev, "Set Advertise: 100Mb on X540/X550 only\n");
- return (EINVAL);
+ err = hw->mac.ops.setup_sfp(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev,
+ "Setup failure - unsupported SFP+ module type.\n");
+ goto out;
+ }
+ if (hw->phy.multispeed_fiber)
+ GROUPTASK_ENQUEUE(&adapter->msf_task);
+out:
+ /* Update media type */
+ switch (hw->mac.ops.get_media_type(hw)) {
+ case ixgbe_media_type_fiber:
+ adapter->optics = IFM_10G_SR;
+ break;
+ case ixgbe_media_type_copper:
+ adapter->optics = IFM_10G_TWINAX;
+ break;
+ case ixgbe_media_type_cx4:
+ adapter->optics = IFM_10G_CX4;
+ break;
+ default:
+ adapter->optics = 0;
+ break;
}
+}
- /* Set new value and report new advertised mode */
- speed = 0;
- if (advertise & 0x1)
- speed |= IXGBE_LINK_SPEED_100_FULL;
- if (advertise & 0x2)
- speed |= IXGBE_LINK_SPEED_1GB_FULL;
- if (advertise & 0x4)
- speed |= IXGBE_LINK_SPEED_10GB_FULL;
- adapter->advertise = advertise;
- hw->mac.autotry_restart = TRUE;
- hw->mac.ops.setup_link(hw, speed, TRUE);
+/* Tasklet for handling MSF (multispeed fiber) interrupts */
- return (0);
+static void
+ixgbe_handle_msf(void *context)
+{
+ if_ctx_t ctx = context;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 autoneg;
+ bool negotiate;
+
+ /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
+ adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
+
+ autoneg = hw->phy.autoneg_advertised;
+ if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
+ hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
+ if (hw->mac.ops.setup_link)
+ hw->mac.ops.setup_link(hw, autoneg, TRUE);
+ /* Adjust media types shown in ifconfig */
+ ifmedia_removeall(adapter->media);
+ ixgbe_add_media_types(adapter->ctx);
+ ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO);
}
-/*
- * The following two sysctls are for X552/X557-AT devices;
- * they deal with the external PHY used in them.
- */
-static int
-ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS)
+
+/* Tasklet for handling interrupts from an external PHY */
+
+static void
+ixgbe_handle_phy(void *context)
{
- struct adapter *adapter = (struct adapter *) arg1;
+ if_ctx_t ctx = context;
+ struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- u16 reg;
+ int error;
- if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
+ error = hw->phy.ops.handle_lasi(hw);
+ if (error == IXGBE_ERR_OVERTEMP)
+ device_printf(adapter->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!! PHY will downshift to lower power state!\n");
+ else if (error)
device_printf(adapter->dev,
- "Device has no supported external thermal sensor.\n");
- return (ENODEV);
- }
+ "Error handling LASI interrupt: %d\n", error);
+ return;
+}
- if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
- &reg)) {
- device_printf(adapter->dev,
- "Error reading from PHY's current temperature register\n");
- return (EAGAIN);
- }
- /* Shift temp for output */
- reg = reg >> 8;
+/*********************************************************************
+ *
+ * This routine disables all traffic on the adapter by issuing a
+ * global reset on the MAC and deallocates TX/RX buffers.
+ *
+ **********************************************************************/
+static void
+ixgbe_if_stop(if_ctx_t ctx)
+{
+ struct ifnet *ifp;
+ struct adapter *adapter = iflib_get_softc(ctx);
+
+ struct ixgbe_hw *hw = &adapter->hw;
+ ifp = iflib_get_ifp(ctx);
+
+ INIT_DEBUGOUT("ixgbe_stop: begin\n");
+
+ ixgbe_reset_hw(hw);
+ hw->adapter_stopped = FALSE;
+ ixgbe_stop_adapter(hw);
+ if (hw->mac.type == ixgbe_mac_82599EB)
+ ixgbe_stop_mac_link_on_d3_82599(hw);
+ /* Turn off the laser - noop with no optics */
+ ixgbe_disable_tx_laser(hw);
+
+ /* Update the stack */
+ adapter->link_up = FALSE;
+ ixgbe_if_update_admin_status(ctx);
- return (sysctl_handle_int(oidp, NULL, reg, req));
+ /* reprogram the RAR[0] in case user changed it. */
+ ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
+
+ return;
}
/*
- * Reports whether the current PHY temperature is over
- * the overtemp threshold.
- * - This is reported directly from the PHY
- */
-static int
-ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS)
+** Note: this routine updates the OS on the link state
+** the real check of the hardware only happens with
+** a link interrupt.
+*/
+static void
+ixgbe_if_update_admin_status(if_ctx_t ctx)
{
- struct adapter *adapter = (struct adapter *) arg1;
+ struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- u16 reg;
+ device_t dev = iflib_get_dev(ctx);
- if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
- device_printf(adapter->dev,
- "Device has no supported external thermal sensor.\n");
- return (ENODEV);
- }
+ if (adapter->link_up) {
+ if (adapter->link_active == FALSE) {
+ if (bootverbose)
+ device_printf(dev, "Link is up %d Gbps %s \n",
+ ((adapter->link_speed == 128) ? 10 : 1),
+ "Full Duplex");
+ adapter->link_active = TRUE;
+ /* Update any Flow Control changes */
+ ixgbe_fc_enable(hw);
+ /* Update DMA coalescing config */
+ ixgbe_config_dmac(adapter);
+ /* should actually be negotiated value */
+ iflib_link_state_change(ctx, LINK_STATE_UP, IF_Gbps(10));
- if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
- &reg)) {
- device_printf(adapter->dev,
- "Error reading from PHY's temperature status register\n");
- return (EAGAIN);
+ if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
+ ixgbe_ping_all_vfs(adapter);
+ }
+ } else { /* Link down */
+ if (adapter->link_active == TRUE) {
+ if (bootverbose)
+ device_printf(dev, "Link is Down\n");
+ iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
+ adapter->link_active = FALSE;
+ if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
+ ixgbe_ping_all_vfs(adapter);
+ }
}
-
- /* Get occurrence bit */
- reg = !!(reg & 0x4000);
- return (sysctl_handle_int(oidp, 0, reg, req));
+ /* Re-enable link interrupts */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
}
-/*
-** Thermal Shutdown Trigger (internal MAC)
-** - Set this to 1 to cause an overtemp event to occur
-*/
-static int
-ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS)
+
+/*********************************************************************
+ *
+ * Configure DMA Coalescing
+ *
+ **********************************************************************/
+static void
+ixgbe_config_dmac(struct adapter *adapter)
{
- struct adapter *adapter = (struct adapter *) arg1;
struct ixgbe_hw *hw = &adapter->hw;
- int error, fire = 0;
+ struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
- error = sysctl_handle_int(oidp, &fire, 0, req);
- if ((error) || (req->newptr == NULL))
- return (error);
+ if (hw->mac.type < ixgbe_mac_X550 ||
+ !hw->mac.ops.dmac_config)
+ return;
- if (fire) {
- u32 reg = IXGBE_READ_REG(hw, IXGBE_EICS);
- reg |= IXGBE_EICR_TS;
- IXGBE_WRITE_REG(hw, IXGBE_EICS, reg);
- }
+ if (dcfg->watchdog_timer ^ adapter->dmac ||
+ dcfg->link_speed ^ adapter->link_speed) {
+ dcfg->watchdog_timer = adapter->dmac;
+ dcfg->fcoe_en = FALSE;
+ dcfg->link_speed = adapter->link_speed;
+ dcfg->num_tcs = 1;
- return (0);
+ INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n",
+ dcfg->watchdog_timer, dcfg->link_speed);
+
+ hw->mac.ops.dmac_config(hw);
+ }
}
-/*
-** Manage DMA Coalescing.
-** Control values:
-** 0/1 - off / on (use default value of 1000)
-**
-** Legal timer values are:
-** 50,100,250,500,1000,2000,5000,10000
-**
-** Turning off interrupt moderation will also turn this off.
-*/
-static int
-ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
+void
+ixgbe_if_enable_intr(if_ctx_t ctx)
{
- struct adapter *adapter = (struct adapter *) arg1;
- struct ifnet *ifp = adapter->ifp;
- int error;
- u32 newval;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ix_rx_queue *que = adapter->rx_queues;
+ u32 mask, fwsm;
- newval = adapter->dmac;
- error = sysctl_handle_int(oidp, &newval, 0, req);
- if ((error) || (req->newptr == NULL))
- return (error);
+ mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
- switch (newval) {
- case 0:
- /* Disabled */
- adapter->dmac = 0;
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ mask |= IXGBE_EIMS_ECC;
+ /* Temperature sensor on some adapters */
+ mask |= IXGBE_EIMS_GPI_SDP0;
+ /* SFP+ (RX_LOS_N & MOD_ABS_N) */
+ mask |= IXGBE_EIMS_GPI_SDP1;
+ mask |= IXGBE_EIMS_GPI_SDP2;
break;
- case 1:
- /* Enable and use default */
- adapter->dmac = 1000;
+ case ixgbe_mac_X540:
+ /* Detect if Thermal Sensor is enabled */
+ fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+ if (fwsm & IXGBE_FWSM_TS_ENABLED)
+ mask |= IXGBE_EIMS_TS;
+ mask |= IXGBE_EIMS_ECC;
break;
- case 50:
- case 100:
- case 250:
- case 500:
- case 1000:
- case 2000:
- case 5000:
- case 10000:
- /* Legal values - allow */
- adapter->dmac = newval;
+ case ixgbe_mac_X550:
+ /* MAC thermal sensor is automatically enabled */
+ mask |= IXGBE_EIMS_TS;
+ mask |= IXGBE_EIMS_ECC;
+ break;
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ /* Some devices use SDP0 for important information */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
+ hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP ||
+ hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N ||
+ hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
+ mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
+ if (hw->phy.type == ixgbe_phy_x550em_ext_t)
+ mask |= IXGBE_EICR_GPI_SDP0_X540;
+ mask |= IXGBE_EIMS_ECC;
break;
default:
- /* Do nothing, illegal value */
- return (EINVAL);
+ break;
}
- /* Re-initialize hardware if it's already running */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixgbe_init(adapter);
-
- return (0);
-}
+ /* Enable Fan Failure detection */
+ if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
+ mask |= IXGBE_EIMS_GPI_SDP1;
+ /* Enable SR-IOV */
+ if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
+ mask |= IXGBE_EIMS_MAILBOX;
+ /* Enable Flow Director */
+ if (adapter->feat_en & IXGBE_FEATURE_FDIR)
+ mask |= IXGBE_EIMS_FLOW_DIR;
-#ifdef IXGBE_DEBUG
-/**
- * Sysctl to test power states
- * Values:
- * 0 - set device to D0
- * 3 - set device to D3
- * (none) - get current device power state
- */
-static int
-ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS)
-{
- struct adapter *adapter = (struct adapter *) arg1;
- device_t dev = adapter->dev;
- int curr_ps, new_ps, error = 0;
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
- curr_ps = new_ps = pci_get_powerstate(dev);
+ /* With MSI-X we use auto clear */
+ if (adapter->intr_type == IFLIB_INTR_MSIX) {
+ mask = IXGBE_EIMS_ENABLE_MASK;
+ /* Don't autoclear Link */
+ mask &= ~IXGBE_EIMS_OTHER;
+ mask &= ~IXGBE_EIMS_LSC;
+ if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
+ mask &= ~IXGBE_EIMS_MAILBOX;
+ IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
+ }
- error = sysctl_handle_int(oidp, &new_ps, 0, req);
- if ((error) || (req->newptr == NULL))
- return (error);
+ /*
+ * Now enable all queues, this is done separately to
+ * allow for handling the extended (beyond 32) MSIX
+ * vectors that can be used by 82599
+ */
+ for (int i = 0; i < adapter->num_rx_queues; i++, que++)
+ ixgbe_enable_queue(adapter, que->msix);
- if (new_ps == curr_ps)
- return (0);
+ IXGBE_WRITE_FLUSH(hw);
+}
- if (new_ps == 3 && curr_ps == 0)
- error = DEVICE_SUSPEND(dev);
- else if (new_ps == 0 && curr_ps == 3)
- error = DEVICE_RESUME(dev);
- else
- return (EINVAL);
+static void
+ixgbe_if_disable_intr(if_ctx_t ctx)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if (adapter->intr_type == IFLIB_INTR_MSIX)
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+ } else {
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
+ }
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+}
- device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
- return (error);
-}
-#endif
-/*
- * Sysctl to enable/disable the WoL capability, if supported by the adapter.
- * Values:
- * 0 - disabled
- * 1 - enabled
- */
static int
-ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS)
+ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
{
- struct adapter *adapter = (struct adapter *) arg1;
- struct ixgbe_hw *hw = &adapter->hw;
- int new_wol_enabled;
- int error = 0;
-
- new_wol_enabled = hw->wol_enabled;
- error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req);
- if ((error) || (req->newptr == NULL))
- return (error);
- new_wol_enabled = !!(new_wol_enabled);
- if (new_wol_enabled == hw->wol_enabled)
- return (0);
-
- if (new_wol_enabled > 0 && !adapter->wol_support)
- return (ENODEV);
- else
- hw->wol_enabled = new_wol_enabled;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_rx_queue *que = &adapter->rx_queues[rxqid];
+ ixgbe_enable_queue(adapter, que->rxr.me);
return (0);
}
/*
- * Sysctl to enable/disable the Energy Efficient Ethernet capability,
- * if supported by the adapter.
- * Values:
- * 0 - disabled
- * 1 - enabled
- */
-static int
-ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS)
+**
+** MSIX Interrupt Handlers and Tasklets
+**
+*/
+
+static void
+ixgbe_enable_queue(struct adapter *adapter, u32 vector)
{
- struct adapter *adapter = (struct adapter *) arg1;
struct ixgbe_hw *hw = &adapter->hw;
- struct ifnet *ifp = adapter->ifp;
- int new_eee_enabled, error = 0;
-
- new_eee_enabled = adapter->eee_enabled;
- error = sysctl_handle_int(oidp, &new_eee_enabled, 0, req);
- if ((error) || (req->newptr == NULL))
- return (error);
- new_eee_enabled = !!(new_eee_enabled);
- if (new_eee_enabled == adapter->eee_enabled)
- return (0);
-
- if (new_eee_enabled > 0 && !hw->mac.ops.setup_eee)
- return (ENODEV);
- else
- adapter->eee_enabled = new_eee_enabled;
-
- /* Re-initialize hardware if it's already running */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixgbe_init(adapter);
+ u64 queue = (u64)(1 << vector);
+ u32 mask;
- return (0);
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ mask = (IXGBE_EIMS_RTX_QUEUE & queue);
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
+ } else {
+ mask = (queue & 0xFFFFFFFF);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
+ mask = (queue >> 32);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
+ }
}
-/*
- * Read-only sysctl indicating whether EEE support was negotiated
- * on the link.
- */
-static int
-ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS)
+static void
+ixgbe_disable_queue(struct adapter *adapter, u32 vector)
{
- struct adapter *adapter = (struct adapter *) arg1;
struct ixgbe_hw *hw = &adapter->hw;
- bool status;
-
- status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) & IXGBE_EEE_STAT_NEG);
+ u64 queue = (u64)(1 << vector);
+ u32 mask;
- return (sysctl_handle_int(oidp, 0, status, req));
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ mask = (IXGBE_EIMS_RTX_QUEUE & queue);
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
+ } else {
+ mask = (queue & 0xFFFFFFFF);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
+ mask = (queue >> 32);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
+ }
}
-/*
- * Read-only sysctl indicating whether RX Link is in LPI state.
- */
-static int
-ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS)
+
+/*********************************************************************
+ *
+ * Legacy Interrupt Service routine
+ *
+ **********************************************************************/
+int
+ixgbe_intr(void *arg)
{
- struct adapter *adapter = (struct adapter *) arg1;
+ struct adapter *adapter = arg;
+ struct ix_rx_queue *que = adapter->rx_queues;
struct ixgbe_hw *hw = &adapter->hw;
- bool status;
+ if_ctx_t ctx = adapter->ctx;
+ u32 reg_eicr;
- status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) &
- IXGBE_EEE_RX_LPI_STATUS);
+ reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
- return (sysctl_handle_int(oidp, 0, status, req));
-}
+ ++que->irqs;
+ if (reg_eicr == 0) {
+ ixgbe_if_enable_intr(ctx);
+ return (FILTER_HANDLED);
+ }
-/*
- * Read-only sysctl indicating whether TX Link is in LPI state.
- */
-static int
-ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS)
-{
- struct adapter *adapter = (struct adapter *) arg1;
- struct ixgbe_hw *hw = &adapter->hw;
- bool status;
+ /* Check for fan failure */
+ if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
+ (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
+ device_printf(adapter->dev,
+ "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
+ }
- status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) &
- IXGBE_EEE_TX_LPI_STATUS);
+ /* Link status change */
+ if (reg_eicr & IXGBE_EICR_LSC) {
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
+ iflib_admin_intr_deferred(ctx);
+ }
+ /* External PHY interrupt */
+ if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
+ (reg_eicr & IXGBE_EICR_GPI_SDP0_X540)) {
+ GROUPTASK_ENQUEUE(&adapter->phy_task);
+ }
- return (sysctl_handle_int(oidp, 0, status, req));
+ return (FILTER_SCHEDULE_THREAD);
}
-/*
- * Read-only sysctl indicating TX Link LPI delay
- */
-static int
-ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS)
+static void
+ixgbe_free_pci_resources(if_ctx_t ctx)
{
- struct adapter *adapter = (struct adapter *) arg1;
- struct ixgbe_hw *hw = &adapter->hw;
- u32 reg;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_rx_queue *que = adapter->rx_queues;
+ device_t dev = iflib_get_dev(ctx);
- reg = IXGBE_READ_REG(hw, IXGBE_EEE_SU);
+ /* Release all msix queue resources */
+ if (adapter->intr_type == IFLIB_INTR_MSIX)
+ iflib_irq_free(ctx, &adapter->irq);
- return (sysctl_handle_int(oidp, 0, reg >> 26, req));
+ if (que != NULL) {
+ for (int i = 0; i < adapter->num_rx_queues; i++, que++) {
+ iflib_irq_free(ctx, &que->que_irq);
+ }
+ }
+
+ /*
+ * Free link/admin interrupt
+ */
+ if (adapter->pci_mem != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ PCIR_BAR(0), adapter->pci_mem);
+}
+
+static void
+ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
+ const char *description, int *limit, int value)
+{
+ *limit = value;
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
+ OID_AUTO, name, CTLFLAG_RW, limit, value, description);
}
+/* Sysctls */
/*
- * Sysctl to enable/disable the types of packets that the
- * adapter will wake up on upon receipt.
- * WUFC - Wake Up Filter Control
- * Flags:
- * 0x1 - Link Status Change
- * 0x2 - Magic Packet
- * 0x4 - Direct Exact
- * 0x8 - Directed Multicast
- * 0x10 - Broadcast
- * 0x20 - ARP/IPv4 Request Packet
- * 0x40 - Direct IPv4 Packet
- * 0x80 - Direct IPv6 Packet
- *
- * Setting another flag will cause the sysctl to return an
- * error.
- */
+** Set flow control using sysctl:
+** Flow control values:
+** 0 - off
+** 1 - rx pause
+** 2 - tx pause
+** 3 - full
+*/
static int
-ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS)
+ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS)
{
- struct adapter *adapter = (struct adapter *) arg1;
- int error = 0;
- u32 new_wufc;
+ struct adapter *adapter;
+ int error, fc;
- new_wufc = adapter->wufc;
+ adapter = (struct adapter *)arg1;
+ fc = adapter->hw.fc.current_mode;
- error = sysctl_handle_int(oidp, &new_wufc, 0, req);
+ error = sysctl_handle_int(oidp, &fc, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
- if (new_wufc == adapter->wufc)
- return (0);
- if (new_wufc & 0xffffff00)
- return (EINVAL);
- else {
- new_wufc &= 0xff;
- new_wufc |= (0xffffff & adapter->wufc);
- adapter->wufc = new_wufc;
- }
+ /* Don't bother if it's not changed */
+ if (fc == adapter->hw.fc.current_mode)
+ return (0);
- return (0);
+ return ixgbe_set_flowcntl(adapter, fc);
}
-#ifdef IXGBE_DEBUG
static int
-ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS)
+ixgbe_set_flowcntl(struct adapter *adapter, int fc)
{
- struct adapter *adapter = (struct adapter *)arg1;
- struct ixgbe_hw *hw = &adapter->hw;
- device_t dev = adapter->dev;
- int error = 0, reta_size;
- struct sbuf *buf;
- u32 reg;
-
- buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
- if (!buf) {
- device_printf(dev, "Could not allocate sbuf for output.\n");
- return (ENOMEM);
- }
-
- // TODO: use sbufs to make a string to print out
- /* Set multiplier for RETA setup and table size based on MAC */
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- reta_size = 128;
+ switch (fc) {
+ case ixgbe_fc_rx_pause:
+ case ixgbe_fc_tx_pause:
+ case ixgbe_fc_full:
+ adapter->hw.fc.requested_mode = fc;
+ if (adapter->num_rx_queues > 1)
+ ixgbe_disable_rx_drop(adapter);
break;
- default:
- reta_size = 32;
+ case ixgbe_fc_none:
+ adapter->hw.fc.requested_mode = ixgbe_fc_none;
+ if (adapter->num_rx_queues > 1)
+ ixgbe_enable_rx_drop(adapter);
break;
+ default:
+ return (EINVAL);
}
- /* Print out the redirection table */
- sbuf_cat(buf, "\n");
- for (int i = 0; i < reta_size; i++) {
- if (i < 32) {
- reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
- sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
- } else {
- reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
- sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
- }
- }
-
- // TODO: print more config
-
- error = sbuf_finish(buf);
- if (error)
- device_printf(dev, "Error finishing sbuf: %d\n", error);
+ /* Don't autoneg if forcing a value */
+ adapter->hw.fc.disable_fc_autoneg = TRUE;
+ ixgbe_fc_enable(&adapter->hw);
- sbuf_delete(buf);
return (0);
}
-#endif /* IXGBE_DEBUG */
/*
** Enable the hardware to drop packets when the buffer is
** full. This is useful when multiqueue,so that no single
** queue being full stalls the entire RX engine. We only
-** enable this when Multiqueue AND when Flow Control is
+** enable this when Multiqueue AND when Flow Control is
** disabled.
*/
static void
ixgbe_enable_rx_drop(struct adapter *adapter)
{
- struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_hw *hw = &adapter->hw;
- for (int i = 0; i < adapter->num_queues; i++) {
- struct rx_ring *rxr = &adapter->rx_rings[i];
- u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
- srrctl |= IXGBE_SRRCTL_DROP_EN;
- IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
+ for (int i = 0; i < adapter->num_rx_queues; i++) {
+ struct rx_ring *rxr = &adapter->rx_queues[i].rxr;
+ u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
+ srrctl |= IXGBE_SRRCTL_DROP_EN;
+ IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
}
-#ifdef PCI_IOV
+
/* enable drop for each vf */
for (int i = 0; i < adapter->num_vfs; i++) {
IXGBE_WRITE_REG(hw, IXGBE_QDE,
- (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) |
- IXGBE_QDE_ENABLE));
+ (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) |
+ IXGBE_QDE_ENABLE));
}
-#endif
}
static void
ixgbe_disable_rx_drop(struct adapter *adapter)
{
- struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_hw *hw = &adapter->hw;
- for (int i = 0; i < adapter->num_queues; i++) {
- struct rx_ring *rxr = &adapter->rx_rings[i];
- u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
- srrctl &= ~IXGBE_SRRCTL_DROP_EN;
- IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
+ for (int i = 0; i < adapter->num_rx_queues; i++) {
+ struct rx_ring *rxr = &adapter->rx_queues[i].rxr;
+ u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
+ srrctl &= ~IXGBE_SRRCTL_DROP_EN;
+ IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
}
-#ifdef PCI_IOV
+
/* disable drop for each vf */
for (int i = 0; i < adapter->num_vfs; i++) {
IXGBE_WRITE_REG(hw, IXGBE_QDE,
- (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT)));
+ (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT)));
}
-#endif
}
-static void
-ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
+/************************************************************************
+ * ixgbe_sysctl_advertise
+ *
+ * SYSCTL wrapper around setting advertised speed
+ ************************************************************************/
+static int
+ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
{
- u32 mask;
+ int error, advertise;
+ struct adapter *adapter;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82598EB:
- mask = (IXGBE_EIMS_RTX_QUEUE & queues);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
- break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- mask = (queues & 0xFFFFFFFF);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
- mask = (queues >> 32);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
- break;
- default:
- break;
- }
-}
+ adapter = (struct adapter *)arg1;
+ advertise = adapter->advertise;
-#ifdef PCI_IOV
+ error = sysctl_handle_int(oidp, &advertise, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
-/*
-** Support functions for SRIOV/VF management
-*/
+ return ixgbe_set_advertise(adapter, advertise);
+}
-static void
-ixgbe_ping_all_vfs(struct adapter *adapter)
+/************************************************************************
+ * ixgbe_set_advertise - Control advertised link speed
+ *
+ * Flags:
+ * 0x1 - advertise 100 Mb
+ * 0x2 - advertise 1G
+ * 0x4 - advertise 10G
+ * 0x8 - advertise 10 Mb (yes, Mb)
+ ************************************************************************/
+static int
+ixgbe_set_advertise(struct adapter *adapter, int advertise)
{
- struct ixgbe_vf *vf;
+ device_t dev = iflib_get_dev(adapter->ctx);
+ struct ixgbe_hw *hw;
+ ixgbe_link_speed speed = 0;
+ ixgbe_link_speed link_caps = 0;
+ s32 err = IXGBE_NOT_IMPLEMENTED;
+ bool negotiate = FALSE;
+
+ /* Checks to validate new value */
+ if (adapter->advertise == advertise) /* no change */
+ return (0);
+
+ hw = &adapter->hw;
+
+ /* No speed changes for backplane media */
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ return (ENODEV);
+
+ if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
+ (hw->phy.multispeed_fiber))) {
+ device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n");
+ return (EINVAL);
+ }
+
+ if (advertise < 0x1 || advertise > 0xF) {
+ device_printf(dev, "Invalid advertised speed; valid modes are 0x1 through 0xF\n");
+ return (EINVAL);
+ }
+
+ if (hw->mac.ops.get_link_capabilities) {
+ err = hw->mac.ops.get_link_capabilities(hw, &link_caps,
+ &negotiate);
+ if (err != IXGBE_SUCCESS) {
+ device_printf(dev, "Unable to determine supported advertise speeds\n");
+ return (ENODEV);
+ }
+ }
+
+ /* Set new value and report new advertised mode */
+ if (advertise & 0x1) {
+ if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) {
+ device_printf(dev, "Interface does not support 100Mb advertised speed\n");
+ return (EINVAL);
+ }
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ }
+ if (advertise & 0x2) {
+ if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) {
+ device_printf(dev, "Interface does not support 1Gb advertised speed\n");
+ return (EINVAL);
+ }
+ speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ }
+ if (advertise & 0x4) {
+ if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) {
+ device_printf(dev, "Interface does not support 10Gb advertised speed\n");
+ return (EINVAL);
+ }
+ speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ }
+ if (advertise & 0x8) {
+ if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) {
+ device_printf(dev, "Interface does not support 10Mb advertised speed\n");
+ return (EINVAL);
+ }
+ speed |= IXGBE_LINK_SPEED_10_FULL;
+ }
+
+ hw->mac.autotry_restart = TRUE;
+ hw->mac.ops.setup_link(hw, speed, TRUE);
+ adapter->advertise = advertise;
- for (int i = 0; i < adapter->num_vfs; i++) {
- vf = &adapter->vfs[i];
- if (vf->flags & IXGBE_VF_ACTIVE)
- ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG);
- }
+ return (0);
}
-
-static void
-ixgbe_vf_set_default_vlan(struct adapter *adapter, struct ixgbe_vf *vf,
- uint16_t tag)
+/** Thermal Shutdown Trigger (internal MAC)
+ ** - Set this to 1 to cause an overtemp event to occur
+ */
+static int
+ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS)
{
- struct ixgbe_hw *hw;
- uint32_t vmolr, vmvir;
-
- hw = &adapter->hw;
-
- vf->vlan_tag = tag;
-
- vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf->pool));
-
- /* Do not receive packets that pass inexact filters. */
- vmolr &= ~(IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE);
-
- /* Disable Multicast Promicuous Mode. */
- vmolr &= ~IXGBE_VMOLR_MPE;
-
- /* Accept broadcasts. */
- vmolr |= IXGBE_VMOLR_BAM;
-
- if (tag == 0) {
- /* Accept non-vlan tagged traffic. */
- //vmolr |= IXGBE_VMOLR_AUPE;
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int error, fire = 0;
- /* Allow VM to tag outgoing traffic; no default tag. */
- vmvir = 0;
- } else {
- /* Require vlan-tagged traffic. */
- vmolr &= ~IXGBE_VMOLR_AUPE;
+ error = sysctl_handle_int(oidp, &fire, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
- /* Tag all traffic with provided vlan tag. */
- vmvir = (tag | IXGBE_VMVIR_VLANA_DEFAULT);
+ if (fire) {
+ printf("Warning: Thermal Shutdown trigger\n");
+ u32 reg = IXGBE_READ_REG(hw, IXGBE_EICS);
+ reg |= IXGBE_EICR_TS;
+ IXGBE_WRITE_REG(hw, IXGBE_EICS, reg);
}
- IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf->pool), vmolr);
- IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf->pool), vmvir);
-}
+ return (0);
+}
-static boolean_t
-ixgbe_vf_frame_size_compatible(struct adapter *adapter, struct ixgbe_vf *vf)
+/* Manage DMA Coalescing.
+** Control values:
+** 0/1 - off / on (use default value of 1000)
+**
+** Legal timer values are:
+** 50,100,250,500,1000,2000,5000,10000
+**
+** Turning off interrupt moderation will also turn this off.
+*/
+static int
+ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
{
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ifnet *ifp = iflib_get_ifp(adapter->ctx);
+ int error;
+ u16 newval;
- /*
- * Frame size compatibility between PF and VF is only a problem on
- * 82599-based cards. X540 and later support any combination of jumbo
- * frames on PFs and VFs.
- */
- if (adapter->hw.mac.type != ixgbe_mac_82599EB)
- return (TRUE);
-
- switch (vf->api_ver) {
- case IXGBE_API_VER_1_0:
- case IXGBE_API_VER_UNKNOWN:
- /*
- * On legacy (1.0 and older) VF versions, we don't support jumbo
- * frames on either the PF or the VF.
- */
- if (adapter->max_frame_size > ETHER_MAX_LEN ||
- vf->max_frame_size > ETHER_MAX_LEN)
- return (FALSE);
-
- return (TRUE);
+ newval = adapter->dmac;
+ error = sysctl_handle_int(oidp, &newval, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+ switch (newval) {
+ case 0:
+ /* Disabled */
+ adapter->dmac = 0;
+ break;
+ case 1: /* Enable and use default */
+ adapter->dmac = 1000;
+ break;
+ case 50:
+ case 100:
+ case 250:
+ case 500:
+ case 1000:
+ case 2000:
+ case 5000:
+ case 10000:
+ /* Legal values - allow */
+ adapter->dmac = newval;
break;
- case IXGBE_API_VER_1_1:
default:
- /*
- * 1.1 or later VF versions always work if they aren't using
- * jumbo frames.
- */
- if (vf->max_frame_size <= ETHER_MAX_LEN)
- return (TRUE);
+ /* Do nothing, illegal value */
+ return (EINVAL);
+ }
- /*
- * Jumbo frames only work with VFs if the PF is also using jumbo
- * frames.
- */
- if (adapter->max_frame_size <= ETHER_MAX_LEN)
- return (TRUE);
+ /* Re-initialize hardware if it's already running */
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ifp->if_init(ifp);
- return (FALSE);
-
- }
+ return (0);
}
-
-static void
-ixgbe_process_vf_reset(struct adapter *adapter, struct ixgbe_vf *vf)
+#ifdef IXGBE_DEBUG
+/**
+ * Sysctl to test power states
+ * Values:
+ * 0 - set device to D0
+ * 3 - set device to D3
+ * (none) - get current device power state
+ */
+static int
+ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS)
{
- ixgbe_vf_set_default_vlan(adapter, vf, vf->default_vlan);
-
- // XXX clear multicast addresses
+ struct adapter *adapter = (struct adapter *)arg1;
+ device_t dev = adapter->dev;
+ int curr_ps, new_ps, error = 0;
- ixgbe_clear_rar(&adapter->hw, vf->rar_index);
+ curr_ps = new_ps = pci_get_powerstate(dev);
- vf->api_ver = IXGBE_API_VER_UNKNOWN;
-}
+ error = sysctl_handle_int(oidp, &new_ps, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+ if (new_ps == curr_ps)
+ return (0);
-static void
-ixgbe_vf_enable_transmit(struct adapter *adapter, struct ixgbe_vf *vf)
-{
- struct ixgbe_hw *hw;
- uint32_t vf_index, vfte;
+ if (new_ps == 3 && curr_ps == 0)
+ error = DEVICE_SUSPEND(dev);
+ else if (new_ps == 0 && curr_ps == 3)
+ error = DEVICE_RESUME(dev);
+ else
+ return (EINVAL);
- hw = &adapter->hw;
+ device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
- vf_index = IXGBE_VF_INDEX(vf->pool);
- vfte = IXGBE_READ_REG(hw, IXGBE_VFTE(vf_index));
- vfte |= IXGBE_VF_BIT(vf->pool);
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_index), vfte);
+ return (error);
}
+#endif
-
-static void
-ixgbe_vf_enable_receive(struct adapter *adapter, struct ixgbe_vf *vf)
+/*
+ * Sysctl to enable/disable the WoL capability, if supported by the adapter.
+ * Values:
+ * 0 - disabled
+ * 1 - enabled
+ */
+static int
+ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS)
{
- struct ixgbe_hw *hw;
- uint32_t vf_index, vfre;
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ int new_wol_enabled;
+ int error = 0;
- hw = &adapter->hw;
-
- vf_index = IXGBE_VF_INDEX(vf->pool);
- vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(vf_index));
- if (ixgbe_vf_frame_size_compatible(adapter, vf))
- vfre |= IXGBE_VF_BIT(vf->pool);
+ new_wol_enabled = hw->wol_enabled;
+ error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+ if (new_wol_enabled == hw->wol_enabled)
+ return (0);
+
+ new_wol_enabled = !!(new_wol_enabled);
+ if (new_wol_enabled > 0 && !adapter->wol_support)
+ return (ENODEV);
else
- vfre &= ~IXGBE_VF_BIT(vf->pool);
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_index), vfre);
-}
+ hw->wol_enabled = new_wol_enabled;
+ return (0);
+}
-static void
-ixgbe_vf_reset_msg(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+/*
+ * Read-only sysctl indicating whether EEE support was negotiated
+ * on the link.
+ */
+static int
+ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS)
{
- struct ixgbe_hw *hw;
- uint32_t ack;
- uint32_t resp[IXGBE_VF_PERMADDR_MSG_LEN];
-
- hw = &adapter->hw;
-
- ixgbe_process_vf_reset(adapter, vf);
-
- if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
- ixgbe_set_rar(&adapter->hw, vf->rar_index,
- vf->ether_addr, vf->pool, TRUE);
- ack = IXGBE_VT_MSGTYPE_ACK;
- } else
- ack = IXGBE_VT_MSGTYPE_NACK;
-
- ixgbe_vf_enable_transmit(adapter, vf);
- ixgbe_vf_enable_receive(adapter, vf);
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ bool status;
- vf->flags |= IXGBE_VF_CTS;
+ status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) & IXGBE_EEE_STAT_NEG);
- resp[0] = IXGBE_VF_RESET | ack | IXGBE_VT_MSGTYPE_CTS;
- bcopy(vf->ether_addr, &resp[1], ETHER_ADDR_LEN);
- resp[3] = hw->mac.mc_filter_type;
- ixgbe_write_mbx(hw, resp, IXGBE_VF_PERMADDR_MSG_LEN, vf->pool);
+ return (sysctl_handle_int(oidp, 0, status, req));
}
-
-static void
-ixgbe_vf_set_mac(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+/*
+ * Read-only sysctl indicating whether RX Link is in LPI state.
+ */
+static int
+ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS)
{
- uint8_t *mac;
-
- mac = (uint8_t*)&msg[1];
-
- /* Check that the VF has permission to change the MAC address. */
- if (!(vf->flags & IXGBE_VF_CAP_MAC) && ixgbe_vf_mac_changed(vf, mac)) {
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
- return;
- }
-
- if (ixgbe_validate_mac_addr(mac) != 0) {
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
- return;
- }
-
- bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN);
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ bool status;
- ixgbe_set_rar(&adapter->hw, vf->rar_index, vf->ether_addr,
- vf->pool, TRUE);
+ status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) &
+ IXGBE_EEE_RX_LPI_STATUS);
- ixgbe_send_vf_ack(adapter, vf, msg[0]);
+ return (sysctl_handle_int(oidp, 0, status, req));
}
-
/*
-** VF multicast addresses are set by using the appropriate bit in
-** 1 of 128 32 bit addresses (4096 possible).
-*/
-static void
-ixgbe_vf_set_mc_addr(struct adapter *adapter, struct ixgbe_vf *vf, u32 *msg)
-{
- u16 *list = (u16*)&msg[1];
- int entries;
- u32 vmolr, vec_bit, vec_reg, mta_reg;
-
- entries = (msg[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
- entries = min(entries, IXGBE_MAX_VF_MC);
-
- vmolr = IXGBE_READ_REG(&adapter->hw, IXGBE_VMOLR(vf->pool));
-
- vf->num_mc_hashes = entries;
-
- /* Set the appropriate MTA bit */
- for (int i = 0; i < entries; i++) {
- vf->mc_hash[i] = list[i];
- vec_reg = (vf->mc_hash[i] >> 5) & 0x7F;
- vec_bit = vf->mc_hash[i] & 0x1F;
- mta_reg = IXGBE_READ_REG(&adapter->hw, IXGBE_MTA(vec_reg));
- mta_reg |= (1 << vec_bit);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_MTA(vec_reg), mta_reg);
- }
-
- vmolr |= IXGBE_VMOLR_ROMPE;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_VMOLR(vf->pool), vmolr);
- ixgbe_send_vf_ack(adapter, vf, msg[0]);
- return;
-}
-
-
-static void
-ixgbe_vf_set_vlan(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+ * Read-only sysctl indicating whether TX Link is in LPI state.
+ */
+static int
+ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS)
{
- struct ixgbe_hw *hw;
- int enable;
- uint16_t tag;
-
- hw = &adapter->hw;
- enable = IXGBE_VT_MSGINFO(msg[0]);
- tag = msg[1] & IXGBE_VLVF_VLANID_MASK;
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ bool status;
- if (!(vf->flags & IXGBE_VF_CAP_VLAN)) {
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
- return;
- }
+ status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) &
+ IXGBE_EEE_TX_LPI_STATUS);
- /* It is illegal to enable vlan tag 0. */
- if (tag == 0 && enable != 0){
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
- return;
- }
-
- ixgbe_set_vfta(hw, tag, vf->pool, enable);
- ixgbe_send_vf_ack(adapter, vf, msg[0]);
+ return (sysctl_handle_int(oidp, 0, status, req));
}
-
-static void
-ixgbe_vf_set_lpe(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+/*
+ * Read-only sysctl indicating TX Link LPI delay
+ */
+static int
+ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS)
{
- struct ixgbe_hw *hw;
- uint32_t vf_max_size, pf_max_size, mhadd;
-
- hw = &adapter->hw;
- vf_max_size = msg[1];
-
- if (vf_max_size < ETHER_CRC_LEN) {
- /* We intentionally ACK invalid LPE requests. */
- ixgbe_send_vf_ack(adapter, vf, msg[0]);
- return;
- }
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reg;
- vf_max_size -= ETHER_CRC_LEN;
+ reg = IXGBE_READ_REG(hw, IXGBE_EEE_SU);
- if (vf_max_size > IXGBE_MAX_FRAME_SIZE) {
- /* We intentionally ACK invalid LPE requests. */
- ixgbe_send_vf_ack(adapter, vf, msg[0]);
- return;
- }
+ return (sysctl_handle_int(oidp, 0, reg >> 26, req));
+}
- vf->max_frame_size = vf_max_size;
- ixgbe_update_max_frame(adapter, vf->max_frame_size);
+/*
+ * Sysctl to enable/disable the types of packets that the
+ * adapter will wake up on upon receipt.
+ * WUFC - Wake Up Filter Control
+ * Flags:
+ * 0x1 - Link Status Change
+ * 0x2 - Magic Packet
+ * 0x4 - Direct Exact
+ * 0x8 - Directed Multicast
+ * 0x10 - Broadcast
+ * 0x20 - ARP/IPv4 Request Packet
+ * 0x40 - Direct IPv4 Packet
+ * 0x80 - Direct IPv6 Packet
+ *
+ * Setting another flag will cause the sysctl to return an
+ * error.
+ */
+static int
+ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *)arg1;
+ int error = 0;
+ u32 new_wufc;
- /*
- * We might have to disable reception to this VF if the frame size is
- * not compatible with the config on the PF.
- */
- ixgbe_vf_enable_receive(adapter, vf);
+ new_wufc = adapter->wufc;
- mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
- pf_max_size = (mhadd & IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
+ error = sysctl_handle_int(oidp, &new_wufc, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+ if (new_wufc == adapter->wufc)
+ return (0);
- if (pf_max_size < adapter->max_frame_size) {
- mhadd &= ~IXGBE_MHADD_MFS_MASK;
- mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
- IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
+ if (new_wufc & 0xffffff00)
+ return (EINVAL);
+ else {
+ new_wufc &= 0xff;
+ new_wufc |= (0xffffff & adapter->wufc);
+ adapter->wufc = new_wufc;
}
- ixgbe_send_vf_ack(adapter, vf, msg[0]);
+ return (0);
}
-static void
-ixgbe_vf_set_macvlan(struct adapter *adapter, struct ixgbe_vf *vf,
- uint32_t *msg)
+#ifdef IXGBE_DEBUG
+static int
+ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS)
{
- //XXX implement this
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
-}
-
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ device_t dev = adapter->dev;
+ int error = 0, reta_size;
+ struct sbuf *buf;
+ u32 reg;
-static void
-ixgbe_vf_api_negotiate(struct adapter *adapter, struct ixgbe_vf *vf,
- uint32_t *msg)
-{
+ buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+ if (!buf) {
+ device_printf(dev, "Could not allocate sbuf for output.\n");
+ return (ENOMEM);
+ }
- switch (msg[1]) {
- case IXGBE_API_VER_1_0:
- case IXGBE_API_VER_1_1:
- vf->api_ver = msg[1];
- ixgbe_send_vf_ack(adapter, vf, msg[0]);
+ // TODO: use sbufs to make a string to print out
+ /* Set multiplier for RETA setup and table size based on MAC */
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ reta_size = 128;
break;
default:
- vf->api_ver = IXGBE_API_VER_UNKNOWN;
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ reta_size = 32;
break;
}
-}
-
-
-static void
-ixgbe_vf_get_queues(struct adapter *adapter, struct ixgbe_vf *vf,
- uint32_t *msg)
-{
- struct ixgbe_hw *hw;
- uint32_t resp[IXGBE_VF_GET_QUEUES_RESP_LEN];
- int num_queues;
-
- hw = &adapter->hw;
- /* GET_QUEUES is not supported on pre-1.1 APIs. */
- switch (msg[0]) {
- case IXGBE_API_VER_1_0:
- case IXGBE_API_VER_UNKNOWN:
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
- return;
+ /* Print out the redirection table */
+ sbuf_cat(buf, "\n");
+ for (int i = 0; i < reta_size; i++) {
+ if (i < 32) {
+ reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
+ sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
+ } else {
+ reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
+ sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
+ }
}
- resp[0] = IXGBE_VF_GET_QUEUES | IXGBE_VT_MSGTYPE_ACK |
- IXGBE_VT_MSGTYPE_CTS;
+ // TODO: print more config
- num_queues = ixgbe_vf_queues(ixgbe_get_iov_mode(adapter));
- resp[IXGBE_VF_TX_QUEUES] = num_queues;
- resp[IXGBE_VF_RX_QUEUES] = num_queues;
- resp[IXGBE_VF_TRANS_VLAN] = (vf->default_vlan != 0);
- resp[IXGBE_VF_DEF_QUEUE] = 0;
+ error = sbuf_finish(buf);
+ if (error)
+ device_printf(dev, "Error finishing sbuf: %d\n", error);
- ixgbe_write_mbx(hw, resp, IXGBE_VF_GET_QUEUES_RESP_LEN, vf->pool);
+ sbuf_delete(buf);
+ return (0);
}
+#endif /* IXGBE_DEBUG */
-
-static void
-ixgbe_process_vf_msg(struct adapter *adapter, struct ixgbe_vf *vf)
+/*
+ * The following two sysctls are for X550 BaseT devices;
+ * they deal with the external PHY used in them.
+ */
+static int
+ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS)
{
- struct ixgbe_hw *hw;
- uint32_t msg[IXGBE_VFMAILBOX_SIZE];
- int error;
-
- hw = &adapter->hw;
-
- error = ixgbe_read_mbx(hw, msg, IXGBE_VFMAILBOX_SIZE, vf->pool);
-
- if (error != 0)
- return;
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u16 reg;
- CTR3(KTR_MALLOC, "%s: received msg %x from %d",
- adapter->ifp->if_xname, msg[0], vf->pool);
- if (msg[0] == IXGBE_VF_RESET) {
- ixgbe_vf_reset_msg(adapter, vf, msg);
- return;
+ if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
+ device_printf(iflib_get_dev(adapter->ctx),
+ "Device has no supported external thermal sensor.\n");
+ return (ENODEV);
}
- if (!(vf->flags & IXGBE_VF_CTS)) {
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
- return;
+ if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
+ device_printf(iflib_get_dev(adapter->ctx),
+ "Error reading from PHY's current temperature register\n");
+ return (EAGAIN);
}
- switch (msg[0] & IXGBE_VT_MSG_MASK) {
- case IXGBE_VF_SET_MAC_ADDR:
- ixgbe_vf_set_mac(adapter, vf, msg);
- break;
- case IXGBE_VF_SET_MULTICAST:
- ixgbe_vf_set_mc_addr(adapter, vf, msg);
- break;
- case IXGBE_VF_SET_VLAN:
- ixgbe_vf_set_vlan(adapter, vf, msg);
- break;
- case IXGBE_VF_SET_LPE:
- ixgbe_vf_set_lpe(adapter, vf, msg);
- break;
- case IXGBE_VF_SET_MACVLAN:
- ixgbe_vf_set_macvlan(adapter, vf, msg);
- break;
- case IXGBE_VF_API_NEGOTIATE:
- ixgbe_vf_api_negotiate(adapter, vf, msg);
- break;
- case IXGBE_VF_GET_QUEUES:
- ixgbe_vf_get_queues(adapter, vf, msg);
- break;
- default:
- ixgbe_send_vf_nack(adapter, vf, msg[0]);
- }
-}
+ /* Shift temp for output */
+ reg = reg >> 8;
+ return (sysctl_handle_int(oidp, NULL, reg, req));
+}
/*
- * Tasklet for handling VF -> PF mailbox messages.
+ * Reports whether the current PHY temperature is over
+ * the overtemp threshold.
+ * - This is reported directly from the PHY
*/
-static void
-ixgbe_handle_mbx(void *context, int pending)
-{
- struct adapter *adapter;
- struct ixgbe_hw *hw;
- struct ixgbe_vf *vf;
- int i;
-
- adapter = context;
- hw = &adapter->hw;
-
- IXGBE_CORE_LOCK(adapter);
- for (i = 0; i < adapter->num_vfs; i++) {
- vf = &adapter->vfs[i];
-
- if (vf->flags & IXGBE_VF_ACTIVE) {
- if (ixgbe_check_for_rst(hw, vf->pool) == 0)
- ixgbe_process_vf_reset(adapter, vf);
-
- if (ixgbe_check_for_msg(hw, vf->pool) == 0)
- ixgbe_process_vf_msg(adapter, vf);
-
- if (ixgbe_check_for_ack(hw, vf->pool) == 0)
- ixgbe_process_vf_ack(adapter, vf);
- }
- }
- IXGBE_CORE_UNLOCK(adapter);
-}
-
-
static int
-ixgbe_init_iov(device_t dev, u16 num_vfs, const nvlist_t *config)
+ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS)
{
- struct adapter *adapter;
- enum ixgbe_iov_mode mode;
-
- adapter = device_get_softc(dev);
- adapter->num_vfs = num_vfs;
- mode = ixgbe_get_iov_mode(adapter);
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u16 reg;
- if (num_vfs > ixgbe_max_vfs(mode)) {
- adapter->num_vfs = 0;
- return (ENOSPC);
+ if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
+ device_printf(iflib_get_dev(adapter->ctx),
+ "Device has no supported external thermal sensor.\n");
+ return (ENODEV);
}
- IXGBE_CORE_LOCK(adapter);
-
- adapter->vfs = malloc(sizeof(*adapter->vfs) * num_vfs, M_IXGBE,
- M_NOWAIT | M_ZERO);
-
- if (adapter->vfs == NULL) {
- adapter->num_vfs = 0;
- IXGBE_CORE_UNLOCK(adapter);
- return (ENOMEM);
+ if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
+ device_printf(iflib_get_dev(adapter->ctx),
+ "Error reading from PHY's temperature status register\n");
+ return (EAGAIN);
}
- ixgbe_init_locked(adapter);
-
- IXGBE_CORE_UNLOCK(adapter);
-
- return (0);
+ /* Get occurrence bit */
+ reg = !!(reg & 0x4000);
+ return (sysctl_handle_int(oidp, 0, reg, req));
}
-
-static void
-ixgbe_uninit_iov(device_t dev)
+/*
+ * Sysctl to enable/disable the Energy Efficient Ethernet capability,
+ * if supported by the adapter.
+ * Values:
+ * 0 - disabled
+ * 1 - enabled
+ */
+static int
+ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS)
{
- struct ixgbe_hw *hw;
- struct adapter *adapter;
- uint32_t pf_reg, vf_reg;
-
- adapter = device_get_softc(dev);
- hw = &adapter->hw;
-
- IXGBE_CORE_LOCK(adapter);
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ifnet *ifp = iflib_get_ifp(adapter->ctx);
+ int new_eee_enabled, error = 0;
- /* Enable rx/tx for the PF and disable it for all VFs. */
- pf_reg = IXGBE_VF_INDEX(adapter->pool);
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(pf_reg),
- IXGBE_VF_BIT(adapter->pool));
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(pf_reg),
- IXGBE_VF_BIT(adapter->pool));
+ new_eee_enabled = adapter->eee_enabled;
+ error = sysctl_handle_int(oidp, &new_eee_enabled, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+ new_eee_enabled = !!(new_eee_enabled);
+ if (new_eee_enabled == adapter->eee_enabled)
+ return (0);
- if (pf_reg == 0)
- vf_reg = 1;
+ if (new_eee_enabled > 0 && !hw->mac.ops.setup_eee)
+ return (ENODEV);
else
- vf_reg = 0;
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg), 0);
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg), 0);
-
- IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, 0);
+ adapter->eee_enabled = new_eee_enabled;
- free(adapter->vfs, M_IXGBE);
- adapter->vfs = NULL;
- adapter->num_vfs = 0;
+ /* Re-initialize hardware if it's already running */
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ifp->if_init(ifp);
- IXGBE_CORE_UNLOCK(adapter);
+ return (0);
}
-
+/************************************************************************
+ * ixgbe_init_device_features
+ ************************************************************************/
static void
-ixgbe_initialize_iov(struct adapter *adapter)
+ixgbe_init_device_features(struct adapter *adapter)
{
- struct ixgbe_hw *hw = &adapter->hw;
- uint32_t mrqc, mtqc, vt_ctl, vf_reg, gcr_ext, gpie;
- enum ixgbe_iov_mode mode;
- int i;
-
- mode = ixgbe_get_iov_mode(adapter);
- if (mode == IXGBE_NO_VM)
- return;
-
- IXGBE_CORE_LOCK_ASSERT(adapter);
+ adapter->feat_cap = IXGBE_FEATURE_NETMAP
+ | IXGBE_FEATURE_RSS
+ | IXGBE_FEATURE_MSI
+ | IXGBE_FEATURE_MSIX
+ | IXGBE_FEATURE_LEGACY_IRQ;
- mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC);
- mrqc &= ~IXGBE_MRQC_MRQE_MASK;
-
- switch (mode) {
- case IXGBE_64_VM:
- mrqc |= IXGBE_MRQC_VMDQRSS64EN;
+ /* Set capabilities first... */
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82598EB:
+ if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT)
+ adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL;
break;
- case IXGBE_32_VM:
- mrqc |= IXGBE_MRQC_VMDQRSS32EN;
+ case ixgbe_mac_X540:
+ adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
+ adapter->feat_cap |= IXGBE_FEATURE_FDIR;
+ if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) &&
+ (adapter->hw.bus.func == 0))
+ adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
break;
- default:
- panic("Unexpected SR-IOV mode %d", mode);
- }
- IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
-
- mtqc = IXGBE_MTQC_VT_ENA;
- switch (mode) {
- case IXGBE_64_VM:
- mtqc |= IXGBE_MTQC_64VF;
+ case ixgbe_mac_X550:
+ adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
+ adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
+ adapter->feat_cap |= IXGBE_FEATURE_FDIR;
break;
- case IXGBE_32_VM:
- mtqc |= IXGBE_MTQC_32VF;
+ case ixgbe_mac_X550EM_x:
+ adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
+ adapter->feat_cap |= IXGBE_FEATURE_FDIR;
+ if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR)
+ adapter->feat_cap |= IXGBE_FEATURE_EEE;
break;
- default:
- panic("Unexpected SR-IOV mode %d", mode);
- }
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc);
-
-
- gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
- gcr_ext |= IXGBE_GCR_EXT_MSIX_EN;
- gcr_ext &= ~IXGBE_GCR_EXT_VT_MODE_MASK;
- switch (mode) {
- case IXGBE_64_VM:
- gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64;
+ case ixgbe_mac_X550EM_a:
+ adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
+ adapter->feat_cap |= IXGBE_FEATURE_FDIR;
+ adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
+ if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) ||
+ (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) {
+ adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
+ adapter->feat_cap |= IXGBE_FEATURE_EEE;
+ }
break;
- case IXGBE_32_VM:
- gcr_ext |= IXGBE_GCR_EXT_VT_MODE_32;
+ case ixgbe_mac_82599EB:
+ adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
+ adapter->feat_cap |= IXGBE_FEATURE_FDIR;
+ if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) &&
+ (adapter->hw.bus.func == 0))
+ adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
+ if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP)
+ adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
break;
default:
- panic("Unexpected SR-IOV mode %d", mode);
- }
- IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
-
-
- gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
- gcr_ext &= ~IXGBE_GPIE_VTMODE_MASK;
- switch (mode) {
- case IXGBE_64_VM:
- gpie |= IXGBE_GPIE_VTMODE_64;
break;
- case IXGBE_32_VM:
- gpie |= IXGBE_GPIE_VTMODE_32;
- break;
- default:
- panic("Unexpected SR-IOV mode %d", mode);
}
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
-
- /* Enable rx/tx for the PF. */
- vf_reg = IXGBE_VF_INDEX(adapter->pool);
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg),
- IXGBE_VF_BIT(adapter->pool));
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg),
- IXGBE_VF_BIT(adapter->pool));
- /* Allow VM-to-VM communication. */
- IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
-
- vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN;
- vt_ctl |= (adapter->pool << IXGBE_VT_CTL_POOL_SHIFT);
- IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl);
-
- for (i = 0; i < adapter->num_vfs; i++)
- ixgbe_init_vf(adapter, &adapter->vfs[i]);
-}
-
-
-/*
-** Check the max frame setting of all active VF's
-*/
-static void
-ixgbe_recalculate_max_frame(struct adapter *adapter)
-{
- struct ixgbe_vf *vf;
-
- IXGBE_CORE_LOCK_ASSERT(adapter);
-
- for (int i = 0; i < adapter->num_vfs; i++) {
- vf = &adapter->vfs[i];
- if (vf->flags & IXGBE_VF_ACTIVE)
- ixgbe_update_max_frame(adapter, vf->max_frame_size);
+ /* Enabled by default... */
+ /* Fan failure detection */
+ if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL)
+ adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL;
+ /* Netmap */
+ if (adapter->feat_cap & IXGBE_FEATURE_NETMAP)
+ adapter->feat_en |= IXGBE_FEATURE_NETMAP;
+ /* EEE */
+ if (adapter->feat_cap & IXGBE_FEATURE_EEE)
+ adapter->feat_en |= IXGBE_FEATURE_EEE;
+ /* Thermal Sensor */
+ if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR)
+ adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR;
+
+ /* Enabled via global sysctl... */
+ /* Flow Director */
+ if (ixgbe_enable_fdir) {
+ if (adapter->feat_cap & IXGBE_FEATURE_FDIR)
+ adapter->feat_en |= IXGBE_FEATURE_FDIR;
+ else
+ device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled.");
}
-}
-
-
+ /*
+ * Message Signal Interrupts - Extended (MSI-X)
+ * Normal MSI is only enabled if MSI-X calls fail.
+ */
+ if (!ixgbe_enable_msix)
+ adapter->feat_cap &= ~IXGBE_FEATURE_MSIX;
+ /* Receive-Side Scaling (RSS) */
+ if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss)
+ adapter->feat_en |= IXGBE_FEATURE_RSS;
+
+ /* Disable features with unmet dependencies... */
+ /* No MSI-X */
+ if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) {
+ adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
+ adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
+ adapter->feat_en &= ~IXGBE_FEATURE_RSS;
+ adapter->feat_en &= ~IXGBE_FEATURE_SRIOV;
+ }
+} /* ixgbe_init_device_features */
+
+/************************************************************************
+ * ixgbe_check_fan_failure
+ ************************************************************************/
static void
-ixgbe_init_vf(struct adapter *adapter, struct ixgbe_vf *vf)
-{
- struct ixgbe_hw *hw;
- uint32_t vf_index, pfmbimr;
-
- IXGBE_CORE_LOCK_ASSERT(adapter);
-
- hw = &adapter->hw;
-
- if (!(vf->flags & IXGBE_VF_ACTIVE))
- return;
-
- vf_index = IXGBE_VF_INDEX(vf->pool);
- pfmbimr = IXGBE_READ_REG(hw, IXGBE_PFMBIMR(vf_index));
- pfmbimr |= IXGBE_VF_BIT(vf->pool);
- IXGBE_WRITE_REG(hw, IXGBE_PFMBIMR(vf_index), pfmbimr);
-
- ixgbe_vf_set_default_vlan(adapter, vf, vf->vlan_tag);
-
- // XXX multicast addresses
-
- if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
- ixgbe_set_rar(&adapter->hw, vf->rar_index,
- vf->ether_addr, vf->pool, TRUE);
- }
-
- ixgbe_vf_enable_transmit(adapter, vf);
- ixgbe_vf_enable_receive(adapter, vf);
-
- ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG);
-}
-
-static int
-ixgbe_add_vf(device_t dev, u16 vfnum, const nvlist_t *config)
+ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt)
{
- struct adapter *adapter;
- struct ixgbe_vf *vf;
- const void *mac;
-
- adapter = device_get_softc(dev);
-
- KASSERT(vfnum < adapter->num_vfs, ("VF index %d is out of range %d",
- vfnum, adapter->num_vfs));
-
- IXGBE_CORE_LOCK(adapter);
- vf = &adapter->vfs[vfnum];
- vf->pool= vfnum;
-
- /* RAR[0] is used by the PF so use vfnum + 1 for VF RAR. */
- vf->rar_index = vfnum + 1;
- vf->default_vlan = 0;
- vf->max_frame_size = ETHER_MAX_LEN;
- ixgbe_update_max_frame(adapter, vf->max_frame_size);
-
- if (nvlist_exists_binary(config, "mac-addr")) {
- mac = nvlist_get_binary(config, "mac-addr", NULL);
- bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN);
- if (nvlist_get_bool(config, "allow-set-mac"))
- vf->flags |= IXGBE_VF_CAP_MAC;
- } else
- /*
- * If the administrator has not specified a MAC address then
- * we must allow the VF to choose one.
- */
- vf->flags |= IXGBE_VF_CAP_MAC;
-
- vf->flags |= IXGBE_VF_ACTIVE;
+ u32 mask;
- ixgbe_init_vf(adapter, vf);
- IXGBE_CORE_UNLOCK(adapter);
+ mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) :
+ IXGBE_ESDP_SDP1;
- return (0);
-}
-#endif /* PCI_IOV */
+ if (reg & mask)
+ device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
+} /* ixgbe_check_fan_failure */
Index: sys/dev/ixgbe/if_ixv.c
===================================================================
--- sys/dev/ixgbe/if_ixv.c
+++ sys/dev/ixgbe/if_ixv.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -33,17 +33,19 @@
/*$FreeBSD$*/
-#ifndef IXGBE_STANDALONE_BUILD
#include "opt_inet.h"
#include "opt_inet6.h"
-#endif
#include "ixgbe.h"
+#include "ifdi_if.h"
+
+#include <net/netmap.h>
+#include <dev/netmap/netmap_kern.h>
/*********************************************************************
* Driver version
*********************************************************************/
-char ixv_driver_version[] = "1.4.6-k";
+char ixv_driver_version[] = "1.5.11-k";
/*********************************************************************
* PCI Device ID Table
@@ -55,88 +57,71 @@
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
*********************************************************************/
-static ixgbe_vendor_info_t ixv_vendor_info_array[] =
+static pci_vendor_info_t ixv_vendor_info_array[] =
{
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_VF, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550_VF, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_VF, 0, 0, 0},
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF, "Intel(R) PRO/10GbE Virtual Function Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_VF, "Intel(R) PRO/10GbE Virtual Function Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550_VF, "Intel(R) PRO/10GbE Virtual Function Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_VF, "Intel(R) PRO/10GbE Virtual Function Network Driver"),
+ PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_VF, "Intel(R) PRO/10GbE Virtual Function Network Driver"),
/* required last entry */
- {0, 0, 0, 0, 0}
-};
-
-/*********************************************************************
- * Table of branding strings
- *********************************************************************/
-
-static char *ixv_strings[] = {
- "Intel(R) PRO/10GbE Virtual Function Network Driver"
+PVID_END
};
/*********************************************************************
* Function prototypes
*********************************************************************/
-static int ixv_probe(device_t);
-static int ixv_attach(device_t);
-static int ixv_detach(device_t);
-static int ixv_shutdown(device_t);
-static int ixv_ioctl(struct ifnet *, u_long, caddr_t);
-static void ixv_init(void *);
-static void ixv_init_locked(struct adapter *);
-static void ixv_stop(void *);
-static void ixv_media_status(struct ifnet *, struct ifmediareq *);
-static int ixv_media_change(struct ifnet *);
-static void ixv_identify_hardware(struct adapter *);
-static int ixv_allocate_pci_resources(struct adapter *);
-static int ixv_allocate_msix(struct adapter *);
-static int ixv_setup_msix(struct adapter *);
-static void ixv_free_pci_resources(struct adapter *);
-static void ixv_local_timer(void *);
-static void ixv_setup_interface(device_t, struct adapter *);
-static void ixv_config_link(struct adapter *);
-
-static void ixv_initialize_transmit_units(struct adapter *);
-static void ixv_initialize_receive_units(struct adapter *);
-
-static void ixv_enable_intr(struct adapter *);
-static void ixv_disable_intr(struct adapter *);
-static void ixv_set_multi(struct adapter *);
-static void ixv_update_link_status(struct adapter *);
-static int ixv_sysctl_debug(SYSCTL_HANDLER_ARGS);
-static void ixv_set_ivar(struct adapter *, u8, u8, s8);
+static void *ixv_register(device_t dev);
+static int ixv_if_attach_pre(if_ctx_t ctx);
+static int ixv_if_attach_post(if_ctx_t ctx);
+static int ixv_if_detach(if_ctx_t ctx);
+
+static int ixv_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
+static int ixv_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets);
+static int ixv_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets);
+static void ixv_if_queues_free(if_ctx_t ctx);
+static void ixv_identify_hardware(if_ctx_t ctx);
+static void ixv_init_device_features(struct adapter *);
+static int ixv_allocate_pci_resources(if_ctx_t ctx);
+static void ixv_free_pci_resources(if_ctx_t ctx);
+static int ixv_setup_interface(if_ctx_t ctx);
+static void ixv_if_media_status(if_ctx_t , struct ifmediareq *);
+static int ixv_if_media_change(if_ctx_t ctx);
+static void ixv_if_update_admin_status(if_ctx_t ctx);
+static int ixv_if_msix_intr_assign(if_ctx_t ctx, int msix);
+
+static int ixv_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
+static void ixv_if_init(if_ctx_t ctx);
+static void ixv_if_local_timer(if_ctx_t ctx, uint16_t qid);
+static void ixv_if_stop(if_ctx_t ctx);
+
+static void ixv_initialize_transmit_units(if_ctx_t ctx);
+static void ixv_initialize_receive_units(if_ctx_t ctx);
+static void ixv_initialize_rss_mapping(struct adapter *);
+
+static void ixv_setup_vlan_support(if_ctx_t ctx);
static void ixv_configure_ivars(struct adapter *);
-static u8 * ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
-
-static void ixv_setup_vlan_support(struct adapter *);
-static void ixv_register_vlan(void *, struct ifnet *, u16);
-static void ixv_unregister_vlan(void *, struct ifnet *, u16);
+static void ixv_if_enable_intr(if_ctx_t ctx);
+static void ixv_if_disable_intr(if_ctx_t ctx);
+static void ixv_if_multi_set(if_ctx_t ctx);
+static void ixv_if_register_vlan(if_ctx_t, u16);
+static void ixv_if_unregister_vlan(if_ctx_t, u16);
static void ixv_save_stats(struct adapter *);
static void ixv_init_stats(struct adapter *);
static void ixv_update_stats(struct adapter *);
-static void ixv_add_stats_sysctls(struct adapter *);
+static void ixv_add_stats_sysctls(struct adapter *adapter);
+
+static int ixv_sysctl_debug(SYSCTL_HANDLER_ARGS);
+static void ixv_set_ivar(struct adapter *, u8, u8, s8);
+
+static u8 * ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
static void ixv_set_sysctl_value(struct adapter *, const char *,
const char *, int *, int);
/* The MSI/X Interrupt handlers */
-static void ixv_msix_que(void *);
-static void ixv_msix_mbx(void *);
-
-/* Deferred interrupt tasklets */
-static void ixv_handle_que(void *, int);
-static void ixv_handle_mbx(void *, int);
-
-#ifdef DEV_NETMAP
-/*
- * This is defined in <dev/netmap/ixgbe_netmap.h>, which is included by
- * if_ix.c.
- */
-extern void ixgbe_netmap_attach(struct adapter *adapter);
-
-#include <net/netmap.h>
-#include <sys/selinfo.h>
-#include <dev/netmap/netmap_kern.h>
-#endif /* DEV_NETMAP */
+static int ixv_msix_que(void *);
+static int ixv_msix_mbx(void *);
/*********************************************************************
* FreeBSD Device Interface Entry Points
@@ -144,10 +129,11 @@
static device_method_t ixv_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, ixv_probe),
- DEVMETHOD(device_attach, ixv_attach),
- DEVMETHOD(device_detach, ixv_detach),
- DEVMETHOD(device_shutdown, ixv_shutdown),
+ DEVMETHOD(device_register, ixv_register),
+ DEVMETHOD(device_probe, iflib_device_probe),
+ DEVMETHOD(device_attach, iflib_device_attach),
+ DEVMETHOD(device_detach, iflib_device_detach),
+ DEVMETHOD(device_shutdown, iflib_device_shutdown),
DEVMETHOD_END
};
@@ -164,6 +150,35 @@
#endif /* DEV_NETMAP */
/* XXX depend on 'ix' ? */
+static device_method_t ixv_if_methods[] = {
+ DEVMETHOD(ifdi_attach_pre, ixv_if_attach_pre),
+ DEVMETHOD(ifdi_attach_post, ixv_if_attach_post),
+ DEVMETHOD(ifdi_detach, ixv_if_detach),
+ DEVMETHOD(ifdi_init, ixv_if_init),
+ DEVMETHOD(ifdi_stop, ixv_if_stop),
+ DEVMETHOD(ifdi_msix_intr_assign, ixv_if_msix_intr_assign),
+ DEVMETHOD(ifdi_intr_enable, ixv_if_enable_intr),
+ DEVMETHOD(ifdi_intr_disable, ixv_if_disable_intr),
+ DEVMETHOD(ifdi_tx_queue_intr_enable, ixv_if_rx_queue_intr_enable),
+ DEVMETHOD(ifdi_rx_queue_intr_enable, ixv_if_rx_queue_intr_enable),
+ DEVMETHOD(ifdi_tx_queues_alloc, ixv_if_tx_queues_alloc),
+ DEVMETHOD(ifdi_rx_queues_alloc, ixv_if_rx_queues_alloc),
+ DEVMETHOD(ifdi_queues_free, ixv_if_queues_free),
+ DEVMETHOD(ifdi_update_admin_status, ixv_if_update_admin_status),
+ DEVMETHOD(ifdi_multi_set, ixv_if_multi_set),
+ DEVMETHOD(ifdi_mtu_set, ixv_if_mtu_set),
+ DEVMETHOD(ifdi_media_status, ixv_if_media_status),
+ DEVMETHOD(ifdi_media_change, ixv_if_media_change),
+ DEVMETHOD(ifdi_timer, ixv_if_local_timer),
+ DEVMETHOD(ifdi_vlan_register, ixv_if_register_vlan),
+ DEVMETHOD(ifdi_vlan_unregister, ixv_if_unregister_vlan),
+ DEVMETHOD_END
+};
+
+static driver_t ixv_if_driver = {
+ "ixv_if", ixv_if_methods, sizeof(struct adapter)
+};
+
/*
** TUNEABLE PARAMETERS:
*/
@@ -220,55 +235,166 @@
** a soft reset and we need to repopulate it.
*/
static u32 ixv_shadow_vfta[IXGBE_VFTA_SIZE];
+extern struct if_txrx ixgbe_txrx;
+
+static struct if_shared_ctx ixv_sctx_init = {
+ .isc_magic = IFLIB_MAGIC,
+ .isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */
+ .isc_tx_maxsize = IXGBE_TSO_SIZE,
+
+ .isc_tx_maxsegsize = PAGE_SIZE,
+
+ .isc_rx_maxsize = MJUM16BYTES,
+ .isc_rx_nsegments = 1,
+ .isc_rx_maxsegsize = MJUM16BYTES,
+ .isc_nfl = 1,
+ .isc_ntxqs = 1,
+ .isc_nrxqs = 1,
+ .isc_admin_intrcnt = 1,
+ .isc_vendor_info = ixv_vendor_info_array,
+ .isc_driver_version = ixv_driver_version,
+ .isc_driver = &ixv_if_driver,
+
+ .isc_nrxd_min = {MIN_RXD},
+ .isc_ntxd_min = {MIN_TXD},
+ .isc_nrxd_max = {MAX_RXD},
+ .isc_ntxd_max = {MAX_TXD},
+ .isc_nrxd_default = {DEFAULT_RXD},
+ .isc_ntxd_default = {DEFAULT_TXD},
+};
-/*********************************************************************
- * Device identification routine
- *
- * ixv_probe determines if the driver should be loaded on
- * adapter based on PCI vendor/device id of the adapter.
- *
- * return BUS_PROBE_DEFAULT on success, positive on failure
- *********************************************************************/
+if_shared_ctx_t ixv_sctx = &ixv_sctx_init;
-static int
-ixv_probe(device_t dev)
+static void *
+ixv_register(device_t dev)
{
- ixgbe_vendor_info_t *ent;
- u16 pci_vendor_id = 0;
- u16 pci_device_id = 0;
- u16 pci_subvendor_id = 0;
- u16 pci_subdevice_id = 0;
- char adapter_name[256];
+ return (ixv_sctx);
+}
+static int
+ixv_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx = adapter->shared;
+ struct ix_tx_queue *que;
+ int i, j, error;
+
+ MPASS(adapter->num_tx_queues == ntxqsets);
+ MPASS(ntxqs == 1);
+
+ /* Allocate queue structure memory */
+ adapter->tx_queues =
+ (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * ntxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!adapter->tx_queues) {
+ device_printf(iflib_get_dev(ctx),
+ "Unable to allocate TX ring memory\n");
+ return (ENOMEM);
+ }
- pci_vendor_id = pci_get_vendor(dev);
- if (pci_vendor_id != IXGBE_INTEL_VENDOR_ID)
- return (ENXIO);
+ for (i = 0, que = adapter->tx_queues; i < ntxqsets; i++, que++) {
+ struct tx_ring *txr = &que->txr;
+
+ txr->me = i;
+ txr->adapter = que->adapter = adapter;
+ adapter->active_queues |= (u64)1 << txr->me;
- pci_device_id = pci_get_device(dev);
- pci_subvendor_id = pci_get_subvendor(dev);
- pci_subdevice_id = pci_get_subdevice(dev);
-
- ent = ixv_vendor_info_array;
- while (ent->vendor_id != 0) {
- if ((pci_vendor_id == ent->vendor_id) &&
- (pci_device_id == ent->device_id) &&
-
- ((pci_subvendor_id == ent->subvendor_id) ||
- (ent->subvendor_id == 0)) &&
-
- ((pci_subdevice_id == ent->subdevice_id) ||
- (ent->subdevice_id == 0))) {
- sprintf(adapter_name, "%s, Version - %s",
- ixv_strings[ent->index],
- ixv_driver_version);
- device_set_desc_copy(dev, adapter_name);
- return (BUS_PROBE_DEFAULT);
+ /* Allocate report status array */
+ if (!(txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_DEVBUF, M_NOWAIT | M_ZERO))) {
+ error = ENOMEM;
+ goto fail;
}
- ent++;
+ for (j = 0; j < scctx->isc_ntxd[0]; j++)
+ txr->tx_rsq[j] = QIDX_INVALID;
+ /* get the virtual and physical address of the hardware queues */
+ txr->tail = IXGBE_VFTDT(txr->me);
+ txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i*ntxqs];
+ txr->tx_paddr = paddrs[i*ntxqs];
+
+ txr->bytes = 0;
+ txr->total_packets = 0;
+
}
- return (ENXIO);
+
+ device_printf(iflib_get_dev(ctx), "allocated for %d queues\n",
+ adapter->num_tx_queues);
+ return (0);
+
+ fail:
+ ixv_if_queues_free(ctx);
+ return (error);
+}
+
+static int
+ixv_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_rx_queue *que;
+ int i, error;
+
+ MPASS(adapter->num_rx_queues == nrxqsets);
+ MPASS(nrxqs == 1);
+
+ /* Allocate queue structure memory */
+ adapter->rx_queues =
+ (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue) * nrxqsets,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!adapter->rx_queues) {
+ device_printf(iflib_get_dev(ctx),
+ "Unable to allocate TX ring memory\n");
+ error = ENOMEM;
+ goto fail;
+ }
+
+ for (i = 0, que = adapter->rx_queues; i < nrxqsets; i++, que++) {
+ struct rx_ring *rxr = &que->rxr;
+ rxr->me = i;
+ rxr->adapter = que->adapter = adapter;
+
+
+ /* get the virtual and physical address of the hardware queues */
+
+ rxr->tail = IXGBE_VFRDT(rxr->me);
+ rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i];
+ rxr->rx_paddr = paddrs[i*nrxqs];
+ rxr->bytes = 0;
+ rxr->que = que;
+ }
+
+ device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n", adapter->num_rx_queues);
+ return (0);
+
+fail:
+ ixv_if_queues_free(ctx);
+ return (error);
+}
+
+static void
+ixv_if_queues_free(if_ctx_t ctx)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_tx_queue *que = adapter->tx_queues;
+ int i;
+
+ if (que == NULL)
+ goto free;
+
+ for (i = 0; i < adapter->num_tx_queues; i++, que++) {
+ struct tx_ring *txr = &que->txr;
+ if (txr->tx_rsq == NULL)
+ break;
+
+ free(txr->tx_rsq, M_DEVBUF);
+ txr->tx_rsq = NULL;
+ }
+ if (adapter->tx_queues != NULL)
+ free(adapter->tx_queues, M_DEVBUF);
+free:
+ if (adapter->rx_queues != NULL)
+ free(adapter->rx_queues, M_DEVBUF);
+ adapter->tx_queues = NULL;
+ adapter->rx_queues = NULL;
}
/*********************************************************************
@@ -282,26 +408,32 @@
*********************************************************************/
static int
-ixv_attach(device_t dev)
+ixv_if_attach_pre(if_ctx_t ctx)
{
+ device_t dev;
struct adapter *adapter;
+ if_softc_ctx_t scctx;
struct ixgbe_hw *hw;
int error = 0;
INIT_DEBUGOUT("ixv_attach: begin");
/* Allocate, clear, and link in our adapter structure */
- adapter = device_get_softc(dev);
+ dev = iflib_get_dev(ctx);
+ adapter = iflib_get_softc(ctx);
adapter->dev = dev;
+ adapter->ctx = ctx;
+ adapter->hw.back = adapter;
+ scctx = adapter->shared = iflib_get_softc_ctx(ctx);
+ adapter->media = iflib_get_media(ctx);
hw = &adapter->hw;
-#ifdef DEV_NETMAP
- adapter->init_locked = ixv_init_locked;
- adapter->stop_locked = ixv_stop;
-#endif
-
- /* Core Lock Init*/
- IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
+ /* Do base PCI setup - map BAR0 */
+ if (ixv_allocate_pci_resources(ctx)) {
+ device_printf(dev, "ixv_allocate_pci_resources() failed!\n");
+ error = ENXIO;
+ goto err;
+ }
/* SYSCTL APIs */
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
@@ -314,94 +446,46 @@
OID_AUTO, "enable_aim", CTLFLAG_RW,
&ixv_enable_aim, 1, "Interrupt Moderation");
- /* Set up the timer callout */
- callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
-
/* Determine hardware revision */
- ixv_identify_hardware(adapter);
-
- /* Do base PCI setup - map BAR0 */
- if (ixv_allocate_pci_resources(adapter)) {
- device_printf(dev, "ixv_allocate_pci_resources() failed!\n");
- error = ENXIO;
- goto err_out;
- }
-
- /* Sysctls for limiting the amount of work done in the taskqueues */
- ixv_set_sysctl_value(adapter, "rx_processing_limit",
- "max number of rx packets to process",
- &adapter->rx_process_limit, ixv_rx_process_limit);
+ ixv_identify_hardware(ctx);
+ ixv_init_device_features(adapter);
- ixv_set_sysctl_value(adapter, "tx_processing_limit",
- "max number of tx packets to process",
- &adapter->tx_process_limit, ixv_tx_process_limit);
-
- /* Do descriptor calc and sanity checks */
- if (((ixv_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
- ixv_txd < MIN_TXD || ixv_txd > MAX_TXD) {
- device_printf(dev, "TXD config issue, using default!\n");
- adapter->num_tx_desc = DEFAULT_TXD;
- } else
- adapter->num_tx_desc = ixv_txd;
-
- if (((ixv_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
- ixv_rxd < MIN_RXD || ixv_rxd > MAX_RXD) {
- device_printf(dev, "RXD config issue, using default!\n");
- adapter->num_rx_desc = DEFAULT_RXD;
- } else
- adapter->num_rx_desc = ixv_rxd;
-
- /* Allocate our TX/RX Queues */
- if (ixgbe_allocate_queues(adapter)) {
- device_printf(dev, "ixgbe_allocate_queues() failed!\n");
- error = ENOMEM;
- goto err_out;
- }
-
- /*
- ** Initialize the shared code: its
- ** at this point the mac type is set.
- */
- error = ixgbe_init_shared_code(hw);
+ /* Initialize the shared code */
+ error = ixgbe_init_ops_vf(hw);
if (error) {
- device_printf(dev, "ixgbe_init_shared_code() failed!\n");
+ device_printf(dev, "ixgbe_init_ops_vf() failed!\n");
error = EIO;
- goto err_late;
+ goto err;
}
/* Setup the mailbox */
ixgbe_init_mbx_params_vf(hw);
- /* Reset mbox api to 1.0 */
error = ixgbe_reset_hw(hw);
if (error == IXGBE_ERR_RESET_FAILED)
device_printf(dev, "ixgbe_reset_hw() failure: Reset Failed!\n");
else if (error)
- device_printf(dev, "ixgbe_reset_hw() failed with error %d\n", error);
- if (error) {
- error = EIO;
- goto err_late;
- }
-
- /* Negotiate mailbox API version */
- error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
+ device_printf(dev,
+ "ixgbe_reset_hw() failed with error %d\n", error);
if (error) {
- device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
error = EIO;
- goto err_late;
+ goto err;
}
error = ixgbe_init_hw(hw);
if (error) {
device_printf(dev, "ixgbe_init_hw() failed!\n");
error = EIO;
- goto err_late;
+ goto err;
}
-
- error = ixv_allocate_msix(adapter);
+
+ /* Negotiate mailbox API version */
+ error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_12);
if (error) {
- device_printf(dev, "ixv_allocate_msix() failed!\n");
- goto err_late;
+ device_printf(dev,
+ "MBX API 1.2 negotiation failed! Error %d\n", error);
+ error = EIO;
+ goto err;
}
/* If no mac address was assigned, make a random one */
@@ -411,234 +495,122 @@
addr[0] &= 0xFE;
addr[0] |= 0x02;
bcopy(addr, hw->mac.addr, sizeof(addr));
+ bcopy(addr, hw->mac.perm_addr, sizeof(addr));
}
- /* Setup OS specific network interface */
- ixv_setup_interface(dev, adapter);
-
- /* Do the stats setup */
- ixv_save_stats(adapter);
- ixv_init_stats(adapter);
- ixv_add_stats_sysctls(adapter);
+ /* Most of the iflib initialization... */
+
+ iflib_set_mac(ctx, hw->mac.addr);
+ scctx->isc_txqsizes[0] =
+ roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) +
+ sizeof(u32), DBA_ALIGN);
+ scctx->isc_rxqsizes[0] =
+ roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc),
+ DBA_ALIGN);
+ /* XXX */
+ scctx->isc_max_txqsets = scctx->isc_max_rxqsets = 2;
+ scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO;
+ scctx->isc_tx_nsegments = IXGBE_82599_SCATTER;
+ scctx->isc_msix_bar = PCIR_BAR(MSIX_82598_BAR);
+ scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments;
+ scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE;
+ scctx->isc_tx_tso_segsize_max = PAGE_SIZE;
+
+ scctx->isc_txrx = &ixgbe_txrx;
- /* Register for VLAN events */
- adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
- ixv_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
- adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
- ixv_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
+ /*
+ * Tell the upper layer(s) we support everything the PF
+ * driver does except...
+ * hardware stats
+ * VLAN tag filtering
+ * Wake-on-LAN
+ * VLAN MTU (device-specific)
+ */
+ scctx->isc_capenable = IXGBE_CAPS;
+ scctx->isc_capenable ^= IFCAP_HWSTATS | IFCAP_VLAN_HWFILTER | IFCAP_WOL;
+ if (adapter->feat_en & IXGBE_FEATURE_FRAME_LIMIT)
+ scctx->isc_capenable ^= IFCAP_VLAN_MTU;
-#ifdef DEV_NETMAP
- ixgbe_netmap_attach(adapter);
-#endif /* DEV_NETMAP */
INIT_DEBUGOUT("ixv_attach: end");
return (0);
-err_late:
- ixgbe_free_transmit_structures(adapter);
- ixgbe_free_receive_structures(adapter);
-err_out:
- ixv_free_pci_resources(adapter);
+err:
+ ixv_free_pci_resources(ctx);
return (error);
}
-/*********************************************************************
- * Device removal routine
- *
- * The detach entry point is called when the driver is being removed.
- * This routine stops the adapter and deallocates all the resources
- * that were allocated for driver operation.
- *
- * return 0 on success, positive on failure
- *********************************************************************/
-
static int
-ixv_detach(device_t dev)
+ixv_if_attach_post(if_ctx_t ctx)
{
- struct adapter *adapter = device_get_softc(dev);
- struct ix_queue *que = adapter->queues;
-
- INIT_DEBUGOUT("ixv_detach: begin");
-
- /* Make sure VLANS are not using driver */
- if (adapter->ifp->if_vlantrunk != NULL) {
- device_printf(dev, "Vlan in use, detach first\n");
- return (EBUSY);
- }
+ struct adapter *adapter = iflib_get_softc(ctx);
+ device_t dev = iflib_get_dev(ctx);
+ int error = 0;
- IXGBE_CORE_LOCK(adapter);
- ixv_stop(adapter);
- IXGBE_CORE_UNLOCK(adapter);
+ /* Sysctls for limiting the amount of work done in the taskqueues */
+ ixv_set_sysctl_value(adapter, "rx_processing_limit",
+ "max number of rx packets to process",
+ &adapter->rx_process_limit, ixv_rx_process_limit);
- for (int i = 0; i < adapter->num_queues; i++, que++) {
- if (que->tq) {
- struct tx_ring *txr = que->txr;
- taskqueue_drain(que->tq, &txr->txq_task);
- taskqueue_drain(que->tq, &que->que_task);
- taskqueue_free(que->tq);
- }
- }
+ ixv_set_sysctl_value(adapter, "tx_processing_limit",
+ "max number of tx packets to process",
+ &adapter->tx_process_limit, ixv_tx_process_limit);
- /* Drain the Mailbox(link) queue */
- if (adapter->tq) {
- taskqueue_drain(adapter->tq, &adapter->link_task);
- taskqueue_free(adapter->tq);
+ /* Setup OS specific network interface */
+ error = ixv_setup_interface(ctx);
+ if (error) {
+ device_printf(dev, "Interface setup failed: %d\n", error);
+ goto end;
}
- /* Unregister VLAN events */
- if (adapter->vlan_attach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
- if (adapter->vlan_detach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
-
- ether_ifdetach(adapter->ifp);
- callout_drain(&adapter->timer);
-#ifdef DEV_NETMAP
- netmap_detach(adapter->ifp);
-#endif /* DEV_NETMAP */
- ixv_free_pci_resources(adapter);
- bus_generic_detach(dev);
- if_free(adapter->ifp);
+ /* Do the stats setup */
+ ixv_save_stats(adapter);
+ ixv_init_stats(adapter);
+ ixv_add_stats_sysctls(adapter);
- ixgbe_free_transmit_structures(adapter);
- ixgbe_free_receive_structures(adapter);
+ INIT_DEBUGOUT("ixv_attachpost: end");
- IXGBE_CORE_LOCK_DESTROY(adapter);
- return (0);
+end:
+ return error;
}
/*********************************************************************
+ * Device removal routine
*
- * Shutdown entry point
+ * The detach entry point is called when the driver is being removed.
+ * This routine stops the adapter and deallocates all the resources
+ * that were allocated for driver operation.
*
- **********************************************************************/
+ * return 0 on success, positive on failure
+ *********************************************************************/
+
static int
-ixv_shutdown(device_t dev)
+ixv_if_detach(if_ctx_t ctx)
{
- struct adapter *adapter = device_get_softc(dev);
- IXGBE_CORE_LOCK(adapter);
- ixv_stop(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- return (0);
-}
+ INIT_DEBUGOUT("ixv_detach: begin");
+ ixv_free_pci_resources(ctx);
-/*********************************************************************
- * Ioctl entry point
- *
- * ixv_ioctl is called when the user wants to configure the
- * interface.
- *
- * return 0 on success, positive on failure
- **********************************************************************/
+ return (0);
+}
static int
-ixv_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
+ixv_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
{
- struct adapter *adapter = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *) data;
-#if defined(INET) || defined(INET6)
- struct ifaddr *ifa = (struct ifaddr *) data;
- bool avoid_reset = FALSE;
-#endif
- int error = 0;
-
- switch (command) {
-
- case SIOCSIFADDR:
-#ifdef INET
- if (ifa->ifa_addr->sa_family == AF_INET)
- avoid_reset = TRUE;
-#endif
-#ifdef INET6
- if (ifa->ifa_addr->sa_family == AF_INET6)
- avoid_reset = TRUE;
-#endif
-#if defined(INET) || defined(INET6)
- /*
- ** Calling init results in link renegotiation,
- ** so we avoid doing it when possible.
- */
- if (avoid_reset) {
- ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- ixv_init(adapter);
- if (!(ifp->if_flags & IFF_NOARP))
- arp_ifinit(ifp, ifa);
- } else
- error = ether_ioctl(ifp, command, data);
- break;
-#endif
- case SIOCSIFMTU:
- IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
- if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) {
- error = EINVAL;
- } else {
- IXGBE_CORE_LOCK(adapter);
- ifp->if_mtu = ifr->ifr_mtu;
- adapter->max_frame_size =
- ifp->if_mtu + IXGBE_MTU_HDR;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixv_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- }
- break;
- case SIOCSIFFLAGS:
- IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
- IXGBE_CORE_LOCK(adapter);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- ixv_init_locked(adapter);
- } else
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ixv_stop(adapter);
- adapter->if_flags = ifp->if_flags;
- IXGBE_CORE_UNLOCK(adapter);
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_CORE_LOCK(adapter);
- ixv_disable_intr(adapter);
- ixv_set_multi(adapter);
- ixv_enable_intr(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- }
- break;
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
- IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
- error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
- break;
- case SIOCSIFCAP:
- {
- int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
- if (mask & IFCAP_HWCSUM)
- ifp->if_capenable ^= IFCAP_HWCSUM;
- if (mask & IFCAP_TSO4)
- ifp->if_capenable ^= IFCAP_TSO4;
- if (mask & IFCAP_LRO)
- ifp->if_capenable ^= IFCAP_LRO;
- if (mask & IFCAP_VLAN_HWTAGGING)
- ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_CORE_LOCK(adapter);
- ixv_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- }
- VLAN_CAPABILITIES(ifp);
- break;
- }
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ int error = 0;
- default:
- IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
- error = ether_ioctl(ifp, command, data);
- break;
+ IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
+ if (mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) {
+ error = EINVAL;
+ } else {
+ ifp->if_mtu = mtu;
+ adapter->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR_VLAN;
+ if (adapter->feat_en & IXGBE_FEATURE_FRAME_LIMIT)
+ adapter->max_frame_size -= ETHER_VLAN_ENCAP_LEN;
}
-
- return (error);
+ return error;
}
/*********************************************************************
@@ -654,45 +626,37 @@
#define IXGBE_MHADD_MFS_SHIFT 16
static void
-ixv_init_locked(struct adapter *adapter)
+ixv_if_init(if_ctx_t ctx)
{
- struct ifnet *ifp = adapter->ifp;
- device_t dev = adapter->dev;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ device_t dev = iflib_get_dev(ctx);
struct ixgbe_hw *hw = &adapter->hw;
int error = 0;
- INIT_DEBUGOUT("ixv_init_locked: begin");
- mtx_assert(&adapter->core_mtx, MA_OWNED);
+ INIT_DEBUGOUT("ixv_init: begin");
hw->adapter_stopped = FALSE;
ixgbe_stop_adapter(hw);
- callout_stop(&adapter->timer);
- /* reprogram the RAR[0] in case user changed it. */
- ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
+ /* reprogram the RAR[0] in case user changed it. */
+ ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
/* Get the latest mac address, User can use a LAA */
- bcopy(IF_LLADDR(adapter->ifp), hw->mac.addr,
- IXGBE_ETH_LENGTH_OF_ADDRESS);
- ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
+ bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
+ ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
hw->addr_ctrl.rar_used_count = 1;
- /* Prepare transmit descriptors and buffers */
- if (ixgbe_setup_transmit_structures(adapter)) {
- device_printf(dev, "Could not setup transmit structures\n");
- ixv_stop(adapter);
- return;
- }
-
/* Reset VF and renegotiate mailbox API version */
ixgbe_reset_hw(hw);
- error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
+ error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_12);
if (error)
- device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
+ device_printf(dev,
+ "MBX API 1.2 negotiation failed! Error %d\n", error);
- ixv_initialize_transmit_units(adapter);
+ ixv_initialize_transmit_units(ctx);
/* Setup Multicast table */
- ixv_set_multi(adapter);
+ ixv_if_multi_set(ctx);
/*
** Determine the correct mbuf pool
@@ -703,29 +667,11 @@
else
adapter->rx_mbuf_sz = MCLBYTES;
- /* Prepare receive descriptors and buffers */
- if (ixgbe_setup_receive_structures(adapter)) {
- device_printf(dev, "Could not setup receive structures\n");
- ixv_stop(adapter);
- return;
- }
-
/* Configure RX settings */
- ixv_initialize_receive_units(adapter);
-
- /* Set the various hardware offload abilities */
- ifp->if_hwassist = 0;
- if (ifp->if_capenable & IFCAP_TSO4)
- ifp->if_hwassist |= CSUM_TSO;
- if (ifp->if_capenable & IFCAP_TXCSUM) {
- ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
-#if __FreeBSD_version >= 800000
- ifp->if_hwassist |= CSUM_SCTP;
-#endif
- }
-
+ ixv_initialize_receive_units(ctx);
+
/* Set up VLAN offload and filter */
- ixv_setup_vlan_support(adapter);
+ ixv_setup_vlan_support(ctx);
/* Set up MSI/X routing */
ixv_configure_ivars(adapter);
@@ -733,45 +679,27 @@
/* Set up auto-mask */
IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_EICS_RTX_QUEUE);
- /* Set moderation on the Link interrupt */
- IXGBE_WRITE_REG(hw, IXGBE_VTEITR(adapter->vector), IXGBE_LINK_ITR);
+ /* Set moderation on the Link interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_VTEITR(adapter->vector), IXGBE_LINK_ITR);
/* Stats init */
ixv_init_stats(adapter);
/* Config/Enable Link */
- ixv_config_link(adapter);
-
- /* Start watchdog */
- callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
+ ixgbe_check_link(hw, &adapter->link_speed, &adapter->link_up,
+ FALSE);
/* And now turn on interrupts */
- ixv_enable_intr(adapter);
-
- /* Now inform the stack we're ready */
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
- return;
-}
-
-static void
-ixv_init(void *arg)
-{
- struct adapter *adapter = arg;
+ ixv_if_enable_intr(ctx);
- IXGBE_CORE_LOCK(adapter);
- ixv_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
return;
}
-
/*
-**
-** MSIX Interrupt Handlers and Tasklets
-**
-*/
+ *
+ * MSIX Interrupt Handlers and Tasklets
+ *
+ */
static inline void
ixv_enable_queue(struct adapter *adapter, u32 vector)
@@ -795,109 +723,51 @@
IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, mask);
}
-static inline void
-ixv_rearm_queues(struct adapter *adapter, u64 queues)
-{
- u32 mask = (IXGBE_EIMS_RTX_QUEUE & queues);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEICS, mask);
-}
-
-
-static void
-ixv_handle_que(void *context, int pending)
-{
- struct ix_queue *que = context;
- struct adapter *adapter = que->adapter;
- struct tx_ring *txr = que->txr;
- struct ifnet *ifp = adapter->ifp;
- bool more;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- more = ixgbe_rxeof(que);
- IXGBE_TX_LOCK(txr);
- ixgbe_txeof(txr);
-#if __FreeBSD_version >= 800000
- if (!drbr_empty(ifp, txr->br))
- ixgbe_mq_start_locked(ifp, txr);
-#else
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- ixgbe_start_locked(txr, ifp);
-#endif
- IXGBE_TX_UNLOCK(txr);
- if (more) {
- taskqueue_enqueue(que->tq, &que->que_task);
- return;
- }
- }
-
- /* Reenable this interrupt */
- ixv_enable_queue(adapter, que->msix);
- return;
-}
/*********************************************************************
*
* MSI Queue Interrupt Service routine
*
**********************************************************************/
-void
+static int
ixv_msix_que(void *arg)
{
- struct ix_queue *que = arg;
+ struct ix_rx_queue *que = arg;
struct adapter *adapter = que->adapter;
- struct ifnet *ifp = adapter->ifp;
- struct tx_ring *txr = que->txr;
- struct rx_ring *rxr = que->rxr;
- bool more;
+ struct rx_ring *rxr = &que->rxr;
u32 newitr = 0;
+#ifdef notyet
+ struct tx_ring *txr = &que->txr;
+#endif
ixv_disable_queue(adapter, que->msix);
++que->irqs;
- more = ixgbe_rxeof(que);
-
- IXGBE_TX_LOCK(txr);
- ixgbe_txeof(txr);
- /*
- ** Make certain that if the stack
- ** has anything queued the task gets
- ** scheduled to handle it.
- */
-#ifdef IXGBE_LEGACY_TX
- if (!IFQ_DRV_IS_EMPTY(&adapter->ifp->if_snd))
- ixgbe_start_locked(txr, ifp);
-#else
- if (!drbr_empty(adapter->ifp, txr->br))
- ixgbe_mq_start_locked(ifp, txr);
-#endif
- IXGBE_TX_UNLOCK(txr);
-
/* Do AIM now? */
if (ixv_enable_aim == FALSE)
goto no_calc;
/*
- ** Do Adaptive Interrupt Moderation:
- ** - Write out last calculated setting
- ** - Calculate based on average size over
- ** the last interval.
- */
- if (que->eitr_setting)
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_VTEITR(que->msix),
+ * Do Adaptive Interrupt Moderation:
+ * - Write out last calculated setting
+ * - Calculate based on average size over
+ * the last interval.
+ */
+ if (que->eitr_setting)
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEITR(que->msix),
que->eitr_setting);
-
- que->eitr_setting = 0;
- /* Idle, do nothing */
- if ((txr->bytes == 0) && (rxr->bytes == 0))
- goto no_calc;
-
+ que->eitr_setting = 0;
+
+#ifdef notyet
if ((txr->bytes) && (txr->packets))
- newitr = txr->bytes/txr->packets;
+ newitr = txr->bytes/txr->packets;
+#endif
+ if (rxr->bytes == 0)
+ goto no_calc;
+
if ((rxr->bytes) && (rxr->packets))
- newitr = max(newitr,
- (rxr->bytes / rxr->packets));
+ newitr = max(newitr, (rxr->bytes / rxr->packets));
newitr += 24; /* account for hardware frame, crc */
/* set an upper boundary */
@@ -910,25 +780,23 @@
newitr = (newitr / 2);
newitr |= newitr << 16;
-
- /* save for next interrupt */
- que->eitr_setting = newitr;
- /* Reset state */
- txr->bytes = 0;
- txr->packets = 0;
- rxr->bytes = 0;
- rxr->packets = 0;
+ /* save for next interrupt */
+ que->eitr_setting = newitr;
+
+#if 0
+ /* Reset state */
+ txr->bytes = 0;
+ txr->packets = 0;
+#endif
+ rxr->bytes = 0;
+ rxr->packets = 0;
no_calc:
- if (more)
- taskqueue_enqueue(que->tq, &que->que_task);
- else /* Reenable this interrupt */
- ixv_enable_queue(adapter, que->msix);
- return;
+ return (FILTER_SCHEDULE_THREAD);
}
-static void
+static int
ixv_msix_mbx(void *arg)
{
struct adapter *adapter = arg;
@@ -944,10 +812,11 @@
/* Link status change */
if (reg & IXGBE_EICR_LSC)
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ iflib_admin_intr_deferred(adapter->ctx);
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_EIMS_OTHER);
- return;
+
+ return (FILTER_HANDLED);
}
/*********************************************************************
@@ -959,21 +828,18 @@
*
**********************************************************************/
static void
-ixv_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
+ixv_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
{
- struct adapter *adapter = ifp->if_softc;
+ struct adapter *adapter = iflib_get_softc(ctx);
INIT_DEBUGOUT("ixv_media_status: begin");
- IXGBE_CORE_LOCK(adapter);
- ixv_update_link_status(adapter);
+ ixv_if_update_admin_status(ctx);
ifmr->ifm_status = IFM_AVALID;
ifmr->ifm_active = IFM_ETHER;
- if (!adapter->link_active) {
- IXGBE_CORE_UNLOCK(adapter);
+ if (!adapter->link_active)
return;
- }
ifmr->ifm_status |= IFM_ACTIVE;
@@ -982,12 +848,16 @@
ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
break;
case IXGBE_LINK_SPEED_10GB_FULL:
- ifmr->ifm_active |= IFM_FDX;
+ ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_100_FULL:
+ ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_10_FULL:
+ ifmr->ifm_active |= IFM_10_T | IFM_FDX;
break;
}
- IXGBE_CORE_UNLOCK(adapter);
-
return;
}
@@ -1000,23 +870,23 @@
*
**********************************************************************/
static int
-ixv_media_change(struct ifnet * ifp)
+ixv_if_media_change(if_ctx_t ctx)
{
- struct adapter *adapter = ifp->if_softc;
- struct ifmedia *ifm = &adapter->media;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ifmedia *ifm = iflib_get_media(ctx);
INIT_DEBUGOUT("ixv_media_change: begin");
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
return (EINVAL);
- switch (IFM_SUBTYPE(ifm->ifm_media)) {
- case IFM_AUTO:
- break;
- default:
- device_printf(adapter->dev, "Only auto media type\n");
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ break;
+ default:
+ device_printf(adapter->dev, "Only auto media type\n");
return (EINVAL);
- }
+ }
return (0);
}
@@ -1031,34 +901,25 @@
#define IXGBE_RAR_ENTRIES 16
static void
-ixv_set_multi(struct adapter *adapter)
+ixv_if_multi_set(if_ctx_t ctx)
{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_t ifp = iflib_get_ifp(ctx);
u8 mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];
u8 *update_ptr;
struct ifmultiaddr *ifma;
int mcnt = 0;
- struct ifnet *ifp = adapter->ifp;
- IOCTL_DEBUGOUT("ixv_set_multi: begin");
+ IOCTL_DEBUGOUT("ixv_if_multi_set: begin");
-#if __FreeBSD_version < 800000
- IF_ADDR_LOCK(ifp);
-#else
- if_maddr_rlock(ifp);
-#endif
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
- bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
+ bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
&mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS],
IXGBE_ETH_LENGTH_OF_ADDRESS);
mcnt++;
}
-#if __FreeBSD_version < 800000
- IF_ADDR_UNLOCK(ifp);
-#else
- if_maddr_runlock(ifp);
-#endif
update_ptr = mta;
@@ -1082,108 +943,65 @@
newptr = addr + IXGBE_ETH_LENGTH_OF_ADDRESS;
*update_ptr = newptr;
+
return addr;
}
-/*********************************************************************
+/************************************************************************
* Timer routine
*
- * This routine checks for link status,updates statistics,
+ * This routine checks for link status, updates statistics,
* and runs the watchdog check.
*
- **********************************************************************/
-
+ ************************************************************************/
static void
-ixv_local_timer(void *arg)
+ixv_if_local_timer(if_ctx_t ctx, uint16_t qid)
{
- struct adapter *adapter = arg;
- device_t dev = adapter->dev;
- struct ix_queue *que = adapter->queues;
- u64 queues = 0;
- int hung = 0;
+ struct adapter *adapter = iflib_get_softc(ctx);
- mtx_assert(&adapter->core_mtx, MA_OWNED);
+ if (qid != 0)
+ return;
- ixv_update_link_status(adapter);
+ adapter->hw.mac.get_link_status = TRUE;
+ ixgbe_check_link(&adapter->hw, &adapter->link_speed, &adapter->link_up,
+ FALSE);
+ ixv_if_update_admin_status(ctx);
/* Stats Update */
ixv_update_stats(adapter);
- /*
- ** Check the TX queues status
- ** - mark hung queues so we don't schedule on them
- ** - watchdog only if all queues show hung
- */
- for (int i = 0; i < adapter->num_queues; i++, que++) {
- /* Keep track of queues with work for soft irq */
- if (que->txr->busy)
- queues |= ((u64)1 << que->me);
- /*
- ** Each time txeof runs without cleaning, but there
- ** are uncleaned descriptors it increments busy. If
- ** we get to the MAX we declare it hung.
- */
- if (que->busy == IXGBE_QUEUE_HUNG) {
- ++hung;
- /* Mark the queue as inactive */
- adapter->active_queues &= ~((u64)1 << que->me);
- continue;
- } else {
- /* Check if we've come back from hung */
- if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
- adapter->active_queues |= ((u64)1 << que->me);
- }
- if (que->busy >= IXGBE_MAX_TX_BUSY) {
- device_printf(dev,"Warning queue %d "
- "appears to be hung!\n", i);
- que->txr->busy = IXGBE_QUEUE_HUNG;
- ++hung;
- }
-
- }
-
- /* Only truly watchdog if all queues show hung */
- if (hung == adapter->num_queues)
- goto watchdog;
- else if (queues != 0) { /* Force an IRQ on queues with work */
- ixv_rearm_queues(adapter, queues);
- }
-
- callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
- return;
-
-watchdog:
- device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
- adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- adapter->watchdog_events++;
- ixv_init_locked(adapter);
+ /* Fire off the adminq task */
+ iflib_admin_intr_deferred(ctx);
}
-/*
-** Note: this routine updates the OS on the link state
-** the real check of the hardware only happens with
-** a link interrupt.
-*/
+/************************************************************************
+ * ixv_if_update_admin_status - Update OS on link state
+ *
+ * Note: Only updates the OS on the cached link state.
+ * The real check of the hardware only happens with
+ * a link interrupt.
+ ************************************************************************/
static void
-ixv_update_link_status(struct adapter *adapter)
+ixv_if_update_admin_status(if_ctx_t ctx)
{
- struct ifnet *ifp = adapter->ifp;
- device_t dev = adapter->dev;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ device_t dev = iflib_get_dev(ctx);
- if (adapter->link_up){
+ if (adapter->link_up) {
if (adapter->link_active == FALSE) {
if (bootverbose)
- device_printf(dev,"Link is up %d Gbps %s \n",
- ((adapter->link_speed == 128)? 10:1),
+ device_printf(dev, "Link is up %d Gbps %s \n",
+ ((adapter->link_speed == 128) ? 10 : 1),
"Full Duplex");
adapter->link_active = TRUE;
- if_link_state_change(ifp, LINK_STATE_UP);
+ iflib_link_state_change(ctx, LINK_STATE_UP,
+ IF_Gbps(10));
}
} else { /* Link down */
if (adapter->link_active == TRUE) {
if (bootverbose)
- device_printf(dev,"Link is Down\n");
- if_link_state_change(ifp, LINK_STATE_DOWN);
+ device_printf(dev, "Link is Down\n");
+ iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
adapter->link_active = FALSE;
}
}
@@ -1200,25 +1018,22 @@
**********************************************************************/
static void
-ixv_stop(void *arg)
+ixv_if_stop(if_ctx_t ctx)
{
- struct ifnet *ifp;
- struct adapter *adapter = arg;
+ struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- ifp = adapter->ifp;
-
- mtx_assert(&adapter->core_mtx, MA_OWNED);
INIT_DEBUGOUT("ixv_stop: begin\n");
- ixv_disable_intr(adapter);
- /* Tell the stack that the interface is no longer active */
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ ixv_if_disable_intr(ctx);
ixgbe_reset_hw(hw);
adapter->hw.adapter_stopped = FALSE;
ixgbe_stop_adapter(hw);
- callout_stop(&adapter->timer);
+
+ /* Update the stack */
+ adapter->link_up = FALSE;
+ ixv_if_update_admin_status(ctx);
/* reprogram the RAR[0] in case user changed it. */
ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
@@ -1233,120 +1048,85 @@
*
**********************************************************************/
static void
-ixv_identify_hardware(struct adapter *adapter)
+ixv_identify_hardware(if_ctx_t ctx)
{
- device_t dev = adapter->dev;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ device_t dev = iflib_get_dev(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- /*
- ** Make sure BUSMASTER is set, on a VM under
- ** KVM it may not be and will break things.
- */
- pci_enable_busmaster(dev);
-
/* Save off the information about this board */
hw->vendor_id = pci_get_vendor(dev);
hw->device_id = pci_get_device(dev);
- hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
- hw->subsystem_vendor_id =
- pci_read_config(dev, PCIR_SUBVEND_0, 2);
- hw->subsystem_device_id =
- pci_read_config(dev, PCIR_SUBDEV_0, 2);
+ hw->revision_id = pci_get_revid(dev);
+ hw->subsystem_vendor_id = pci_get_subvendor(dev);
+ hw->subsystem_device_id = pci_get_subdevice(dev);
/* We need this to determine device-specific things */
ixgbe_set_mac_type(hw);
- /* Set the right number of segments */
- adapter->num_segs = IXGBE_82599_SCATTER;
-
return;
}
/*********************************************************************
*
- * Setup MSIX Interrupt resources and handlers
+ * Setup MSIX Interrupt resources and handlers
*
**********************************************************************/
static int
-ixv_allocate_msix(struct adapter *adapter)
+ixv_if_msix_intr_assign(if_ctx_t ctx, int msix)
{
- device_t dev = adapter->dev;
- struct ix_queue *que = adapter->queues;
- struct tx_ring *txr = adapter->tx_rings;
- int error, rid, vector = 0;
-
- for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
+ struct adapter *adapter = iflib_get_softc(ctx);
+ device_t dev = iflib_get_dev(ctx);
+ struct ix_rx_queue *rx_que = adapter->rx_queues;
+ struct ix_tx_queue *tx_que;
+ int error, rid, vector = 0;
+ char buf[16];
+
+ /* Admin Que is vector 0*/
+ rid = vector + 1;
+ for (int i = 0; i < adapter->num_rx_queues; i++, vector++, rx_que++) {
rid = vector + 1;
- que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (que->res == NULL) {
- device_printf(dev,"Unable to allocate"
- " bus resource: que interrupt [%d]\n", vector);
- return (ENXIO);
- }
- /* Set the handler function */
- error = bus_setup_intr(dev, que->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixv_msix_que, que, &que->tag);
+
+ snprintf(buf, sizeof(buf), "rxq%d", i);
+ error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid,
+ IFLIB_INTR_RX, ixv_msix_que, rx_que, rx_que->rxr.me, buf);
+
if (error) {
- que->res = NULL;
- device_printf(dev, "Failed to register QUE handler");
- return (error);
+ device_printf(iflib_get_dev(ctx),
+ "Failed to allocate que int %d err: %d", i, error);
+ adapter->num_rx_queues = i + 1;
+ goto fail;
}
-#if __FreeBSD_version >= 800504
- bus_describe_intr(dev, que->res, que->tag, "que %d", i);
-#endif
- que->msix = vector;
- adapter->active_queues |= (u64)(1 << que->msix);
- /*
- ** Bind the msix vector, and thus the
- ** ring to the corresponding cpu.
- */
- if (adapter->num_queues > 1)
- bus_bind_intr(dev, que->res, i);
- TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
- TASK_INIT(&que->que_task, 0, ixv_handle_que, que);
- que->tq = taskqueue_create_fast("ixv_que", M_NOWAIT,
- taskqueue_thread_enqueue, &que->tq);
- taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
- device_get_nameunit(adapter->dev));
+
+ rx_que->msix = vector;
+ adapter->active_queues |= (u64)(1 << rx_que->msix);
+
}
- /* and Mailbox */
- rid = vector + 1;
- adapter->res = bus_alloc_resource_any(dev,
- SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
- if (!adapter->res) {
- device_printf(dev,"Unable to allocate"
- " bus resource: MBX interrupt [%d]\n", rid);
- return (ENXIO);
+ for (int i = 0; i < adapter->num_tx_queues; i++) {
+ snprintf(buf, sizeof(buf), "txq%d", i);
+ tx_que = &adapter->tx_queues[i];
+ tx_que->msix = i % adapter->num_rx_queues;
+ iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_TX, tx_que,
+ tx_que->txr.me, buf);
}
- /* Set the mbx handler function */
- error = bus_setup_intr(dev, adapter->res,
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixv_msix_mbx, adapter, &adapter->tag);
+ rid = vector + 1;
+ error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid,
+ IFLIB_INTR_ADMIN, ixv_msix_mbx, adapter, 0, "aq");
if (error) {
- adapter->res = NULL;
- device_printf(dev, "Failed to register LINK handler");
+ device_printf(iflib_get_dev(ctx),
+ "Failed to register admin handler");
return (error);
}
-#if __FreeBSD_version >= 800504
- bus_describe_intr(dev, adapter->res, adapter->tag, "mbx");
-#endif
+
adapter->vector = vector;
- /* Tasklets for Mailbox */
- TASK_INIT(&adapter->link_task, 0, ixv_handle_mbx, adapter);
- adapter->tq = taskqueue_create_fast("ixv_mbx", M_NOWAIT,
- taskqueue_thread_enqueue, &adapter->tq);
- taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s mbxq",
- device_get_nameunit(adapter->dev));
/*
- ** Due to a broken design QEMU will fail to properly
- ** enable the guest for MSIX unless the vectors in
- ** the table are all set up, so we must rewrite the
- ** ENABLE in the MSIX control register again at this
- ** point to cause it to successfully initialize us.
- */
+ * Due to a broken design QEMU will fail to properly
+ * enable the guest for MSIX unless the vectors in
+ * the table are all set up, so we must rewrite the
+ * ENABLE in the MSIX control register again at this
+ * point to cause it to successfully initialize us.
+ */
if (adapter->hw.mac.type == ixgbe_mac_82599_vf) {
int msix_ctrl;
pci_find_cap(dev, PCIY_MSIX, &rid);
@@ -1357,65 +1137,21 @@
}
return (0);
-}
-
-/*
- * Setup MSIX resources, note that the VF
- * device MUST use MSIX, there is no fallback.
- */
-static int
-ixv_setup_msix(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- int rid, want, msgs;
-
-
- /* Must have at least 2 MSIX vectors */
- msgs = pci_msix_count(dev);
- if (msgs < 2)
- goto out;
- rid = PCIR_BAR(3);
- adapter->msix_mem = bus_alloc_resource_any(dev,
- SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (adapter->msix_mem == NULL) {
- device_printf(adapter->dev,
- "Unable to map MSIX table \n");
- goto out;
- }
- /*
- ** Want vectors for the queues,
- ** plus an additional for mailbox.
- */
- want = adapter->num_queues + 1;
- if (want > msgs) {
- want = msgs;
- adapter->num_queues = msgs - 1;
- } else
- msgs = want;
- if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) {
- device_printf(adapter->dev,
- "Using MSIX interrupts with %d vectors\n", want);
- return (want);
- }
- /* Release in case alloc was insufficient */
- pci_release_msi(dev);
-out:
- if (adapter->msix_mem != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY,
- rid, adapter->msix_mem);
- adapter->msix_mem = NULL;
- }
- device_printf(adapter->dev,"MSIX config error\n");
- return (ENXIO);
+fail:
+ iflib_irq_free(ctx, &adapter->irq);
+ rx_que = adapter->rx_queues;
+ for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++)
+ iflib_irq_free(ctx, &rx_que->que_irq);
+ return (error);
}
-
static int
-ixv_allocate_pci_resources(struct adapter *adapter)
+ixv_allocate_pci_resources(if_ctx_t ctx)
{
+ struct adapter *adapter = iflib_get_softc(ctx);
int rid;
- device_t dev = adapter->dev;
+ device_t dev = iflib_get_dev(ctx);
rid = PCIR_BAR(0);
adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -1426,86 +1162,38 @@
return (ENXIO);
}
- adapter->osdep.mem_bus_space_tag =
- rman_get_bustag(adapter->pci_mem);
+ adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem);
adapter->osdep.mem_bus_space_handle =
- rman_get_bushandle(adapter->pci_mem);
+ rman_get_bushandle(adapter->pci_mem);
adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle;
/* Pick up the tuneable queues */
- adapter->num_queues = ixv_num_queues;
- adapter->hw.back = adapter;
+ adapter->num_rx_queues = adapter->num_tx_queues = ixv_num_queues;
- /*
- ** Now setup MSI/X, should
- ** return us the number of
- ** configured vectors.
- */
- adapter->msix = ixv_setup_msix(adapter);
- if (adapter->msix == ENXIO)
- return (ENXIO);
- else
- return (0);
+ return (0);
}
static void
-ixv_free_pci_resources(struct adapter * adapter)
+ixv_free_pci_resources(if_ctx_t ctx)
{
- struct ix_queue *que = adapter->queues;
- device_t dev = adapter->dev;
- int rid, memrid;
-
- memrid = PCIR_BAR(MSIX_82598_BAR);
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_rx_queue *que = adapter->rx_queues;
+ device_t dev = iflib_get_dev(ctx);
- /*
- ** There is a slight possibility of a failure mode
- ** in attach that will result in entering this function
- ** before interrupt resources have been initialized, and
- ** in that case we do not want to execute the loops below
- ** We can detect this reliably by the state of the adapter
- ** res pointer.
- */
- if (adapter->res == NULL)
- goto mem;
+ /* Release all msix queue resources */
+ if (adapter->intr_type == IFLIB_INTR_MSIX)
+ iflib_irq_free(ctx, &adapter->irq);
- /*
- ** Release all msix queue resources:
- */
- for (int i = 0; i < adapter->num_queues; i++, que++) {
- rid = que->msix + 1;
- if (que->tag != NULL) {
- bus_teardown_intr(dev, que->res, que->tag);
- que->tag = NULL;
+ if (que != NULL) {
+ for (int i = 0; i < adapter->num_rx_queues; i++, que++) {
+ iflib_irq_free(ctx, &que->que_irq);
}
- if (que->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
}
-
/* Clean the Legacy or Link interrupt last */
- if (adapter->vector) /* we are doing MSIX */
- rid = adapter->vector + 1;
- else
- (adapter->msix != 0) ? (rid = 1):(rid = 0);
-
- if (adapter->tag != NULL) {
- bus_teardown_intr(dev, adapter->res, adapter->tag);
- adapter->tag = NULL;
- }
- if (adapter->res != NULL)
- bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res);
-
-mem:
- if (adapter->msix)
- pci_release_msi(dev);
-
- if (adapter->msix_mem != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- memrid, adapter->msix_mem);
-
if (adapter->pci_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
- PCIR_BAR(0), adapter->pci_mem);
+ PCIR_BAR(0), adapter->pci_mem);
return;
}
@@ -1515,134 +1203,193 @@
* Setup networking device structure and register an interface.
*
**********************************************************************/
-static void
-ixv_setup_interface(device_t dev, struct adapter *adapter)
+static int
+ixv_setup_interface(if_ctx_t ctx)
{
- struct ifnet *ifp;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx = adapter->shared;
+ struct ifnet *ifp = iflib_get_ifp(ctx);
INIT_DEBUGOUT("ixv_setup_interface: begin");
- ifp = adapter->ifp = if_alloc(IFT_ETHER);
- if (ifp == NULL)
- panic("%s: can not if_alloc()\n", device_get_nameunit(dev));
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_baudrate = 1000000000;
- ifp->if_init = ixv_init;
- ifp->if_softc = adapter;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = ixv_ioctl;
-#if __FreeBSD_version >= 800000
- ifp->if_transmit = ixgbe_mq_start;
- ifp->if_qflush = ixgbe_qflush;
-#else
- ifp->if_start = ixgbe_start;
-#endif
- ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 2;
-
- ether_ifattach(ifp, adapter->hw.mac.addr);
-
- adapter->max_frame_size =
- ifp->if_mtu + IXGBE_MTU_HDR_VLAN;
+ if_setifheaderlen(ifp, sizeof(struct ether_vlan_header));
+ if_setbaudrate(ifp, IF_Gbps(10));
+ ifp->if_snd.ifq_maxlen = scctx->isc_ntxd[0] - 2;
- /*
- * Tell the upper layer(s) we support long frames.
- */
- ifp->if_hdrlen = sizeof(struct ether_vlan_header);
-
- ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;
- ifp->if_capabilities |= IFCAP_JUMBO_MTU;
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
- | IFCAP_VLAN_HWTSO
- | IFCAP_VLAN_MTU;
- ifp->if_capabilities |= IFCAP_LRO;
- ifp->if_capenable = ifp->if_capabilities;
-
- /*
- * Specify the media types supported by this adapter and register
- * callbacks to update media and link information
- */
- ifmedia_init(&adapter->media, IFM_IMASK, ixv_media_change,
- ixv_media_status);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
+ adapter->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR_VLAN;
+ if (adapter->feat_en & IXGBE_FEATURE_FRAME_LIMIT)
+ adapter->max_frame_size -= ETHER_VLAN_ENCAP_LEN;
- return;
-}
-
-static void
-ixv_config_link(struct adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- u32 autoneg;
+ ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO);
- if (hw->mac.ops.check_link)
- hw->mac.ops.check_link(hw, &autoneg,
- &adapter->link_up, FALSE);
+ return 0;
}
-
/*********************************************************************
*
* Enable transmit unit.
*
**********************************************************************/
static void
-ixv_initialize_transmit_units(struct adapter *adapter)
+ixv_initialize_transmit_units(if_ctx_t ctx)
{
- struct tx_ring *txr = adapter->tx_rings;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx = adapter->shared;
+ struct ix_tx_queue *que = adapter->tx_queues;
struct ixgbe_hw *hw = &adapter->hw;
+ int i;
-
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- u64 tdba = txr->txdma.dma_paddr;
+ for (i = 0; i < adapter->num_tx_queues; i++, que++) {
+ struct tx_ring *txr = &que->txr;
+ u64 tdba = txr->tx_paddr;
u32 txctrl, txdctl;
+ int j = txr->me;
/* Set WTHRESH to 8, burst writeback */
- txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i));
+ txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j));
txdctl |= (8 << 16);
- IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl);
/* Set the HW Tx Head and Tail indices */
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDH(i), 0);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDT(i), 0);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDH(j), 0);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDT(j), 0);
/* Set Tx Tail register */
- txr->tail = IXGBE_VFTDT(i);
+ txr->tail = IXGBE_VFTDT(j);
+
+ txr->tx_rs_cidx = txr->tx_rs_pidx = txr->tx_cidx_processed = 0;
+ for (int k = 0; k < scctx->isc_ntxd[0]; k++)
+ txr->tx_rsq[k] = QIDX_INVALID;
/* Set Ring parameters */
- IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(i),
- (tdba & 0x00000000ffffffffULL));
- IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(i), (tdba >> 32));
- IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(i),
- adapter->num_tx_desc *
- sizeof(struct ixgbe_legacy_tx_desc));
- txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(i));
+ IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(j),
+ (tdba & 0x00000000ffffffffULL));
+ IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(j), (tdba >> 32));
+ IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(j),
+ scctx->isc_ntxd[0] * sizeof(struct ixgbe_legacy_tx_desc));
+ txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(j));
txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
- IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(i), txctrl);
+ IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(j), txctrl);
/* Now enable */
- txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i));
+ txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j));
txdctl |= IXGBE_TXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl);
}
return;
}
+/************************************************************************
+ * ixv_initialize_rss_mapping
+ ************************************************************************/
+static void
+ixv_initialize_rss_mapping(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reta = 0, mrqc, rss_key[10];
+ int queue_id;
+ int i, j;
+ u32 rss_hash_config;
+
+ if (adapter->feat_en & IXGBE_FEATURE_RSS) {
+ /* Fetch the configured RSS key */
+ rss_getkey((uint8_t *)&rss_key);
+ } else {
+ /* set up random bits */
+ arc4rand(&rss_key, sizeof(rss_key), 0);
+ }
+
+ /* Now fill out hash function seeds */
+ for (i = 0; i < 10; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), rss_key[i]);
+
+ /* Set up the redirection table */
+ for (i = 0, j = 0; i < 64; i++, j++) {
+ if (j == adapter->num_rx_queues)
+ j = 0;
+
+ if (adapter->feat_en & IXGBE_FEATURE_RSS) {
+ /*
+ * Fetch the RSS bucket id for the given indirection
+ * entry. Cap it at the number of configured buckets
+ * (which is num_rx_queues.)
+ */
+ queue_id = rss_get_indirection_to_bucket(i);
+ queue_id = queue_id % adapter->num_rx_queues;
+ } else
+ queue_id = j;
+
+ /*
+ * The low 8 bits are for hash value (n+0);
+ * The next 8 bits are for hash value (n+1), etc.
+ */
+ reta >>= 8;
+ reta |= ((uint32_t)queue_id) << 24;
+ if ((i & 3) == 3) {
+ IXGBE_WRITE_REG(hw, IXGBE_VFRETA(i >> 2), reta);
+ reta = 0;
+ }
+ }
+
+ /* Perform hash on these packet types */
+ if (adapter->feat_en & IXGBE_FEATURE_RSS)
+ rss_hash_config = rss_gethashconfig();
+ else {
+ /*
+ * Disable UDP - IP fragments aren't currently being handled
+ * and so we end up with a mix of 2-tuple and 4-tuple
+ * traffic.
+ */
+ rss_hash_config = RSS_HASHTYPE_RSS_IPV4
+ | RSS_HASHTYPE_RSS_TCP_IPV4
+ | RSS_HASHTYPE_RSS_IPV6
+ | RSS_HASHTYPE_RSS_TCP_IPV6;
+ }
+
+ mrqc = IXGBE_MRQC_RSSEN;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
+ device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_IPV6_EX defined, but not supported\n",
+ __func__);
+ if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
+ device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_TCP_IPV6_EX defined, but not supported\n",
+ __func__);
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
+ device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, but not supported\n",
+ __func__);
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
+ if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
+ device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV6_EX defined, but not supported\n",
+ __func__);
+ IXGBE_WRITE_REG(hw, IXGBE_VFMRQC, mrqc);
+} /* ixv_initialize_rss_mapping */
+
/*********************************************************************
*
* Setup receive registers and features.
*
**********************************************************************/
-#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
-
static void
-ixv_initialize_receive_units(struct adapter *adapter)
+ixv_initialize_receive_units(if_ctx_t ctx)
{
- struct rx_ring *rxr = adapter->rx_rings;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx;
struct ixgbe_hw *hw = &adapter->hw;
- struct ifnet *ifp = adapter->ifp;
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+ struct ix_rx_queue *que = adapter->rx_queues;
u32 bufsz, rxcsum, psrtype;
if (ifp->if_mtu > ETHERMTU)
@@ -1654,21 +1401,29 @@
IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR |
IXGBE_PSRTYPE_L2HDR;
+ if (adapter->num_rx_queues > 1)
+ psrtype |= 1 << 29;
+
IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype);
/* Tell PF our max_frame size */
- ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size);
+ if (ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size) != 0) {
+ device_printf(adapter->dev, "There is a problem with the PF setup. It is likely the receive unit for this VF will not function correctly.\n");
+ }
+ scctx = adapter->shared;
- for (int i = 0; i < adapter->num_queues; i++, rxr++) {
- u64 rdba = rxr->rxdma.dma_paddr;
+ for (int i = 0; i < adapter->num_rx_queues; i++, que++) {
+ struct rx_ring *rxr = &que->rxr;
+ u64 rdba = rxr->rx_paddr;
u32 reg, rxdctl;
+ int j = rxr->me;
/* Disable the queue */
- rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
+ rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
rxdctl &= ~IXGBE_RXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl);
- for (int j = 0; j < 10; j++) {
- if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) &
+ IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl);
+ for (int k = 0; k < 10; k++) {
+ if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)) &
IXGBE_RXDCTL_ENABLE)
msec_delay(1);
else
@@ -1676,37 +1431,35 @@
}
wmb();
/* Setup the Base and Length of the Rx Descriptor Ring */
- IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(i),
+ IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(j),
(rdba & 0x00000000ffffffffULL));
- IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(i),
- (rdba >> 32));
- IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(i),
- adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
+ IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(j), (rdba >> 32));
+ IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(j),
+ scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc));
/* Reset the ring indices */
IXGBE_WRITE_REG(hw, IXGBE_VFRDH(rxr->me), 0);
IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), 0);
/* Set up the SRRCTL register */
- reg = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i));
+ reg = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(j));
reg &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
reg &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
reg |= bufsz;
reg |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
- IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(i), reg);
+ IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(j), reg);
/* Capture Rx Tail index */
rxr->tail = IXGBE_VFRDT(rxr->me);
/* Do the queue enabling last */
rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME;
- IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl);
- for (int k = 0; k < 10; k++) {
- if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) &
+ IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl);
+ for (int l = 0; l < 10; l++) {
+ if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)) &
IXGBE_RXDCTL_ENABLE)
break;
- else
- msec_delay(1);
+ msec_delay(1);
}
wmb();
@@ -1729,19 +1482,26 @@
* so RDT = num_rx_desc - 1 means the whole ring is available.
*/
if (ifp->if_capenable & IFCAP_NETMAP) {
- struct netmap_adapter *na = NA(adapter->ifp);
- struct netmap_kring *kring = &na->rx_rings[i];
+ struct netmap_adapter *na = NA(ifp);
+ struct netmap_kring *kring = &na->rx_rings[j];
int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), t);
} else
#endif /* DEV_NETMAP */
IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me),
- adapter->num_rx_desc - 1);
+ scctx->isc_nrxd[0] - 1);
}
rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+ ixv_initialize_rss_mapping(adapter);
+
+ if (adapter->num_rx_queues > 1) {
+ /* RSS and RX IPP Checksum are mutually exclusive */
+ rxcsum |= IXGBE_RXCSUM_PCSD;
+ }
+
if (ifp->if_capenable & IFCAP_RXCSUM)
rxcsum |= IXGBE_RXCSUM_PCSD;
@@ -1754,11 +1514,11 @@
}
static void
-ixv_setup_vlan_support(struct adapter *adapter)
+ixv_setup_vlan_support(if_ctx_t ctx)
{
+ struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
u32 ctrl, vid, vfta, retry;
- struct rx_ring *rxr;
/*
** We get here thru init_locked, meaning
@@ -1770,7 +1530,7 @@
return;
/* Enable the queues */
- for (int i = 0; i < adapter->num_queues; i++) {
+ for (int i = 0; i < adapter->num_rx_queues; i++) {
ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
ctrl |= IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl);
@@ -1778,8 +1538,7 @@
* Let Rx path know that it needs to store VLAN tag
* as part of extra mbuf info.
*/
- rxr = &adapter->rx_rings[i];
- rxr->vtag_strip = TRUE;
+ adapter->rx_queues[i].rxr.vtag_strip = TRUE;
}
/*
@@ -1801,7 +1560,7 @@
continue;
vid = (i * 32) + j;
/* Call the shared code mailbox routine */
- while (ixgbe_set_vfta(hw, vid, 0, TRUE)) {
+ while (ixgbe_set_vfta(hw, vid, 0, TRUE, FALSE)) {
if (++retry > 5)
break;
}
@@ -1810,76 +1569,56 @@
}
/*
-** This routine is run via an vlan config EVENT,
+** This routine is run via a vlan config EVENT,
** it enables us to use the HW Filter table since
** we can get the vlan id. This just creates the
** entry in the soft version of the VFTA, init will
** repopulate the real table.
*/
static void
-ixv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
+ixv_if_register_vlan(if_ctx_t ctx, u16 vtag)
{
- struct adapter *adapter = ifp->if_softc;
+ struct adapter *adapter = iflib_get_softc(ctx);
u16 index, bit;
- if (ifp->if_softc != arg) /* Not our event */
- return;
-
- if ((vtag == 0) || (vtag > 4095)) /* Invalid */
- return;
-
- IXGBE_CORE_LOCK(adapter);
index = (vtag >> 5) & 0x7F;
bit = vtag & 0x1F;
ixv_shadow_vfta[index] |= (1 << bit);
++adapter->num_vlans;
- /* Re-init to load the changes */
- ixv_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
}
/*
-** This routine is run via an vlan
+** This routine is run via a vlan
** unconfig EVENT, remove our entry
** in the soft vfta.
*/
static void
-ixv_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
+ixv_if_unregister_vlan(if_ctx_t ctx, u16 vtag)
{
- struct adapter *adapter = ifp->if_softc;
+ struct adapter *adapter = iflib_get_softc(ctx);
u16 index, bit;
- if (ifp->if_softc != arg)
- return;
-
- if ((vtag == 0) || (vtag > 4095)) /* Invalid */
- return;
-
- IXGBE_CORE_LOCK(adapter);
index = (vtag >> 5) & 0x7F;
bit = vtag & 0x1F;
ixv_shadow_vfta[index] &= ~(1 << bit);
--adapter->num_vlans;
- /* Re-init to load the changes */
- ixv_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
}
static void
-ixv_enable_intr(struct adapter *adapter)
+ixv_if_enable_intr(if_ctx_t ctx)
{
+ struct adapter *adapter = iflib_get_softc(ctx);
struct ixgbe_hw *hw = &adapter->hw;
- struct ix_queue *que = adapter->queues;
+ struct ix_rx_queue *que = adapter->rx_queues;
u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
-
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
mask = IXGBE_EIMS_ENABLE_MASK;
mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, mask);
- for (int i = 0; i < adapter->num_queues; i++, que++)
+ for (int i = 0; i < adapter->num_rx_queues; i++, que++)
ixv_enable_queue(adapter, que->msix);
IXGBE_WRITE_FLUSH(hw);
@@ -1888,14 +1627,25 @@
}
static void
-ixv_disable_intr(struct adapter *adapter)
+ixv_if_disable_intr(if_ctx_t ctx)
{
+ struct adapter *adapter = iflib_get_softc(ctx);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEIAC, 0);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEIMC, ~0);
IXGBE_WRITE_FLUSH(&adapter->hw);
return;
}
+static int
+ixv_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ix_rx_queue *que = &adapter->rx_queues[rxqid];
+
+ ixv_enable_queue(adapter, que->rxr.me);
+ return (0);
+}
+
/*
** Setup the correct IVAR register for a particular MSIX interrupt
** - entry is the register array entry
@@ -1927,39 +1677,26 @@
static void
ixv_configure_ivars(struct adapter *adapter)
{
- struct ix_queue *que = adapter->queues;
+ struct ix_rx_queue *que = adapter->rx_queues;
+
+ MPASS(adapter->num_rx_queues == adapter->num_tx_queues);
- for (int i = 0; i < adapter->num_queues; i++, que++) {
+ for (int i = 0; i < adapter->num_rx_queues; i++, que++) {
/* First the RX queue entry */
- ixv_set_ivar(adapter, i, que->msix, 0);
+ ixv_set_ivar(adapter, i, que->msix, 0);
/* ... and the TX */
ixv_set_ivar(adapter, i, que->msix, 1);
/* Set an initial value in EITR */
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_VTEITR(que->msix), IXV_EITR_DEFAULT);
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_VTEITR(que->msix), IXV_EITR_DEFAULT);
}
/* For the mailbox interrupt */
- ixv_set_ivar(adapter, 1, adapter->vector, -1);
-}
-
-
-/*
-** Tasklet handler for MSIX MBX interrupts
-** - do outside interrupt since it might sleep
-*/
-static void
-ixv_handle_mbx(void *context, int pending)
-{
- struct adapter *adapter = context;
-
- ixgbe_check_link(&adapter->hw,
- &adapter->link_speed, &adapter->link_up, 0);
- ixv_update_link_status(adapter);
+ ixv_set_ivar(adapter, 1, adapter->vector, -1);
}
/*
-** The VF stats registers never have a truly virgin
+** The VF stats registers never have a truely virgin
** starting point, so this routine tries to make an
** artificial one, marking ground zero on attach as
** it were.
@@ -1980,12 +1717,12 @@
adapter->stats.vf.vfmprc - adapter->stats.vf.base_vfmprc;
}
}
-
+
static void
ixv_init_stats(struct adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
-
+
adapter->stats.vf.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC);
adapter->stats.vf.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB);
adapter->stats.vf.last_vfgorc |=
@@ -2015,7 +1752,7 @@
count |= current; \
}
-#define UPDATE_STAT_36(lsb, msb, last, count) \
+#define UPDATE_STAT_36(lsb, msb, last, count) \
{ \
u64 cur_lsb = IXGBE_READ_REG(hw, lsb); \
u64 cur_msb = IXGBE_READ_REG(hw, msb); \
@@ -2033,17 +1770,17 @@
void
ixv_update_stats(struct adapter *adapter)
{
- struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_hw *hw = &adapter->hw;
- UPDATE_STAT_32(IXGBE_VFGPRC, adapter->stats.vf.last_vfgprc,
+ UPDATE_STAT_32(IXGBE_VFGPRC, adapter->stats.vf.last_vfgprc,
adapter->stats.vf.vfgprc);
- UPDATE_STAT_32(IXGBE_VFGPTC, adapter->stats.vf.last_vfgptc,
+ UPDATE_STAT_32(IXGBE_VFGPTC, adapter->stats.vf.last_vfgptc,
adapter->stats.vf.vfgptc);
- UPDATE_STAT_36(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB,
+ UPDATE_STAT_36(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB,
adapter->stats.vf.last_vfgorc, adapter->stats.vf.vfgorc);
- UPDATE_STAT_36(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB,
+ UPDATE_STAT_36(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB,
adapter->stats.vf.last_vfgotc, adapter->stats.vf.vfgotc);
- UPDATE_STAT_32(IXGBE_VFMPRC, adapter->stats.vf.last_vfmprc,
+ UPDATE_STAT_32(IXGBE_VFMPRC, adapter->stats.vf.last_vfmprc,
adapter->stats.vf.vfmprc);
}
@@ -2054,78 +1791,69 @@
ixv_add_stats_sysctls(struct adapter *adapter)
{
device_t dev = adapter->dev;
- struct ix_queue *que = &adapter->queues[0];
- struct tx_ring *txr = que->txr;
- struct rx_ring *rxr = que->rxr;
-
+ struct ix_tx_queue *tx_que = adapter->tx_queues;
+ struct ix_rx_queue *rx_que = adapter->rx_queues;
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
struct sysctl_oid *tree = device_get_sysctl_tree(dev);
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
struct ixgbevf_hw_stats *stats = &adapter->stats.vf;
-
struct sysctl_oid *stat_node, *queue_node;
struct sysctl_oid_list *stat_list, *queue_list;
+#define QUEUE_NAME_LEN 32
+ char namebuf[QUEUE_NAME_LEN];
+
/* Driver Statistics */
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
- CTLFLAG_RD, &adapter->dropped_pkts,
- "Driver dropped packets");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_failed",
- CTLFLAG_RD, &adapter->mbuf_defrag_failed,
- "m_defrag() failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
- CTLFLAG_RD, &adapter->watchdog_events,
- "Watchdog timeouts");
+ CTLFLAG_RD, &adapter->watchdog_events, "Watchdog timeouts");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
+ CTLFLAG_RD, &adapter->link_irq, "Link MSI-X IRQ Handled");
+
+ for (int i = 0; i < adapter->num_tx_queues; i++, tx_que++) {
+ struct tx_ring *txr = &tx_que->txr;
+ snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
+ queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
+ CTLFLAG_RD, NULL, "Queue Name");
+ queue_list = SYSCTL_CHILDREN(queue_node);
+
+ SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tso_tx",
+ CTLFLAG_RD, &(txr->tso_tx), "TSO");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
+ CTLFLAG_RD, &(txr->total_packets), "TX Packets");
+ }
+
+ for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++) {
+ struct rx_ring *rxr = &rx_que->rxr;
+ snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
+ queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
+ CTLFLAG_RD, NULL, "Queue Name");
+ queue_list = SYSCTL_CHILDREN(queue_node);
+
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
+ CTLFLAG_RD, &(rx_que->irqs), "IRQs on queue");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
+ CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
+ CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received");
+ SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies",
+ CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames");
+ }
stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac",
- CTLFLAG_RD, NULL,
- "VF Statistics (read from HW registers)");
+ CTLFLAG_RD, NULL, "VF Statistics (read from HW registers)");
stat_list = SYSCTL_CHILDREN(stat_node);
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
- CTLFLAG_RD, &stats->vfgprc,
- "Good Packets Received");
+ CTLFLAG_RD, &stats->vfgprc, "Good Packets Received");
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
- CTLFLAG_RD, &stats->vfgorc,
- "Good Octets Received");
+ CTLFLAG_RD, &stats->vfgorc, "Good Octets Received");
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
- CTLFLAG_RD, &stats->vfmprc,
- "Multicast Packets Received");
+ CTLFLAG_RD, &stats->vfmprc, "Multicast Packets Received");
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
- CTLFLAG_RD, &stats->vfgptc,
- "Good Packets Transmitted");
+ CTLFLAG_RD, &stats->vfgptc, "Good Packets Transmitted");
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
- CTLFLAG_RD, &stats->vfgotc,
- "Good Octets Transmitted");
-
- queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "que",
- CTLFLAG_RD, NULL,
- "Queue Statistics (collected by SW)");
- queue_list = SYSCTL_CHILDREN(queue_node);
-
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
- CTLFLAG_RD, &(que->irqs),
- "IRQs on queue");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_irqs",
- CTLFLAG_RD, &(rxr->rx_irq),
- "RX irqs on queue");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
- CTLFLAG_RD, &(rxr->rx_packets),
- "RX packets");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
- CTLFLAG_RD, &(rxr->rx_bytes),
- "RX bytes");
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded",
- CTLFLAG_RD, &(rxr->rx_discarded),
- "Discarded RX packets");
-
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
- CTLFLAG_RD, &(txr->total_packets),
- "TX Packets");
-
- SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_no_desc",
- CTLFLAG_RD, &(txr->no_desc_avail),
- "# of times not enough descriptors were available during TX");
+ CTLFLAG_RD, &stats->vfgotc, "Good Octets Transmitted");
+
}
static void
@@ -2148,39 +1876,14 @@
static void
ixv_print_debug_info(struct adapter *adapter)
{
- device_t dev = adapter->dev;
- struct ixgbe_hw *hw = &adapter->hw;
- struct ix_queue *que = adapter->queues;
- struct rx_ring *rxr;
- struct tx_ring *txr;
- struct lro_ctrl *lro;
-
- device_printf(dev,"Error Byte Count = %u \n",
- IXGBE_READ_REG(hw, IXGBE_ERRBC));
-
- for (int i = 0; i < adapter->num_queues; i++, que++) {
- txr = que->txr;
- rxr = que->rxr;
- lro = &rxr->lro;
- device_printf(dev,"QUE(%d) IRQs Handled: %lu\n",
- que->msix, (long)que->irqs);
- device_printf(dev,"RX(%d) Packets Received: %lld\n",
- rxr->me, (long long)rxr->rx_packets);
- device_printf(dev,"RX(%d) Bytes Received: %lu\n",
- rxr->me, (long)rxr->rx_bytes);
- device_printf(dev,"RX(%d) LRO Queued= %lld\n",
- rxr->me, (long long)lro->lro_queued);
- device_printf(dev,"RX(%d) LRO Flushed= %lld\n",
- rxr->me, (long long)lro->lro_flushed);
- device_printf(dev,"TX(%d) Packets Sent: %lu\n",
- txr->me, (long)txr->total_packets);
- device_printf(dev,"TX(%d) NO Desc Avail: %lu\n",
- txr->me, (long)txr->no_desc_avail);
- }
-
- device_printf(dev,"MBX IRQ Handled: %lu\n",
- (long)adapter->link_irq);
- return;
+ device_t dev = adapter->dev;
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ device_printf(dev, "Error Byte Count = %u \n",
+ IXGBE_READ_REG(hw, IXGBE_ERRBC));
+
+ device_printf(dev, "MBX IRQ Handled: %lu\n", (long)adapter->link_irq);
+ return;
}
static int
@@ -2196,9 +1899,52 @@
return (error);
if (result == 1) {
- adapter = (struct adapter *) arg1;
+ adapter = (struct adapter *)arg1;
ixv_print_debug_info(adapter);
}
return error;
}
+/************************************************************************
+ * ixv_init_device_features
+ ************************************************************************/
+static void
+ixv_init_device_features(struct adapter *adapter)
+{
+ adapter->feat_cap = IXGBE_FEATURE_NETMAP
+ | IXGBE_FEATURE_VF
+ | IXGBE_FEATURE_RSS;
+
+ /* A tad short on feature flags for VFs, atm. */
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599_vf:
+ adapter->feat_cap |= IXGBE_FEATURE_FRAME_LIMIT;
+ break;
+ case ixgbe_mac_X540_vf:
+ break;
+ case ixgbe_mac_X550_vf:
+ case ixgbe_mac_X550EM_x_vf:
+ case ixgbe_mac_X550EM_a_vf:
+ adapter->feat_cap |= IXGBE_FEATURE_NEEDS_CTXD;
+ default:
+ break;
+ }
+
+ /* Enabled by default... */
+ /* Is a virtual function (VF) */
+ if (adapter->feat_cap & IXGBE_FEATURE_VF)
+ adapter->feat_en |= IXGBE_FEATURE_VF;
+ /* Netmap */
+ if (adapter->feat_cap & IXGBE_FEATURE_NETMAP)
+ adapter->feat_en |= IXGBE_FEATURE_NETMAP;
+ /* Receive-Side Scaling (RSS) */
+ if (adapter->feat_cap & IXGBE_FEATURE_RSS)
+ adapter->feat_en |= IXGBE_FEATURE_RSS;
+ /* Frame size limitation */
+ if (adapter->feat_cap & IXGBE_FEATURE_FRAME_LIMIT)
+ adapter->feat_en |= IXGBE_FEATURE_FRAME_LIMIT;
+ /* Needs advanced context descriptor regardless of offloads req'd */
+ if (adapter->feat_cap & IXGBE_FEATURE_NEEDS_CTXD)
+ adapter->feat_en |= IXGBE_FEATURE_NEEDS_CTXD;
+} /* ixv_init_device_features */
+
Index: sys/dev/ixgbe/if_sriov.c
===================================================================
--- /dev/null
+++ sys/dev/ixgbe/if_sriov.c
@@ -0,0 +1,894 @@
+/******************************************************************************
+
+ Copyright (c) 2001-2017, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*$FreeBSD$*/
+
+#include "ixgbe.h"
+
+#ifdef PCI_IOV
+
+MALLOC_DECLARE(M_IXGBE);
+
+/************************************************************************
+ * ixgbe_pci_iov_detach
+ ************************************************************************/
+int
+ixgbe_pci_iov_detach(device_t dev)
+{
+ return pci_iov_detach(dev);
+}
+
+/************************************************************************
+ * ixgbe_define_iov_schemas
+ ************************************************************************/
+void
+ixgbe_define_iov_schemas(device_t dev, int *error)
+{
+ nvlist_t *pf_schema, *vf_schema;
+
+ pf_schema = pci_iov_schema_alloc_node();
+ vf_schema = pci_iov_schema_alloc_node();
+ pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL);
+ pci_iov_schema_add_bool(vf_schema, "mac-anti-spoof",
+ IOV_SCHEMA_HASDEFAULT, TRUE);
+ pci_iov_schema_add_bool(vf_schema, "allow-set-mac",
+ IOV_SCHEMA_HASDEFAULT, FALSE);
+ pci_iov_schema_add_bool(vf_schema, "allow-promisc",
+ IOV_SCHEMA_HASDEFAULT, FALSE);
+ *error = pci_iov_attach(dev, pf_schema, vf_schema);
+ if (*error != 0) {
+ device_printf(dev,
+ "Error %d setting up SR-IOV\n", *error);
+ }
+} /* ixgbe_define_iov_schemas */
+
+/************************************************************************
+ * ixgbe_align_all_queue_indices
+ ************************************************************************/
+inline void
+ixgbe_align_all_queue_indices(struct adapter *adapter)
+{
+ int i;
+ int index;
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ index = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool, i);
+ adapter->rx_queues[i].rxr.me = index;
+ }
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ index = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool, i);
+ adapter->tx_queues[i].txr.me = index;
+ }
+}
+
+/* Support functions for SR-IOV/VF management */
+static inline void
+ixgbe_send_vf_msg(struct adapter *adapter, struct ixgbe_vf *vf, u32 msg)
+{
+ if (vf->flags & IXGBE_VF_CTS)
+ msg |= IXGBE_VT_MSGTYPE_CTS;
+
+ adapter->hw.mbx.ops.write(&adapter->hw, &msg, 1, vf->pool);
+}
+
+static inline void
+ixgbe_send_vf_ack(struct adapter *adapter, struct ixgbe_vf *vf, u32 msg)
+{
+ msg &= IXGBE_VT_MSG_MASK;
+ ixgbe_send_vf_msg(adapter, vf, msg | IXGBE_VT_MSGTYPE_ACK);
+}
+
+static inline void
+ixgbe_send_vf_nack(struct adapter *adapter, struct ixgbe_vf *vf, u32 msg)
+{
+ msg &= IXGBE_VT_MSG_MASK;
+ ixgbe_send_vf_msg(adapter, vf, msg | IXGBE_VT_MSGTYPE_NACK);
+}
+
+static inline void
+ixgbe_process_vf_ack(struct adapter *adapter, struct ixgbe_vf *vf)
+{
+ if (!(vf->flags & IXGBE_VF_CTS))
+ ixgbe_send_vf_nack(adapter, vf, 0);
+}
+
+static inline boolean_t
+ixgbe_vf_mac_changed(struct ixgbe_vf *vf, const uint8_t *mac)
+{
+ return (bcmp(mac, vf->ether_addr, ETHER_ADDR_LEN) != 0);
+}
+
+static inline int
+ixgbe_vf_queues(int mode)
+{
+ switch (mode) {
+ case IXGBE_64_VM:
+ return (2);
+ case IXGBE_32_VM:
+ return (4);
+ case IXGBE_NO_VM:
+ default:
+ return (0);
+ }
+}
+
+inline int
+ixgbe_vf_que_index(int mode, int vfnum, int num)
+{
+ return ((vfnum * ixgbe_vf_queues(mode)) + num);
+}
+
+static inline void
+ixgbe_update_max_frame(struct adapter * adapter, int max_frame)
+{
+ if (adapter->max_frame_size < max_frame)
+ adapter->max_frame_size = max_frame;
+}
+
+inline u32
+ixgbe_get_mrqc(int iov_mode)
+{
+ u32 mrqc;
+
+ switch (iov_mode) {
+ case IXGBE_64_VM:
+ mrqc = IXGBE_MRQC_VMDQRSS64EN;
+ break;
+ case IXGBE_32_VM:
+ mrqc = IXGBE_MRQC_VMDQRSS32EN;
+ break;
+ case IXGBE_NO_VM:
+ mrqc = 0;
+ break;
+ default:
+ panic("Unexpected SR-IOV mode %d", iov_mode);
+ }
+
+ return mrqc;
+}
+
+
+inline u32
+ixgbe_get_mtqc(int iov_mode)
+{
+ uint32_t mtqc;
+
+ switch (iov_mode) {
+ case IXGBE_64_VM:
+ mtqc = IXGBE_MTQC_64VF | IXGBE_MTQC_VT_ENA;
+ break;
+ case IXGBE_32_VM:
+ mtqc = IXGBE_MTQC_32VF | IXGBE_MTQC_VT_ENA;
+ break;
+ case IXGBE_NO_VM:
+ mtqc = IXGBE_MTQC_64Q_1PB;
+ break;
+ default:
+ panic("Unexpected SR-IOV mode %d", iov_mode);
+ }
+
+ return mtqc;
+}
+
+void
+ixgbe_ping_all_vfs(struct adapter *adapter)
+{
+ struct ixgbe_vf *vf;
+
+ for (int i = 0; i < adapter->num_vfs; i++) {
+ vf = &adapter->vfs[i];
+ if (vf->flags & IXGBE_VF_ACTIVE)
+ ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG);
+ }
+} /* ixgbe_ping_all_vfs */
+
+
+static void
+ixgbe_vf_set_default_vlan(struct adapter *adapter, struct ixgbe_vf *vf,
+ uint16_t tag)
+{
+ struct ixgbe_hw *hw;
+ uint32_t vmolr, vmvir;
+
+ hw = &adapter->hw;
+
+ vf->vlan_tag = tag;
+
+ vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf->pool));
+
+ /* Do not receive packets that pass inexact filters. */
+ vmolr &= ~(IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE);
+
+ /* Disable Multicast Promicuous Mode. */
+ vmolr &= ~IXGBE_VMOLR_MPE;
+
+ /* Accept broadcasts. */
+ vmolr |= IXGBE_VMOLR_BAM;
+
+ if (tag == 0) {
+ /* Accept non-vlan tagged traffic. */
+ vmolr |= IXGBE_VMOLR_AUPE;
+
+ /* Allow VM to tag outgoing traffic; no default tag. */
+ vmvir = 0;
+ } else {
+ /* Require vlan-tagged traffic. */
+ vmolr &= ~IXGBE_VMOLR_AUPE;
+
+ /* Tag all traffic with provided vlan tag. */
+ vmvir = (tag | IXGBE_VMVIR_VLANA_DEFAULT);
+ }
+ IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf->pool), vmolr);
+ IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf->pool), vmvir);
+} /* ixgbe_vf_set_default_vlan */
+
+
+static boolean_t
+ixgbe_vf_frame_size_compatible(struct adapter *adapter, struct ixgbe_vf *vf)
+{
+
+ /*
+ * Frame size compatibility between PF and VF is only a problem on
+ * 82599-based cards. X540 and later support any combination of jumbo
+ * frames on PFs and VFs.
+ */
+ if (adapter->hw.mac.type != ixgbe_mac_82599EB)
+ return (TRUE);
+
+ switch (vf->api_ver) {
+ case IXGBE_API_VER_1_0:
+ case IXGBE_API_VER_UNKNOWN:
+ /*
+ * On legacy (1.0 and older) VF versions, we don't support jumbo
+ * frames on either the PF or the VF.
+ */
+ if (adapter->max_frame_size > ETHER_MAX_LEN ||
+ vf->maximum_frame_size > ETHER_MAX_LEN)
+ return (FALSE);
+
+ return (TRUE);
+
+ break;
+ case IXGBE_API_VER_1_1:
+ default:
+ /*
+ * 1.1 or later VF versions always work if they aren't using
+ * jumbo frames.
+ */
+ if (vf->maximum_frame_size <= ETHER_MAX_LEN)
+ return (TRUE);
+
+ /*
+ * Jumbo frames only work with VFs if the PF is also using jumbo
+ * frames.
+ */
+ if (adapter->max_frame_size <= ETHER_MAX_LEN)
+ return (TRUE);
+
+ return (FALSE);
+ }
+} /* ixgbe_vf_frame_size_compatible */
+
+
+static void
+ixgbe_process_vf_reset(struct adapter *adapter, struct ixgbe_vf *vf)
+{
+ ixgbe_vf_set_default_vlan(adapter, vf, vf->default_vlan);
+
+ // XXX clear multicast addresses
+
+ ixgbe_clear_rar(&adapter->hw, vf->rar_index);
+
+ vf->api_ver = IXGBE_API_VER_UNKNOWN;
+} /* ixgbe_process_vf_reset */
+
+
+static void
+ixgbe_vf_enable_transmit(struct adapter *adapter, struct ixgbe_vf *vf)
+{
+ struct ixgbe_hw *hw;
+ uint32_t vf_index, vfte;
+
+ hw = &adapter->hw;
+
+ vf_index = IXGBE_VF_INDEX(vf->pool);
+ vfte = IXGBE_READ_REG(hw, IXGBE_VFTE(vf_index));
+ vfte |= IXGBE_VF_BIT(vf->pool);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_index), vfte);
+} /* ixgbe_vf_enable_transmit */
+
+
+static void
+ixgbe_vf_enable_receive(struct adapter *adapter, struct ixgbe_vf *vf)
+{
+ struct ixgbe_hw *hw;
+ uint32_t vf_index, vfre;
+
+ hw = &adapter->hw;
+
+ vf_index = IXGBE_VF_INDEX(vf->pool);
+ vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(vf_index));
+ if (ixgbe_vf_frame_size_compatible(adapter, vf))
+ vfre |= IXGBE_VF_BIT(vf->pool);
+ else
+ vfre &= ~IXGBE_VF_BIT(vf->pool);
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_index), vfre);
+} /* ixgbe_vf_enable_receive */
+
+
+static void
+ixgbe_vf_reset_msg(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+{
+ struct ixgbe_hw *hw;
+ uint32_t ack;
+ uint32_t resp[IXGBE_VF_PERMADDR_MSG_LEN];
+
+ hw = &adapter->hw;
+
+ ixgbe_process_vf_reset(adapter, vf);
+
+ if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
+ ixgbe_set_rar(&adapter->hw, vf->rar_index, vf->ether_addr,
+ vf->pool, TRUE);
+ ack = IXGBE_VT_MSGTYPE_ACK;
+ } else
+ ack = IXGBE_VT_MSGTYPE_NACK;
+
+ ixgbe_vf_enable_transmit(adapter, vf);
+ ixgbe_vf_enable_receive(adapter, vf);
+
+ vf->flags |= IXGBE_VF_CTS;
+
+ resp[0] = IXGBE_VF_RESET | ack | IXGBE_VT_MSGTYPE_CTS;
+ bcopy(vf->ether_addr, &resp[1], ETHER_ADDR_LEN);
+ resp[3] = hw->mac.mc_filter_type;
+ ixgbe_write_mbx(hw, resp, IXGBE_VF_PERMADDR_MSG_LEN, vf->pool);
+} /* ixgbe_vf_reset_msg */
+
+
+static void
+ixgbe_vf_set_mac(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+{
+ uint8_t *mac;
+
+ mac = (uint8_t*)&msg[1];
+
+ /* Check that the VF has permission to change the MAC address. */
+ if (!(vf->flags & IXGBE_VF_CAP_MAC) && ixgbe_vf_mac_changed(vf, mac)) {
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ return;
+ }
+
+ if (ixgbe_validate_mac_addr(mac) != 0) {
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ return;
+ }
+
+ bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN);
+
+ ixgbe_set_rar(&adapter->hw, vf->rar_index, vf->ether_addr, vf->pool,
+ TRUE);
+
+ ixgbe_send_vf_ack(adapter, vf, msg[0]);
+} /* ixgbe_vf_set_mac */
+
+
+/*
+ * VF multicast addresses are set by using the appropriate bit in
+ * 1 of 128 32 bit addresses (4096 possible).
+ */
+static void
+ixgbe_vf_set_mc_addr(struct adapter *adapter, struct ixgbe_vf *vf, u32 *msg)
+{
+ u16 *list = (u16*)&msg[1];
+ int entries;
+ u32 vmolr, vec_bit, vec_reg, mta_reg;
+
+ entries = (msg[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
+ entries = min(entries, IXGBE_MAX_VF_MC);
+
+ vmolr = IXGBE_READ_REG(&adapter->hw, IXGBE_VMOLR(vf->pool));
+
+ vf->num_mc_hashes = entries;
+
+ /* Set the appropriate MTA bit */
+ for (int i = 0; i < entries; i++) {
+ vf->mc_hash[i] = list[i];
+ vec_reg = (vf->mc_hash[i] >> 5) & 0x7F;
+ vec_bit = vf->mc_hash[i] & 0x1F;
+ mta_reg = IXGBE_READ_REG(&adapter->hw, IXGBE_MTA(vec_reg));
+ mta_reg |= (1 << vec_bit);
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_MTA(vec_reg), mta_reg);
+ }
+
+ vmolr |= IXGBE_VMOLR_ROMPE;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_VMOLR(vf->pool), vmolr);
+ ixgbe_send_vf_ack(adapter, vf, msg[0]);
+} /* ixgbe_vf_set_mc_addr */
+
+
+static void
+ixgbe_vf_set_vlan(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+{
+ struct ixgbe_hw *hw;
+ int enable;
+ uint16_t tag;
+
+ hw = &adapter->hw;
+ enable = IXGBE_VT_MSGINFO(msg[0]);
+ tag = msg[1] & IXGBE_VLVF_VLANID_MASK;
+
+ if (!(vf->flags & IXGBE_VF_CAP_VLAN)) {
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ return;
+ }
+
+ /* It is illegal to enable vlan tag 0. */
+ if (tag == 0 && enable != 0) {
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ return;
+ }
+
+ ixgbe_set_vfta(hw, tag, vf->pool, enable, false);
+ ixgbe_send_vf_ack(adapter, vf, msg[0]);
+} /* ixgbe_vf_set_vlan */
+
+
+static void
+ixgbe_vf_set_lpe(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+{
+ struct ixgbe_hw *hw;
+ uint32_t vf_max_size, pf_max_size, mhadd;
+
+ hw = &adapter->hw;
+ vf_max_size = msg[1];
+
+ if (vf_max_size < ETHER_CRC_LEN) {
+ /* We intentionally ACK invalid LPE requests. */
+ ixgbe_send_vf_ack(adapter, vf, msg[0]);
+ return;
+ }
+
+ vf_max_size -= ETHER_CRC_LEN;
+
+ if (vf_max_size > IXGBE_MAX_FRAME_SIZE) {
+ /* We intentionally ACK invalid LPE requests. */
+ ixgbe_send_vf_ack(adapter, vf, msg[0]);
+ return;
+ }
+
+ vf->maximum_frame_size = vf_max_size;
+ ixgbe_update_max_frame(adapter, vf->maximum_frame_size);
+
+ /*
+ * We might have to disable reception to this VF if the frame size is
+ * not compatible with the config on the PF.
+ */
+ ixgbe_vf_enable_receive(adapter, vf);
+
+ mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
+ pf_max_size = (mhadd & IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
+
+ if (pf_max_size < adapter->max_frame_size) {
+ mhadd &= ~IXGBE_MHADD_MFS_MASK;
+ mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
+ IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
+ }
+
+ ixgbe_send_vf_ack(adapter, vf, msg[0]);
+} /* ixgbe_vf_set_lpe */
+
+
+static void
+ixgbe_vf_set_macvlan(struct adapter *adapter, struct ixgbe_vf *vf,
+ uint32_t *msg)
+{
+ //XXX implement this
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+} /* ixgbe_vf_set_macvlan */
+
+
+static void
+ixgbe_vf_api_negotiate(struct adapter *adapter, struct ixgbe_vf *vf,
+ uint32_t *msg)
+{
+
+ switch (msg[1]) {
+ case IXGBE_API_VER_1_0:
+ case IXGBE_API_VER_1_1:
+ vf->api_ver = msg[1];
+ ixgbe_send_vf_ack(adapter, vf, msg[0]);
+ break;
+ default:
+ vf->api_ver = IXGBE_API_VER_UNKNOWN;
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ break;
+ }
+} /* ixgbe_vf_api_negotiate */
+
+
+static void
+ixgbe_vf_get_queues(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
+{
+ struct ixgbe_hw *hw;
+ uint32_t resp[IXGBE_VF_GET_QUEUES_RESP_LEN];
+ int num_queues;
+
+ hw = &adapter->hw;
+
+ /* GET_QUEUES is not supported on pre-1.1 APIs. */
+ switch (msg[0]) {
+ case IXGBE_API_VER_1_0:
+ case IXGBE_API_VER_UNKNOWN:
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ return;
+ }
+
+ resp[0] = IXGBE_VF_GET_QUEUES | IXGBE_VT_MSGTYPE_ACK |
+ IXGBE_VT_MSGTYPE_CTS;
+
+ num_queues = ixgbe_vf_queues(adapter->iov_mode);
+ resp[IXGBE_VF_TX_QUEUES] = num_queues;
+ resp[IXGBE_VF_RX_QUEUES] = num_queues;
+ resp[IXGBE_VF_TRANS_VLAN] = (vf->default_vlan != 0);
+ resp[IXGBE_VF_DEF_QUEUE] = 0;
+
+ ixgbe_write_mbx(hw, resp, IXGBE_VF_GET_QUEUES_RESP_LEN, vf->pool);
+} /* ixgbe_vf_get_queues */
+
+
+static void
+ixgbe_process_vf_msg(if_ctx_t ctx, struct ixgbe_vf *vf)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+#ifdef KTR
+ struct ifnet *ifp = iflib_get_ifp(ctx);
+#endif
+ struct ixgbe_hw *hw;
+ uint32_t msg[IXGBE_VFMAILBOX_SIZE];
+ int error;
+
+ hw = &adapter->hw;
+
+ error = hw->mbx.ops.read(hw, msg, IXGBE_VFMAILBOX_SIZE, vf->pool);
+
+ if (error != 0)
+ return;
+
+ CTR3(KTR_MALLOC, "%s: received msg %x from %d", ifp->if_xname,
+ msg[0], vf->pool);
+ if (msg[0] == IXGBE_VF_RESET) {
+ ixgbe_vf_reset_msg(adapter, vf, msg);
+ return;
+ }
+
+ if (!(vf->flags & IXGBE_VF_CTS)) {
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ return;
+ }
+
+ switch (msg[0] & IXGBE_VT_MSG_MASK) {
+ case IXGBE_VF_SET_MAC_ADDR:
+ ixgbe_vf_set_mac(adapter, vf, msg);
+ break;
+ case IXGBE_VF_SET_MULTICAST:
+ ixgbe_vf_set_mc_addr(adapter, vf, msg);
+ break;
+ case IXGBE_VF_SET_VLAN:
+ ixgbe_vf_set_vlan(adapter, vf, msg);
+ break;
+ case IXGBE_VF_SET_LPE:
+ ixgbe_vf_set_lpe(adapter, vf, msg);
+ break;
+ case IXGBE_VF_SET_MACVLAN:
+ ixgbe_vf_set_macvlan(adapter, vf, msg);
+ break;
+ case IXGBE_VF_API_NEGOTIATE:
+ ixgbe_vf_api_negotiate(adapter, vf, msg);
+ break;
+ case IXGBE_VF_GET_QUEUES:
+ ixgbe_vf_get_queues(adapter, vf, msg);
+ break;
+ default:
+ ixgbe_send_vf_nack(adapter, vf, msg[0]);
+ }
+} /* ixgbe_process_vf_msg */
+
+
+/* Tasklet for handling VF -> PF mailbox messages */
+void
+ixgbe_handle_mbx(void *context)
+{
+ if_ctx_t ctx = context;
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct ixgbe_hw *hw;
+ struct ixgbe_vf *vf;
+ int i;
+
+ hw = &adapter->hw;
+
+ for (i = 0; i < adapter->num_vfs; i++) {
+ vf = &adapter->vfs[i];
+
+ if (vf->flags & IXGBE_VF_ACTIVE) {
+ if (hw->mbx.ops.check_for_rst(hw, vf->pool) == 0)
+ ixgbe_process_vf_reset(adapter, vf);
+
+ if (hw->mbx.ops.check_for_msg(hw, vf->pool) == 0)
+ ixgbe_process_vf_msg(ctx, vf);
+
+ if (hw->mbx.ops.check_for_ack(hw, vf->pool) == 0)
+ ixgbe_process_vf_ack(adapter, vf);
+ }
+ }
+} /* ixgbe_handle_mbx */
+
+int
+ixgbe_if_iov_init(if_ctx_t ctx, u16 num_vfs, const nvlist_t *config)
+{
+ struct adapter *adapter;
+ int retval = 0;
+
+ adapter = iflib_get_softc(ctx);
+ adapter->iov_mode = IXGBE_NO_VM;
+
+ if (num_vfs == 0) {
+ /* Would we ever get num_vfs = 0? */
+ retval = EINVAL;
+ goto err_init_iov;
+ }
+
+ /*
+ * We've got to reserve a VM's worth of queues for the PF,
+ * thus we go into "64 VF mode" if 32+ VFs are requested.
+ * With 64 VFs, you can only have two queues per VF.
+ * With 32 VFs, you can have up to four queues per VF.
+ */
+ if (num_vfs >= IXGBE_32_VM)
+ adapter->iov_mode = IXGBE_64_VM;
+ else
+ adapter->iov_mode = IXGBE_32_VM;
+
+ /* Again, reserving 1 VM's worth of queues for the PF */
+ adapter->pool = adapter->iov_mode - 1;
+
+ if ((num_vfs > adapter->pool) || (num_vfs >= IXGBE_64_VM)) {
+ retval = ENOSPC;
+ goto err_init_iov;
+ }
+
+ adapter->vfs = malloc(sizeof(*adapter->vfs) * num_vfs, M_IXGBE,
+ M_NOWAIT | M_ZERO);
+
+ if (adapter->vfs == NULL) {
+ retval = ENOMEM;
+ goto err_init_iov;
+ }
+
+ adapter->num_vfs = num_vfs;
+ ixgbe_if_init(adapter->ctx);
+ adapter->feat_en |= IXGBE_FEATURE_SRIOV;
+
+ return (retval);
+
+err_init_iov:
+ adapter->num_vfs = 0;
+ adapter->pool = 0;
+ adapter->iov_mode = IXGBE_NO_VM;
+
+ return (retval);
+} /* ixgbe_if_iov_init */
+
+void
+ixgbe_if_iov_uninit(if_ctx_t ctx)
+{
+ struct ixgbe_hw *hw;
+ struct adapter *adapter;
+ uint32_t pf_reg, vf_reg;
+
+ adapter = iflib_get_softc(ctx);
+ hw = &adapter->hw;
+
+ /* Enable rx/tx for the PF and disable it for all VFs. */
+ pf_reg = IXGBE_VF_INDEX(adapter->pool);
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(pf_reg), IXGBE_VF_BIT(adapter->pool));
+ IXGBE_WRITE_REG(hw, IXGBE_VFTE(pf_reg), IXGBE_VF_BIT(adapter->pool));
+
+ if (pf_reg == 0)
+ vf_reg = 1;
+ else
+ vf_reg = 0;
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg), 0);
+
+ IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, 0);
+
+ free(adapter->vfs, M_IXGBE);
+ adapter->vfs = NULL;
+ adapter->num_vfs = 0;
+ adapter->feat_en &= ~IXGBE_FEATURE_SRIOV;
+} /* ixgbe_if_iov_uninit */
+
+static void
+ixgbe_init_vf(struct adapter *adapter, struct ixgbe_vf *vf)
+{
+ struct ixgbe_hw *hw;
+ uint32_t vf_index, pfmbimr;
+
+ hw = &adapter->hw;
+
+ if (!(vf->flags & IXGBE_VF_ACTIVE))
+ return;
+
+ vf_index = IXGBE_VF_INDEX(vf->pool);
+ pfmbimr = IXGBE_READ_REG(hw, IXGBE_PFMBIMR(vf_index));
+ pfmbimr |= IXGBE_VF_BIT(vf->pool);
+ IXGBE_WRITE_REG(hw, IXGBE_PFMBIMR(vf_index), pfmbimr);
+
+ ixgbe_vf_set_default_vlan(adapter, vf, vf->vlan_tag);
+
+ // XXX multicast addresses
+
+ if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
+ ixgbe_set_rar(&adapter->hw, vf->rar_index,
+ vf->ether_addr, vf->pool, TRUE);
+ }
+
+ ixgbe_vf_enable_transmit(adapter, vf);
+ ixgbe_vf_enable_receive(adapter, vf);
+
+ ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG);
+} /* ixgbe_init_vf */
+
+void
+ixgbe_initialize_iov(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ uint32_t mrqc, mtqc, vt_ctl, vf_reg, gcr_ext, gpie;
+ int i;
+
+ if (adapter->iov_mode == IXGBE_NO_VM)
+ return;
+
+ /* RMW appropriate registers based on IOV mode */
+ /* Read... */
+ mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC);
+ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+ gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+ /* Modify... */
+ mrqc &= ~IXGBE_MRQC_MRQE_MASK;
+ mtqc = IXGBE_MTQC_VT_ENA; /* No initial MTQC read needed */
+ gcr_ext |= IXGBE_GCR_EXT_MSIX_EN;
+ gcr_ext &= ~IXGBE_GCR_EXT_VT_MODE_MASK;
+ gpie &= ~IXGBE_GPIE_VTMODE_MASK;
+ switch (adapter->iov_mode) {
+ case IXGBE_64_VM:
+ mrqc |= IXGBE_MRQC_VMDQRSS64EN;
+ mtqc |= IXGBE_MTQC_64VF;
+ gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64;
+ gpie |= IXGBE_GPIE_VTMODE_64;
+ break;
+ case IXGBE_32_VM:
+ mrqc |= IXGBE_MRQC_VMDQRSS32EN;
+ mtqc |= IXGBE_MTQC_32VF;
+ gcr_ext |= IXGBE_GCR_EXT_VT_MODE_32;
+ gpie |= IXGBE_GPIE_VTMODE_32;
+ break;
+ default:
+ panic("Unexpected SR-IOV mode %d", adapter->iov_mode);
+ }
+ /* Write... */
+ IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+ IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc);
+ IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
+ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+
+ /* Enable rx/tx for the PF. */
+ vf_reg = IXGBE_VF_INDEX(adapter->pool);
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg), IXGBE_VF_BIT(adapter->pool));
+ IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg), IXGBE_VF_BIT(adapter->pool));
+
+ /* Allow VM-to-VM communication. */
+ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+
+ vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN;
+ vt_ctl |= (adapter->pool << IXGBE_VT_CTL_POOL_SHIFT);
+ IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl);
+
+ for (i = 0; i < adapter->num_vfs; i++)
+ ixgbe_init_vf(adapter, &adapter->vfs[i]);
+} /* ixgbe_initialize_iov */
+
+
+/* Check the max frame setting of all active VF's */
+void
+ixgbe_recalculate_max_frame(struct adapter *adapter)
+{
+ struct ixgbe_vf *vf;
+
+ for (int i = 0; i < adapter->num_vfs; i++) {
+ vf = &adapter->vfs[i];
+ if (vf->flags & IXGBE_VF_ACTIVE)
+ ixgbe_update_max_frame(adapter, vf->maximum_frame_size);
+ }
+} /* ixgbe_recalculate_max_frame */
+
+int
+ixgbe_if_iov_vf_add(if_ctx_t ctx, u16 vfnum, const nvlist_t *config)
+{
+ struct adapter *adapter;
+ struct ixgbe_vf *vf;
+ const void *mac;
+
+ adapter = iflib_get_softc(ctx);
+
+ KASSERT(vfnum < adapter->num_vfs, ("VF index %d is out of range %d",
+ vfnum, adapter->num_vfs));
+
+ vf = &adapter->vfs[vfnum];
+ vf->pool= vfnum;
+
+ /* RAR[0] is used by the PF so use vfnum + 1 for VF RAR. */
+ vf->rar_index = vfnum + 1;
+ vf->default_vlan = 0;
+ vf->maximum_frame_size = ETHER_MAX_LEN;
+ ixgbe_update_max_frame(adapter, vf->maximum_frame_size);
+
+ if (nvlist_exists_binary(config, "mac-addr")) {
+ mac = nvlist_get_binary(config, "mac-addr", NULL);
+ bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN);
+ if (nvlist_get_bool(config, "allow-set-mac"))
+ vf->flags |= IXGBE_VF_CAP_MAC;
+ } else
+ /*
+ * If the administrator has not specified a MAC address then
+ * we must allow the VF to choose one.
+ */
+ vf->flags |= IXGBE_VF_CAP_MAC;
+
+ vf->flags = IXGBE_VF_ACTIVE;
+
+ ixgbe_init_vf(adapter, vf);
+
+ return (0);
+} /* ixgbe_if_iov_vf_add */
+
+#else
+
+void
+ixgbe_handle_mbx(void *context)
+{
+ UNREFERENCED_PARAMETER(context);
+} /* ixgbe_handle_mbx */
+
+#endif
Index: sys/dev/ixgbe/ix_txrx.c
===================================================================
--- sys/dev/ixgbe/ix_txrx.c
+++ sys/dev/ixgbe/ix_txrx.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -41,1969 +41,424 @@
#include "ixgbe.h"
-#ifdef RSS
-#include <net/rss_config.h>
-#include <netinet/in_rss.h>
-#endif
-
-#ifdef DEV_NETMAP
-#include <net/netmap.h>
-#include <sys/selinfo.h>
-#include <dev/netmap/netmap_kern.h>
+#undef CSUM_TCP
+#define CSUM_TCP (CSUM_IP_TCP | CSUM_IP6_TCP)
+#undef CSUM_UDP
+#define CSUM_UDP (CSUM_IP_UDP | CSUM_IP6_UDP)
+#undef CSUM_SCTP
+#define CSUM_SCTP (CSUM_IP_SCTP | CSUM_IP6_SCTP)
-extern int ix_crcstrip;
-#endif
-/*
-** HW RSC control:
-** this feature only works with
-** IPv4, and only on 82599 and later.
-** Also this will cause IP forwarding to
-** fail and that can't be controlled by
-** the stack as LRO can. For all these
-** reasons I've deemed it best to leave
-** this off and not bother with a tuneable
-** interface, this would need to be compiled
-** to enable.
-*/
-static bool ixgbe_rsc_enable = FALSE;
-
-#ifdef IXGBE_FDIR
-/*
-** For Flow Director: this is the
-** number of TX packets we sample
-** for the filter pool, this means
-** every 20th packet will be probed.
-**
-** This feature can be disabled by
-** setting this to 0.
-*/
-static int atr_sample_rate = 20;
-#endif
/*********************************************************************
* Local Function prototypes
*********************************************************************/
-static void ixgbe_setup_transmit_ring(struct tx_ring *);
-static void ixgbe_free_transmit_buffers(struct tx_ring *);
-static int ixgbe_setup_receive_ring(struct rx_ring *);
-static void ixgbe_free_receive_buffers(struct rx_ring *);
-
-static void ixgbe_rx_checksum(u32, struct mbuf *, u32);
-static void ixgbe_refresh_mbufs(struct rx_ring *, int);
-static int ixgbe_xmit(struct tx_ring *, struct mbuf **);
-static int ixgbe_tx_ctx_setup(struct tx_ring *,
- struct mbuf *, u32 *, u32 *);
-static int ixgbe_tso_setup(struct tx_ring *,
- struct mbuf *, u32 *, u32 *);
-#ifdef IXGBE_FDIR
-static void ixgbe_atr(struct tx_ring *, struct mbuf *);
-#endif
-static __inline void ixgbe_rx_discard(struct rx_ring *, int);
-static __inline void ixgbe_rx_input(struct rx_ring *, struct ifnet *,
- struct mbuf *, u32);
+static int ixgbe_isc_txd_encap(void *arg, if_pkt_info_t pi);
+static void ixgbe_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx);
+static int ixgbe_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear);
+
+static void ixgbe_isc_rxd_refill(void *arg, if_rxd_update_t iru);
+static void ixgbe_isc_rxd_flush(void *arg, uint16_t qsidx, uint8_t flidx __unused, qidx_t pidx);
+static int ixgbe_isc_rxd_available(void *arg, uint16_t qsidx, qidx_t pidx,
+ qidx_t budget);
+static int ixgbe_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
+
+static void ixgbe_rx_checksum(u32 staterr, if_rxd_info_t ri, u32 ptype);
+
+extern void ixgbe_if_enable_intr(if_ctx_t ctx);
+static int ixgbe_determine_rsstype(u16 pkt_info);
+
+struct if_txrx ixgbe_txrx = {
+ ixgbe_isc_txd_encap,
+ ixgbe_isc_txd_flush,
+ ixgbe_isc_txd_credits_update,
+ ixgbe_isc_rxd_available,
+ ixgbe_isc_rxd_pkt_get,
+ ixgbe_isc_rxd_refill,
+ ixgbe_isc_rxd_flush,
+ NULL
+};
+
+extern if_shared_ctx_t ixgbe_sctx;
-#ifdef IXGBE_LEGACY_TX
/*********************************************************************
- * Transmit entry point
*
- * ixgbe_start is called by the stack to initiate a transmit.
- * The driver will remain in this routine as long as there are
- * packets to transmit and transmit resources are available.
- * In case resources are not available stack is notified and
- * the packet is requeued.
+ * Advanced Context Descriptor setup for VLAN, CSUM or TSO
+ *
**********************************************************************/
-
-void
-ixgbe_start_locked(struct tx_ring *txr, struct ifnet * ifp)
-{
- struct mbuf *m_head;
- struct adapter *adapter = txr->adapter;
-
- IXGBE_TX_LOCK_ASSERT(txr);
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
- if (!adapter->link_active)
- return;
-
- while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
- if (txr->tx_avail <= IXGBE_QUEUE_MIN_FREE)
- break;
-
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
- if (m_head == NULL)
- break;
-
- if (ixgbe_xmit(txr, &m_head)) {
- if (m_head != NULL)
- IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
- break;
- }
- /* Send a copy of the frame to the BPF listener */
- ETHER_BPF_MTAP(ifp, m_head);
- }
- return;
-}
-
-/*
- * Legacy TX start - called by the stack, this
- * always uses the first tx ring, and should
- * not be used with multiqueue tx enabled.
- */
-void
-ixgbe_start(struct ifnet *ifp)
+static int
+ixgbe_tx_ctx_setup(struct ixgbe_adv_tx_context_desc *TXD, if_pkt_info_t pi)
{
- struct adapter *adapter = ifp->if_softc;
- struct tx_ring *txr = adapter->tx_rings;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_TX_LOCK(txr);
- ixgbe_start_locked(txr, ifp);
- IXGBE_TX_UNLOCK(txr);
- }
- return;
-}
-
-#else /* ! IXGBE_LEGACY_TX */
+ u32 vlan_macip_lens, type_tucmd_mlhl;
+ u32 olinfo_status, mss_l4len_idx, pktlen, offload;
+ u8 ehdrlen;
-/*
-** Multiqueue Transmit Entry Point
-** (if_transmit function)
-*/
-int
-ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m)
-{
- struct adapter *adapter = ifp->if_softc;
- struct ix_queue *que;
- struct tx_ring *txr;
- int i, err = 0;
-#ifdef RSS
- uint32_t bucket_id;
-#endif
+ offload = TRUE;
+ olinfo_status = mss_l4len_idx = vlan_macip_lens = type_tucmd_mlhl = 0;
+ /* VLAN MACLEN IPLEN */
+ vlan_macip_lens |= (htole16(pi->ipi_vtag) << IXGBE_ADVTXD_VLAN_SHIFT);
/*
- * When doing RSS, map it to the same outbound queue
- * as the incoming flow would be mapped to.
- *
- * If everything is setup correctly, it should be the
- * same bucket that the current CPU we're on is.
+ * Some of our VF devices need a context descriptor for every
+ * packet. That means the ehdrlen needs to be non-zero in order
+ * for the host driver not to flag a malicious event. The stack
+ * will most likely populate this for all other reasons of why
+ * this function was called.
*/
- if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
-#ifdef RSS
- if (rss_hash2bucket(m->m_pkthdr.flowid,
- M_HASHTYPE_GET(m), &bucket_id) == 0) {
- i = bucket_id % adapter->num_queues;
-#ifdef IXGBE_DEBUG
- if (bucket_id > adapter->num_queues)
- if_printf(ifp, "bucket_id (%d) > num_queues "
- "(%d)\n", bucket_id, adapter->num_queues);
-#endif
- } else
-#endif
- i = m->m_pkthdr.flowid % adapter->num_queues;
+ if (pi->ipi_ehdrlen == 0) {
+ ehdrlen = ETHER_HDR_LEN;
+ ehdrlen += (pi->ipi_vtag != 0) ? ETHER_VLAN_ENCAP_LEN : 0;
} else
- i = curcpu % adapter->num_queues;
+ ehdrlen = pi->ipi_ehdrlen;
+ vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
- /* Check for a hung queue and pick alternative */
- if (((1 << i) & adapter->active_queues) == 0)
- i = ffsl(adapter->active_queues);
+ pktlen = pi->ipi_len;
+ /* First check if TSO is to be used */
+ if (pi->ipi_csum_flags & CSUM_TSO) {
+ /* This is used in the transmit desc in encap */
+ pktlen = pi->ipi_len - ehdrlen - pi->ipi_ip_hlen - pi->ipi_tcp_hlen;
+ mss_l4len_idx |= (pi->ipi_tso_segsz << IXGBE_ADVTXD_MSS_SHIFT);
+ mss_l4len_idx |= (pi->ipi_tcp_hlen << IXGBE_ADVTXD_L4LEN_SHIFT);
+ }
- txr = &adapter->tx_rings[i];
- que = &adapter->queues[i];
+ olinfo_status |= pktlen << IXGBE_ADVTXD_PAYLEN_SHIFT;
- err = drbr_enqueue(ifp, txr->br, m);
- if (err)
- return (err);
- if (IXGBE_TX_TRYLOCK(txr)) {
- ixgbe_mq_start_locked(ifp, txr);
- IXGBE_TX_UNLOCK(txr);
- } else
- taskqueue_enqueue(que->tq, &txr->txq_task);
+ if (pi->ipi_flags & IPI_TX_IPV4) {
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
+ /* Tell transmit desc to also do IPv4 checksum. */
+ if (pi->ipi_csum_flags & (CSUM_IP|CSUM_TSO))
+ olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
+ } else if (pi->ipi_flags & IPI_TX_IPV6)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
+ else
+ offload = FALSE;
- return (0);
-}
+ vlan_macip_lens |= pi->ipi_ip_hlen;
-int
-ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr)
-{
- struct adapter *adapter = txr->adapter;
- struct mbuf *next;
- int enqueued = 0, err = 0;
-
- if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) ||
- adapter->link_active == 0)
- return (ENETDOWN);
-
- /* Process the queue */
-#if __FreeBSD_version < 901504
- next = drbr_dequeue(ifp, txr->br);
- while (next != NULL) {
- if ((err = ixgbe_xmit(txr, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(ifp, txr->br, next);
-#else
- while ((next = drbr_peek(ifp, txr->br)) != NULL) {
- if ((err = ixgbe_xmit(txr, &next)) != 0) {
- if (next == NULL) {
- drbr_advance(ifp, txr->br);
- } else {
- drbr_putback(ifp, txr->br, next);
- }
-#endif
- break;
- }
-#if __FreeBSD_version >= 901504
- drbr_advance(ifp, txr->br);
-#endif
- enqueued++;
-#if 0 // this is VF-only
-#if __FreeBSD_version >= 1100036
- /*
- * Since we're looking at the tx ring, we can check
- * to see if we're a VF by examing our tail register
- * address.
- */
- if (txr->tail < IXGBE_TDT(0) && next->m_flags & M_MCAST)
- if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
-#endif
-#endif
- /* Send a copy of the frame to the BPF listener */
- ETHER_BPF_MTAP(ifp, next);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- break;
-#if __FreeBSD_version < 901504
- next = drbr_dequeue(ifp, txr->br);
-#endif
+ switch (pi->ipi_ipproto) {
+ case IPPROTO_TCP:
+ if (pi->ipi_csum_flags & CSUM_TCP)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ else
+ offload = FALSE;
+ break;
+ case IPPROTO_UDP:
+ if (pi->ipi_csum_flags & CSUM_UDP)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
+ else
+ offload = FALSE;
+ break;
+ case IPPROTO_SCTP:
+ if (pi->ipi_csum_flags & CSUM_SCTP)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ else
+ offload = FALSE;
+ break;
+ default:
+ offload = FALSE;
+ break;
}
+/* Insert L4 checksum into data descriptors */
+ if (offload)
+ olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
- if (txr->tx_avail < IXGBE_TX_CLEANUP_THRESHOLD)
- ixgbe_txeof(txr);
-
- return (err);
-}
+ type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
-/*
- * Called from a taskqueue to drain queued transmit packets.
- */
-void
-ixgbe_deferred_mq_start(void *arg, int pending)
-{
- struct tx_ring *txr = arg;
- struct adapter *adapter = txr->adapter;
- struct ifnet *ifp = adapter->ifp;
-
- IXGBE_TX_LOCK(txr);
- if (!drbr_empty(ifp, txr->br))
- ixgbe_mq_start_locked(ifp, txr);
- IXGBE_TX_UNLOCK(txr);
-}
+ /* Now copy bits into descriptor */
+ TXD->vlan_macip_lens = htole32(vlan_macip_lens);
+ TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
+ TXD->seqnum_seed = htole32(0);
+ TXD->mss_l4len_idx = htole32(mss_l4len_idx);
-/*
- * Flush all ring buffers
- */
-void
-ixgbe_qflush(struct ifnet *ifp)
-{
- struct adapter *adapter = ifp->if_softc;
- struct tx_ring *txr = adapter->tx_rings;
- struct mbuf *m;
-
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- IXGBE_TX_LOCK(txr);
- while ((m = buf_ring_dequeue_sc(txr->br)) != NULL)
- m_freem(m);
- IXGBE_TX_UNLOCK(txr);
- }
- if_qflush(ifp);
+ return (olinfo_status);
}
-#endif /* IXGBE_LEGACY_TX */
-
-
-/*********************************************************************
- *
- * This routine maps the mbufs to tx descriptors, allowing the
- * TX engine to transmit the packets.
- * - return 0 on success, positive on failure
- *
- **********************************************************************/
static int
-ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
-{
- struct adapter *adapter = txr->adapter;
- u32 olinfo_status = 0, cmd_type_len;
- int i, j, error, nsegs;
- int first;
- bool remap = TRUE;
- struct mbuf *m_head;
- bus_dma_segment_t segs[adapter->num_segs];
- bus_dmamap_t map;
- struct ixgbe_tx_buf *txbuf;
- union ixgbe_adv_tx_desc *txd = NULL;
-
- m_head = *m_headp;
-
- /* Basic descriptor defines */
- cmd_type_len = (IXGBE_ADVTXD_DTYP_DATA |
- IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);
-
- if (m_head->m_flags & M_VLANTAG)
- cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
-
- /*
- * Important to capture the first descriptor
- * used because it will contain the index of
- * the one we tell the hardware to report back
- */
- first = txr->next_avail_desc;
- txbuf = &txr->tx_buffers[first];
- map = txbuf->map;
-
- /*
- * Map the packet for DMA.
- */
-retry:
- error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
- *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
- if (__predict_false(error)) {
- struct mbuf *m;
-
- switch (error) {
- case EFBIG:
- /* Try it again? - one try */
- if (remap == TRUE) {
- remap = FALSE;
- /*
- * XXX: m_defrag will choke on
- * non-MCLBYTES-sized clusters
- */
- m = m_defrag(*m_headp, M_NOWAIT);
- if (m == NULL) {
- adapter->mbuf_defrag_failed++;
- m_freem(*m_headp);
- *m_headp = NULL;
- return (ENOBUFS);
- }
- *m_headp = m;
- goto retry;
- } else
- return (error);
- case ENOMEM:
- txr->no_tx_dma_setup++;
- return (error);
- default:
- txr->no_tx_dma_setup++;
- m_freem(*m_headp);
- *m_headp = NULL;
- return (error);
+ixgbe_isc_txd_encap(void *arg, if_pkt_info_t pi)
+{
+ struct adapter *sc = arg;
+ if_softc_ctx_t scctx = sc->shared;
+ struct ix_tx_queue *que = &sc->tx_queues[pi->ipi_qsidx];
+ struct tx_ring *txr = &que->txr;
+ int nsegs = pi->ipi_nsegs;
+ bus_dma_segment_t *segs = pi->ipi_segs;
+ union ixgbe_adv_tx_desc *txd = NULL;
+ struct ixgbe_adv_tx_context_desc *TXD;
+ int i, j, first, pidx_last;
+ u32 olinfo_status, cmd, flags;
+ qidx_t ntxd;
+
+ cmd = (IXGBE_ADVTXD_DTYP_DATA |
+ IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);
+
+ if (pi->ipi_mflags & M_VLANTAG)
+ cmd |= IXGBE_ADVTXD_DCMD_VLE;
+
+ i = first = pi->ipi_pidx;
+ flags = (pi->ipi_flags & IPI_TX_INTR) ? IXGBE_TXD_CMD_RS : 0;
+ ntxd = scctx->isc_ntxd[0];
+
+ TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[first];
+ if ((pi->ipi_csum_flags & CSUM_OFFLOAD) ||
+ (sc->feat_en & IXGBE_FEATURE_NEEDS_CTXD) ||
+ pi->ipi_vtag) {
+ /*********************************************
+ * Set up the appropriate offload context
+ * this will consume the first descriptor
+ *********************************************/
+ olinfo_status = ixgbe_tx_ctx_setup(TXD, pi);
+ if (pi->ipi_csum_flags & CSUM_TSO) {
+ cmd |= IXGBE_ADVTXD_DCMD_TSE;
+ ++txr->tso_tx;
}
- }
- /* Make certain there are enough descriptors */
- if (txr->tx_avail < (nsegs + 2)) {
- txr->no_desc_avail++;
- bus_dmamap_unload(txr->txtag, map);
- return (ENOBUFS);
- }
- m_head = *m_headp;
-
- /*
- * Set up the appropriate offload context
- * this will consume the first descriptor
- */
- error = ixgbe_tx_ctx_setup(txr, m_head, &cmd_type_len, &olinfo_status);
- if (__predict_false(error)) {
- if (error == ENOBUFS)
- *m_headp = NULL;
- return (error);
- }
-
-#ifdef IXGBE_FDIR
- /* Do the flow director magic */
- if ((txr->atr_sample) && (!adapter->fdir_reinit)) {
- ++txr->atr_count;
- if (txr->atr_count >= atr_sample_rate) {
- ixgbe_atr(txr, m_head);
- txr->atr_count = 0;
- }
+ if (++i == scctx->isc_ntxd[0])
+ i = 0;
+ } else {
+ /* Indicate the whole packet as payload when not doing TSO */
+ olinfo_status = pi->ipi_len << IXGBE_ADVTXD_PAYLEN_SHIFT;
}
-#endif
olinfo_status |= IXGBE_ADVTXD_CC;
- i = txr->next_avail_desc;
for (j = 0; j < nsegs; j++) {
bus_size_t seglen;
- bus_addr_t segaddr;
- txbuf = &txr->tx_buffers[i];
txd = &txr->tx_base[i];
seglen = segs[j].ds_len;
- segaddr = htole64(segs[j].ds_addr);
- txd->read.buffer_addr = segaddr;
- txd->read.cmd_type_len = htole32(txr->txd_cmd |
- cmd_type_len |seglen);
+ txd->read.buffer_addr = htole64(segs[j].ds_addr);
+ txd->read.cmd_type_len = htole32(cmd | seglen);
txd->read.olinfo_status = htole32(olinfo_status);
- if (++i == txr->num_desc)
+ pidx_last = i;
+ if (++i == scctx->isc_ntxd[0]) {
i = 0;
+ }
}
- txd->read.cmd_type_len |=
- htole32(IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS);
- txr->tx_avail -= nsegs;
- txr->next_avail_desc = i;
-
- txbuf->m_head = m_head;
- /*
- * Here we swap the map so the last descriptor,
- * which gets the completion interrupt has the
- * real map, and the first descriptor gets the
- * unused map from this descriptor.
- */
- txr->tx_buffers[first].map = txbuf->map;
- txbuf->map = map;
- bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
+ if (flags) {
+ txr->tx_rsq[txr->tx_rs_pidx] = pidx_last;
+ txr->tx_rs_pidx = (txr->tx_rs_pidx + 1) & (ntxd - 1);
+ }
+ txd->read.cmd_type_len |= htole32(IXGBE_TXD_CMD_EOP | flags);
- /* Set the EOP descriptor that will be marked done */
- txbuf = &txr->tx_buffers[first];
- txbuf->eop = txd;
+ txr->bytes += pi->ipi_len;
+ pi->ipi_new_pidx = i;
- bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- /*
- * Advance the Transmit Descriptor Tail (Tdt), this tells the
- * hardware that this frame is available to transmit.
- */
++txr->total_packets;
- IXGBE_WRITE_REG(&adapter->hw, txr->tail, i);
-
- /* Mark queue as having work */
- if (txr->busy == 0)
- txr->busy = 1;
return (0);
}
-
-/*********************************************************************
- *
- * Allocate memory for tx_buffer structures. The tx_buffer stores all
- * the information needed to transmit a packet on the wire. This is
- * called only once at attach, setup is done every reset.
- *
- **********************************************************************/
-int
-ixgbe_allocate_transmit_buffers(struct tx_ring *txr)
-{
- struct adapter *adapter = txr->adapter;
- device_t dev = adapter->dev;
- struct ixgbe_tx_buf *txbuf;
- int error, i;
-
- /*
- * Setup DMA descriptor areas.
- */
- if ((error = bus_dma_tag_create(
- bus_get_dma_tag(adapter->dev), /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- IXGBE_TSO_SIZE, /* maxsize */
- adapter->num_segs, /* nsegments */
- PAGE_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockfuncarg */
- &txr->txtag))) {
- device_printf(dev,"Unable to allocate TX DMA tag\n");
- goto fail;
- }
-
- if (!(txr->tx_buffers =
- (struct ixgbe_tx_buf *) malloc(sizeof(struct ixgbe_tx_buf) *
- adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate tx_buffer memory\n");
- error = ENOMEM;
- goto fail;
- }
-
- /* Create the descriptor buffer dma maps */
- txbuf = txr->tx_buffers;
- for (i = 0; i < adapter->num_tx_desc; i++, txbuf++) {
- error = bus_dmamap_create(txr->txtag, 0, &txbuf->map);
- if (error != 0) {
- device_printf(dev, "Unable to create TX DMA map\n");
- goto fail;
- }
- }
-
- return 0;
-fail:
- /* We free all, it handles case where we are in the middle */
- ixgbe_free_transmit_structures(adapter);
- return (error);
-}
-
-/*********************************************************************
- *
- * Initialize a transmit ring.
- *
- **********************************************************************/
static void
-ixgbe_setup_transmit_ring(struct tx_ring *txr)
-{
- struct adapter *adapter = txr->adapter;
- struct ixgbe_tx_buf *txbuf;
-#ifdef DEV_NETMAP
- struct netmap_adapter *na = NA(adapter->ifp);
- struct netmap_slot *slot;
-#endif /* DEV_NETMAP */
-
- /* Clear the old ring contents */
- IXGBE_TX_LOCK(txr);
-#ifdef DEV_NETMAP
- /*
- * (under lock): if in netmap mode, do some consistency
- * checks and set slot to entry 0 of the netmap ring.
- */
- slot = netmap_reset(na, NR_TX, txr->me, 0);
-#endif /* DEV_NETMAP */
- bzero((void *)txr->tx_base,
- (sizeof(union ixgbe_adv_tx_desc)) * adapter->num_tx_desc);
- /* Reset indices */
- txr->next_avail_desc = 0;
- txr->next_to_clean = 0;
-
- /* Free any existing tx buffers. */
- txbuf = txr->tx_buffers;
- for (int i = 0; i < txr->num_desc; i++, txbuf++) {
- if (txbuf->m_head != NULL) {
- bus_dmamap_sync(txr->txtag, txbuf->map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(txr->txtag, txbuf->map);
- m_freem(txbuf->m_head);
- txbuf->m_head = NULL;
- }
-#ifdef DEV_NETMAP
- /*
- * In netmap mode, set the map for the packet buffer.
- * NOTE: Some drivers (not this one) also need to set
- * the physical buffer address in the NIC ring.
- * Slots in the netmap ring (indexed by "si") are
- * kring->nkr_hwofs positions "ahead" wrt the
- * corresponding slot in the NIC ring. In some drivers
- * (not here) nkr_hwofs can be negative. Function
- * netmap_idx_n2k() handles wraparounds properly.
- */
- if (slot) {
- int si = netmap_idx_n2k(&na->tx_rings[txr->me], i);
- netmap_load_map(na, txr->txtag,
- txbuf->map, NMB(na, slot + si));
- }
-#endif /* DEV_NETMAP */
- /* Clear the EOP descriptor pointer */
- txbuf->eop = NULL;
- }
-
-#ifdef IXGBE_FDIR
- /* Set the rate at which we sample packets */
- if (adapter->hw.mac.type != ixgbe_mac_82598EB)
- txr->atr_sample = atr_sample_rate;
-#endif
-
- /* Set number of descriptors available */
- txr->tx_avail = adapter->num_tx_desc;
-
- bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- IXGBE_TX_UNLOCK(txr);
-}
-
-/*********************************************************************
- *
- * Initialize all transmit rings.
- *
- **********************************************************************/
-int
-ixgbe_setup_transmit_structures(struct adapter *adapter)
-{
- struct tx_ring *txr = adapter->tx_rings;
-
- for (int i = 0; i < adapter->num_queues; i++, txr++)
- ixgbe_setup_transmit_ring(txr);
-
- return (0);
-}
-
-/*********************************************************************
- *
- * Free all transmit rings.
- *
- **********************************************************************/
-void
-ixgbe_free_transmit_structures(struct adapter *adapter)
+ixgbe_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
{
- struct tx_ring *txr = adapter->tx_rings;
-
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- IXGBE_TX_LOCK(txr);
- ixgbe_free_transmit_buffers(txr);
- ixgbe_dma_free(adapter, &txr->txdma);
- IXGBE_TX_UNLOCK(txr);
- IXGBE_TX_LOCK_DESTROY(txr);
- }
- free(adapter->tx_rings, M_DEVBUF);
-}
+ struct adapter *sc = arg;
+ struct ix_tx_queue *que = &sc->tx_queues[txqid];
+ struct tx_ring *txr = &que->txr;
-/*********************************************************************
- *
- * Free transmit ring related data structures.
- *
- **********************************************************************/
-static void
-ixgbe_free_transmit_buffers(struct tx_ring *txr)
-{
- struct adapter *adapter = txr->adapter;
- struct ixgbe_tx_buf *tx_buffer;
- int i;
-
- INIT_DEBUGOUT("ixgbe_free_transmit_ring: begin");
-
- if (txr->tx_buffers == NULL)
- return;
-
- tx_buffer = txr->tx_buffers;
- for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
- if (tx_buffer->m_head != NULL) {
- bus_dmamap_sync(txr->txtag, tx_buffer->map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(txr->txtag,
- tx_buffer->map);
- m_freem(tx_buffer->m_head);
- tx_buffer->m_head = NULL;
- if (tx_buffer->map != NULL) {
- bus_dmamap_destroy(txr->txtag,
- tx_buffer->map);
- tx_buffer->map = NULL;
- }
- } else if (tx_buffer->map != NULL) {
- bus_dmamap_unload(txr->txtag,
- tx_buffer->map);
- bus_dmamap_destroy(txr->txtag,
- tx_buffer->map);
- tx_buffer->map = NULL;
- }
- }
-#ifdef IXGBE_LEGACY_TX
- if (txr->br != NULL)
- buf_ring_free(txr->br, M_DEVBUF);
-#endif
- if (txr->tx_buffers != NULL) {
- free(txr->tx_buffers, M_DEVBUF);
- txr->tx_buffers = NULL;
- }
- if (txr->txtag != NULL) {
- bus_dma_tag_destroy(txr->txtag);
- txr->txtag = NULL;
- }
- return;
+ IXGBE_WRITE_REG(&sc->hw, txr->tail, pidx);
}
-/*********************************************************************
- *
- * Advanced Context Descriptor setup for VLAN, CSUM or TSO
- *
- **********************************************************************/
-
static int
-ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
- u32 *cmd_type_len, u32 *olinfo_status)
+ixgbe_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
{
- struct adapter *adapter = txr->adapter;
- struct ixgbe_adv_tx_context_desc *TXD;
- struct ether_vlan_header *eh;
-#ifdef INET
- struct ip *ip;
-#endif
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
- u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
- int ehdrlen, ip_hlen = 0;
- u16 etype;
- u8 ipproto = 0;
- int offload = TRUE;
- int ctxd = txr->next_avail_desc;
- u16 vtag = 0;
- caddr_t l3d;
+ struct adapter *sc = arg;
+ if_softc_ctx_t scctx = sc->shared;
+ struct ix_tx_queue *que = &sc->tx_queues[txqid];
+ struct tx_ring *txr = &que->txr;
+ qidx_t processed = 0;
+ int updated;
+ qidx_t cur, prev, ntxd, rs_cidx;
+ int32_t delta;
+ uint8_t status;
- /* First check if TSO is to be used */
- if (mp->m_pkthdr.csum_flags & (CSUM_IP_TSO|CSUM_IP6_TSO))
- return (ixgbe_tso_setup(txr, mp, cmd_type_len, olinfo_status));
-
- if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0)
- offload = FALSE;
-
- /* Indicate the whole packet as payload when not doing TSO */
- *olinfo_status |= mp->m_pkthdr.len << IXGBE_ADVTXD_PAYLEN_SHIFT;
-
- /* Now ready a context descriptor */
- TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];
-
- /*
- ** In advanced descriptors the vlan tag must
- ** be placed into the context descriptor. Hence
- ** we need to make one even if not doing offloads.
- */
- if (mp->m_flags & M_VLANTAG) {
- vtag = htole16(mp->m_pkthdr.ether_vtag);
- vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT);
- } else if (!IXGBE_IS_X550VF(adapter) && (offload == FALSE))
+ rs_cidx = txr->tx_rs_cidx;
+ if (rs_cidx == txr->tx_rs_pidx)
return (0);
- /*
- * Determine where frame payload starts.
- * Jump over vlan headers if already present,
- * helpful for QinQ too.
- */
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- etype = ntohs(eh->evl_proto);
- ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- } else {
- etype = ntohs(eh->evl_encap_proto);
- ehdrlen = ETHER_HDR_LEN;
- }
-
- /* Set the ether header length */
- vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
-
- if (offload == FALSE)
- goto no_offloads;
-
- /*
- * If the first mbuf only includes the ethernet header, jump to the next one
- * XXX: This assumes the stack splits mbufs containing headers on header boundaries
- * XXX: And assumes the entire IP header is contained in one mbuf
- */
- if (mp->m_len == ehdrlen && mp->m_next)
- l3d = mtod(mp->m_next, caddr_t);
- else
- l3d = mtod(mp, caddr_t) + ehdrlen;
-
- switch (etype) {
-#ifdef INET
- case ETHERTYPE_IP:
- ip = (struct ip *)(l3d);
- ip_hlen = ip->ip_hl << 2;
- ipproto = ip->ip_p;
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
- /* Insert IPv4 checksum into data descriptors */
- if (mp->m_pkthdr.csum_flags & CSUM_IP) {
- ip->ip_sum = 0;
- *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
- }
- break;
-#endif
-#ifdef INET6
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(l3d);
- ip_hlen = sizeof(struct ip6_hdr);
- ipproto = ip6->ip6_nxt;
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
- break;
-#endif
- default:
- offload = FALSE;
- break;
- }
-
- vlan_macip_lens |= ip_hlen;
-
- /* No support for offloads for non-L4 next headers */
- switch (ipproto) {
- case IPPROTO_TCP:
- if (mp->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP))
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
- else
- offload = false;
- break;
- case IPPROTO_UDP:
- if (mp->m_pkthdr.csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP))
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
- else
- offload = false;
- break;
- case IPPROTO_SCTP:
- if (mp->m_pkthdr.csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP))
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
- else
- offload = false;
- break;
- default:
- offload = false;
- break;
- }
-
- if (offload) /* Insert L4 checksum into data descriptors */
- *olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-
-no_offloads:
- type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
-
- /* Now copy bits into descriptor */
- TXD->vlan_macip_lens = htole32(vlan_macip_lens);
- TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
- TXD->seqnum_seed = htole32(0);
- TXD->mss_l4len_idx = htole32(0);
-
- /* We've consumed the first desc, adjust counters */
- if (++ctxd == txr->num_desc)
- ctxd = 0;
- txr->next_avail_desc = ctxd;
- --txr->tx_avail;
-
- return (0);
-}
-
-/**********************************************************************
- *
- * Setup work for hardware segmentation offload (TSO) on
- * adapters using advanced tx descriptors
- *
- **********************************************************************/
-static int
-ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp,
- u32 *cmd_type_len, u32 *olinfo_status)
-{
- struct ixgbe_adv_tx_context_desc *TXD;
- u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
- u32 mss_l4len_idx = 0, paylen;
- u16 vtag = 0, eh_type;
- int ctxd, ehdrlen, ip_hlen, tcp_hlen;
- struct ether_vlan_header *eh;
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
-#ifdef INET
- struct ip *ip;
-#endif
- struct tcphdr *th;
-
- /*
- * Determine where frame payload starts.
- * Jump over vlan headers if already present
- */
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- eh_type = eh->evl_proto;
- } else {
- ehdrlen = ETHER_HDR_LEN;
- eh_type = eh->evl_encap_proto;
- }
-
- switch (ntohs(eh_type)) {
-#ifdef INET6
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
- /* XXX-BZ For now we do not pretend to support ext. hdrs. */
- if (ip6->ip6_nxt != IPPROTO_TCP)
- return (ENXIO);
- ip_hlen = sizeof(struct ip6_hdr);
- ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
- th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
- th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0);
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
- break;
-#endif
-#ifdef INET
- case ETHERTYPE_IP:
- ip = (struct ip *)(mp->m_data + ehdrlen);
- if (ip->ip_p != IPPROTO_TCP)
- return (ENXIO);
- ip->ip_sum = 0;
- ip_hlen = ip->ip_hl << 2;
- th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
- th->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(IPPROTO_TCP));
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
- /* Tell transmit desc to also do IPv4 checksum. */
- *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
- break;
-#endif
- default:
- panic("%s: CSUM_TSO but no supported IP version (0x%04x)",
- __func__, ntohs(eh_type));
- break;
- }
-
- ctxd = txr->next_avail_desc;
- TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];
-
- tcp_hlen = th->th_off << 2;
-
- /* This is used in the transmit desc in encap */
- paylen = mp->m_pkthdr.len - ehdrlen - ip_hlen - tcp_hlen;
-
- /* VLAN MACLEN IPLEN */
- if (mp->m_flags & M_VLANTAG) {
- vtag = htole16(mp->m_pkthdr.ether_vtag);
- vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT);
- }
-
- vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
- vlan_macip_lens |= ip_hlen;
- TXD->vlan_macip_lens = htole32(vlan_macip_lens);
-
- /* ADV DTYPE TUCMD */
- type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
- TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
-
- /* MSS L4LEN IDX */
- mss_l4len_idx |= (mp->m_pkthdr.tso_segsz << IXGBE_ADVTXD_MSS_SHIFT);
- mss_l4len_idx |= (tcp_hlen << IXGBE_ADVTXD_L4LEN_SHIFT);
- TXD->mss_l4len_idx = htole32(mss_l4len_idx);
-
- TXD->seqnum_seed = htole32(0);
-
- if (++ctxd == txr->num_desc)
- ctxd = 0;
-
- txr->tx_avail--;
- txr->next_avail_desc = ctxd;
- *cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
- *olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
- *olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
- ++txr->tso_tx;
- return (0);
-}
-
-
-/**********************************************************************
- *
- * Examine each tx_buffer in the used queue. If the hardware is done
- * processing the packet then free associated resources. The
- * tx_buffer is put back on the free queue.
- *
- **********************************************************************/
-void
-ixgbe_txeof(struct tx_ring *txr)
-{
- struct adapter *adapter = txr->adapter;
-#ifdef DEV_NETMAP
- struct ifnet *ifp = adapter->ifp;
-#endif
- u32 work, processed = 0;
- u32 limit = adapter->tx_process_limit;
- struct ixgbe_tx_buf *buf;
- union ixgbe_adv_tx_desc *txd;
-
- mtx_assert(&txr->tx_mtx, MA_OWNED);
-
-#ifdef DEV_NETMAP
- if (ifp->if_capenable & IFCAP_NETMAP) {
- struct netmap_adapter *na = NA(ifp);
- struct netmap_kring *kring = &na->tx_rings[txr->me];
- txd = txr->tx_base;
- bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
- BUS_DMASYNC_POSTREAD);
- /*
- * In netmap mode, all the work is done in the context
- * of the client thread. Interrupt handlers only wake up
- * clients, which may be sleeping on individual rings
- * or on a global resource for all rings.
- * To implement tx interrupt mitigation, we wake up the client
- * thread roughly every half ring, even if the NIC interrupts
- * more frequently. This is implemented as follows:
- * - ixgbe_txsync() sets kring->nr_kflags with the index of
- * the slot that should wake up the thread (nkr_num_slots
- * means the user thread should not be woken up);
- * - the driver ignores tx interrupts unless netmap_mitigate=0
- * or the slot has the DD bit set.
- */
- if (!netmap_mitigate ||
- (kring->nr_kflags < kring->nkr_num_slots &&
- txd[kring->nr_kflags].wb.status & IXGBE_TXD_STAT_DD)) {
- netmap_tx_irq(ifp, txr->me);
- }
- return;
- }
-#endif /* DEV_NETMAP */
-
- if (txr->tx_avail == txr->num_desc) {
- txr->busy = 0;
- return;
- }
+ cur = txr->tx_rsq[rs_cidx];
+ status = txr->tx_base[cur].wb.status;
+ updated = !!(status & IXGBE_TXD_STAT_DD);
- /* Get work starting point */
- work = txr->next_to_clean;
- buf = &txr->tx_buffers[work];
- txd = &txr->tx_base[work];
- work -= txr->num_desc; /* The distance to ring end */
- bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
- BUS_DMASYNC_POSTREAD);
+ if (clear == false || updated == 0)
+ return (updated);
+ prev = txr->tx_cidx_processed;
+ ntxd = scctx->isc_ntxd[0];
do {
- union ixgbe_adv_tx_desc *eop = buf->eop;
- if (eop == NULL) /* No work */
+ delta = (int32_t)cur - (int32_t)prev;
+ if (delta < 0)
+ delta += ntxd;
+
+ processed += delta;
+ prev = cur;
+ rs_cidx = (rs_cidx + 1) & (ntxd - 1);
+ if (rs_cidx == txr->tx_rs_pidx)
break;
- if ((eop->wb.status & IXGBE_TXD_STAT_DD) == 0)
- break; /* I/O not complete */
-
- if (buf->m_head) {
- txr->bytes +=
- buf->m_head->m_pkthdr.len;
- bus_dmamap_sync(txr->txtag,
- buf->map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(txr->txtag,
- buf->map);
- m_freem(buf->m_head);
- buf->m_head = NULL;
- }
- buf->eop = NULL;
- ++txr->tx_avail;
-
- /* We clean the range if multi segment */
- while (txd != eop) {
- ++txd;
- ++buf;
- ++work;
- /* wrap the ring? */
- if (__predict_false(!work)) {
- work -= txr->num_desc;
- buf = txr->tx_buffers;
- txd = txr->tx_base;
- }
- if (buf->m_head) {
- txr->bytes +=
- buf->m_head->m_pkthdr.len;
- bus_dmamap_sync(txr->txtag,
- buf->map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(txr->txtag,
- buf->map);
- m_freem(buf->m_head);
- buf->m_head = NULL;
- }
- ++txr->tx_avail;
- buf->eop = NULL;
-
- }
- ++txr->packets;
- ++processed;
-
- /* Try the next packet */
- ++txd;
- ++buf;
- ++work;
- /* reset with a wrap */
- if (__predict_false(!work)) {
- work -= txr->num_desc;
- buf = txr->tx_buffers;
- txd = txr->tx_base;
- }
- prefetch(txd);
- } while (__predict_true(--limit));
-
- bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- work += txr->num_desc;
- txr->next_to_clean = work;
+ cur = txr->tx_rsq[rs_cidx];
+ status = txr->tx_base[cur].wb.status;
+ } while ((status & IXGBE_TXD_STAT_DD));
- /*
- ** Queue Hang detection, we know there's
- ** work outstanding or the first return
- ** would have been taken, so increment busy
- ** if nothing managed to get cleaned, then
- ** in local_timer it will be checked and
- ** marked as HUNG if it exceeds a MAX attempt.
- */
- if ((processed == 0) && (txr->busy != IXGBE_QUEUE_HUNG))
- ++txr->busy;
- /*
- ** If anything gets cleaned we reset state to 1,
- ** note this will turn off HUNG if its set.
- */
- if (processed)
- txr->busy = 1;
+ txr->tx_rs_cidx = rs_cidx;
+ txr->tx_cidx_processed = prev;
- if (txr->tx_avail == txr->num_desc)
- txr->busy = 0;
-
- return;
+ return (processed);
}
-
-#ifdef IXGBE_FDIR
-/*
-** This routine parses packet headers so that Flow
-** Director can make a hashed filter table entry
-** allowing traffic flows to be identified and kept
-** on the same cpu. This would be a performance
-** hit, but we only do it at IXGBE_FDIR_RATE of
-** packets.
-*/
static void
-ixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
+ixgbe_isc_rxd_refill(void *arg, if_rxd_update_t iru)
{
- struct adapter *adapter = txr->adapter;
- struct ix_queue *que;
- struct ip *ip;
- struct tcphdr *th;
- struct udphdr *uh;
- struct ether_vlan_header *eh;
- union ixgbe_atr_hash_dword input = {.dword = 0};
- union ixgbe_atr_hash_dword common = {.dword = 0};
- int ehdrlen, ip_hlen;
- u16 etype;
-
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- etype = eh->evl_proto;
- } else {
- ehdrlen = ETHER_HDR_LEN;
- etype = eh->evl_encap_proto;
- }
-
- /* Only handling IPv4 */
- if (etype != htons(ETHERTYPE_IP))
- return;
+ struct adapter *sc = arg;
+ struct ix_rx_queue *que = &sc->rx_queues[iru->iru_qsidx];
+ struct rx_ring *rxr = &que->rxr;
+ uint64_t *paddrs;
+ int i;
+ uint32_t next_pidx, pidx;
+ uint16_t count;
- ip = (struct ip *)(mp->m_data + ehdrlen);
- ip_hlen = ip->ip_hl << 2;
+ paddrs = iru->iru_paddrs;
+ pidx = iru->iru_pidx;
+ count = iru->iru_count;
- /* check if we're UDP or TCP */
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
- /* src and dst are inverted */
- common.port.dst ^= th->th_sport;
- common.port.src ^= th->th_dport;
- input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_TCPV4;
- break;
- case IPPROTO_UDP:
- uh = (struct udphdr *)((caddr_t)ip + ip_hlen);
- /* src and dst are inverted */
- common.port.dst ^= uh->uh_sport;
- common.port.src ^= uh->uh_dport;
- input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_UDPV4;
- break;
- default:
- return;
- }
-
- input.formatted.vlan_id = htobe16(mp->m_pkthdr.ether_vtag);
- if (mp->m_pkthdr.ether_vtag)
- common.flex_bytes ^= htons(ETHERTYPE_VLAN);
- else
- common.flex_bytes ^= etype;
- common.ip ^= ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
-
- que = &adapter->queues[txr->me];
- /*
- ** This assumes the Rx queue and Tx
- ** queue are bound to the same CPU
- */
- ixgbe_fdir_add_signature_filter_82599(&adapter->hw,
- input, common, que->msix);
-}
-#endif /* IXGBE_FDIR */
-
-/*
-** Used to detect a descriptor that has
-** been merged by Hardware RSC.
-*/
-static inline u32
-ixgbe_rsc_count(union ixgbe_adv_rx_desc *rx)
-{
- return (le32toh(rx->wb.lower.lo_dword.data) &
- IXGBE_RXDADV_RSCCNT_MASK) >> IXGBE_RXDADV_RSCCNT_SHIFT;
-}
-
-/*********************************************************************
- *
- * Initialize Hardware RSC (LRO) feature on 82599
- * for an RX ring, this is toggled by the LRO capability
- * even though it is transparent to the stack.
- *
- * NOTE: since this HW feature only works with IPV4 and
- * our testing has shown soft LRO to be as effective
- * I have decided to disable this by default.
- *
- **********************************************************************/
-static void
-ixgbe_setup_hw_rsc(struct rx_ring *rxr)
-{
- struct adapter *adapter = rxr->adapter;
- struct ixgbe_hw *hw = &adapter->hw;
- u32 rscctrl, rdrxctl;
-
- /* If turning LRO/RSC off we need to disable it */
- if ((adapter->ifp->if_capenable & IFCAP_LRO) == 0) {
- rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(rxr->me));
- rscctrl &= ~IXGBE_RSCCTL_RSCEN;
- return;
+ for (i = 0, next_pidx = pidx; i < count; i++) {
+ rxr->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]);
+ if (++next_pidx == sc->shared->isc_nrxd[0])
+ next_pidx = 0;
}
-
- rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
- rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
-#ifdef DEV_NETMAP /* crcstrip is optional in netmap */
- if (adapter->ifp->if_capenable & IFCAP_NETMAP && !ix_crcstrip)
-#endif /* DEV_NETMAP */
- rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
- rdrxctl |= IXGBE_RDRXCTL_RSCACKC;
- IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
-
- rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(rxr->me));
- rscctrl |= IXGBE_RSCCTL_RSCEN;
- /*
- ** Limit the total number of descriptors that
- ** can be combined, so it does not exceed 64K
- */
- if (rxr->mbuf_sz == MCLBYTES)
- rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
- else if (rxr->mbuf_sz == MJUMPAGESIZE)
- rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
- else if (rxr->mbuf_sz == MJUM9BYTES)
- rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
- else /* Using 16K cluster */
- rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
-
- IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(rxr->me), rscctrl);
-
- /* Enable TCP header recognition */
- IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0),
- (IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0)) |
- IXGBE_PSRTYPE_TCPHDR));
-
- /* Disable RSC for ACK packets */
- IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
- (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
-
- rxr->hw_rsc = TRUE;
}
-/*********************************************************************
- *
- * Refresh mbuf buffers for RX descriptor rings
- * - now keeps its own state so discards due to resource
- * exhaustion are unnecessary, if an mbuf cannot be obtained
- * it just returns, keeping its placeholder, thus it can simply
- * be recalled to try again.
- *
- **********************************************************************/
static void
-ixgbe_refresh_mbufs(struct rx_ring *rxr, int limit)
-{
- struct adapter *adapter = rxr->adapter;
- bus_dma_segment_t seg[1];
- struct ixgbe_rx_buf *rxbuf;
- struct mbuf *mp;
- int i, j, nsegs, error;
- bool refreshed = FALSE;
-
- i = j = rxr->next_to_refresh;
- /* Control the loop with one beyond */
- if (++j == rxr->num_desc)
- j = 0;
-
- while (j != limit) {
- rxbuf = &rxr->rx_buffers[i];
- if (rxbuf->buf == NULL) {
- mp = m_getjcl(M_NOWAIT, MT_DATA,
- M_PKTHDR, rxr->mbuf_sz);
- if (mp == NULL)
- goto update;
- if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN))
- m_adj(mp, ETHER_ALIGN);
- } else
- mp = rxbuf->buf;
-
- mp->m_pkthdr.len = mp->m_len = rxr->mbuf_sz;
-
- /* If we're dealing with an mbuf that was copied rather
- * than replaced, there's no need to go through busdma.
- */
- if ((rxbuf->flags & IXGBE_RX_COPY) == 0) {
- /* Get the memory mapping */
- bus_dmamap_unload(rxr->ptag, rxbuf->pmap);
- error = bus_dmamap_load_mbuf_sg(rxr->ptag,
- rxbuf->pmap, mp, seg, &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("Refresh mbufs: payload dmamap load"
- " failure - %d\n", error);
- m_free(mp);
- rxbuf->buf = NULL;
- goto update;
- }
- rxbuf->buf = mp;
- bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
- BUS_DMASYNC_PREREAD);
- rxbuf->addr = rxr->rx_base[i].read.pkt_addr =
- htole64(seg[0].ds_addr);
- } else {
- rxr->rx_base[i].read.pkt_addr = rxbuf->addr;
- rxbuf->flags &= ~IXGBE_RX_COPY;
- }
-
- refreshed = TRUE;
- /* Next is precalculated */
- i = j;
- rxr->next_to_refresh = i;
- if (++j == rxr->num_desc)
- j = 0;
- }
-update:
- if (refreshed) /* Update hardware tail index */
- IXGBE_WRITE_REG(&adapter->hw,
- rxr->tail, rxr->next_to_refresh);
- return;
-}
-
-/*********************************************************************
- *
- * Allocate memory for rx_buffer structures. Since we use one
- * rx_buffer per received packet, the maximum number of rx_buffer's
- * that we'll need is equal to the number of receive descriptors
- * that we've allocated.
- *
- **********************************************************************/
-int
-ixgbe_allocate_receive_buffers(struct rx_ring *rxr)
-{
- struct adapter *adapter = rxr->adapter;
- device_t dev = adapter->dev;
- struct ixgbe_rx_buf *rxbuf;
- int bsize, error;
-
- bsize = sizeof(struct ixgbe_rx_buf) * rxr->num_desc;
- if (!(rxr->rx_buffers =
- (struct ixgbe_rx_buf *) malloc(bsize,
- M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate rx_buffer memory\n");
- error = ENOMEM;
- goto fail;
- }
-
- if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MJUM16BYTES, /* maxsize */
- 1, /* nsegments */
- MJUM16BYTES, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockfuncarg */
- &rxr->ptag))) {
- device_printf(dev, "Unable to create RX DMA tag\n");
- goto fail;
- }
-
- for (int i = 0; i < rxr->num_desc; i++, rxbuf++) {
- rxbuf = &rxr->rx_buffers[i];
- error = bus_dmamap_create(rxr->ptag, 0, &rxbuf->pmap);
- if (error) {
- device_printf(dev, "Unable to create RX dma map\n");
- goto fail;
- }
- }
-
- return (0);
-
-fail:
- /* Frees all, but can handle partial completion */
- ixgbe_free_receive_structures(adapter);
- return (error);
-}
-
-static void
-ixgbe_free_receive_ring(struct rx_ring *rxr)
+ixgbe_isc_rxd_flush(void *arg, uint16_t qsidx, uint8_t flidx __unused, qidx_t pidx)
{
+ struct adapter *sc = arg;
+ struct ix_rx_queue *que = &sc->rx_queues[qsidx];
+ struct rx_ring *rxr = &que->rxr;
- for (int i = 0; i < rxr->num_desc; i++) {
- ixgbe_rx_discard(rxr, i);
- }
+ IXGBE_WRITE_REG(&sc->hw, rxr->tail, pidx);
}
-/*********************************************************************
- *
- * Initialize a receive ring and its buffers.
- *
- **********************************************************************/
static int
-ixgbe_setup_receive_ring(struct rx_ring *rxr)
+ixgbe_isc_rxd_available(void *arg, uint16_t qsidx, qidx_t pidx, qidx_t budget)
{
- struct adapter *adapter;
- struct ifnet *ifp;
- device_t dev;
- struct ixgbe_rx_buf *rxbuf;
- bus_dma_segment_t seg[1];
- struct lro_ctrl *lro = &rxr->lro;
- int rsize, nsegs, error = 0;
-#ifdef DEV_NETMAP
- struct netmap_adapter *na = NA(rxr->adapter->ifp);
- struct netmap_slot *slot;
-#endif /* DEV_NETMAP */
-
- adapter = rxr->adapter;
- ifp = adapter->ifp;
- dev = adapter->dev;
-
- /* Clear the ring contents */
- IXGBE_RX_LOCK(rxr);
-#ifdef DEV_NETMAP
- /* same as in ixgbe_setup_transmit_ring() */
- slot = netmap_reset(na, NR_RX, rxr->me, 0);
-#endif /* DEV_NETMAP */
- rsize = roundup2(adapter->num_rx_desc *
- sizeof(union ixgbe_adv_rx_desc), DBA_ALIGN);
- bzero((void *)rxr->rx_base, rsize);
- /* Cache the size */
- rxr->mbuf_sz = adapter->rx_mbuf_sz;
-
- /* Free current RX buffer structs and their mbufs */
- ixgbe_free_receive_ring(rxr);
-
- /* Now replenish the mbufs */
- for (int j = 0; j != rxr->num_desc; ++j) {
- struct mbuf *mp;
-
- rxbuf = &rxr->rx_buffers[j];
-#ifdef DEV_NETMAP
- /*
- * In netmap mode, fill the map and set the buffer
- * address in the NIC ring, considering the offset
- * between the netmap and NIC rings (see comment in
- * ixgbe_setup_transmit_ring() ). No need to allocate
- * an mbuf, so end the block with a continue;
- */
- if (slot) {
- int sj = netmap_idx_n2k(&na->rx_rings[rxr->me], j);
- uint64_t paddr;
- void *addr;
-
- addr = PNMB(na, slot + sj, &paddr);
- netmap_load_map(na, rxr->ptag, rxbuf->pmap, addr);
- /* Update descriptor and the cached value */
- rxr->rx_base[j].read.pkt_addr = htole64(paddr);
- rxbuf->addr = htole64(paddr);
- continue;
- }
-#endif /* DEV_NETMAP */
- rxbuf->flags = 0;
- rxbuf->buf = m_getjcl(M_NOWAIT, MT_DATA,
- M_PKTHDR, adapter->rx_mbuf_sz);
- if (rxbuf->buf == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- mp = rxbuf->buf;
- mp->m_pkthdr.len = mp->m_len = rxr->mbuf_sz;
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->ptag,
- rxbuf->pmap, mp, seg,
- &nsegs, BUS_DMA_NOWAIT);
- if (error != 0)
- goto fail;
- bus_dmamap_sync(rxr->ptag,
- rxbuf->pmap, BUS_DMASYNC_PREREAD);
- /* Update the descriptor and the cached value */
- rxr->rx_base[j].read.pkt_addr = htole64(seg[0].ds_addr);
- rxbuf->addr = htole64(seg[0].ds_addr);
- }
-
+ struct adapter *sc = arg;
+ struct ix_rx_queue *que = &sc->rx_queues[qsidx];
+ struct rx_ring *rxr = &que->rxr;
+ union ixgbe_adv_rx_desc *rxd;
+ u32 staterr;
+ int cnt, i, nrxd;
- /* Setup our descriptor indices */
- rxr->next_to_check = 0;
- rxr->next_to_refresh = 0;
- rxr->lro_enabled = FALSE;
- rxr->rx_copies = 0;
- rxr->rx_bytes = 0;
- rxr->vtag_strip = FALSE;
+ if (budget == 1) {
+ rxd = &rxr->rx_base[pidx];
+ staterr = le32toh(rxd->wb.upper.status_error);
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- /*
- ** Now set up the LRO interface:
- */
- if (ixgbe_rsc_enable)
- ixgbe_setup_hw_rsc(rxr);
- else if (ifp->if_capenable & IFCAP_LRO) {
- int err = tcp_lro_init(lro);
- if (err) {
- device_printf(dev, "LRO Initialization failed!\n");
- goto fail;
- }
- INIT_DEBUGOUT("RX Soft LRO Initialized\n");
- rxr->lro_enabled = TRUE;
- lro->ifp = adapter->ifp;
+ return (staterr & IXGBE_RXD_STAT_DD);
}
- IXGBE_RX_UNLOCK(rxr);
- return (0);
-
-fail:
- ixgbe_free_receive_ring(rxr);
- IXGBE_RX_UNLOCK(rxr);
- return (error);
-}
+ nrxd = sc->shared->isc_nrxd[0];
+ // em has cnt < nrxd. off by 1 here or there?
+// for (cnt = 0, i = pidx; cnt < nrxd && cnt <= budget;) {
+ for (cnt = 0, i = pidx; cnt < nrxd-1 && cnt <= budget;) {
+ rxd = &rxr->rx_base[i];
+ staterr = le32toh(rxd->wb.upper.status_error);
-/*********************************************************************
- *
- * Initialize all receive rings.
- *
- **********************************************************************/
-int
-ixgbe_setup_receive_structures(struct adapter *adapter)
-{
- struct rx_ring *rxr = adapter->rx_rings;
- int j;
-
- for (j = 0; j < adapter->num_queues; j++, rxr++)
- if (ixgbe_setup_receive_ring(rxr))
- goto fail;
-
- return (0);
-fail:
- /*
- * Free RX buffers allocated so far, we will only handle
- * the rings that completed, the failing case will have
- * cleaned up for itself. 'j' failed, so its the terminus.
- */
- for (int i = 0; i < j; ++i) {
- rxr = &adapter->rx_rings[i];
- IXGBE_RX_LOCK(rxr);
- ixgbe_free_receive_ring(rxr);
- IXGBE_RX_UNLOCK(rxr);
- }
-
- return (ENOBUFS);
-}
-
-
-/*********************************************************************
- *
- * Free all receive rings.
- *
- **********************************************************************/
-void
-ixgbe_free_receive_structures(struct adapter *adapter)
-{
- struct rx_ring *rxr = adapter->rx_rings;
-
- INIT_DEBUGOUT("ixgbe_free_receive_structures: begin");
-
- for (int i = 0; i < adapter->num_queues; i++, rxr++) {
- struct lro_ctrl *lro = &rxr->lro;
- ixgbe_free_receive_buffers(rxr);
- /* Free LRO memory */
- tcp_lro_free(lro);
- /* Free the ring memory as well */
- ixgbe_dma_free(adapter, &rxr->rxdma);
+ if ((staterr & IXGBE_RXD_STAT_DD) == 0)
+ break;
+ if (++i == nrxd)
+ i = 0;
+ if (staterr & IXGBE_RXD_STAT_EOP)
+ cnt++;
}
- free(adapter->rx_rings, M_DEVBUF);
+ return (cnt);
}
-
-/*********************************************************************
+/****************************************************************
+ * Routine sends data which has been dma'ed into host memory
+ * to upper layer. Initialize ri structure.
*
- * Free receive ring data structures
- *
- **********************************************************************/
-void
-ixgbe_free_receive_buffers(struct rx_ring *rxr)
-{
- struct adapter *adapter = rxr->adapter;
- struct ixgbe_rx_buf *rxbuf;
-
- INIT_DEBUGOUT("ixgbe_free_receive_buffers: begin");
-
- /* Cleanup any existing buffers */
- if (rxr->rx_buffers != NULL) {
- for (int i = 0; i < adapter->num_rx_desc; i++) {
- rxbuf = &rxr->rx_buffers[i];
- ixgbe_rx_discard(rxr, i);
- if (rxbuf->pmap != NULL) {
- bus_dmamap_destroy(rxr->ptag, rxbuf->pmap);
- rxbuf->pmap = NULL;
- }
- }
- if (rxr->rx_buffers != NULL) {
- free(rxr->rx_buffers, M_DEVBUF);
- rxr->rx_buffers = NULL;
- }
- }
-
- if (rxr->ptag != NULL) {
- bus_dma_tag_destroy(rxr->ptag);
- rxr->ptag = NULL;
- }
-
- return;
-}
-
-static __inline void
-ixgbe_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u32 ptype)
-{
-
- /*
- * ATM LRO is only for IP/TCP packets and TCP checksum of the packet
- * should be computed by hardware. Also it should not have VLAN tag in
- * ethernet header. In case of IPv6 we do not yet support ext. hdrs.
- */
- if (rxr->lro_enabled &&
- (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
- (ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&
- ((ptype & (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)) ==
- (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP) ||
- (ptype & (IXGBE_RXDADV_PKTTYPE_IPV6 | IXGBE_RXDADV_PKTTYPE_TCP)) ==
- (IXGBE_RXDADV_PKTTYPE_IPV6 | IXGBE_RXDADV_PKTTYPE_TCP)) &&
- (m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) ==
- (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) {
- /*
- * Send to the stack if:
- ** - LRO not enabled, or
- ** - no LRO resources, or
- ** - lro enqueue fails
- */
- if (rxr->lro.lro_cnt != 0)
- if (tcp_lro_rx(&rxr->lro, m, 0) == 0)
- return;
- }
- IXGBE_RX_UNLOCK(rxr);
- (*ifp->if_input)(ifp, m);
- IXGBE_RX_LOCK(rxr);
-}
-
-static __inline void
-ixgbe_rx_discard(struct rx_ring *rxr, int i)
-{
- struct ixgbe_rx_buf *rbuf;
+ * Returns 0 upon success, errno on failure
+ ***************************************************************/
- rbuf = &rxr->rx_buffers[i];
-
-
- /*
- ** With advanced descriptors the writeback
- ** clobbers the buffer addrs, so its easier
- ** to just free the existing mbufs and take
- ** the normal refresh path to get new buffers
- ** and mapping.
- */
-
- if (rbuf->fmp != NULL) {/* Partial chain ? */
- bus_dmamap_sync(rxr->ptag, rbuf->pmap, BUS_DMASYNC_POSTREAD);
- m_freem(rbuf->fmp);
- rbuf->fmp = NULL;
- rbuf->buf = NULL; /* rbuf->buf is part of fmp's chain */
- } else if (rbuf->buf) {
- bus_dmamap_sync(rxr->ptag, rbuf->pmap, BUS_DMASYNC_POSTREAD);
- m_free(rbuf->buf);
- rbuf->buf = NULL;
- }
- bus_dmamap_unload(rxr->ptag, rbuf->pmap);
+static int
+ixgbe_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
+{
+ struct adapter *adapter = arg;
+ struct ix_rx_queue *que = &adapter->rx_queues[ri->iri_qsidx];
+ struct rx_ring *rxr = &que->rxr;
+ struct ifnet *ifp = iflib_get_ifp(adapter->ctx);
+ union ixgbe_adv_rx_desc *rxd;
+
+ u16 pkt_info, len, cidx, i;
+ u16 vtag = 0;
+ u32 ptype;
+ u32 staterr = 0;
+ bool eop;
+
+ i = 0;
+ cidx = ri->iri_cidx;
+ do {
+ rxd = &rxr->rx_base[cidx];
+ staterr = le32toh(rxd->wb.upper.status_error);
+ pkt_info = le16toh(rxd->wb.lower.lo_dword.hs_rss.pkt_info);
- rbuf->flags = 0;
-
- return;
-}
+ /* Error Checking then decrement count */
+ MPASS ((staterr & IXGBE_RXD_STAT_DD) != 0);
+ len = le16toh(rxd->wb.upper.length);
+ ptype = le32toh(rxd->wb.lower.lo_dword.data) &
+ IXGBE_RXDADV_PKTTYPE_MASK;
-/*********************************************************************
- *
- * This routine executes in interrupt context. It replenishes
- * the mbufs in the descriptor and sends data which has been
- * dma'ed into host memory to upper layer.
- *
- * Return TRUE for more work, FALSE for all clean.
- *********************************************************************/
-bool
-ixgbe_rxeof(struct ix_queue *que)
-{
- struct adapter *adapter = que->adapter;
- struct rx_ring *rxr = que->rxr;
- struct ifnet *ifp = adapter->ifp;
- struct lro_ctrl *lro = &rxr->lro;
- int i, nextp, processed = 0;
- u32 staterr = 0;
- u32 count = adapter->rx_process_limit;
- union ixgbe_adv_rx_desc *cur;
- struct ixgbe_rx_buf *rbuf, *nbuf;
- u16 pkt_info;
-
- IXGBE_RX_LOCK(rxr);
-
-#ifdef DEV_NETMAP
- /* Same as the txeof routine: wakeup clients on intr. */
- if (netmap_rx_irq(ifp, rxr->me, &processed)) {
- IXGBE_RX_UNLOCK(rxr);
- return (FALSE);
- }
-#endif /* DEV_NETMAP */
-
- for (i = rxr->next_to_check; count != 0;) {
- struct mbuf *sendmp, *mp;
- u32 rsc, ptype;
- u16 len;
- u16 vtag = 0;
- bool eop;
-
- /* Sync the ring. */
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
- cur = &rxr->rx_base[i];
- staterr = le32toh(cur->wb.upper.status_error);
- pkt_info = le16toh(cur->wb.lower.lo_dword.hs_rss.pkt_info);
+ ri->iri_len += len;
+ rxr->bytes += len;
- if ((staterr & IXGBE_RXD_STAT_DD) == 0)
- break;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- break;
-
- count--;
- sendmp = NULL;
- nbuf = NULL;
- rsc = 0;
- cur->wb.upper.status_error = 0;
- rbuf = &rxr->rx_buffers[i];
- mp = rbuf->buf;
-
- len = le16toh(cur->wb.upper.length);
- ptype = le32toh(cur->wb.lower.lo_dword.data) &
- IXGBE_RXDADV_PKTTYPE_MASK;
+ rxd->wb.upper.status_error = 0;
eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);
+ if (staterr & IXGBE_RXD_STAT_VP) {
+ vtag = le16toh(rxd->wb.upper.vlan);
+ } else {
+ vtag = 0;
+ }
/* Make sure bad packets are discarded */
if (eop && (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) {
+
#if __FreeBSD_version >= 1100036
- if (IXGBE_IS_VF(adapter))
+ if (adapter->feat_en & IXGBE_FEATURE_VF)
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
#endif
- rxr->rx_discarded++;
- ixgbe_rx_discard(rxr, i);
- goto next_desc;
- }
- bus_dmamap_sync(rxr->ptag, rbuf->pmap, BUS_DMASYNC_POSTREAD);
-
- /*
- ** On 82599 which supports a hardware
- ** LRO (called HW RSC), packets need
- ** not be fragmented across sequential
- ** descriptors, rather the next descriptor
- ** is indicated in bits of the descriptor.
- ** This also means that we might proceses
- ** more than one packet at a time, something
- ** that has never been true before, it
- ** required eliminating global chain pointers
- ** in favor of what we are doing here. -jfv
- */
- if (!eop) {
- /*
- ** Figure out the next descriptor
- ** of this frame.
- */
- if (rxr->hw_rsc == TRUE) {
- rsc = ixgbe_rsc_count(cur);
- rxr->rsc_num += (rsc - 1);
- }
- if (rsc) { /* Get hardware index */
- nextp = ((staterr &
- IXGBE_RXDADV_NEXTP_MASK) >>
- IXGBE_RXDADV_NEXTP_SHIFT);
- } else { /* Just sequential */
- nextp = i + 1;
- if (nextp == adapter->num_rx_desc)
- nextp = 0;
- }
- nbuf = &rxr->rx_buffers[nextp];
- prefetch(nbuf);
- }
- /*
- ** Rather than using the fmp/lmp global pointers
- ** we now keep the head of a packet chain in the
- ** buffer struct and pass this along from one
- ** descriptor to the next, until we get EOP.
- */
- mp->m_len = len;
- /*
- ** See if there is a stored head
- ** that determines what we are
- */
- sendmp = rbuf->fmp;
- if (sendmp != NULL) { /* secondary frag */
- rbuf->buf = rbuf->fmp = NULL;
- mp->m_flags &= ~M_PKTHDR;
- sendmp->m_pkthdr.len += mp->m_len;
- } else {
- /*
- * Optimize. This might be a small packet,
- * maybe just a TCP ACK. Do a fast copy that
- * is cache aligned into a new mbuf, and
- * leave the old mbuf+cluster for re-use.
- */
- if (eop && len <= IXGBE_RX_COPY_LEN) {
- sendmp = m_gethdr(M_NOWAIT, MT_DATA);
- if (sendmp != NULL) {
- sendmp->m_data +=
- IXGBE_RX_COPY_ALIGN;
- ixgbe_bcopy(mp->m_data,
- sendmp->m_data, len);
- sendmp->m_len = len;
- rxr->rx_copies++;
- rbuf->flags |= IXGBE_RX_COPY;
- }
- }
- if (sendmp == NULL) {
- rbuf->buf = rbuf->fmp = NULL;
- sendmp = mp;
- }
-
- /* first desc of a non-ps chain */
- sendmp->m_flags |= M_PKTHDR;
- sendmp->m_pkthdr.len = mp->m_len;
- }
- ++processed;
-
- /* Pass the head pointer on */
- if (eop == 0) {
- nbuf->fmp = sendmp;
- sendmp = NULL;
- mp->m_next = nbuf->buf;
- } else { /* Sending this frame */
- sendmp->m_pkthdr.rcvif = ifp;
- rxr->rx_packets++;
- /* capture data for AIM */
- rxr->bytes += sendmp->m_pkthdr.len;
- rxr->rx_bytes += sendmp->m_pkthdr.len;
- /* Process vlan info */
- if ((rxr->vtag_strip) &&
- (staterr & IXGBE_RXD_STAT_VP))
- vtag = le16toh(cur->wb.upper.vlan);
- if (vtag) {
- sendmp->m_pkthdr.ether_vtag = vtag;
- sendmp->m_flags |= M_VLANTAG;
- }
- if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
- ixgbe_rx_checksum(staterr, sendmp, ptype);
-
- /*
- * In case of multiqueue, we have RXCSUM.PCSD bit set
- * and never cleared. This means we have RSS hash
- * available to be used.
- */
- if (adapter->num_queues > 1) {
- sendmp->m_pkthdr.flowid =
- le32toh(cur->wb.lower.hi_dword.rss);
- switch (pkt_info & IXGBE_RXDADV_RSSTYPE_MASK) {
- case IXGBE_RXDADV_RSSTYPE_IPV4:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_IPV4);
- break;
- case IXGBE_RXDADV_RSSTYPE_IPV4_TCP:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_TCP_IPV4);
- break;
- case IXGBE_RXDADV_RSSTYPE_IPV6:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_IPV6);
- break;
- case IXGBE_RXDADV_RSSTYPE_IPV6_TCP:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_TCP_IPV6);
- break;
- case IXGBE_RXDADV_RSSTYPE_IPV6_EX:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_IPV6_EX);
- break;
- case IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_TCP_IPV6_EX);
- break;
-#if __FreeBSD_version > 1100000
- case IXGBE_RXDADV_RSSTYPE_IPV4_UDP:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_UDP_IPV4);
- break;
- case IXGBE_RXDADV_RSSTYPE_IPV6_UDP:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_UDP_IPV6);
- break;
- case IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_RSS_UDP_IPV6_EX);
- break;
-#endif
- default:
- M_HASHTYPE_SET(sendmp,
- M_HASHTYPE_OPAQUE_HASH);
- }
- } else {
- sendmp->m_pkthdr.flowid = que->msix;
- M_HASHTYPE_SET(sendmp, M_HASHTYPE_OPAQUE);
- }
- }
-next_desc:
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- /* Advance our pointers to the next descriptor. */
- if (++i == rxr->num_desc)
- i = 0;
-
- /* Now send to the stack or do LRO */
- if (sendmp != NULL) {
- rxr->next_to_check = i;
- ixgbe_rx_input(rxr, ifp, sendmp, ptype);
- i = rxr->next_to_check;
- }
-
- /* Every 8 descriptors we go to refresh mbufs */
- if (processed == 8) {
- ixgbe_refresh_mbufs(rxr, i);
- processed = 0;
+ rxr->rx_discarded++;
+ return (EBADMSG);
}
- }
-
- /* Refresh any remaining buf structs */
- if (ixgbe_rx_unrefreshed(rxr))
- ixgbe_refresh_mbufs(rxr, i);
-
- rxr->next_to_check = i;
-
- /*
- * Flush any outstanding LRO work
- */
- tcp_lro_flush_all(lro);
-
- IXGBE_RX_UNLOCK(rxr);
-
- /*
- ** Still have cleaning to do?
- */
- if ((staterr & IXGBE_RXD_STAT_DD) != 0)
- return (TRUE);
- else
- return (FALSE);
+ ri->iri_frags[i].irf_flid = 0;
+ ri->iri_frags[i].irf_idx = cidx;
+ ri->iri_frags[i].irf_len = len;
+ if (++cidx == adapter->shared->isc_nrxd[0])
+ cidx = 0;
+ i++;
+ /* even a 16K packet shouldn't consume more than 8 clusters */
+ MPASS(i < 9);
+ } while (!eop);
+
+ rxr->rx_packets++;
+ rxr->packets++;
+ rxr->rx_bytes += ri->iri_len;
+
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
+ ixgbe_rx_checksum(staterr, ri, ptype);
+
+ ri->iri_flowid = le32toh(rxd->wb.lower.hi_dword.rss);
+ ri->iri_rsstype = ixgbe_determine_rsstype(pkt_info);
+ ri->iri_vtag = vtag;
+ ri->iri_nfrags = i;
+ if (vtag)
+ ri->iri_flags |= M_VLANTAG;
+ return (0);
}
-
/*********************************************************************
*
* Verify that the hardware indicated that the checksum is valid.
@@ -2012,280 +467,65 @@
*
*********************************************************************/
static void
-ixgbe_rx_checksum(u32 staterr, struct mbuf * mp, u32 ptype)
+ixgbe_rx_checksum(u32 staterr, if_rxd_info_t ri, u32 ptype)
{
- u16 status = (u16) staterr;
- u8 errors = (u8) (staterr >> 24);
- bool sctp = false;
+ u16 status = (u16)staterr;
+ u8 errors = (u8)(staterr >> 24);
+ bool sctp = FALSE;
if ((ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&
(ptype & IXGBE_RXDADV_PKTTYPE_SCTP) != 0)
- sctp = true;
+ sctp = TRUE;
- /* IPv4 checksum */
if (status & IXGBE_RXD_STAT_IPCS) {
- mp->m_pkthdr.csum_flags |= CSUM_L3_CALC;
- /* IP Checksum Good */
- if (!(errors & IXGBE_RXD_ERR_IPE))
- mp->m_pkthdr.csum_flags |= CSUM_L3_VALID;
+ if (!(errors & IXGBE_RXD_ERR_IPE)) {
+ /* IP Checksum Good */
+ ri->iri_csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID;
+ } else
+ ri->iri_csum_flags = 0;
}
- /* TCP/UDP/SCTP checksum */
if (status & IXGBE_RXD_STAT_L4CS) {
- mp->m_pkthdr.csum_flags |= CSUM_L4_CALC;
+ u64 type = (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+#if __FreeBSD_version >= 800000
+ if (sctp)
+ type = CSUM_SCTP_VALID;
+#endif
if (!(errors & IXGBE_RXD_ERR_TCPE)) {
- mp->m_pkthdr.csum_flags |= CSUM_L4_VALID;
+ ri->iri_csum_flags |= type;
if (!sctp)
- mp->m_pkthdr.csum_data = htons(0xffff);
+ ri->iri_csum_data = htons(0xffff);
}
}
}
/********************************************************************
- * Manage DMA'able memory.
- *******************************************************************/
-static void
-ixgbe_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error)
-{
- if (error)
- return;
- *(bus_addr_t *) arg = segs->ds_addr;
- return;
-}
-
-int
-ixgbe_dma_malloc(struct adapter *adapter, bus_size_t size,
- struct ixgbe_dma_alloc *dma, int mapflags)
-{
- device_t dev = adapter->dev;
- int r;
-
- r = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */
- DBA_ALIGN, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- size, /* maxsize */
- 1, /* nsegments */
- size, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockfuncarg */
- &dma->dma_tag);
- if (r != 0) {
- device_printf(dev,"ixgbe_dma_malloc: bus_dma_tag_create failed; "
- "error %u\n", r);
- goto fail_0;
- }
- r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,
- BUS_DMA_NOWAIT, &dma->dma_map);
- if (r != 0) {
- device_printf(dev,"ixgbe_dma_malloc: bus_dmamem_alloc failed; "
- "error %u\n", r);
- goto fail_1;
- }
- r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
- size,
- ixgbe_dmamap_cb,
- &dma->dma_paddr,
- mapflags | BUS_DMA_NOWAIT);
- if (r != 0) {
- device_printf(dev,"ixgbe_dma_malloc: bus_dmamap_load failed; "
- "error %u\n", r);
- goto fail_2;
- }
- dma->dma_size = size;
- return (0);
-fail_2:
- bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
-fail_1:
- bus_dma_tag_destroy(dma->dma_tag);
-fail_0:
- dma->dma_tag = NULL;
- return (r);
-}
-
-void
-ixgbe_dma_free(struct adapter *adapter, struct ixgbe_dma_alloc *dma)
-{
- bus_dmamap_sync(dma->dma_tag, dma->dma_map,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(dma->dma_tag, dma->dma_map);
- bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
- bus_dma_tag_destroy(dma->dma_tag);
-}
-
-
-/*********************************************************************
*
- * Allocate memory for the transmit and receive rings, and then
- * the descriptors associated with each, called only once at attach.
+ * Parse the packet type to determine the appropriate hash
*
- **********************************************************************/
-int
-ixgbe_allocate_queues(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- struct ix_queue *que;
- struct tx_ring *txr;
- struct rx_ring *rxr;
- int rsize, tsize, error = IXGBE_SUCCESS;
- int txconf = 0, rxconf = 0;
-#ifdef PCI_IOV
- enum ixgbe_iov_mode iov_mode;
-#endif
-
- /* First allocate the top level queue structs */
- if (!(adapter->queues =
- (struct ix_queue *) malloc(sizeof(struct ix_queue) *
- adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate queue memory\n");
- error = ENOMEM;
- goto fail;
- }
-
- /* First allocate the TX ring struct memory */
- if (!(adapter->tx_rings =
- (struct tx_ring *) malloc(sizeof(struct tx_ring) *
- adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate TX ring memory\n");
- error = ENOMEM;
- goto tx_fail;
- }
-
- /* Next allocate the RX */
- if (!(adapter->rx_rings =
- (struct rx_ring *) malloc(sizeof(struct rx_ring) *
- adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
- device_printf(dev, "Unable to allocate RX ring memory\n");
- error = ENOMEM;
- goto rx_fail;
- }
-
- /* For the ring itself */
- tsize = roundup2(adapter->num_tx_desc *
- sizeof(union ixgbe_adv_tx_desc), DBA_ALIGN);
-
-#ifdef PCI_IOV
- iov_mode = ixgbe_get_iov_mode(adapter);
- adapter->pool = ixgbe_max_vfs(iov_mode);
-#else
- adapter->pool = 0;
-#endif
- /*
- * Now set up the TX queues, txconf is needed to handle the
- * possibility that things fail midcourse and we need to
- * undo memory gracefully
- */
- for (int i = 0; i < adapter->num_queues; i++, txconf++) {
- /* Set up some basics */
- txr = &adapter->tx_rings[i];
- txr->adapter = adapter;
-#ifdef PCI_IOV
- txr->me = ixgbe_pf_que_index(iov_mode, i);
-#else
- txr->me = i;
-#endif
- txr->num_desc = adapter->num_tx_desc;
-
- /* Initialize the TX side lock */
- snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
- device_get_nameunit(dev), txr->me);
- mtx_init(&txr->tx_mtx, txr->mtx_name, NULL, MTX_DEF);
-
- if (ixgbe_dma_malloc(adapter, tsize,
- &txr->txdma, BUS_DMA_NOWAIT)) {
- device_printf(dev,
- "Unable to allocate TX Descriptor memory\n");
- error = ENOMEM;
- goto err_tx_desc;
- }
- txr->tx_base = (union ixgbe_adv_tx_desc *)txr->txdma.dma_vaddr;
- bzero((void *)txr->tx_base, tsize);
-
- /* Now allocate transmit buffers for the ring */
- if (ixgbe_allocate_transmit_buffers(txr)) {
- device_printf(dev,
- "Critical Failure setting up transmit buffers\n");
- error = ENOMEM;
- goto err_tx_desc;
- }
-#ifndef IXGBE_LEGACY_TX
- /* Allocate a buf ring */
- txr->br = buf_ring_alloc(IXGBE_BR_SIZE, M_DEVBUF,
- M_WAITOK, &txr->tx_mtx);
- if (txr->br == NULL) {
- device_printf(dev,
- "Critical Failure setting up buf ring\n");
- error = ENOMEM;
- goto err_tx_desc;
- }
-#endif
- }
-
- /*
- * Next the RX queues...
- */
- rsize = roundup2(adapter->num_rx_desc *
- sizeof(union ixgbe_adv_rx_desc), DBA_ALIGN);
- for (int i = 0; i < adapter->num_queues; i++, rxconf++) {
- rxr = &adapter->rx_rings[i];
- /* Set up some basics */
- rxr->adapter = adapter;
-#ifdef PCI_IOV
- rxr->me = ixgbe_pf_que_index(iov_mode, i);
-#else
- rxr->me = i;
-#endif
- rxr->num_desc = adapter->num_rx_desc;
-
- /* Initialize the RX side lock */
- snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",
- device_get_nameunit(dev), rxr->me);
- mtx_init(&rxr->rx_mtx, rxr->mtx_name, NULL, MTX_DEF);
-
- if (ixgbe_dma_malloc(adapter, rsize,
- &rxr->rxdma, BUS_DMA_NOWAIT)) {
- device_printf(dev,
- "Unable to allocate RxDescriptor memory\n");
- error = ENOMEM;
- goto err_rx_desc;
- }
- rxr->rx_base = (union ixgbe_adv_rx_desc *)rxr->rxdma.dma_vaddr;
- bzero((void *)rxr->rx_base, rsize);
-
- /* Allocate receive buffers for the ring*/
- if (ixgbe_allocate_receive_buffers(rxr)) {
- device_printf(dev,
- "Critical Failure setting up receive buffers\n");
- error = ENOMEM;
- goto err_rx_desc;
- }
- }
-
- /*
- ** Finally set up the queue holding structs
- */
- for (int i = 0; i < adapter->num_queues; i++) {
- que = &adapter->queues[i];
- que->adapter = adapter;
- que->me = i;
- que->txr = &adapter->tx_rings[i];
- que->rxr = &adapter->rx_rings[i];
- }
-
- return (0);
-
-err_rx_desc:
- for (rxr = adapter->rx_rings; rxconf > 0; rxr++, rxconf--)
- ixgbe_dma_free(adapter, &rxr->rxdma);
-err_tx_desc:
- for (txr = adapter->tx_rings; txconf > 0; txr++, txconf--)
- ixgbe_dma_free(adapter, &txr->txdma);
- free(adapter->rx_rings, M_DEVBUF);
-rx_fail:
- free(adapter->tx_rings, M_DEVBUF);
-tx_fail:
- free(adapter->queues, M_DEVBUF);
-fail:
- return (error);
+ ******************************************************************/
+static int
+ixgbe_determine_rsstype(u16 pkt_info)
+{
+ switch (pkt_info & IXGBE_RXDADV_RSSTYPE_MASK) {
+ case IXGBE_RXDADV_RSSTYPE_IPV4_TCP:
+ return M_HASHTYPE_RSS_TCP_IPV4;
+ case IXGBE_RXDADV_RSSTYPE_IPV4:
+ return M_HASHTYPE_RSS_IPV4;
+ case IXGBE_RXDADV_RSSTYPE_IPV6_TCP:
+ return M_HASHTYPE_RSS_TCP_IPV6;
+ case IXGBE_RXDADV_RSSTYPE_IPV6_EX:
+ return M_HASHTYPE_RSS_IPV6_EX;
+ case IXGBE_RXDADV_RSSTYPE_IPV6:
+ return M_HASHTYPE_RSS_IPV6;
+ case IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX:
+ return M_HASHTYPE_RSS_TCP_IPV6_EX;
+ case IXGBE_RXDADV_RSSTYPE_IPV4_UDP:
+ return M_HASHTYPE_RSS_UDP_IPV4;
+ case IXGBE_RXDADV_RSSTYPE_IPV6_UDP:
+ return M_HASHTYPE_RSS_UDP_IPV6;
+ case IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX:
+ return M_HASHTYPE_RSS_UDP_IPV6_EX;
+ default:
+ return M_HASHTYPE_OPAQUE;
+ }
}
Index: sys/dev/ixgbe/ixgbe.h
===================================================================
--- sys/dev/ixgbe/ixgbe.h
+++ sys/dev/ixgbe/ixgbe.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -59,20 +59,13 @@
#include <net/if_dl.h>
#include <net/if_media.h>
-#include <net/bpf.h>
#include <net/if_types.h>
#include <net/if_vlan_var.h>
+#include <net/iflib.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_lro.h>
-#include <netinet/udp.h>
-
-#include <machine/in_cksum.h>
#include <sys/bus.h>
#include <machine/bus.h>
@@ -86,28 +79,18 @@
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/endian.h>
-#include <sys/taskqueue.h>
+#include <sys/gtaskqueue.h>
#include <sys/pcpu.h>
#include <sys/smp.h>
#include <machine/smp.h>
#include <sys/sbuf.h>
-#ifdef PCI_IOV
-#include <sys/nv.h>
-#include <sys/iov_schema.h>
-#include <dev/pci/pci_iov.h>
-#endif
-
+#include "ixgbe_features.h"
#include "ixgbe_api.h"
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
#include "ixgbe_vf.h"
-#ifdef PCI_IOV
-#include "ixgbe_common.h"
-#include "ixgbe_mbx.h"
-#endif
-
/* Tunables */
/*
@@ -117,7 +100,7 @@
* bytes. Performance tests have show the 2K value to be optimal for top
* performance.
*/
-#define DEFAULT_TXD 1024
+#define DEFAULT_TXD 2048
#define PERFORM_TXD 2048
#define MAX_TXD 4096
#define MIN_TXD 64
@@ -126,13 +109,13 @@
* RxDescriptors Valid Range: 64-4096 Default Value: 256 This value is the
* number of receive descriptors allocated for each RX queue. Increasing this
* value allows the driver to buffer more incoming packets. Each descriptor
- * is 16 bytes. A receive buffer is also allocated for each descriptor.
- *
- * Note: with 8 rings and a dual port card, it is possible to bump up
+ * is 16 bytes. A receive buffer is also allocated for each descriptor.
+ *
+ * Note: with 8 rings and a dual port card, it is possible to bump up
* against the system mbuf pool limit, you can tune nmbclusters
* to adjust for this.
*/
-#define DEFAULT_RXD 1024
+#define DEFAULT_RXD 2048
#define PERFORM_RXD 2048
#define MAX_RXD 4096
#define MIN_RXD 64
@@ -170,7 +153,7 @@
/*
* Used for optimizing small rx mbufs. Effort is made to keep the copy
* small and aligned for the CPU L1 cache.
- *
+ *
* MHLEN is typically 168 bytes, giving us 8-byte alignment. Getting
* 32 byte alignment needed for the fast bcopy results in 8 bytes being
* wasted. Getting 64 byte alignment, which _should_ be ideal for
@@ -230,6 +213,11 @@
#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP)
#endif
+#define IXGBE_CAPS (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 | IFCAP_TSO | \
+ IFCAP_LRO | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | \
+ IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU | IFCAP_VLAN_MTU | \
+ IFCAP_HWSTATS | IFCAP_VLAN_HWFILTER | IFCAP_WOL)
+
/* Backward compatibility items for very old versions */
#ifndef pci_find_cap
#define pci_find_cap pci_find_extcap
@@ -240,7 +228,7 @@
#endif
/*
- * Interrupt Moderation parameters
+ * Interrupt Moderation parameters
*/
#define IXGBE_LOW_LATENCY 128
#define IXGBE_AVE_LATENCY 400
@@ -251,47 +239,14 @@
#define IXGBE_LINK_ITR ((IXGBE_LINK_ITR_QUANTA << 3) & \
IXGBE_EITR_ITR_INT_MASK)
-/* MAC type macros */
-#define IXGBE_IS_X550VF(_adapter) \
- ((_adapter->hw.mac.type == ixgbe_mac_X550_vf) || \
- (_adapter->hw.mac.type == ixgbe_mac_X550EM_x_vf))
-
-#define IXGBE_IS_VF(_adapter) \
- (IXGBE_IS_X550VF(_adapter) || \
- (_adapter->hw.mac.type == ixgbe_mac_X540_vf) || \
- (_adapter->hw.mac.type == ixgbe_mac_82599_vf))
-
-#ifdef PCI_IOV
-#define IXGBE_VF_INDEX(vmdq) ((vmdq) / 32)
-#define IXGBE_VF_BIT(vmdq) (1 << ((vmdq) % 32))
-
-#define IXGBE_VT_MSG_MASK 0xFFFF
-
-#define IXGBE_VT_MSGINFO(msg) \
- (((msg) & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT)
-
-#define IXGBE_VF_GET_QUEUES_RESP_LEN 5
-
-#define IXGBE_API_VER_1_0 0
-#define IXGBE_API_VER_2_0 1 /* Solaris API. Not supported. */
-#define IXGBE_API_VER_1_1 2
-#define IXGBE_API_VER_UNKNOWN UINT16_MAX
-
-enum ixgbe_iov_mode {
- IXGBE_64_VM,
- IXGBE_32_VM,
- IXGBE_NO_VM
-};
-#endif /* PCI_IOV */
-
/*
*****************************************************************************
* vendor_info_array
- *
+ *
* This array contains the list of Subvendor/Subdevice IDs on which the driver
* should load.
- *
+ *
*****************************************************************************
*/
typedef struct _ixgbe_vendor_info_t {
@@ -302,21 +257,12 @@
unsigned int index;
} ixgbe_vendor_info_t;
-
-struct ixgbe_tx_buf {
- union ixgbe_adv_tx_desc *eop;
- struct mbuf *m_head;
- bus_dmamap_t map;
+struct ixgbe_bp_data {
+ u32 low;
+ u32 high;
+ u32 log;
};
-struct ixgbe_rx_buf {
- struct mbuf *buf;
- struct mbuf *fmp;
- bus_dmamap_t pmap;
- u_int flags;
-#define IXGBE_RX_COPY 0x01
- uint64_t addr;
-};
/*
* Bus dma allocation structure used by ixgbe_dma_malloc and ixgbe_dma_free.
@@ -337,60 +283,28 @@
};
/*
-** Driver queue struct: this is the interrupt container
-** for the associated tx and rx ring.
-*/
-struct ix_queue {
- struct adapter *adapter;
- u32 msix; /* This queue's MSIX vector */
- u32 eims; /* This queue's EIMS bit */
- u32 eitr_setting;
- u32 me;
- struct resource *res;
- void *tag;
- int busy;
- struct tx_ring *txr;
- struct rx_ring *rxr;
- struct task que_task;
- struct taskqueue *tq;
- u64 irqs;
-};
-
-/*
* The transmit ring, one per queue
*/
struct tx_ring {
- struct adapter *adapter;
- struct mtx tx_mtx;
- u32 me;
- u32 tail;
- int busy;
- union ixgbe_adv_tx_desc *tx_base;
- struct ixgbe_tx_buf *tx_buffers;
- struct ixgbe_dma_alloc txdma;
- volatile u16 tx_avail;
- u16 next_avail_desc;
- u16 next_to_clean;
- u16 num_desc;
- u32 txd_cmd;
- bus_dma_tag_t txtag;
- char mtx_name[16];
-#ifndef IXGBE_LEGACY_TX
- struct buf_ring *br;
- struct task txq_task;
-#endif
-#ifdef IXGBE_FDIR
- u16 atr_sample;
- u16 atr_count;
-#endif
- u32 bytes; /* used for AIM */
- u32 packets;
+ struct adapter *adapter;
+ union ixgbe_adv_tx_desc *tx_base;
+ uint64_t tx_paddr;
+ u32 tail;
+ qidx_t *tx_rsq;
+ qidx_t tx_rs_cidx;
+ qidx_t tx_rs_pidx;
+ qidx_t tx_cidx_processed;
+ uint8_t me;
+
+ /* Flow Director */
+ u16 atr_sample;
+ u16 atr_count;
+
+ u32 bytes; /* used for AIM */
+ u32 packets;
/* Soft Stats */
- unsigned long tso_tx;
- unsigned long no_tx_map_avail;
- unsigned long no_tx_dma_setup;
- u64 no_desc_avail;
- u64 total_packets;
+ unsigned long tso_tx;
+ u64 total_packets;
};
@@ -398,22 +312,14 @@
* The Receive ring, one per rx queue
*/
struct rx_ring {
- struct adapter *adapter;
- struct mtx rx_mtx;
+ struct ix_rx_queue *que;
+ struct adapter *adapter;
u32 me;
u32 tail;
union ixgbe_adv_rx_desc *rx_base;
- struct ixgbe_dma_alloc rxdma;
- struct lro_ctrl lro;
- bool lro_enabled;
+ uint64_t rx_paddr;
bool hw_rsc;
bool vtag_strip;
- u16 next_to_refresh;
- u16 next_to_check;
- u16 num_desc;
- u16 mbuf_sz;
- char mtx_name[16];
- struct ixgbe_rx_buf *rx_buffers;
bus_dma_tag_t ptag;
u32 bytes; /* Used for AIM calc */
@@ -423,26 +329,43 @@
u64 rx_irq;
u64 rx_copies;
u64 rx_packets;
- u64 rx_bytes;
- u64 rx_discarded;
- u64 rsc_num;
-#ifdef IXGBE_FDIR
+ u64 rx_bytes;
+ u64 rx_discarded;
+ u64 rsc_num;
+
+ /* Flow Director */
u64 flm;
-#endif
};
-#ifdef PCI_IOV
-#define IXGBE_VF_CTS (1 << 0) /* VF is clear to send. */
-#define IXGBE_VF_CAP_MAC (1 << 1) /* VF is permitted to change MAC. */
-#define IXGBE_VF_CAP_VLAN (1 << 2) /* VF is permitted to join vlans. */
-#define IXGBE_VF_ACTIVE (1 << 3) /* VF is active. */
+/*
+** Driver queue struct: this is the interrupt container
+** for the associated tx and rx ring.
+*/
+struct ix_rx_queue {
+ struct adapter *adapter;
+ u32 msix; /* This queue's MSIX vector */
+ u32 eims; /* This queue's EIMS bit */
+ u32 eitr_setting;
+ struct resource *res;
+ void *tag;
+ int busy;
+ struct rx_ring rxr;
+ struct if_irq que_irq;
+ u64 irqs;
+};
+
+struct ix_tx_queue {
+ struct adapter *adapter;
+ u32 msix; /* This queue's MSIX vector */
+ struct tx_ring txr;
+};
#define IXGBE_MAX_VF_MC 30 /* Max number of multicast entries */
struct ixgbe_vf {
u_int pool;
u_int rar_index;
- u_int max_frame_size;
+ u_int maximum_frame_size;
uint32_t flags;
uint8_t ether_addr[ETHER_ADDR_LEN];
uint16_t mc_hash[IXGBE_MAX_VF_MC];
@@ -451,39 +374,38 @@
uint16_t vlan_tag;
uint16_t api_ver;
};
-#endif /* PCI_IOV */
/* Our adapter structure */
struct adapter {
+ /* much of the code assumes this is first :< */
struct ixgbe_hw hw;
struct ixgbe_osdep osdep;
-
- device_t dev;
+ if_ctx_t ctx;
+ if_softc_ctx_t shared;
+#define num_tx_queues shared->isc_ntxqsets
+#define num_rx_queues shared->isc_nrxqsets
+#define max_frame_size shared->isc_max_frame_size
+#define intr_type shared->isc_intr
struct ifnet *ifp;
+ struct device *dev;
+
struct resource *pci_mem;
- struct resource *msix_mem;
/*
* Interrupt resources: this set is
* either used for legacy, or for Link
* when doing MSIX
*/
+ struct if_irq irq;
void *tag;
- struct resource *res;
+ struct resource *res;
- struct ifmedia media;
- struct callout timer;
+ struct ifmedia *media;
int msix;
int if_flags;
- struct mtx core_mtx;
-
- eventhandler_tag vlan_attach;
- eventhandler_tag vlan_detach;
-
u16 num_vlans;
- u16 num_queues;
/*
** Shadow VFTA table, this is needed because
@@ -495,15 +417,13 @@
/* Info about the interface */
u32 optics;
- u32 fc; /* local flow ctrl setting */
int advertise; /* link speeds */
bool enable_aim; /* adaptive interrupt moderation */
bool link_active;
- u16 max_frame_size;
u16 num_segs;
u32 link_speed;
bool link_up;
- u32 vector;
+ u32 vector;
u16 dmac;
bool eee_enabled;
u32 phy_layer;
@@ -512,67 +432,54 @@
bool wol_support;
u32 wufc;
- /* Mbuf cluster size */
- u32 rx_mbuf_sz;
-
/* Support for pluggable optics */
bool sfp_probe;
- struct task link_task; /* Link tasklet */
- struct task mod_task; /* SFP tasklet */
- struct task msf_task; /* Multispeed Fiber */
-#ifdef PCI_IOV
- struct task mbx_task; /* VF -> PF mailbox interrupt */
-#endif /* PCI_IOV */
-#ifdef IXGBE_FDIR
+
+ struct grouptask mod_task; /* SFP tasklet */
+ struct grouptask msf_task; /* Multispeed Fiber */
+
+ struct grouptask mbx_task; /* VF -> PF mailbox interrupt */
+
+ /* Flow Director */
int fdir_reinit;
- struct task fdir_task;
-#endif
- struct task phy_task; /* PHY intr tasklet */
- struct taskqueue *tq;
+ struct grouptask fdir_task;
+
+ struct grouptask phy_task; /* PHY intr tasklet */
/*
- ** Queues:
+ ** Queues:
** This is the irq holder, it has
** and RX/TX pair or rings associated
** with it.
*/
- struct ix_queue *queues;
-
- /*
- * Transmit rings:
- * Allocated at run time, an array of rings.
- */
- struct tx_ring *tx_rings;
- u32 num_tx_desc;
- u32 tx_process_limit;
-
- /*
- * Receive rings:
- * Allocated at run time, an array of rings.
- */
- struct rx_ring *rx_rings;
+ struct ix_tx_queue *tx_queues;
+ struct ix_rx_queue *rx_queues;
u64 active_queues;
- u32 num_rx_desc;
+
+ u32 tx_process_limit;
u32 rx_process_limit;
/* Multicast array memory */
struct ixgbe_mc_addr *mta;
+
+ /* SR-IOV */
+ int iov_mode;
int num_vfs;
int pool;
-#ifdef PCI_IOV
struct ixgbe_vf *vfs;
-#endif
#ifdef DEV_NETMAP
- void (*init_locked)(struct adapter *);
- void (*stop_locked)(void *);
+ void (*init_locked)(struct adapter *);
+ void (*stop_locked)(void *);
#endif
+ /* Bypass */
+ struct ixgbe_bp_data bypass;
+
/* Misc stats maintained by the driver */
- unsigned long dropped_pkts;
- unsigned long mbuf_defrag_failed;
- unsigned long mbuf_header_failed;
- unsigned long mbuf_packet_failed;
- unsigned long watchdog_events;
+ unsigned long rx_mbuf_sz;
+ unsigned long mbuf_header_failed;
+ unsigned long mbuf_packet_failed;
+ unsigned long watchdog_events;
unsigned long link_irq;
union {
struct ixgbe_hw_stats pf;
@@ -591,31 +498,17 @@
u64 iqdrops;
u64 noproto;
#endif
+ /* Feature capable/enabled flags. See ixgbe_features.h */
+ u32 feat_cap;
+ u32 feat_en;
};
-
/* Precision Time Sync (IEEE 1588) defines */
#define ETHERTYPE_IEEE1588 0x88F7
#define PICOSECS_PER_TICK 20833
#define TSYNC_UDP_PORT 319 /* UDP port for the protocol */
#define IXGBE_ADVTXD_TSTAMP 0x00080000
-
-#define IXGBE_CORE_LOCK_INIT(_sc, _name) \
- mtx_init(&(_sc)->core_mtx, _name, "IXGBE Core Lock", MTX_DEF)
-#define IXGBE_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
-#define IXGBE_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx)
-#define IXGBE_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
-#define IXGBE_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
-#define IXGBE_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
-#define IXGBE_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx)
-#define IXGBE_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
-#define IXGBE_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
-#define IXGBE_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
-#define IXGBE_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx)
-#define IXGBE_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
-#define IXGBE_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
-
/* For backward compatibility */
#if !defined(PCIER_LINK_STA)
#define PCIER_LINK_STA PCIR_EXPRESS_LINK_STA
@@ -655,8 +548,9 @@
"\nControl advertised link speed using these flags:\n" \
"\t0x1 - advertise 100M\n" \
"\t0x2 - advertise 1G\n" \
- "\t0x4 - advertise 10G\n\n" \
- "\t100M is only supported on certain 10GBaseT adapters.\n"
+ "\t0x4 - advertise 10G\n" \
+ "\t0x8 - advertise 10M\n\n" \
+ "\t100M and 10M are only supported on certain adapters.\n"
#define IXGBE_SYSCTL_DESC_SET_FC \
"\nSet flow control mode using these values:\n" \
@@ -665,53 +559,20 @@
"\t2 - tx pause\n" \
"\t3 - tx and rx pause"
-static inline bool
-ixgbe_is_sfp(struct ixgbe_hw *hw)
-{
- switch (hw->phy.type) {
- case ixgbe_phy_sfp_avago:
- case ixgbe_phy_sfp_ftl:
- case ixgbe_phy_sfp_intel:
- case ixgbe_phy_sfp_unknown:
- case ixgbe_phy_sfp_passive_tyco:
- case ixgbe_phy_sfp_passive_unknown:
- case ixgbe_phy_qsfp_passive_unknown:
- case ixgbe_phy_qsfp_active_unknown:
- case ixgbe_phy_qsfp_intel:
- case ixgbe_phy_qsfp_unknown:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
/* Workaround to make 8.0 buildable */
#if __FreeBSD_version >= 800000 && __FreeBSD_version < 800504
static __inline int
drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
{
#ifdef ALTQ
- if (ALTQ_IS_ENABLED(&ifp->if_snd))
- return (1);
+ if (ALTQ_IS_ENABLED(&ifp->if_snd))
+ return (1);
#endif
- return (!buf_ring_empty(br));
+ return (!buf_ring_empty(br));
}
#endif
/*
-** Find the number of unrefreshed RX descriptors
-*/
-static inline u16
-ixgbe_rx_unrefreshed(struct rx_ring *rxr)
-{
- if (rxr->next_to_check > rxr->next_to_refresh)
- return (rxr->next_to_check - rxr->next_to_refresh - 1);
- else
- return ((rxr->num_desc + rxr->next_to_check) -
- rxr->next_to_refresh - 1);
-}
-
-/*
** This checks for a zero mac addr, something that will be likely
** unless the Admin on the Host has created one.
*/
@@ -728,16 +589,6 @@
/* Shared Prototypes */
-#ifdef IXGBE_LEGACY_TX
-void ixgbe_start(struct ifnet *);
-void ixgbe_start_locked(struct tx_ring *, struct ifnet *);
-#else /* ! IXGBE_LEGACY_TX */
-int ixgbe_mq_start(struct ifnet *, struct mbuf *);
-int ixgbe_mq_start_locked(struct ifnet *, struct tx_ring *);
-void ixgbe_qflush(struct ifnet *);
-void ixgbe_deferred_mq_start(void *, int);
-#endif /* IXGBE_LEGACY_TX */
-
int ixgbe_allocate_queues(struct adapter *);
int ixgbe_allocate_transmit_buffers(struct tx_ring *);
int ixgbe_setup_transmit_structures(struct adapter *);
@@ -745,156 +596,16 @@
int ixgbe_allocate_receive_buffers(struct rx_ring *);
int ixgbe_setup_receive_structures(struct adapter *);
void ixgbe_free_receive_structures(struct adapter *);
-void ixgbe_txeof(struct tx_ring *);
-bool ixgbe_rxeof(struct ix_queue *);
int ixgbe_dma_malloc(struct adapter *,
bus_size_t, struct ixgbe_dma_alloc *, int);
void ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *);
+int ixgbe_get_regs(SYSCTL_HANDLER_ARGS);
+void ixgbe_if_init(if_ctx_t ctx);
-#ifdef PCI_IOV
-
-static inline boolean_t
-ixgbe_vf_mac_changed(struct ixgbe_vf *vf, const uint8_t *mac)
-{
- return (bcmp(mac, vf->ether_addr, ETHER_ADDR_LEN) != 0);
-}
-
-static inline void
-ixgbe_send_vf_msg(struct adapter *adapter, struct ixgbe_vf *vf, u32 msg)
-{
-
- if (vf->flags & IXGBE_VF_CTS)
- msg |= IXGBE_VT_MSGTYPE_CTS;
-
- ixgbe_write_mbx(&adapter->hw, &msg, 1, vf->pool);
-}
-
-static inline void
-ixgbe_send_vf_ack(struct adapter *adapter, struct ixgbe_vf *vf, u32 msg)
-{
- msg &= IXGBE_VT_MSG_MASK;
- ixgbe_send_vf_msg(adapter, vf, msg | IXGBE_VT_MSGTYPE_ACK);
-}
-
-static inline void
-ixgbe_send_vf_nack(struct adapter *adapter, struct ixgbe_vf *vf, u32 msg)
-{
- msg &= IXGBE_VT_MSG_MASK;
- ixgbe_send_vf_msg(adapter, vf, msg | IXGBE_VT_MSGTYPE_NACK);
-}
-
-static inline void
-ixgbe_process_vf_ack(struct adapter *adapter, struct ixgbe_vf *vf)
-{
- if (!(vf->flags & IXGBE_VF_CTS))
- ixgbe_send_vf_nack(adapter, vf, 0);
-}
-
-static inline enum ixgbe_iov_mode
-ixgbe_get_iov_mode(struct adapter *adapter)
-{
- if (adapter->num_vfs == 0)
- return (IXGBE_NO_VM);
- if (adapter->num_queues <= 2)
- return (IXGBE_64_VM);
- else if (adapter->num_queues <= 4)
- return (IXGBE_32_VM);
- else
- return (IXGBE_NO_VM);
-}
-
-static inline u16
-ixgbe_max_vfs(enum ixgbe_iov_mode mode)
-{
- /*
- * We return odd numbers below because we
- * reserve 1 VM's worth of queues for the PF.
- */
- switch (mode) {
- case IXGBE_64_VM:
- return (63);
- case IXGBE_32_VM:
- return (31);
- case IXGBE_NO_VM:
- default:
- return (0);
- }
-}
-
-static inline int
-ixgbe_vf_queues(enum ixgbe_iov_mode mode)
-{
- switch (mode) {
- case IXGBE_64_VM:
- return (2);
- case IXGBE_32_VM:
- return (4);
- case IXGBE_NO_VM:
- default:
- return (0);
- }
-}
-
-static inline int
-ixgbe_vf_que_index(enum ixgbe_iov_mode mode, u32 vfnum, int num)
-{
- return ((vfnum * ixgbe_vf_queues(mode)) + num);
-}
-
-static inline int
-ixgbe_pf_que_index(enum ixgbe_iov_mode mode, int num)
-{
- return (ixgbe_vf_que_index(mode, ixgbe_max_vfs(mode), num));
-}
-
-static inline void
-ixgbe_update_max_frame(struct adapter * adapter, int max_frame)
-{
- if (adapter->max_frame_size < max_frame)
- adapter->max_frame_size = max_frame;
-}
-
-static inline u32
-ixgbe_get_mrqc(enum ixgbe_iov_mode mode)
-{
- u32 mrqc = 0;
- switch (mode) {
- case IXGBE_64_VM:
- mrqc = IXGBE_MRQC_VMDQRSS64EN;
- break;
- case IXGBE_32_VM:
- mrqc = IXGBE_MRQC_VMDQRSS32EN;
- break;
- case IXGBE_NO_VM:
- mrqc = 0;
- break;
- default:
- panic("Unexpected SR-IOV mode %d", mode);
- }
- return(mrqc);
-}
-
-
-static inline u32
-ixgbe_get_mtqc(enum ixgbe_iov_mode mode)
-{
- uint32_t mtqc = 0;
- switch (mode) {
- case IXGBE_64_VM:
- mtqc |= IXGBE_MTQC_64VF | IXGBE_MTQC_VT_ENA;
- break;
- case IXGBE_32_VM:
- mtqc |= IXGBE_MTQC_32VF | IXGBE_MTQC_VT_ENA;
- break;
- case IXGBE_NO_VM:
- mtqc = IXGBE_MTQC_64Q_1PB;
- break;
- default:
- panic("Unexpected SR-IOV mode %d", mode);
- }
- return(mtqc);
-}
-#endif /* PCI_IOV */
+#include "ixgbe_sriov.h"
+#include "ixgbe_bypass.h"
+#include "ixgbe_fdir.h"
+#include "ixgbe_rss.h"
#endif /* _IXGBE_H_ */
Index: sys/dev/ixgbe/ixgbe_82598.h
===================================================================
--- sys/dev/ixgbe/ixgbe_82598.h
+++ sys/dev/ixgbe/ixgbe_82598.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -40,12 +40,13 @@
s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw);
s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
-s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
+s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on,
+ bool vlvf_bypass);
s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data);
-u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
+u64 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
Index: sys/dev/ixgbe/ixgbe_82598.c
===================================================================
--- sys/dev/ixgbe/ixgbe_82598.c
+++ sys/dev/ixgbe/ixgbe_82598.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -996,17 +996,20 @@
* @vlan: VLAN id to write to VLAN filter
* @vind: VMDq output index that maps queue to VLAN id in VFTA
* @vlan_on: boolean flag to turn on/off VLAN in VFTA
+ * @vlvf_bypass: boolean flag - unused
*
* Turn on/off specified VLAN in the VLAN filter table.
**/
s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on)
+ bool vlan_on, bool vlvf_bypass)
{
u32 regindex;
u32 bitindex;
u32 bits;
u32 vftabyte;
+ UNREFERENCED_1PARAMETER(vlvf_bypass);
+
DEBUGFUNC("ixgbe_set_vfta_82598");
if (vlan > 4095)
@@ -1220,9 +1223,9 @@
*
* Determines physical layer capabilities of the current configuration.
**/
-u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
+u64 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
Index: sys/dev/ixgbe/ixgbe_82599.h
===================================================================
--- sys/dev/ixgbe/ixgbe_82599.h
+++ sys/dev/ixgbe/ixgbe_82599.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -58,7 +58,7 @@
s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw);
s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw);
-u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
+u64 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval);
s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, u32 *reg_val);
s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 reg_val, bool locked);
Index: sys/dev/ixgbe/ixgbe_82599.c
===================================================================
--- sys/dev/ixgbe/ixgbe_82599.c
+++ sys/dev/ixgbe/ixgbe_82599.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -394,6 +394,10 @@
/* Manageability interface */
mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic;
+ mac->ops.bypass_rw = ixgbe_bypass_rw_generic;
+ mac->ops.bypass_valid_rd = ixgbe_bypass_valid_rd_generic;
+ mac->ops.bypass_set = ixgbe_bypass_set_generic;
+ mac->ops.bypass_rd_eep = ixgbe_bypass_rd_eep_generic;
mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
@@ -1177,12 +1181,16 @@
/* Add the SAN MAC address to the RAR only if it's a valid address */
if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
- hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
- hw->mac.san_addr, 0, IXGBE_RAH_AV);
-
/* Save the SAN MAC RAR index */
hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
+ hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index,
+ hw->mac.san_addr, 0, IXGBE_RAH_AV);
+
+ /* clear VMDq pool/queue selection for this RAR */
+ hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index,
+ IXGBE_CLEAR_VMDQ_ALL);
+
/* Reserve the last RAR for the SAN MAC address */
hw->mac.num_rar_entries--;
}
@@ -1381,9 +1389,6 @@
(0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
(0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
(4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
- if ((hw->mac.type == ixgbe_mac_X550) ||
- (hw->mac.type == ixgbe_mac_X550EM_x))
- fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
if (cloud_mode)
fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD <<
@@ -1412,7 +1417,8 @@
/* Set drop queue */
fdirctrl |= (dropqueue << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
if ((hw->mac.type == ixgbe_mac_X550) ||
- (hw->mac.type == ixgbe_mac_X550EM_x))
+ (hw->mac.type == ixgbe_mac_X550EM_x) ||
+ (hw->mac.type == ixgbe_mac_X550EM_a))
fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
@@ -1809,14 +1815,23 @@
}
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIP6M, fdirip6m);
- /* Set all bits in FDIRTCPM, FDIRUDPM, FDIRSIP4M and
- * FDIRDIP4M in cloud mode to allow L3/L3 packets to
- * tunnel.
+ /* Set all bits in FDIRTCPM, FDIRUDPM, FDIRSCTPM,
+ * FDIRSIP4M and FDIRDIP4M in cloud mode to allow
+ * L3/L3 packets to tunnel.
*/
IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xFFFFFFFF);
IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xFFFFFFFF);
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, 0xFFFFFFFF);
IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, 0xFFFFFFFF);
+ switch (hw->mac.type) {
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, 0xFFFFFFFF);
+ break;
+ default:
+ break;
+ }
}
/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
@@ -1834,6 +1849,7 @@
switch (hw->mac.type) {
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
break;
default:
@@ -2158,9 +2174,9 @@
*
* Determines physical layer capabilities of the current configuration.
**/
-u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
+u64 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
Index: sys/dev/ixgbe/ixgbe_api.h
===================================================================
--- sys/dev/ixgbe/ixgbe_api.h
+++ sys/dev/ixgbe/ixgbe_api.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -46,6 +46,8 @@
extern s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw);
extern s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw);
extern s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw);
+extern s32 ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw);
+extern s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw);
extern s32 ixgbe_init_ops_vf(struct ixgbe_hw *hw);
s32 ixgbe_set_mac_type(struct ixgbe_hw *hw);
@@ -125,13 +127,14 @@
s32 ixgbe_disable_mc(struct ixgbe_hw *hw);
s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
- u32 vind, bool vlan_on);
+ u32 vind, bool vlan_on, bool vlvf_bypass);
s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on, bool *vfta_changed);
+ bool vlan_on, u32 *vfta_delta, u32 vfta,
+ bool vlvf_bypass);
s32 ixgbe_fc_enable(struct ixgbe_hw *hw);
s32 ixgbe_setup_fc(struct ixgbe_hw *hw);
s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
- u8 ver);
+ u8 ver, u16 len, char *driver_ver);
void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr);
s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw,
u16 *firmware_version);
@@ -139,7 +142,7 @@
s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw);
s32 ixgbe_read_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data);
-u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw);
+u64 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval);
s32 ixgbe_disable_sec_rx_path(struct ixgbe_hw *hw);
s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw);
@@ -175,26 +178,29 @@
u8 *data);
s32 ixgbe_read_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
-s32 ixgbe_read_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val);
-s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
- u16 *val);
+s32 ixgbe_read_link(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val);
+s32 ixgbe_read_link_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val);
s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
u8 data);
void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue);
s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
-s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val);
-s32 ixgbe_write_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
- u16 val);
+s32 ixgbe_write_link(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val);
+s32 ixgbe_write_link_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val);
s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data);
s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps);
s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u32 mask);
void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u32 mask);
+void ixgbe_init_swfw_semaphore(struct ixgbe_hw *hw);
s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix,
u16 *wwpn_prefix);
s32 ixgbe_get_fcoe_boot_status(struct ixgbe_hw *hw, u16 *bs);
+s32 ixgbe_bypass_rw(struct ixgbe_hw *hw, u32 cmd, u32 *status);
+s32 ixgbe_bypass_set(struct ixgbe_hw *hw, u32 cmd, u32 event, u32 action);
+s32 ixgbe_bypass_rd_eep(struct ixgbe_hw *hw, u32 addr, u8 *value);
+bool ixgbe_bypass_valid_rd(struct ixgbe_hw *hw, u32 in_reg, u32 out_reg);
s32 ixgbe_dmac_config(struct ixgbe_hw *hw);
s32 ixgbe_dmac_update_tcs(struct ixgbe_hw *hw);
s32 ixgbe_dmac_config_tcs(struct ixgbe_hw *hw);
@@ -216,5 +222,7 @@
void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed);
void ixgbe_disable_rx(struct ixgbe_hw *hw);
void ixgbe_enable_rx(struct ixgbe_hw *hw);
+s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+ u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
#endif /* _IXGBE_API_H_ */
Index: sys/dev/ixgbe/ixgbe_api.c
===================================================================
--- sys/dev/ixgbe/ixgbe_api.c
+++ sys/dev/ixgbe/ixgbe_api.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -53,6 +53,10 @@
IXGBE_MVALS_INIT(_X550EM_x)
};
+static const u32 ixgbe_mvals_X550EM_a[IXGBE_MVALS_IDX_LIMIT] = {
+ IXGBE_MVALS_INIT(_X550EM_a)
+};
+
/**
* ixgbe_dcb_get_rtrup2tc - read rtrup2tc reg
* @hw: pointer to hardware structure
@@ -103,12 +107,16 @@
status = ixgbe_init_ops_X550(hw);
break;
case ixgbe_mac_X550EM_x:
- status = ixgbe_init_ops_X550EM(hw);
+ status = ixgbe_init_ops_X550EM_x(hw);
+ break;
+ case ixgbe_mac_X550EM_a:
+ status = ixgbe_init_ops_X550EM_a(hw);
break;
case ixgbe_mac_82599_vf:
case ixgbe_mac_X540_vf:
case ixgbe_mac_X550_vf:
case ixgbe_mac_X550EM_x_vf:
+ case ixgbe_mac_X550EM_a_vf:
status = ixgbe_init_ops_vf(hw);
break;
default:
@@ -199,9 +207,24 @@
case IXGBE_DEV_ID_X550EM_X_10G_T:
case IXGBE_DEV_ID_X550EM_X_1G_T:
case IXGBE_DEV_ID_X550EM_X_SFP:
+ case IXGBE_DEV_ID_X550EM_X_XFI:
hw->mac.type = ixgbe_mac_X550EM_x;
hw->mvals = ixgbe_mvals_X550EM_x;
break;
+ case IXGBE_DEV_ID_X550EM_A_KR:
+ case IXGBE_DEV_ID_X550EM_A_KR_L:
+ case IXGBE_DEV_ID_X550EM_A_SFP_N:
+ case IXGBE_DEV_ID_X550EM_A_SGMII:
+ case IXGBE_DEV_ID_X550EM_A_SGMII_L:
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_QSFP:
+ case IXGBE_DEV_ID_X550EM_A_QSFP_N:
+ case IXGBE_DEV_ID_X550EM_A_SFP:
+ hw->mac.type = ixgbe_mac_X550EM_a;
+ hw->mvals = ixgbe_mvals_X550EM_a;
+ break;
case IXGBE_DEV_ID_X550_VF:
case IXGBE_DEV_ID_X550_VF_HV:
hw->mac.type = ixgbe_mac_X550_vf;
@@ -212,6 +235,11 @@
hw->mac.type = ixgbe_mac_X550EM_x_vf;
hw->mvals = ixgbe_mvals_X550EM_x;
break;
+ case IXGBE_DEV_ID_X550EM_A_VF:
+ case IXGBE_DEV_ID_X550EM_A_VF_HV:
+ hw->mac.type = ixgbe_mac_X550EM_a_vf;
+ hw->mvals = ixgbe_mvals_X550EM_a;
+ break;
default:
ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
@@ -1059,13 +1087,15 @@
* @vlan: VLAN id to write to VLAN filter
* @vind: VMDq output index that maps queue to VLAN id in VFTA
* @vlan_on: boolean flag to turn on/off VLAN in VFTA
+ * @vlvf_bypass: boolean flag indicating updating the default pool is okay
*
* Turn on/off specified VLAN in the VLAN filter table.
**/
-s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
+s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on,
+ bool vlvf_bypass)
{
return ixgbe_call_func(hw, hw->mac.ops.set_vfta, (hw, vlan, vind,
- vlan_on), IXGBE_NOT_IMPLEMENTED);
+ vlan_on, vlvf_bypass), IXGBE_NOT_IMPLEMENTED);
}
/**
@@ -1074,16 +1104,19 @@
* @vlan: VLAN id to write to VLAN filter
* @vind: VMDq output index that maps queue to VLAN id in VFVFB
* @vlan_on: boolean flag to turn on/off VLAN in VFVF
- * @vfta_changed: pointer to boolean flag which indicates whether VFTA
- * should be changed
+ * @vfta_delta: pointer to the difference between the current value of VFTA
+ * and the desired value
+ * @vfta: the desired value of the VFTA
+ * @vlvf_bypass: boolean flag indicating updating the default pool is okay
*
* Turn on/off specified bit in VLVF table.
**/
s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on,
- bool *vfta_changed)
+ u32 *vfta_delta, u32 vfta, bool vlvf_bypass)
{
return ixgbe_call_func(hw, hw->mac.ops.set_vlvf, (hw, vlan, vind,
- vlan_on, vfta_changed), IXGBE_NOT_IMPLEMENTED);
+ vlan_on, vfta_delta, vfta, vlvf_bypass),
+ IXGBE_NOT_IMPLEMENTED);
}
/**
@@ -1117,12 +1150,15 @@
* @min: driver minor number to be sent to firmware
* @build: driver build number to be sent to firmware
* @ver: driver version number to be sent to firmware
+ * @len: length of driver_ver string
+ * @driver_ver: driver string
**/
s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
- u8 ver)
+ u8 ver, u16 len, char *driver_ver)
{
return ixgbe_call_func(hw, hw->mac.ops.set_fw_drv_ver, (hw, maj, min,
- build, ver), IXGBE_NOT_IMPLEMENTED);
+ build, ver, len, driver_ver),
+ IXGBE_NOT_IMPLEMENTED);
}
@@ -1317,6 +1353,69 @@
}
/**
+ * ixgbe_bypass_rw - Bit bang data into by_pass FW
+ * @hw: pointer to hardware structure
+ * @cmd: Command we send to the FW
+ * @status: The reply from the FW
+ *
+ * Bit-bangs the cmd to the by_pass FW status points to what is returned.
+ **/
+s32 ixgbe_bypass_rw(struct ixgbe_hw *hw, u32 cmd, u32 *status)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.bypass_rw, (hw, cmd, status),
+ IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_bypass_valid_rd - Verify valid return from bit-bang.
+ *
+ * If we send a write we can't be sure it took until we can read back
+ * that same register. It can be a problem as some of the feilds may
+ * for valid reasons change inbetween the time wrote the register and
+ * we read it again to verify. So this function check everything we
+ * can check and then assumes it worked.
+ *
+ * @u32 in_reg - The register cmd for the bit-bang read.
+ * @u32 out_reg - The register returned from a bit-bang read.
+ **/
+bool ixgbe_bypass_valid_rd(struct ixgbe_hw *hw, u32 in_reg, u32 out_reg)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.bypass_valid_rd,
+ (in_reg, out_reg), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_bypass_set - Set a bypass field in the FW CTRL Regiter.
+ * @hw: pointer to hardware structure
+ * @cmd: The control word we are setting.
+ * @event: The event we are setting in the FW. This also happens to
+ * be the mask for the event we are setting (handy)
+ * @action: The action we set the event to in the FW. This is in a
+ * bit field that happens to be what we want to put in
+ * the event spot (also handy)
+ *
+ * Writes to the cmd control the bits in actions.
+ **/
+s32 ixgbe_bypass_set(struct ixgbe_hw *hw, u32 cmd, u32 event, u32 action)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.bypass_set,
+ (hw, cmd, event, action),
+ IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_bypass_rd_eep - Read the bypass FW eeprom address
+ * @hw: pointer to hardware structure
+ * @addr: The bypass eeprom address to read.
+ * @value: The 8b of data at the address above.
+ **/
+s32 ixgbe_bypass_rd_eep(struct ixgbe_hw *hw, u32 addr, u8 *value)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.bypass_rd_eep,
+ (hw, addr, value), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
* ixgbe_read_analog_reg8 - Reads 8 bit analog register
* @hw: pointer to hardware structure
* @reg: analog register to read
@@ -1391,35 +1490,33 @@
}
/**
- * ixgbe_read_i2c_combined - Perform I2C read combined operation
+ * ixgbe_read_link - Perform read operation on link device
* @hw: pointer to the hardware structure
- * @addr: I2C bus address to read from
- * @reg: I2C device register to read from
+ * @addr: bus address to read from
+ * @reg: device register to read from
* @val: pointer to location to receive read value
*
* Returns an error code on error.
*/
-s32 ixgbe_read_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val)
+s32 ixgbe_read_link(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val)
{
- return ixgbe_call_func(hw, hw->phy.ops.read_i2c_combined, (hw, addr,
+ return ixgbe_call_func(hw, hw->link.ops.read_link, (hw, addr,
reg, val), IXGBE_NOT_IMPLEMENTED);
}
/**
- * ixgbe_read_i2c_combined_unlocked - Perform I2C read combined operation
+ * ixgbe_read_link_unlocked - Perform read operation on link device
* @hw: pointer to the hardware structure
- * @addr: I2C bus address to read from
- * @reg: I2C device register to read from
+ * @addr: bus address to read from
+ * @reg: device register to read from
* @val: pointer to location to receive read value
*
* Returns an error code on error.
**/
-s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
- u16 *val)
+s32 ixgbe_read_link_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val)
{
- return ixgbe_call_func(hw, hw->phy.ops.read_i2c_combined_unlocked,
- (hw, addr, reg, val),
- IXGBE_NOT_IMPLEMENTED);
+ return ixgbe_call_func(hw, hw->link.ops.read_link_unlocked,
+ (hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED);
}
/**
@@ -1458,33 +1555,32 @@
}
/**
- * ixgbe_write_i2c_combined - Perform I2C write combined operation
+ * ixgbe_write_link - Perform write operation on link device
* @hw: pointer to the hardware structure
- * @addr: I2C bus address to write to
- * @reg: I2C device register to write to
+ * @addr: bus address to write to
+ * @reg: device register to write to
* @val: value to write
*
* Returns an error code on error.
*/
-s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val)
+s32 ixgbe_write_link(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val)
{
- return ixgbe_call_func(hw, hw->phy.ops.write_i2c_combined, (hw, addr,
- reg, val), IXGBE_NOT_IMPLEMENTED);
+ return ixgbe_call_func(hw, hw->link.ops.write_link,
+ (hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED);
}
/**
- * ixgbe_write_i2c_combined_unlocked - Perform I2C write combined operation
+ * ixgbe_write_link_unlocked - Perform write operation on link device
* @hw: pointer to the hardware structure
- * @addr: I2C bus address to write to
- * @reg: I2C device register to write to
+ * @addr: bus address to write to
+ * @reg: device register to write to
* @val: value to write
*
* Returns an error code on error.
**/
-s32 ixgbe_write_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
- u16 val)
+s32 ixgbe_write_link_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val)
{
- return ixgbe_call_func(hw, hw->phy.ops.write_i2c_combined_unlocked,
+ return ixgbe_call_func(hw, hw->link.ops.write_link_unlocked,
(hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED);
}
@@ -1525,7 +1621,7 @@
*
* Determines physical layer capabilities of the current configuration.
**/
-u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw)
+u64 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, hw->mac.ops.get_supported_physical_layer,
(hw), IXGBE_PHYSICAL_LAYER_UNKNOWN);
@@ -1596,6 +1692,21 @@
hw->mac.ops.release_swfw_sync(hw, mask);
}
+/**
+ * ixgbe_init_swfw_semaphore - Clean up SWFW semaphore
+ * @hw: pointer to hardware structure
+ *
+ * Attempts to acquire the SWFW semaphore through SW_FW_SYNC register.
+ * Regardless of whether is succeeds or not it then release the semaphore.
+ * This is function is called to recover from catastrophic failures that
+ * may have left the semaphore locked.
+ **/
+void ixgbe_init_swfw_semaphore(struct ixgbe_hw *hw)
+{
+ if (hw->mac.ops.init_swfw_sync)
+ hw->mac.ops.init_swfw_sync(hw);
+}
+
void ixgbe_disable_rx(struct ixgbe_hw *hw)
{
Index: sys/dev/ixgbe/ixgbe_bypass.h
===================================================================
--- sys/dev/ixgbe/ixgbe_bypass.h
+++ sys/dev/ixgbe/ixgbe_bypass.h
@@ -1,53 +1,51 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
/*$FreeBSD$*/
-#ifndef _IXGBE_82598_H_
-#define _IXGBE_82598_H_
-
-u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw);
-s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw);
-s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
-void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw);
-s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
-s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
-s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
-s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
-s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
- u8 *eeprom_data);
-u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
-s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
-void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
-void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
-s32 ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, u32 regval);
-#endif /* _IXGBE_82598_H_ */
+#ifndef _IXGBE_BYPASS_H_
+#define _IXGBE_BYPASS_H_
+
+
+/*
+ * The bypass driver needs to set FW to a epoc of the number of
+ * seconds we are into this year. This macro's help support that.
+ */
+#define SEC_PER_DAY (60 * 60 * 24)
+#define SEC_PER_YEAR (SEC_PER_DAY * 365)
+#define SEC_PER_LYEAR (SEC_PER_DAY * 366)
+#define LEAP_YR(y) ((y % 400 == 0) || ((y % 4 == 0) && (y % 100 != 0)))
+#define SEC_THIS_YEAR(y) (LEAP_YR(y) ? SEC_PER_LYEAR : SEC_PER_YEAR)
+
+void ixgbe_bypass_init(struct adapter *);
+
+#endif
Index: sys/dev/ixgbe/ixgbe_common.h
===================================================================
--- sys/dev/ixgbe/ixgbe_common.h
+++ sys/dev/ixgbe/ixgbe_common.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -75,6 +75,7 @@
s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
+s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
@@ -136,11 +137,12 @@
s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw);
s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan,
- u32 vind, bool vlan_on);
+ u32 vind, bool vlan_on, bool vlvf_bypass);
s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on, bool *vfta_changed);
+ bool vlan_on, u32 *vfta_delta, u32 vfta,
+ bool vlvf_bypass);
s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
+s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass);
s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
@@ -150,19 +152,27 @@
u16 *wwpn_prefix);
s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs);
-void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
+void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps);
void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom,
int strategy);
void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw);
s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
- u8 build, u8 ver);
+ u8 build, u8 ver, u16 len, const char *str);
u8 ixgbe_calculate_checksum(u8 *buffer, u32 length);
s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
u32 length, u32 timeout, bool return_data);
-
+s32 ixgbe_hic_unlocked(struct ixgbe_hw *, u32 *buffer, u32 length, u32 timeout);
+s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *);
+s32 ixgbe_fw_phy_activity(struct ixgbe_hw *, u16 activity,
+ u32 (*data)[FW_PHY_ACT_DATA_COUNT]);
void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
+s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status);
+bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg);
+s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
+ u32 action);
+s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value);
extern s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw);
Index: sys/dev/ixgbe/ixgbe_common.c
===================================================================
--- sys/dev/ixgbe/ixgbe_common.c
+++ sys/dev/ixgbe/ixgbe_common.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -114,6 +114,7 @@
mac->ops.led_off = ixgbe_led_off_generic;
mac->ops.blink_led_start = ixgbe_blink_led_start_generic;
mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic;
+ mac->ops.init_led_link_act = ixgbe_init_led_link_act_generic;
/* RAR, Multicast, VLAN */
mac->ops.set_rar = ixgbe_set_rar_generic;
@@ -136,6 +137,7 @@
/* Flow Control */
mac->ops.fc_enable = ixgbe_fc_enable_generic;
mac->ops.setup_fc = ixgbe_setup_fc_generic;
+ mac->ops.fc_autoneg = ixgbe_fc_autoneg;
/* Link */
mac->ops.get_link_capabilities = NULL;
@@ -169,16 +171,30 @@
case ixgbe_media_type_fiber_fixed:
case ixgbe_media_type_fiber_qsfp:
case ixgbe_media_type_fiber:
- hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
- /* if link is down, assume supported */
- if (link_up)
- supported = speed == IXGBE_LINK_SPEED_1GB_FULL ?
+ /* flow control autoneg black list */
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_A_SFP:
+ case IXGBE_DEV_ID_X550EM_A_SFP_N:
+ case IXGBE_DEV_ID_X550EM_A_QSFP:
+ case IXGBE_DEV_ID_X550EM_A_QSFP_N:
+ supported = FALSE;
+ break;
+ default:
+ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
+ /* if link is down, assume supported */
+ if (link_up)
+ supported = speed == IXGBE_LINK_SPEED_1GB_FULL ?
TRUE : FALSE;
- else
- supported = TRUE;
+ else
+ supported = TRUE;
+ }
+
break;
case ixgbe_media_type_backplane:
- supported = TRUE;
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI)
+ supported = FALSE;
+ else
+ supported = TRUE;
break;
case ixgbe_media_type_copper:
/* only some copper devices support flow control autoneg */
@@ -190,6 +206,9 @@
case IXGBE_DEV_ID_X550T:
case IXGBE_DEV_ID_X550T1:
case IXGBE_DEV_ID_X550EM_X_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
supported = TRUE;
break;
default:
@@ -377,6 +396,7 @@
{
s32 ret_val;
u32 ctrl_ext;
+ u16 device_caps;
DEBUGFUNC("ixgbe_start_hw_generic");
@@ -399,14 +419,31 @@
/* Setup flow control */
ret_val = ixgbe_setup_fc(hw);
- if (ret_val != IXGBE_SUCCESS)
- goto out;
+ if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED) {
+ DEBUGOUT1("Flow control setup failed, returning %d\n", ret_val);
+ return ret_val;
+ }
+
+ /* Cache bit indicating need for crosstalk fix */
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ hw->mac.ops.get_device_caps(hw, &device_caps);
+ if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR)
+ hw->need_crosstalk_fix = FALSE;
+ else
+ hw->need_crosstalk_fix = TRUE;
+ break;
+ default:
+ hw->need_crosstalk_fix = FALSE;
+ break;
+ }
/* Clear adapter stopped flag */
hw->adapter_stopped = FALSE;
-out:
- return ret_val;
+ return IXGBE_SUCCESS;
}
/**
@@ -467,11 +504,17 @@
/* Reset the hardware */
status = hw->mac.ops.reset_hw(hw);
- if (status == IXGBE_SUCCESS) {
+ if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) {
/* Start the HW */
status = hw->mac.ops.start_hw(hw);
}
+ /* Initialize the LED link active for LED blink support */
+ hw->mac.ops.init_led_link_act(hw);
+
+ if (status != IXGBE_SUCCESS)
+ DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status);
+
return status;
}
@@ -1027,24 +1070,33 @@
* ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
* @hw: pointer to the HW structure
*
- * Determines the LAN function id by reading memory-mapped registers
- * and swaps the port value if requested.
+ * Determines the LAN function id by reading memory-mapped registers and swaps
+ * the port value if requested, and set MAC instance for devices that share
+ * CS4227.
**/
void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
{
struct ixgbe_bus_info *bus = &hw->bus;
u32 reg;
+ u16 ee_ctrl_4;
DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
- bus->lan_id = bus->func;
+ bus->lan_id = (u8)bus->func;
/* check for a port swap */
reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
if (reg & IXGBE_FACTPS_LFS)
bus->func ^= 0x1;
+
+ /* Get MAC instance from EEPROM for configuring CS4227 */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) {
+ hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4);
+ bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >>
+ IXGBE_EE_CTRL_4_INST_ID_SHIFT;
+ }
}
/**
@@ -1102,6 +1154,47 @@
}
/**
+ * ixgbe_init_led_link_act_generic - Store the LED index link/activity.
+ * @hw: pointer to hardware structure
+ *
+ * Store the index for the link active LED. This will be used to support
+ * blinking the LED.
+ **/
+s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ u32 led_reg, led_mode;
+ u8 i;
+
+ led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+ /* Get LED link active from the LEDCTL register */
+ for (i = 0; i < 4; i++) {
+ led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i);
+
+ if ((led_mode & IXGBE_LED_MODE_MASK_BASE) ==
+ IXGBE_LED_LINK_ACTIVE) {
+ mac->led_link_act = i;
+ return IXGBE_SUCCESS;
+ }
+ }
+
+ /*
+ * If LEDCTL register does not have the LED link active set, then use
+ * known MAC defaults.
+ */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X550EM_a:
+ case ixgbe_mac_X550EM_x:
+ mac->led_link_act = 1;
+ break;
+ default:
+ mac->led_link_act = 2;
+ }
+ return IXGBE_SUCCESS;
+}
+
+/**
* ixgbe_led_on_generic - Turns on the software controllable LEDs.
* @hw: pointer to hardware structure
* @index: led number to turn on
@@ -1112,6 +1205,9 @@
DEBUGFUNC("ixgbe_led_on_generic");
+ if (index > 3)
+ return IXGBE_ERR_PARAM;
+
/* To turn on the LED, set mode to ON. */
led_reg &= ~IXGBE_LED_MODE_MASK(index);
led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
@@ -1132,6 +1228,9 @@
DEBUGFUNC("ixgbe_led_off_generic");
+ if (index > 3)
+ return IXGBE_ERR_PARAM;
+
/* To turn off the LED, set mode to OFF. */
led_reg &= ~IXGBE_LED_MODE_MASK(index);
led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
@@ -2407,10 +2506,11 @@
hw->mac.addr[4], hw->mac.addr[5]);
hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
- /* clear VMDq pool/queue selection for RAR 0 */
- hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
}
+
+ /* clear VMDq pool/queue selection for RAR 0 */
+ hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
+
hw->addr_ctrl.overflow_promisc = 0;
hw->addr_ctrl.rar_used_count = 1;
@@ -2739,7 +2839,7 @@
}
/* Negotiate the fc mode to use */
- ixgbe_fc_autoneg(hw);
+ hw->mac.ops.fc_autoneg(hw);
/* Disable any previous flow control settings */
mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
@@ -2849,8 +2949,8 @@
* Find the intersection between advertised settings and link partner's
* advertised settings
**/
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
- u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
+s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+ u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
{
if ((!(adv_reg)) || (!(lp_reg))) {
ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED,
@@ -3323,7 +3423,7 @@
**/
s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw)
{
- int secrxreg;
+ u32 secrxreg;
DEBUGFUNC("ixgbe_enable_sec_rx_path_generic");
@@ -3370,6 +3470,9 @@
DEBUGFUNC("ixgbe_blink_led_start_generic");
+ if (index > 3)
+ return IXGBE_ERR_PARAM;
+
/*
* Link must be up to auto-blink the LEDs;
* Force it if link is down.
@@ -3415,6 +3518,9 @@
DEBUGFUNC("ixgbe_blink_led_stop_generic");
+ if (index > 3)
+ return IXGBE_ERR_PARAM;
+
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
if (ret_val != IXGBE_SUCCESS)
goto out;
@@ -3581,6 +3687,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
break;
@@ -3719,7 +3826,8 @@
}
/* was that the last pool using this rar? */
- if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
+ if (mpsar_lo == 0 && mpsar_hi == 0 &&
+ rar != 0 && rar != hw->mac.san_mac_rar_index)
hw->mac.ops.clear_rar(hw, rar);
done:
return IXGBE_SUCCESS;
@@ -3809,68 +3917,65 @@
* return the VLVF index where this VLAN id should be placed
*
**/
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
+s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass)
{
- u32 bits = 0;
- u32 first_empty_slot = 0;
- s32 regindex;
+ s32 regindex, first_empty_slot;
+ u32 bits;
/* short cut the special case */
if (vlan == 0)
return 0;
- /*
- * Search for the vlan id in the VLVF entries. Save off the first empty
- * slot found along the way
- */
- for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
+ /* if vlvf_bypass is set we don't want to use an empty slot, we
+ * will simply bypass the VLVF if there are no entries present in the
+ * VLVF that contain our VLAN
+ */
+ first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0;
+
+ /* add VLAN enable bit for comparison */
+ vlan |= IXGBE_VLVF_VIEN;
+
+ /* Search for the vlan id in the VLVF entries. Save off the first empty
+ * slot found along the way.
+ *
+ * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1
+ */
+ for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) {
bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
- if (!bits && !(first_empty_slot))
+ if (bits == vlan)
+ return regindex;
+ if (!first_empty_slot && !bits)
first_empty_slot = regindex;
- else if ((bits & 0x0FFF) == vlan)
- break;
}
- /*
- * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan
- * in the VLVF. Else use the first empty VLVF register for this
- * vlan id.
- */
- if (regindex >= IXGBE_VLVF_ENTRIES) {
- if (first_empty_slot)
- regindex = first_empty_slot;
- else {
- ERROR_REPORT1(IXGBE_ERROR_SOFTWARE,
- "No space in VLVF.\n");
- regindex = IXGBE_ERR_NO_SPACE;
- }
- }
+ /* If we are here then we didn't find the VLAN. Return first empty
+ * slot we found during our search, else error.
+ */
+ if (!first_empty_slot)
+ ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n");
- return regindex;
+ return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE;
}
/**
* ixgbe_set_vfta_generic - Set VLAN filter table
* @hw: pointer to hardware structure
* @vlan: VLAN id to write to VLAN filter
- * @vind: VMDq output index that maps queue to VLAN id in VFVFB
- * @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ * @vind: VMDq output index that maps queue to VLAN id in VLVFB
+ * @vlan_on: boolean flag to turn on/off VLAN
+ * @vlvf_bypass: boolean flag indicating updating default pool is okay
*
* Turn on/off specified VLAN in the VLAN filter table.
**/
s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on)
+ bool vlan_on, bool vlvf_bypass)
{
- s32 regindex;
- u32 bitindex;
- u32 vfta;
- u32 targetbit;
- s32 ret_val = IXGBE_SUCCESS;
- bool vfta_changed = FALSE;
+ u32 regidx, vfta_delta, vfta;
+ s32 ret_val;
DEBUGFUNC("ixgbe_set_vfta_generic");
- if (vlan > 4095)
+ if (vlan > 4095 || vind > 63)
return IXGBE_ERR_PARAM;
/*
@@ -3885,33 +3990,33 @@
* bits[11-5]: which register
* bits[4-0]: which bit in the register
*/
- regindex = (vlan >> 5) & 0x7F;
- bitindex = vlan & 0x1F;
- targetbit = (1 << bitindex);
- vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
-
- if (vlan_on) {
- if (!(vfta & targetbit)) {
- vfta |= targetbit;
- vfta_changed = TRUE;
- }
- } else {
- if ((vfta & targetbit)) {
- vfta &= ~targetbit;
- vfta_changed = TRUE;
- }
- }
+ regidx = vlan / 32;
+ vfta_delta = 1 << (vlan % 32);
+ vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx));
+
+ /*
+ * vfta_delta represents the difference between the current value
+ * of vfta and the value we want in the register. Since the diff
+ * is an XOR mask we can just update the vfta using an XOR
+ */
+ vfta_delta &= vlan_on ? ~vfta : vfta;
+ vfta ^= vfta_delta;
/* Part 2
* Call ixgbe_set_vlvf_generic to set VLVFB and VLVF
*/
- ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on,
- &vfta_changed);
- if (ret_val != IXGBE_SUCCESS)
+ ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta,
+ vfta, vlvf_bypass);
+ if (ret_val != IXGBE_SUCCESS) {
+ if (vlvf_bypass)
+ goto vfta_update;
return ret_val;
+ }
- if (vfta_changed)
- IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
+vfta_update:
+ /* Update VFTA now that we are ready for traffic */
+ if (vfta_delta)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
return IXGBE_SUCCESS;
}
@@ -3920,21 +4025,25 @@
* ixgbe_set_vlvf_generic - Set VLAN Pool Filter
* @hw: pointer to hardware structure
* @vlan: VLAN id to write to VLAN filter
- * @vind: VMDq output index that maps queue to VLAN id in VFVFB
- * @vlan_on: boolean flag to turn on/off VLAN in VFVF
- * @vfta_changed: pointer to boolean flag which indicates whether VFTA
- * should be changed
+ * @vind: VMDq output index that maps queue to VLAN id in VLVFB
+ * @vlan_on: boolean flag to turn on/off VLAN in VLVF
+ * @vfta_delta: pointer to the difference between the current value of VFTA
+ * and the desired value
+ * @vfta: the desired value of the VFTA
+ * @vlvf_bypass: boolean flag indicating updating default pool is okay
*
* Turn on/off specified bit in VLVF table.
**/
s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on, bool *vfta_changed)
+ bool vlan_on, u32 *vfta_delta, u32 vfta,
+ bool vlvf_bypass)
{
- u32 vt;
+ u32 bits;
+ s32 vlvf_index;
DEBUGFUNC("ixgbe_set_vlvf_generic");
- if (vlan > 4095)
+ if (vlan > 4095 || vind > 63)
return IXGBE_ERR_PARAM;
/* If VT Mode is set
@@ -3944,83 +4053,60 @@
* Or !vlan_on
* clear the pool bit and possibly the vind
*/
- vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
- if (vt & IXGBE_VT_CTL_VT_ENABLE) {
- s32 vlvf_index;
- u32 bits;
-
- vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
- if (vlvf_index < 0)
- return vlvf_index;
-
- if (vlan_on) {
- /* set the pool bit */
- if (vind < 32) {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB(vlvf_index * 2));
- bits |= (1 << vind);
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB(vlvf_index * 2),
- bits);
- } else {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB((vlvf_index * 2) + 1));
- bits |= (1 << (vind - 32));
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB((vlvf_index * 2) + 1),
- bits);
- }
- } else {
- /* clear the pool bit */
- if (vind < 32) {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB(vlvf_index * 2));
- bits &= ~(1 << vind);
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB(vlvf_index * 2),
- bits);
- bits |= IXGBE_READ_REG(hw,
- IXGBE_VLVFB((vlvf_index * 2) + 1));
- } else {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB((vlvf_index * 2) + 1));
- bits &= ~(1 << (vind - 32));
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB((vlvf_index * 2) + 1),
- bits);
- bits |= IXGBE_READ_REG(hw,
- IXGBE_VLVFB(vlvf_index * 2));
- }
- }
+ if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
+ return IXGBE_SUCCESS;
- /*
- * If there are still bits set in the VLVFB registers
- * for the VLAN ID indicated we need to see if the
- * caller is requesting that we clear the VFTA entry bit.
- * If the caller has requested that we clear the VFTA
- * entry bit but there are still pools/VFs using this VLAN
- * ID entry then ignore the request. We're not worried
- * about the case where we're turning the VFTA VLAN ID
- * entry bit on, only when requested to turn it off as
- * there may be multiple pools and/or VFs using the
- * VLAN ID entry. In that case we cannot clear the
- * VFTA bit until all pools/VFs using that VLAN ID have also
- * been cleared. This will be indicated by "bits" being
- * zero.
+ vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass);
+ if (vlvf_index < 0)
+ return vlvf_index;
+
+ bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32));
+
+ /* set the pool bit */
+ bits |= 1 << (vind % 32);
+ if (vlan_on)
+ goto vlvf_update;
+
+ /* clear the pool bit */
+ bits ^= 1 << (vind % 32);
+
+ if (!bits &&
+ !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) {
+ /* Clear VFTA first, then disable VLVF. Otherwise
+ * we run the risk of stray packets leaking into
+ * the PF via the default pool
*/
- if (bits) {
- IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
- (IXGBE_VLVF_VIEN | vlan));
- if ((!vlan_on) && (vfta_changed != NULL)) {
- /* someone wants to clear the vfta entry
- * but some pools/VFs are still using it.
- * Ignore it. */
- *vfta_changed = FALSE;
- }
- } else
- IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
+ if (*vfta_delta)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta);
+
+ /* disable VLVF and clear remaining bit from pool */
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0);
+
+ return IXGBE_SUCCESS;
}
+ /* If there are still bits set in the VLVFB registers
+ * for the VLAN ID indicated we need to see if the
+ * caller is requesting that we clear the VFTA entry bit.
+ * If the caller has requested that we clear the VFTA
+ * entry bit but there are still pools/VFs using this VLAN
+ * ID entry then ignore the request. We're not worried
+ * about the case where we're turning the VFTA VLAN ID
+ * entry bit on, only when requested to turn it off as
+ * there may be multiple pools and/or VFs using the
+ * VLAN ID entry. In that case we cannot clear the
+ * VFTA bit until all pools/VFs using that VLAN ID have also
+ * been cleared. This will be indicated by "bits" being
+ * zero.
+ */
+ *vfta_delta = 0;
+
+vlvf_update:
+ /* record pool change and enable VLAN ID if not already enabled */
+ IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits);
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan);
+
return IXGBE_SUCCESS;
}
@@ -4049,6 +4135,32 @@
}
/**
+ * ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix
+ * @hw: pointer to hardware structure
+ *
+ * Contains the logic to identify if we need to verify link for the
+ * crosstalk fix
+ **/
+static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw)
+{
+
+ /* Does FW say we need the fix */
+ if (!hw->need_crosstalk_fix)
+ return FALSE;
+
+ /* Only consider SFP+ PHYs i.e. media type fiber */
+ switch (hw->mac.ops.get_media_type(hw)) {
+ case ixgbe_media_type_fiber:
+ case ixgbe_media_type_fiber_qsfp:
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
* ixgbe_check_mac_link_generic - Determine link and speed status
* @hw: pointer to hardware structure
* @speed: pointer to link speed
@@ -4065,6 +4177,35 @@
DEBUGFUNC("ixgbe_check_mac_link_generic");
+ /* If Crosstalk fix enabled do the sanity check of making sure
+ * the SFP+ cage is full.
+ */
+ if (ixgbe_need_crosstalk_fix(hw)) {
+ u32 sfp_cage_full;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
+ IXGBE_ESDP_SDP2;
+ break;
+ case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
+ sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
+ IXGBE_ESDP_SDP0;
+ break;
+ default:
+ /* sanity check - No SFP+ devices here */
+ sfp_cage_full = FALSE;
+ break;
+ }
+
+ if (!sfp_cage_full) {
+ *link_up = FALSE;
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
+ return IXGBE_SUCCESS;
+ }
+ }
+
/* clear the old state */
links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
@@ -4106,11 +4247,18 @@
break;
case IXGBE_LINKS_SPEED_100_82599:
*speed = IXGBE_LINK_SPEED_100_FULL;
- if (hw->mac.type >= ixgbe_mac_X550) {
+ if (hw->mac.type == ixgbe_mac_X550) {
if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
*speed = IXGBE_LINK_SPEED_5GB_FULL;
}
break;
+ case IXGBE_LINKS_SPEED_10_X550EM_A:
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
+ hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
+ *speed = IXGBE_LINK_SPEED_10_FULL;
+ }
+ break;
default:
*speed = IXGBE_LINK_SPEED_UNKNOWN;
}
@@ -4228,43 +4376,25 @@
/**
* ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
* @hw: pointer to hardware structure
- * @enable: enable or disable switch for anti-spoofing
- * @pf: Physical Function pool - do not enable anti-spoofing for the PF
+ * @enable: enable or disable switch for MAC anti-spoofing
+ * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing
*
**/
-void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf)
+void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
{
- int j;
- int pf_target_reg = pf >> 3;
- int pf_target_shift = pf % 8;
- u32 pfvfspoof = 0;
+ int vf_target_reg = vf >> 3;
+ int vf_target_shift = vf % 8;
+ u32 pfvfspoof;
if (hw->mac.type == ixgbe_mac_82598EB)
return;
+ pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
if (enable)
- pfvfspoof = IXGBE_SPOOF_MACAS_MASK;
-
- /*
- * PFVFSPOOF register array is size 8 with 8 bits assigned to
- * MAC anti-spoof enables in each register array element.
- */
- for (j = 0; j < pf_target_reg; j++)
- IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof);
-
- /*
- * The PF should be allowed to spoof so that it can support
- * emulation mode NICs. Do not set the bits assigned to the PF
- */
- pfvfspoof &= (1 << pf_target_shift) - 1;
- IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof);
-
- /*
- * Remaining pools belong to the PF so they do not need to have
- * anti-spoofing enabled.
- */
- for (j++; j < IXGBE_PFVFSPOOF_REG_COUNT; j++)
- IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), 0);
+ pfvfspoof |= (1 << vf_target_shift);
+ else
+ pfvfspoof &= ~(1 << vf_target_shift);
+ IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
}
/**
@@ -4360,49 +4490,45 @@
}
/**
- * ixgbe_host_interface_command - Issue command to manageability block
+ * ixgbe_hic_unlocked - Issue command to manageability block unlocked
* @hw: pointer to the HW structure
- * @buffer: contains the command to write and where the return status will
- * be placed
+ * @buffer: command to write and where the return status will be placed
* @length: length of buffer, must be multiple of 4 bytes
* @timeout: time in ms to wait for command completion
- * @return_data: read and return data from the buffer (TRUE) or not (FALSE)
- * Needed because FW structures are big endian and decoding of
- * these fields can be 8 bit or 16 bit based on command. Decoding
- * is not easily understood without making a table of commands.
- * So we will leave this up to the caller to read back the data
- * in these cases.
*
- * Communicates with the manageability block. On success return IXGBE_SUCCESS
- * else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
+ * Communicates with the manageability block. On success return IXGBE_SUCCESS
+ * else returns semaphore error when encountering an error acquiring
+ * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ *
+ * This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held
+ * by the caller.
**/
-s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
- u32 length, u32 timeout, bool return_data)
+s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length,
+ u32 timeout)
{
- u32 hicr, i, bi, fwsts;
- u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
- u16 buf_len;
+ u32 hicr, i, fwsts;
u16 dword_len;
- DEBUGFUNC("ixgbe_host_interface_command");
+ DEBUGFUNC("ixgbe_hic_unlocked");
- if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+ if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
DEBUGOUT1("Buffer length failure buffersize=%d.\n", length);
return IXGBE_ERR_HOST_INTERFACE_COMMAND;
}
+
/* Set bit 9 of FWSTS clearing FW reset indication */
fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS);
IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI);
/* Check that the host interface is enabled. */
hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
- if ((hicr & IXGBE_HICR_EN) == 0) {
+ if (!(hicr & IXGBE_HICR_EN)) {
DEBUGOUT("IXGBE_HOST_EN bit disabled.\n");
return IXGBE_ERR_HOST_INTERFACE_COMMAND;
}
/* Calculate length in DWORDs. We must be DWORD aligned */
- if ((length % (sizeof(u32))) != 0) {
+ if (length % sizeof(u32)) {
DEBUGOUT("Buffer length failure, not aligned to dword");
return IXGBE_ERR_INVALID_ARGUMENT;
}
@@ -4427,15 +4553,61 @@
}
/* Check command completion */
- if ((timeout != 0 && i == timeout) ||
+ if ((timeout && i == timeout) ||
!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) {
ERROR_REPORT1(IXGBE_ERROR_CAUTION,
"Command has failed with no status valid.\n");
return IXGBE_ERR_HOST_INTERFACE_COMMAND;
}
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_host_interface_command - Issue command to manageability block
+ * @hw: pointer to the HW structure
+ * @buffer: contains the command to write and where the return status will
+ * be placed
+ * @length: length of buffer, must be multiple of 4 bytes
+ * @timeout: time in ms to wait for command completion
+ * @return_data: read and return data from the buffer (TRUE) or not (FALSE)
+ * Needed because FW structures are big endian and decoding of
+ * these fields can be 8 bit or 16 bit based on command. Decoding
+ * is not easily understood without making a table of commands.
+ * So we will leave this up to the caller to read back the data
+ * in these cases.
+ *
+ * Communicates with the manageability block. On success return IXGBE_SUCCESS
+ * else returns semaphore error when encountering an error acquiring
+ * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
+ u32 length, u32 timeout, bool return_data)
+{
+ u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
+ u16 dword_len;
+ u16 buf_len;
+ s32 status;
+ u32 bi;
+
+ DEBUGFUNC("ixgbe_host_interface_command");
+
+ if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+ DEBUGOUT1("Buffer length failure buffersize=%d.\n", length);
+ return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ /* Take management host interface semaphore */
+ status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+ if (status)
+ return status;
+
+ status = ixgbe_hic_unlocked(hw, buffer, length, timeout);
+ if (status)
+ goto rel_out;
+
if (!return_data)
- return 0;
+ goto rel_out;
/* Calculate length in DWORDs */
dword_len = hdr_size >> 2;
@@ -4448,12 +4620,13 @@
/* If there is any thing in data position pull it in */
buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
- if (buf_len == 0)
- return 0;
+ if (!buf_len)
+ goto rel_out;
if (length < buf_len + hdr_size) {
DEBUGOUT("Buffer not large enough for reply message.\n");
- return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ status = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+ goto rel_out;
}
/* Calculate length in DWORDs, add 3 for odd lengths */
@@ -4465,7 +4638,10 @@
IXGBE_LE32_TO_CPUS(&buffer[bi]);
}
- return 0;
+rel_out:
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+
+ return status;
}
/**
@@ -4482,19 +4658,15 @@
* semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
**/
s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
- u8 build, u8 sub)
+ u8 build, u8 sub, u16 len,
+ const char *driver_ver)
{
struct ixgbe_hic_drv_info fw_cmd;
int i;
s32 ret_val = IXGBE_SUCCESS;
DEBUGFUNC("ixgbe_set_fw_drv_ver_generic");
-
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM)
- != IXGBE_SUCCESS) {
- ret_val = IXGBE_ERR_SWFW_SYNC;
- goto out;
- }
+ UNREFERENCED_2PARAMETER(len, driver_ver);
fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
@@ -4527,8 +4699,6 @@
break;
}
- hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
-out:
return ret_val;
}
@@ -4652,6 +4822,253 @@
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
}
+/**
+ * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW
+ *
+ * @hw: pointer to hardware structure
+ * @cmd: Command we send to the FW
+ * @status: The reply from the FW
+ *
+ * Bit-bangs the cmd to the by_pass FW status points to what is returned.
+ **/
+#define IXGBE_BYPASS_BB_WAIT 1
+s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status)
+{
+ int i;
+ u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo;
+ u32 esdp;
+
+ if (!status)
+ return IXGBE_ERR_PARAM;
+
+ *status = 0;
+
+ /* SDP vary by MAC type */
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ sck = IXGBE_ESDP_SDP7;
+ sdi = IXGBE_ESDP_SDP0;
+ sdo = IXGBE_ESDP_SDP6;
+ dir_sck = IXGBE_ESDP_SDP7_DIR;
+ dir_sdi = IXGBE_ESDP_SDP0_DIR;
+ dir_sdo = IXGBE_ESDP_SDP6_DIR;
+ break;
+ case ixgbe_mac_X540:
+ sck = IXGBE_ESDP_SDP2;
+ sdi = IXGBE_ESDP_SDP0;
+ sdo = IXGBE_ESDP_SDP1;
+ dir_sck = IXGBE_ESDP_SDP2_DIR;
+ dir_sdi = IXGBE_ESDP_SDP0_DIR;
+ dir_sdo = IXGBE_ESDP_SDP1_DIR;
+ break;
+ default:
+ return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
+ }
+
+ /* Set SDP pins direction */
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ esdp |= dir_sck; /* SCK as output */
+ esdp |= dir_sdi; /* SDI as output */
+ esdp &= ~dir_sdo; /* SDO as input */
+ esdp |= sck;
+ esdp |= sdi;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+
+ /* Generate start condition */
+ esdp &= ~sdi;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+
+ esdp &= ~sck;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+
+ /* Clock out the new control word and clock in the status */
+ for (i = 0; i < 32; i++) {
+ if ((cmd >> (31 - i)) & 0x01) {
+ esdp |= sdi;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ } else {
+ esdp &= ~sdi;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ }
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+
+ esdp |= sck;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+
+ esdp &= ~sck;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ if (esdp & sdo)
+ *status = (*status << 1) | 0x01;
+ else
+ *status = (*status << 1) | 0x00;
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+ }
+
+ /* stop condition */
+ esdp |= sck;
+ esdp &= ~sdi;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(IXGBE_BYPASS_BB_WAIT);
+
+ esdp |= sdi;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* set the page bits to match the cmd that the status it belongs to */
+ *status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang.
+ *
+ * If we send a write we can't be sure it took until we can read back
+ * that same register. It can be a problem as some of the feilds may
+ * for valid reasons change inbetween the time wrote the register and
+ * we read it again to verify. So this function check everything we
+ * can check and then assumes it worked.
+ *
+ * @u32 in_reg - The register cmd for the bit-bang read.
+ * @u32 out_reg - The register returned from a bit-bang read.
+ **/
+bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg)
+{
+ u32 mask;
+
+ /* Page must match for all control pages */
+ if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
+ return FALSE;
+
+ switch (in_reg & BYPASS_PAGE_M) {
+ case BYPASS_PAGE_CTL0:
+ /* All the following can't change since the last write
+ * - All the event actions
+ * - The timeout value
+ */
+ mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M |
+ BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M |
+ BYPASS_WDTIMEOUT_M |
+ BYPASS_WDT_VALUE_M;
+ if ((out_reg & mask) != (in_reg & mask))
+ return FALSE;
+
+ /* 0x0 is never a valid value for bypass status */
+ if (!(out_reg & BYPASS_STATUS_OFF_M))
+ return FALSE;
+ break;
+ case BYPASS_PAGE_CTL1:
+ /* All the following can't change since the last write
+ * - time valid bit
+ * - time we last sent
+ */
+ mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M;
+ if ((out_reg & mask) != (in_reg & mask))
+ return FALSE;
+ break;
+ case BYPASS_PAGE_CTL2:
+ /* All we can check in this page is control number
+ * which is already done above.
+ */
+ break;
+ }
+
+ /* We are as sure as we can be return TRUE */
+ return TRUE;
+}
+
+/**
+ * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter.
+ *
+ * @hw: pointer to hardware structure
+ * @cmd: The control word we are setting.
+ * @event: The event we are setting in the FW. This also happens to
+ * be the mask for the event we are setting (handy)
+ * @action: The action we set the event to in the FW. This is in a
+ * bit field that happens to be what we want to put in
+ * the event spot (also handy)
+ **/
+s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
+ u32 action)
+{
+ u32 by_ctl = 0;
+ u32 cmd, verify;
+ u32 count = 0;
+
+ /* Get current values */
+ cmd = ctrl; /* just reading only need control number */
+ if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
+ return IXGBE_ERR_INVALID_ARGUMENT;
+
+ /* Set to new action */
+ cmd = (by_ctl & ~event) | BYPASS_WE | action;
+ if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
+ return IXGBE_ERR_INVALID_ARGUMENT;
+
+ /* Page 0 force a FW eeprom write which is slow so verify */
+ if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) {
+ verify = BYPASS_PAGE_CTL0;
+ do {
+ if (count++ > 5)
+ return IXGBE_BYPASS_FW_WRITE_FAILURE;
+
+ if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl))
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl));
+ } else {
+ /* We have give the FW time for the write to stick */
+ msec_delay(100);
+ }
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres.
+ *
+ * @hw: pointer to hardware structure
+ * @addr: The bypass eeprom address to read.
+ * @value: The 8b of data at the address above.
+ **/
+s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value)
+{
+ u32 cmd;
+ u32 status;
+
+
+ /* send the request */
+ cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
+ cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
+ if (ixgbe_bypass_rw_generic(hw, cmd, &status))
+ return IXGBE_ERR_INVALID_ARGUMENT;
+
+ /* We have give the FW time for the write to stick */
+ msec_delay(100);
+
+ /* now read the results */
+ cmd &= ~BYPASS_WE;
+ if (ixgbe_bypass_rw_generic(hw, cmd, &status))
+ return IXGBE_ERR_INVALID_ARGUMENT;
+
+ *value = status & BYPASS_CTL2_DATA_M;
+
+ return IXGBE_SUCCESS;
+}
+
/**
* ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg
@@ -4789,14 +5206,6 @@
speedcnt++;
highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
- /* If we already have link at this speed, just jump out */
- status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
- if (status != IXGBE_SUCCESS)
- return status;
-
- if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
- goto out;
-
/* Set the module link speed */
switch (hw->phy.media_type) {
case ixgbe_media_type_fiber_fixed:
@@ -4848,14 +5257,6 @@
if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
- /* If we already have link at this speed, just jump out */
- status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
- if (status != IXGBE_SUCCESS)
- return status;
-
- if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
- goto out;
-
/* Set the module link speed */
switch (hw->phy.media_type) {
case ixgbe_media_type_fiber_fixed:
Index: sys/dev/ixgbe/ixgbe_dcb.h
===================================================================
--- sys/dev/ixgbe/ixgbe_dcb.h
+++ sys/dev/ixgbe/ixgbe_dcb.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Index: sys/dev/ixgbe/ixgbe_dcb.c
===================================================================
--- sys/dev/ixgbe/ixgbe_dcb.c
+++ sys/dev/ixgbe/ixgbe_dcb.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -401,6 +401,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_get_tc_stats_82599(hw, stats, tc_count);
break;
@@ -431,6 +432,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_get_pfc_stats_82599(hw, stats, tc_count);
break;
@@ -472,6 +474,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwgid,
tsa, map);
@@ -513,6 +516,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
bwgid, tsa);
@@ -556,6 +560,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max,
bwgid, tsa,
@@ -593,6 +598,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map);
break;
@@ -621,6 +627,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_config_tc_stats_82599(hw, NULL);
break;
@@ -668,6 +675,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ixgbe_dcb_config_82599(hw, dcb_config);
ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->link_speed,
@@ -702,6 +710,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map);
break;
@@ -727,6 +736,7 @@
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
#if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
tsa, map);
Index: sys/dev/ixgbe/ixgbe_dcb_82598.h
===================================================================
--- sys/dev/ixgbe/ixgbe_dcb_82598.h
+++ sys/dev/ixgbe/ixgbe_dcb_82598.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Index: sys/dev/ixgbe/ixgbe_dcb_82598.c
===================================================================
--- sys/dev/ixgbe/ixgbe_dcb_82598.c
+++ sys/dev/ixgbe/ixgbe_dcb_82598.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Index: sys/dev/ixgbe/ixgbe_dcb_82599.h
===================================================================
--- sys/dev/ixgbe/ixgbe_dcb_82599.h
+++ sys/dev/ixgbe/ixgbe_dcb_82599.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Index: sys/dev/ixgbe/ixgbe_dcb_82599.c
===================================================================
--- sys/dev/ixgbe/ixgbe_dcb_82599.c
+++ sys/dev/ixgbe/ixgbe_dcb_82599.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Index: sys/dev/ixgbe/ixgbe_fdir.h
===================================================================
--- sys/dev/ixgbe/ixgbe_fdir.h
+++ sys/dev/ixgbe/ixgbe_fdir.h
@@ -1,53 +1,58 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
/*$FreeBSD$*/
-#ifndef _IXGBE_82598_H_
-#define _IXGBE_82598_H_
-
-u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw);
-s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw);
-s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
-void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw);
-s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
-s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
-s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
-s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
-s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
- u8 *eeprom_data);
-u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
-s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
-void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
-void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
-s32 ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, u32 regval);
-#endif /* _IXGBE_82598_H_ */
+#ifndef _IXGBE_FDIR_H_
+#define _IXGBE_FDIR_H_
+
+#ifdef IXGBE_FDIR
+
+/*
+ * Flow Director actually 'steals' part of the packet buffer
+ * as its filter pool, this variable controls how much it uses:
+ * 0 = 64K, 1 = 128K, 2 = 256K
+ */
+int fdir_pballoc = 1;
+
+void ixgbe_init_fdir(struct adapter *);
+
+#else
+
+#define ixgbe_init_fdir(_a)
+
+#endif
+
+void ixgbe_reinit_fdir(void *);
+void ixgbe_atr(struct tx_ring *, struct mbuf *);
+
+#endif
Index: sys/dev/ixgbe/ixgbe_features.h
===================================================================
--- /dev/null
+++ sys/dev/ixgbe/ixgbe_features.h
@@ -0,0 +1,78 @@
+/******************************************************************************
+
+ Copyright (c) 2001-2017, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*$FreeBSD$*/
+
+
+#ifndef _IXGBE_FEATURES_H_
+#define _IXGBE_FEATURES_H_
+
+/*
+ * Feature defines. Eventually, we'd like to get to a point where we
+ * can remove MAC/Phy type checks scattered throughout the code in
+ * favor of checking these feature flags. If the feature expects OS
+ * support, make sure to add an #undef below if expected to run on
+ * OSs that don't support said feature.
+ */
+#define IXGBE_FEATURE_VF (u32)(1 << 0)
+#define IXGBE_FEATURE_SRIOV (u32)(1 << 1)
+#define IXGBE_FEATURE_RSS (u32)(1 << 2)
+#define IXGBE_FEATURE_NETMAP (u32)(1 << 3)
+#define IXGBE_FEATURE_FAN_FAIL (u32)(1 << 4)
+#define IXGBE_FEATURE_TEMP_SENSOR (u32)(1 << 5)
+#define IXGBE_FEATURE_BYPASS (u32)(1 << 6)
+#define IXGBE_FEATURE_LEGACY_TX (u32)(1 << 7)
+#define IXGBE_FEATURE_FDIR (u32)(1 << 8)
+#define IXGBE_FEATURE_MSI (u32)(1 << 9)
+#define IXGBE_FEATURE_MSIX (u32)(1 << 10)
+#define IXGBE_FEATURE_FRAME_LIMIT (u32)(1 << 11)
+#define IXGBE_FEATURE_EEE (u32)(1 << 12)
+#define IXGBE_FEATURE_LEGACY_IRQ (u32)(1 << 13)
+#define IXGBE_FEATURE_NEEDS_CTXD (u32)(1 << 14)
+
+/* Check for OS support. Undefine features if not included in the OS */
+#ifndef PCI_IOV
+#undef IXGBE_FEATURE_SRIOV
+#define IXGBE_FEATURE_SRIOV 0
+#endif
+
+#ifndef RSS
+#undef IXGBE_FEATURE_RSS
+#define IXGBE_FEATURE_RSS 0
+#endif
+
+#ifndef DEV_NETMAP
+#undef IXGBE_FEATURE_NETMAP
+#define IXGBE_FEATURE_NETMAP 0
+#endif
+
+#endif /* _IXGBE_FEATURES_H_ */
Index: sys/dev/ixgbe/ixgbe_mbx.h
===================================================================
--- sys/dev/ixgbe/ixgbe_mbx.h
+++ sys/dev/ixgbe/ixgbe_mbx.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -90,6 +90,8 @@
ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */
ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */
ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
+ ixgbe_mbox_api_12, /* API version 1.2, linux/freebsd VF driver */
+ ixgbe_mbox_api_13, /* API version 1.3, linux/freebsd VF driver */
/* This value should always be last */
ixgbe_mbox_api_unknown, /* indicates that API version is not known */
};
@@ -108,6 +110,19 @@
/* mailbox API, version 1.1 VF requests */
#define IXGBE_VF_GET_QUEUES 0x09 /* get queue configuration */
+/* mailbox API, version 1.2 VF requests */
+#define IXGBE_VF_GET_RETA 0x0a /* VF request for RETA */
+#define IXGBE_VF_GET_RSS_KEY 0x0b /* get RSS key */
+#define IXGBE_VF_UPDATE_XCAST_MODE 0x0c
+
+/* mode choices for IXGBE_VF_UPDATE_XCAST_MODE */
+enum ixgbevf_xcast_modes {
+ IXGBEVF_XCAST_MODE_NONE = 0,
+ IXGBEVF_XCAST_MODE_MULTI,
+ IXGBEVF_XCAST_MODE_ALLMULTI,
+ IXGBEVF_XCAST_MODE_PROMISC,
+};
+
/* GET_QUEUES return data indices within the mailbox */
#define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */
#define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */
Index: sys/dev/ixgbe/ixgbe_mbx.c
===================================================================
--- sys/dev/ixgbe/ixgbe_mbx.c
+++ sys/dev/ixgbe/ixgbe_mbx.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -607,6 +607,7 @@
break;
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
case ixgbe_mac_X540:
vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
break;
@@ -744,6 +745,7 @@
if (hw->mac.type != ixgbe_mac_82599EB &&
hw->mac.type != ixgbe_mac_X550 &&
hw->mac.type != ixgbe_mac_X550EM_x &&
+ hw->mac.type != ixgbe_mac_X550EM_a &&
hw->mac.type != ixgbe_mac_X540)
return;
Index: sys/dev/ixgbe/ixgbe_osdep.h
===================================================================
--- sys/dev/ixgbe/ixgbe_osdep.h
+++ sys/dev/ixgbe/ixgbe_osdep.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -55,7 +55,7 @@
#include <dev/pci/pcireg.h>
#define ASSERT(x) if(!(x)) panic("IXGBE: x")
-#define EWARN(H, W, S) printf(W)
+#define EWARN(H, W) printf(W)
enum {
IXGBE_ERROR_SOFTWARE,
@@ -135,10 +135,13 @@
#define IXGBE_NTOHS(_i) ntohs(_i)
/* XXX these need to be revisited */
+#define IXGBE_CPU_TO_LE16 htole16
#define IXGBE_CPU_TO_LE32 htole32
+#define IXGBE_LE32_TO_CPU le32toh
#define IXGBE_LE32_TO_CPUS(x)
#define IXGBE_CPU_TO_BE16 htobe16
#define IXGBE_CPU_TO_BE32 htobe32
+#define IXGBE_BE32_TO_CPU be32toh
typedef uint8_t u8;
typedef int8_t s8;
@@ -159,7 +162,7 @@
#define __be32 u32
#define __be64 u64
-#define le16_to_cpu
+#define le16_to_cpu
#if __FreeBSD_version < 800000
#if defined(__i386__) || defined(__amd64__)
@@ -209,7 +212,7 @@
};
/* These routines need struct ixgbe_hw declared */
-struct ixgbe_hw;
+struct ixgbe_hw;
device_t ixgbe_dev_from_hw(struct ixgbe_hw *hw);
/* These routines are needed by the shared code */
Index: sys/dev/ixgbe/ixgbe_osdep.c
===================================================================
--- sys/dev/ixgbe/ixgbe_osdep.c
+++ sys/dev/ixgbe/ixgbe_osdep.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Index: sys/dev/ixgbe/ixgbe_phy.h
===================================================================
--- sys/dev/ixgbe/ixgbe_phy.h
+++ sys/dev/ixgbe/ixgbe_phy.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -90,8 +90,12 @@
#define IXGBE_CS4227 0xBE /* CS4227 address */
#define IXGBE_CS4227_GLOBAL_ID_LSB 0
+#define IXGBE_CS4227_GLOBAL_ID_MSB 1
#define IXGBE_CS4227_SCRATCH 2
#define IXGBE_CS4227_GLOBAL_ID_VALUE 0x03E5
+#define IXGBE_CS4227_EFUSE_PDF_SKU 0x19F
+#define IXGBE_CS4223_SKU_ID 0x0010 /* Quad port */
+#define IXGBE_CS4227_SKU_ID 0x0014 /* Dual port */
#define IXGBE_CS4227_RESET_PENDING 0x1357
#define IXGBE_CS4227_RESET_COMPLETE 0x5AA5
#define IXGBE_CS4227_RETRIES 15
@@ -189,7 +193,7 @@
s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on);
s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw);
s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
-s32 ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw);
+u64 ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw);
s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
u16 *list_offset,
@@ -208,4 +212,8 @@
s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 eeprom_data);
void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
+s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 *val, bool lock);
+s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 val, bool lock);
#endif /* _IXGBE_PHY_H_ */
Index: sys/dev/ixgbe/ixgbe_phy.c
===================================================================
--- sys/dev/ixgbe/ixgbe_phy.c
+++ sys/dev/ixgbe/ixgbe_phy.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -110,11 +110,11 @@
*
* Returns an error code on error.
*/
-static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
- u16 reg, u16 *val, bool lock)
+s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg,
+ u16 *val, bool lock)
{
u32 swfw_mask = hw->phy.phy_semaphore_mask;
- int max_retry = 10;
+ int max_retry = 3;
int retry = 0;
u8 csum_byte;
u8 high_bits;
@@ -122,8 +122,6 @@
u8 reg_high;
u8 csum;
- if (hw->mac.type >= ixgbe_mac_X550)
- max_retry = 3;
reg_high = ((reg >> 7) & 0xFE) | 1; /* Indicate read combined */
csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
csum = ~csum;
@@ -181,37 +179,6 @@
}
/**
- * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to read from
- * @reg: I2C device register to read from
- * @val: pointer to location to receive read value
- *
- * Returns an error code on error.
- **/
-static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
- u16 reg, u16 *val)
-{
- return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
-}
-
-/**
- * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to read from
- * @reg: I2C device register to read from
- * @val: pointer to location to receive read value
- *
- * Returns an error code on error.
- **/
-static s32
-ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
- u16 reg, u16 *val)
-{
- return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
-}
-
-/**
* ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation
* @hw: pointer to the hardware structure
* @addr: I2C bus address to write to
@@ -221,8 +188,8 @@
*
* Returns an error code on error.
*/
-static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
- u16 reg, u16 val, bool lock)
+s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg,
+ u16 val, bool lock)
{
u32 swfw_mask = hw->phy.phy_semaphore_mask;
int max_retry = 1;
@@ -277,37 +244,6 @@
}
/**
- * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to write to
- * @reg: I2C device register to write to
- * @val: value to write
- *
- * Returns an error code on error.
- **/
-static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
- u8 addr, u16 reg, u16 val)
-{
- return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
-}
-
-/**
- * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to write to
- * @reg: I2C device register to write to
- * @val: value to write
- *
- * Returns an error code on error.
- **/
-static s32
-ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
- u8 addr, u16 reg, u16 val)
-{
- return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
-}
-
-/**
* ixgbe_init_phy_ops_generic - Inits PHY function ptrs
* @hw: pointer to the hardware structure
*
@@ -338,12 +274,6 @@
phy->ops.i2c_bus_clear = ixgbe_i2c_bus_clear;
phy->ops.identify_sfp = ixgbe_identify_module_generic;
phy->sfp_type = ixgbe_sfp_type_unknown;
- phy->ops.read_i2c_combined = ixgbe_read_i2c_combined_generic;
- phy->ops.write_i2c_combined = ixgbe_write_i2c_combined_generic;
- phy->ops.read_i2c_combined_unlocked =
- ixgbe_read_i2c_combined_generic_unlocked;
- phy->ops.write_i2c_combined_unlocked =
- ixgbe_write_i2c_combined_generic_unlocked;
phy->ops.read_i2c_byte_unlocked = ixgbe_read_i2c_byte_generic_unlocked;
phy->ops.write_i2c_byte_unlocked =
ixgbe_write_i2c_byte_generic_unlocked;
@@ -352,6 +282,42 @@
}
/**
+ * ixgbe_probe_phy - Probe a single address for a PHY
+ * @hw: pointer to hardware structure
+ * @phy_addr: PHY address to probe
+ *
+ * Returns TRUE if PHY found
+ */
+static bool ixgbe_probe_phy(struct ixgbe_hw *hw, u16 phy_addr)
+{
+ u16 ext_ability = 0;
+
+ if (!ixgbe_validate_phy_addr(hw, phy_addr)) {
+ DEBUGOUT1("Unable to validate PHY address 0x%04X\n",
+ phy_addr);
+ return FALSE;
+ }
+
+ if (ixgbe_get_phy_id(hw))
+ return FALSE;
+
+ hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id);
+
+ if (hw->phy.type == ixgbe_phy_unknown) {
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
+ if (ext_ability &
+ (IXGBE_MDIO_PHY_10GBASET_ABILITY |
+ IXGBE_MDIO_PHY_1000BASET_ABILITY))
+ hw->phy.type = ixgbe_phy_cu_unknown;
+ else
+ hw->phy.type = ixgbe_phy_generic;
+ }
+
+ return TRUE;
+}
+
+/**
* ixgbe_identify_phy_generic - Get physical layer module
* @hw: pointer to hardware structure
*
@@ -360,8 +326,7 @@
s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
{
s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
- u32 phy_addr;
- u16 ext_ability = 0;
+ u16 phy_addr;
DEBUGFUNC("ixgbe_identify_phy_generic");
@@ -372,45 +337,33 @@
hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
}
- if (hw->phy.type == ixgbe_phy_unknown) {
- for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
- if (ixgbe_validate_phy_addr(hw, phy_addr)) {
- hw->phy.addr = phy_addr;
- ixgbe_get_phy_id(hw);
- hw->phy.type =
- ixgbe_get_phy_type_from_id(hw->phy.id);
-
- if (hw->phy.type == ixgbe_phy_unknown) {
- hw->phy.ops.read_reg(hw,
- IXGBE_MDIO_PHY_EXT_ABILITY,
- IXGBE_MDIO_PMA_PMD_DEV_TYPE,
- &ext_ability);
- if (ext_ability &
- (IXGBE_MDIO_PHY_10GBASET_ABILITY |
- IXGBE_MDIO_PHY_1000BASET_ABILITY))
- hw->phy.type =
- ixgbe_phy_cu_unknown;
- else
- hw->phy.type =
- ixgbe_phy_generic;
- }
+ if (hw->phy.type != ixgbe_phy_unknown)
+ return IXGBE_SUCCESS;
- status = IXGBE_SUCCESS;
- break;
- }
- }
+ if (hw->phy.nw_mng_if_sel) {
+ phy_addr = (hw->phy.nw_mng_if_sel &
+ IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
+ IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
+ if (ixgbe_probe_phy(hw, phy_addr))
+ return IXGBE_SUCCESS;
+ else
+ return IXGBE_ERR_PHY_ADDR_INVALID;
+ }
- /* Certain media types do not have a phy so an address will not
- * be found and the code will take this path. Caller has to
- * decide if it is an error or not.
- */
- if (status != IXGBE_SUCCESS) {
- hw->phy.addr = 0;
+ for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
+ if (ixgbe_probe_phy(hw, phy_addr)) {
+ status = IXGBE_SUCCESS;
+ break;
}
- } else {
- status = IXGBE_SUCCESS;
}
+ /* Certain media types do not have a phy so an address will not
+ * be found and the code will take this path. Caller has to
+ * decide if it is an error or not.
+ */
+ if (status != IXGBE_SUCCESS)
+ hw->phy.addr = 0;
+
return status;
}
@@ -462,6 +415,8 @@
if (phy_id != 0xFFFF && phy_id != 0x0)
valid = TRUE;
+ DEBUGOUT1("PHY ID HIGH is 0x%04X\n", phy_id);
+
return valid;
}
@@ -490,12 +445,15 @@
hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
}
+ DEBUGOUT2("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X\n",
+ phy_id_high, phy_id_low);
+
return status;
}
/**
* ixgbe_get_phy_type_from_id - Get the phy type
- * @hw: pointer to hardware structure
+ * @phy_id: PHY ID information
*
**/
enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
@@ -508,7 +466,6 @@
case TN1010_PHY_ID:
phy_type = ixgbe_phy_tn;
break;
- case X550_PHY_ID1:
case X550_PHY_ID2:
case X550_PHY_ID3:
case X540_PHY_ID:
@@ -521,6 +478,7 @@
phy_type = ixgbe_phy_nl;
break;
case X557_PHY_ID:
+ case X557_PHY_ID2:
phy_type = ixgbe_phy_x550em_ext_t;
break;
default:
@@ -574,11 +532,30 @@
*/
for (i = 0; i < 30; i++) {
msec_delay(100);
- hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
- IXGBE_MDIO_PHY_XS_DEV_TYPE, &ctrl);
- if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET)) {
- usec_delay(2);
- break;
+ if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
+ status = hw->phy.ops.read_reg(hw,
+ IXGBE_MDIO_TX_VENDOR_ALARMS_3,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ &ctrl);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ if (ctrl & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
+ usec_delay(2);
+ break;
+ }
+ } else {
+ status = hw->phy.ops.read_reg(hw,
+ IXGBE_MDIO_PHY_XS_CONTROL,
+ IXGBE_MDIO_PHY_XS_DEV_TYPE,
+ &ctrl);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET)) {
+ usec_delay(2);
+ break;
+ }
}
}
@@ -686,13 +663,12 @@
DEBUGFUNC("ixgbe_read_phy_reg_generic");
- if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == IXGBE_SUCCESS) {
- status = ixgbe_read_phy_reg_mdi(hw, reg_addr, device_type,
- phy_data);
- hw->mac.ops.release_swfw_sync(hw, gssr);
- } else {
- status = IXGBE_ERR_SWFW_SYNC;
- }
+ if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
+ return IXGBE_ERR_SWFW_SYNC;
+
+ status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
+
+ hw->mac.ops.release_swfw_sync(hw, gssr);
return status;
}
@@ -788,7 +764,7 @@
DEBUGFUNC("ixgbe_write_phy_reg_generic");
if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == IXGBE_SUCCESS) {
- status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type,
+ status = hw->phy.ops.write_reg_mdi(hw, reg_addr, device_type,
phy_data);
hw->mac.ops.release_swfw_sync(hw, gssr);
} else {
@@ -815,91 +791,63 @@
ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
- if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
- /* Set or unset auto-negotiation 10G advertisement */
- hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
+ /* Set or unset auto-negotiation 10G advertisement */
+ hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &autoneg_reg);
- autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE;
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
- autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE;
+ autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_10GB_FULL))
+ autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE;
- hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
- }
+ hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ autoneg_reg);
- if (hw->mac.type == ixgbe_mac_X550) {
- if (speed & IXGBE_LINK_SPEED_5GB_FULL) {
- /* Set or unset auto-negotiation 5G advertisement */
- hw->phy.ops.read_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
-
- autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE;
- if (hw->phy.autoneg_advertised &
- IXGBE_LINK_SPEED_5GB_FULL)
- autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE;
-
- hw->phy.ops.write_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
- }
+ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &autoneg_reg);
- if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) {
- /* Set or unset auto-negotiation 2.5G advertisement */
- hw->phy.ops.read_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
-
- autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE;
- if (hw->phy.autoneg_advertised &
- IXGBE_LINK_SPEED_2_5GB_FULL)
- autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE;
-
- hw->phy.ops.write_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
- }
+ if (hw->mac.type == ixgbe_mac_X550) {
+ /* Set or unset auto-negotiation 5G advertisement */
+ autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_5GB_FULL))
+ autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE;
+
+ /* Set or unset auto-negotiation 2.5G advertisement */
+ autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised &
+ IXGBE_LINK_SPEED_2_5GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_2_5GB_FULL))
+ autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE;
}
- if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
- /* Set or unset auto-negotiation 1G advertisement */
- hw->phy.ops.read_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
+ /* Set or unset auto-negotiation 1G advertisement */
+ autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) &&
+ (speed & IXGBE_LINK_SPEED_1GB_FULL))
+ autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
- autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
- autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
+ hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ autoneg_reg);
- hw->phy.ops.write_reg(hw,
- IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
- }
-
- if (speed & IXGBE_LINK_SPEED_100_FULL) {
- /* Set or unset auto-negotiation 100M advertisement */
- hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
+ /* Set or unset auto-negotiation 100M advertisement */
+ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &autoneg_reg);
- autoneg_reg &= ~(IXGBE_MII_100BASE_T_ADVERTISE |
- IXGBE_MII_100BASE_T_ADVERTISE_HALF);
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
- autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE;
+ autoneg_reg &= ~(IXGBE_MII_100BASE_T_ADVERTISE |
+ IXGBE_MII_100BASE_T_ADVERTISE_HALF);
+ if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) &&
+ (speed & IXGBE_LINK_SPEED_100_FULL))
+ autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE;
- hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
- }
+ hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ autoneg_reg);
/* Blocked by MNG FW so don't reset PHY */
if (ixgbe_check_reset_blocked(hw))
@@ -951,6 +899,9 @@
if (speed & IXGBE_LINK_SPEED_100_FULL)
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
+ if (speed & IXGBE_LINK_SPEED_10_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10_FULL;
+
/* Setup link based on the new speed settings */
ixgbe_setup_phy_link(hw);
@@ -988,6 +939,7 @@
hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
break;
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_X550EM_a:
hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
break;
default:
@@ -1591,7 +1543,7 @@
"module or the adapter. Intel "
"Corporation is not responsible "
"for any harm caused by using "
- "untested modules.\n", status);
+ "untested modules.\n");
status = IXGBE_SUCCESS;
} else {
DEBUGOUT("SFP+ module not supported\n");
@@ -1623,9 +1575,9 @@
*
* Determines physical layer capabilities of the current SFP.
*/
-s32 ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw)
+u64 ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw)
{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
u8 comp_codes_10g = 0;
u8 comp_codes_1g = 0;
@@ -1853,7 +1805,7 @@
"module or the adapter. Intel "
"Corporation is not responsible "
"for any harm caused by using "
- "untested modules.\n", status);
+ "untested modules.\n");
status = IXGBE_SUCCESS;
} else {
DEBUGOUT("QSFP module not supported\n");
Index: sys/dev/ixgbe/ixgbe_rss.h
===================================================================
--- sys/dev/ixgbe/ixgbe_rss.h
+++ sys/dev/ixgbe/ixgbe_rss.h
@@ -1,53 +1,64 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
/*$FreeBSD$*/
-#ifndef _IXGBE_82598_H_
-#define _IXGBE_82598_H_
-
-u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw);
-s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw);
-s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
-void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw);
-s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
-s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
-s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
-s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
-s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
- u8 *eeprom_data);
-u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
-s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
-void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
-void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
-s32 ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, u32 regval);
-#endif /* _IXGBE_82598_H_ */
+#ifndef _IXGBE_RSS_H_
+#define _IXGBE_RSS_H_
+
+#ifdef RSS
+
+#include <net/rss_config.h>
+#include <netinet/in_rss.h>
+
+#else
+
+#define RSS_HASHTYPE_RSS_IPV4 (1 << 1)
+#define RSS_HASHTYPE_RSS_TCP_IPV4 (1 << 2)
+#define RSS_HASHTYPE_RSS_IPV6 (1 << 3)
+#define RSS_HASHTYPE_RSS_TCP_IPV6 (1 << 4)
+#define RSS_HASHTYPE_RSS_IPV6_EX (1 << 5)
+#define RSS_HASHTYPE_RSS_TCP_IPV6_EX (1 << 6)
+#define RSS_HASHTYPE_RSS_UDP_IPV4 (1 << 7)
+#define RSS_HASHTYPE_RSS_UDP_IPV4_EX (1 << 8)
+#define RSS_HASHTYPE_RSS_UDP_IPV6 (1 << 9)
+#define RSS_HASHTYPE_RSS_UDP_IPV6_EX (1 << 10)
+
+#define rss_getcpu(_a) 0
+#define rss_getnumbuckets() 1
+#define rss_getkey(_a)
+#define rss_get_indirection_to_bucket(_a) 0
+#define rss_gethashconfig() 0x7E
+#define rss_hash2bucket(_a,_b,_c) -1
+
+#endif
+#endif /* _IXGBE_RSS_H_ */
Index: sys/dev/ixgbe/ixgbe_sriov.h
===================================================================
--- /dev/null
+++ sys/dev/ixgbe/ixgbe_sriov.h
@@ -0,0 +1,104 @@
+/******************************************************************************
+
+ Copyright (c) 2001-2017, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*$FreeBSD$*/
+
+
+#ifndef _IXGBE_SRIOV_H_
+#define _IXGBE_SRIOV_H_
+
+#ifdef PCI_IOV
+
+#include <sys/nv.h>
+#include <sys/iov_schema.h>
+#include <dev/pci/pci_iov.h>
+#include <net/iflib.h>
+#include "ixgbe_mbx.h"
+
+#define IXGBE_VF_CTS (1 << 0) /* VF is clear to send. */
+#define IXGBE_VF_CAP_MAC (1 << 1) /* VF is permitted to change MAC. */
+#define IXGBE_VF_CAP_VLAN (1 << 2) /* VF is permitted to join vlans. */
+#define IXGBE_VF_ACTIVE (1 << 3) /* VF is active. */
+#define IXGBE_VF_INDEX(vmdq) ((vmdq) / 32)
+#define IXGBE_VF_BIT(vmdq) (1 << ((vmdq) % 32))
+
+#define IXGBE_VT_MSG_MASK 0xFFFF
+
+#define IXGBE_VT_MSGINFO(msg) \
+ (((msg) & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT)
+
+#define IXGBE_VF_GET_QUEUES_RESP_LEN 5
+
+#define IXGBE_API_VER_1_0 0
+#define IXGBE_API_VER_2_0 1 /* Solaris API. Not supported. */
+#define IXGBE_API_VER_1_1 2
+#define IXGBE_API_VER_UNKNOWN UINT16_MAX
+
+#define IXGBE_NO_VM 0
+#define IXGBE_32_VM 32
+#define IXGBE_64_VM 64
+
+int ixgbe_if_iov_vf_add(if_ctx_t, u16, const nvlist_t *);
+int ixgbe_if_iov_init(if_ctx_t, u16, const nvlist_t *);
+void ixgbe_if_iov_uninit(if_ctx_t);
+void ixgbe_initialize_iov(struct adapter *);
+void ixgbe_recalculate_max_frame(struct adapter *);
+void ixgbe_ping_all_vfs(struct adapter *);
+int ixgbe_pci_iov_detach(device_t);
+void ixgbe_define_iov_schemas(device_t, int *);
+void ixgbe_align_all_queue_indices(struct adapter *);
+int ixgbe_vf_que_index(int, int, int);
+u32 ixgbe_get_mtqc(int);
+u32 ixgbe_get_mrqc(int);
+
+/******************************************************************************/
+#else /* PCI_IOV */
+/******************************************************************************/
+
+#define ixgbe_add_vf(_a,_b,_c)
+#define ixgbe_init_iov(_a,_b,_c)
+#define ixgbe_uninit_iov(_a)
+#define ixgbe_initialize_iov(_a)
+#define ixgbe_recalculate_max_frame(_a)
+#define ixgbe_ping_all_vfs(_a)
+#define ixgbe_pci_iov_detach(_a) 0
+#define ixgbe_define_iov_schemas(_a,_b)
+#define ixgbe_align_all_queue_indices(_a)
+#define ixgbe_vf_que_index(_a,_b,_c) _c
+#define ixgbe_get_mtqc(_a) IXGBE_MTQC_64Q_1PB
+#define ixgbe_get_mrqc(_a) 0
+
+#endif /* PCI_IOV */
+
+void ixgbe_handle_mbx(void *);
+
+#endif
Index: sys/dev/ixgbe/ixgbe_sysctl.c
===================================================================
--- /dev/null
+++ sys/dev/ixgbe/ixgbe_sysctl.c
@@ -0,0 +1,564 @@
+/*-
+ * Copyright (c) 2016, Matthew Macy <mmacy@nextbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Neither the name of Matthew Macy nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "ixgbe.h"
+/********************************************************************
+ *
+ * Dump Registers
+ *
+ ********************************************************************/
+#define IXGBE_REGS_LEN 1139
+extern if_shared_ctx_t ixgbe_sctx;
+
+int ixgbe_get_regs(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+#if 0
+ struct ix_tx_queue *tx_que = &adapter->tx_queues[0];
+ struct ix_rx_queue *rx_que = &adapter->rx_queues[0];
+ struct rx_ring *rxr = &rx_que->rxr;
+ struct tx_ring *txr = &tx_que->txr;
+ int ntxd = ixgbe_sctx->isc_ntxd[0];
+ int nrxd = ixgbe_sctx->isc_nrxd[0];
+ int j;
+#endif
+
+ struct sbuf *sb;
+ u32 *regs_buff = (u32 *)malloc(sizeof(u32) * IXGBE_REGS_LEN, M_DEVBUF,
+ M_NOWAIT);
+ int i;
+ int rc;
+
+ memset(regs_buff, 0, IXGBE_REGS_LEN * sizeof(u32));
+
+ rc = sysctl_wire_old_buffer(req, 0);
+ MPASS(rc == 0);
+ if (rc != 0)
+ return (rc);
+
+ sb = sbuf_new_for_sysctl(NULL, NULL, 32*PAGE_SIZE, req);
+ MPASS(sb != NULL);
+ if (sb == NULL)
+ return (ENOMEM);
+
+ /* General Registers */
+ sbuf_printf(sb, "General Registers\n");
+ regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_CTRL);
+ sbuf_printf(sb, "\tIXGBE_CTRL\t %08x\n", regs_buff[0]);
+ regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_STATUS);
+ sbuf_printf(sb, "\tIXGBE_STATUS\t %08x\n", regs_buff[1]);
+ regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
+ sbuf_printf(sb, "\tIXGBE_CTRL_EXT\t %08x\n", regs_buff[2]);
+ regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ sbuf_printf(sb, "\tIXGBE_ESDP\t %08x\n", regs_buff[3]);
+ regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_EODSDP);
+ sbuf_printf(sb, "\tIXGBE_EODSDP\t %08x\n", regs_buff[4]);
+ regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ sbuf_printf(sb, "\tIXGBE_LEDCTL\t %08x\n", regs_buff[5]);
+ regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_FRTIMER);
+ sbuf_printf(sb, "\tIXGBE_FRTIMER\t %08x\n", regs_buff[6]);
+ regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_TCPTIMER);
+ sbuf_printf(sb, "\tIXGBE_TCPTIMER\t %08x\n\n", regs_buff[7]);
+
+ /* Interrupt */
+ /* don't read EICR because it can clear interrupt causes, instead
+ * read EICS which is a shadow but doesn't clear EICR */
+ sbuf_printf(sb, "Interrupt\n");
+ regs_buff[18] = IXGBE_READ_REG(hw, IXGBE_EICS);
+ sbuf_printf(sb, "\tIXGBE_EICS\t %08x\n", regs_buff[18]);
+ regs_buff[19] = IXGBE_READ_REG(hw, IXGBE_EICS);
+ sbuf_printf(sb, "\tIXGBE_EICS\t %08x\n", regs_buff[19]);
+ regs_buff[20] = IXGBE_READ_REG(hw, IXGBE_EIMS);
+ sbuf_printf(sb, "\tIXGBE_EIMS\t %08x\n", regs_buff[20]);
+ regs_buff[21] = IXGBE_READ_REG(hw, IXGBE_EIMC);
+ sbuf_printf(sb, "\tIXGBE_EIMC\t %08x\n", regs_buff[21]);
+ regs_buff[22] = IXGBE_READ_REG(hw, IXGBE_EIAC);
+ sbuf_printf(sb, "\tIXGBE_EIAC\t %08x\n", regs_buff[22]);
+ regs_buff[23] = IXGBE_READ_REG(hw, IXGBE_EIAM);
+ sbuf_printf(sb, "\tIXGBE_EIAM\t %08x\n", regs_buff[23]);
+ regs_buff[24] = IXGBE_READ_REG(hw, IXGBE_EITR(0));
+ sbuf_printf(sb, "\tIXGBE_EITR(0)\t %08x\n", regs_buff[24]);
+ regs_buff[25] = IXGBE_READ_REG(hw, IXGBE_IVAR(0));
+ sbuf_printf(sb, "\tIXGBE_IVAR(0)\t %08x\n", regs_buff[25]);
+ regs_buff[26] = IXGBE_READ_REG(hw, IXGBE_MSIXT);
+ sbuf_printf(sb, "\tIXGBE_MSIXT\t %08x\n", regs_buff[26]);
+ regs_buff[27] = IXGBE_READ_REG(hw, IXGBE_MSIXPBA);
+ sbuf_printf(sb, "\tIXGBE_MSIXPBA\t %08x\n", regs_buff[27]);
+ regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_PBACL(0));
+ sbuf_printf(sb, "\tIXGBE_PBACL(0)\t %08x\n", regs_buff[28]);
+ regs_buff[29] = IXGBE_READ_REG(hw, IXGBE_GPIE);
+ sbuf_printf(sb, "\tIXGBE_GPIE\t %08x\n", regs_buff[29]);
+
+ /* Flow Control */
+ sbuf_printf(sb, "\nFlow Control\n");
+ regs_buff[30] = IXGBE_READ_REG(hw, IXGBE_PFCTOP);
+ sbuf_printf(sb, "\tIXGBE_PFCTOP\t %08x\n", regs_buff[30]);
+ regs_buff[31] = IXGBE_READ_REG(hw, IXGBE_FCTTV(0));
+ sbuf_printf(sb, "\tIXGBE_FCTTV(0)\t %08x\n", regs_buff[31]);
+ regs_buff[32] = IXGBE_READ_REG(hw, IXGBE_FCTTV(1));
+ sbuf_printf(sb, "\tIXGBE_FCTTV(1)\t %08x\n", regs_buff[32]);
+ regs_buff[33] = IXGBE_READ_REG(hw, IXGBE_FCTTV(2));
+ sbuf_printf(sb, "\tIXGBE_FCTTV(2)\t %08x\n", regs_buff[33]);
+ regs_buff[34] = IXGBE_READ_REG(hw, IXGBE_FCTTV(3));
+ sbuf_printf(sb, "\tIXGBE_FCTTV(3)\t %08x\n", regs_buff[34]);
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i));
+ sbuf_printf(sb, "\tIXGBE_FCRTL(%2d)\t %08x\n", i, regs_buff[35+i]);
+ regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i));
+ sbuf_printf(sb, "\tIXGBE_FCRTH(%2d)\t %08x\n", i, regs_buff[43+i]);
+ break;
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i));
+ regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i));
+ break;
+ default:
+ break;
+ }
+ }
+ regs_buff[51] = IXGBE_READ_REG(hw, IXGBE_FCRTV);
+ sbuf_printf(sb, "\tIXGBE_FCRTV\t %08x\n", regs_buff[51]);
+ regs_buff[52] = IXGBE_READ_REG(hw, IXGBE_TFCS);
+ sbuf_printf(sb, "\tIXGBE_TFCS\t %08x\n", regs_buff[52]);
+
+ /* Receive DMA */
+ sbuf_printf(sb, "\nReceive DMA\n");
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[53 + i] = IXGBE_READ_REG(hw, IXGBE_RDBAL(i));
+ sbuf_printf(sb, "\tIXGBE_RDBAL(%2d)\t %08x\n", i, regs_buff[53+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[117 + i] = IXGBE_READ_REG(hw, IXGBE_RDBAH(i));
+ sbuf_printf(sb, "\tIXGBE_RDBAH(%2d)\t %08x\n", i, regs_buff[117+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[181 + i] = IXGBE_READ_REG(hw, IXGBE_RDLEN(i));
+ sbuf_printf(sb, "\tIXGBE_RDLEN(%2d)\t %08x\n", i, regs_buff[181+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[245 + i] = IXGBE_READ_REG(hw, IXGBE_RDH(i));
+ sbuf_printf(sb, "\tIXGBE_RDH(%2d)\t %08x\n", i, regs_buff[245+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[309 + i] = IXGBE_READ_REG(hw, IXGBE_RDT(i));
+ sbuf_printf(sb, "\tIXGBE_RDT(%2d)\t %08x\n", i, regs_buff[309+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[373 + i] = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
+ sbuf_printf(sb, "\tIXGBE_RXDCTL(%2d)\t %08x\n", i, regs_buff[373+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[437 + i] = IXGBE_READ_REG(hw, IXGBE_SRRCTL(i));
+ sbuf_printf(sb, "\tIXGBE_SRRCTL(%2d)\t %08x\n", i, regs_buff[437+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[453 + i] = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
+ sbuf_printf(sb, "\tIXGBE_DCA_RXCTRL(%2d)\t %08x\n", i, regs_buff[453+i]);
+ }
+ regs_buff[469] = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+ sbuf_printf(sb, "\tIXGBE_RDRXCTL\t %08x\n", regs_buff[469]);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[470 + i] = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
+ sbuf_printf(sb, "\tIXGBE_RXPBSIZE(%2d)\t %08x\n", i, regs_buff[470+i]);
+ }
+ regs_buff[478] = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+ sbuf_printf(sb, "\tIXGBE_RXCTRL\t %08x\n", regs_buff[478]);
+ regs_buff[479] = IXGBE_READ_REG(hw, IXGBE_DROPEN);
+ sbuf_printf(sb, "\tIXGBE_DROPEN\t %08x\n", regs_buff[479]);
+
+ /* Receive */
+ sbuf_printf(sb, "\nReceive\n");
+ regs_buff[480] = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+ sbuf_printf(sb, "\tIXGBE_RXCSUM\t %08x\n", regs_buff[480]);
+ regs_buff[481] = IXGBE_READ_REG(hw, IXGBE_RFCTL);
+ sbuf_printf(sb, "\tIXGBE_RFCTL\t %08x\n", regs_buff[481]);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[482 + i] = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+ sbuf_printf(sb, "\tIXGBE_RAL(%2d)\t %08x\n", i, regs_buff[482+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[498 + i] = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+ sbuf_printf(sb, "\tIXGBE_RAH(%2d)\t %08x\n", i, regs_buff[498+i]);
+ }
+ regs_buff[514] = IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0));
+ sbuf_printf(sb, "\tIXGBE_PSRTYPE\t %08x\n", regs_buff[514]);
+ regs_buff[515] = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ sbuf_printf(sb, "\tIXGBE_FCTRL\t %08x\n", regs_buff[515]);
+ regs_buff[516] = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ sbuf_printf(sb, "\tIXGBE_VLNCTRL\t %08x\n", regs_buff[516]);
+ regs_buff[517] = IXGBE_READ_REG(hw, IXGBE_MCSTCTRL);
+ sbuf_printf(sb, "\tIXGBE_MCSTCTRL\t %08x\n", regs_buff[517]);
+ regs_buff[518] = IXGBE_READ_REG(hw, IXGBE_MRQC);
+ sbuf_printf(sb, "\tIXGBE_MRQC\t %08x\n", regs_buff[518]);
+ regs_buff[519] = IXGBE_READ_REG(hw, IXGBE_VMD_CTL);
+ sbuf_printf(sb, "\tIXGBE_VMD_CTL\t %08x\n", regs_buff[519]);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[520 + i] = IXGBE_READ_REG(hw, IXGBE_IMIR(i));
+ sbuf_printf(sb, "\tIXGBE_IMIR(%2d)\t %08x\n", i, regs_buff[520+i]);
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[528 + i] = IXGBE_READ_REG(hw, IXGBE_IMIREXT(i));
+ sbuf_printf(sb, "\tIXGBE_IMIREXT(%2d)\t %08x\n", i, regs_buff[528+i]);
+ }
+ regs_buff[536] = IXGBE_READ_REG(hw, IXGBE_IMIRVP);
+ sbuf_printf(sb, "\tIXGBE_IMIRVP\t %08x\n", regs_buff[536]);
+
+ /* Transmit */
+ sbuf_printf(sb, "\nTransmit\n");
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[537 + i] = IXGBE_READ_REG(hw, IXGBE_TDBAL(i));
+ sbuf_printf(sb, "\tIXGBE_TDBAL(%2d)\t %08x\n", i, regs_buff[537+i]);
+ }
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[569 + i] = IXGBE_READ_REG(hw, IXGBE_TDBAH(i));
+ sbuf_printf(sb, "\tIXGBE_TDBAH(%2d)\t %08x\n", i, regs_buff[569+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[601 + i] = IXGBE_READ_REG(hw, IXGBE_TDLEN(i));
+ sbuf_printf(sb, "\tIXGBE_TDLEN(%2d)\t %08x\n", i, regs_buff[601+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[633 + i] = IXGBE_READ_REG(hw, IXGBE_TDH(i));
+ sbuf_printf(sb, "\tIXGBE_TDH(%2d)\t %08x\n", i, regs_buff[633+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[665 + i] = IXGBE_READ_REG(hw, IXGBE_TDT(i));
+ sbuf_printf(sb, "\tIXGBE_TDT(%2d)\t %08x\n", i, regs_buff[665+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[697 + i] = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
+ sbuf_printf(sb, "\tIXGBE_TXDCTL(%2d)\t %08x\n", i, regs_buff[697+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[729 + i] = IXGBE_READ_REG(hw, IXGBE_TDWBAL(i));
+ sbuf_printf(sb, "\tIXGBE_TDWBAL(%2d)\t %08x\n", i, regs_buff[729+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[761 + i] = IXGBE_READ_REG(hw, IXGBE_TDWBAH(i));
+ sbuf_printf(sb, "\tIXGBE_TDWBAH(%2d)\t %08x\n", i, regs_buff[761+i]);
+ }
+ regs_buff[793] = IXGBE_READ_REG(hw, IXGBE_DTXCTL);
+ sbuf_printf(sb, "\tIXGBE_DTXCTL\t %08x\n", regs_buff[793]);
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[794 + i] = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
+ sbuf_printf(sb, "\tIXGBE_DCA_TXCTRL(%2d)\t %08x\n", i, regs_buff[794+i]);
+ }
+ regs_buff[810] = IXGBE_READ_REG(hw, IXGBE_TIPG);
+ sbuf_printf(sb, "\tIXGBE_TIPG\t %08x\n", regs_buff[810]);
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[811 + i] = IXGBE_READ_REG(hw, IXGBE_TXPBSIZE(i));
+ sbuf_printf(sb, "\tIXGBE_TXPBSIZE(%2d)\t %08x\n", i,
+ regs_buff[811+i]);
+ }
+ regs_buff[819] = IXGBE_READ_REG(hw, IXGBE_MNGTXMAP);
+ sbuf_printf(sb, "\tIXGBE_MNGTXMAP\t %08x\n", regs_buff[819]);
+
+ /* Wake Up */
+ sbuf_printf(sb, "\nWake Up\n");
+ regs_buff[820] = IXGBE_READ_REG(hw, IXGBE_WUC);
+ sbuf_printf(sb, "\tIXGBE_WUC\t %08x\n", regs_buff[820]);
+ regs_buff[821] = IXGBE_READ_REG(hw, IXGBE_WUFC);
+ sbuf_printf(sb, "\tIXGBE_WUFC\t %08x\n", regs_buff[821]);
+ regs_buff[822] = IXGBE_READ_REG(hw, IXGBE_WUS);
+ sbuf_printf(sb, "\tIXGBE_WUS\t %08x\n", regs_buff[822]);
+ regs_buff[823] = IXGBE_READ_REG(hw, IXGBE_IPAV);
+ sbuf_printf(sb, "\tIXGBE_IPAV\t %08x\n", regs_buff[823]);
+ regs_buff[824] = IXGBE_READ_REG(hw, IXGBE_IP4AT);
+ sbuf_printf(sb, "\tIXGBE_IP4AT\t %08x\n", regs_buff[824]);
+ regs_buff[825] = IXGBE_READ_REG(hw, IXGBE_IP6AT);
+ sbuf_printf(sb, "\tIXGBE_IP6AT\t %08x\n", regs_buff[825]);
+ regs_buff[826] = IXGBE_READ_REG(hw, IXGBE_WUPL);
+ sbuf_printf(sb, "\tIXGBE_WUPL\t %08x\n", regs_buff[826]);
+ regs_buff[827] = IXGBE_READ_REG(hw, IXGBE_WUPM);
+ sbuf_printf(sb, "\tIXGBE_WUPM\t %08x\n", regs_buff[827]);
+ regs_buff[828] = IXGBE_READ_REG(hw, IXGBE_FHFT(0));
+ sbuf_printf(sb, "\tIXGBE_FHFT\t %08x\n", regs_buff[828]);
+
+ /* DCB */
+ sbuf_printf(sb, "\nDCB\n");
+ regs_buff[829] = IXGBE_READ_REG(hw, IXGBE_RMCS); /* same as FCCFG */
+ sbuf_printf(sb, "\tIXGBE_RMCS\t %08x\n", regs_buff[829]);
+ regs_buff[831] = IXGBE_READ_REG(hw, IXGBE_PDPMCS); /* same as RTTPCS */
+ sbuf_printf(sb, "\tIXGBE_PDPMCS\t %08x\n", regs_buff[831]);
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_DPMCS);
+ sbuf_printf(sb, "\tIXGBE_DPMCS\t %08x\n", regs_buff[830]);
+ regs_buff[832] = IXGBE_READ_REG(hw, IXGBE_RUPPBMR);
+ sbuf_printf(sb, "\tIXGBE_RUPPBMR\t %08x\n", regs_buff[832]);
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[833 + i] = IXGBE_READ_REG(hw, IXGBE_RT2CR(i));
+ sbuf_printf(sb, "\tIXGBE_RT2CR(%2d)\t %08x\n", i,
+ regs_buff[833+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[841 + i] = IXGBE_READ_REG(hw, IXGBE_RT2SR(i));
+ sbuf_printf(sb, "\tIXGBE_RT2SR(%2d)\t %08x\n", i,
+ regs_buff[841+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[849 + i] = IXGBE_READ_REG(hw,
+ IXGBE_TDTQ2TCCR(i));
+ sbuf_printf(sb, "\tIXGBE_TDTQ2TCCR(%2d)\t %08x\n", i,
+ regs_buff[849+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[857 + i] = IXGBE_READ_REG(hw,
+ IXGBE_TDTQ2TCSR(i));
+ sbuf_printf(sb, "\tIXGBE_TDTQ2TCSR(%2d)\t %08x\n", i,
+ regs_buff[857+i]);
+ }
+ break;
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
+ regs_buff[832] = IXGBE_READ_REG(hw, IXGBE_RTRPCS);
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ regs_buff[833 + i] =
+ IXGBE_READ_REG(hw, IXGBE_RTRPT4C(i));
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ regs_buff[841 + i] =
+ IXGBE_READ_REG(hw, IXGBE_RTRPT4S(i));
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ regs_buff[849 + i] =
+ IXGBE_READ_REG(hw, IXGBE_RTTDT2C(i));
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ regs_buff[857 + i] =
+ IXGBE_READ_REG(hw, IXGBE_RTTDT2S(i));
+ break;
+ default:
+ break;
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[865 + i] = IXGBE_READ_REG(hw, IXGBE_TDPT2TCCR(i)); /* same as RTTPT2C */
+ sbuf_printf(sb, "\tIXGBE_TDPT2TCCR(%2d)\t %08x\n", i, regs_buff[865+i]);
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ regs_buff[873 + i] = IXGBE_READ_REG(hw, IXGBE_TDPT2TCSR(i)); /* same as RTTPT2S */
+ sbuf_printf(sb, "\tIXGBE_TDPT2TCSR(%2d)\t %08x\n", i, regs_buff[873+i]);
+ }
+ /* MAC */
+ sbuf_printf(sb, "\nMAC\n");
+ regs_buff[1038] = IXGBE_READ_REG(hw, IXGBE_PCS1GCFIG);
+ sbuf_printf(sb, "\tIXGBE_PCS1GCFIG\t %08x\n", regs_buff[1038]);
+ regs_buff[1039] = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+ sbuf_printf(sb, "\tIXGBE_PCSIG1CTL\t %08x\n", regs_buff[1039]);
+ regs_buff[1040] = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+ sbuf_printf(sb, "\tIXGBE_PCSIGLSTA\t %08x\n", regs_buff[1040]);
+ regs_buff[1041] = IXGBE_READ_REG(hw, IXGBE_PCS1GDBG0);
+ sbuf_printf(sb, "\tIXGBE_PCS1GDBG0\t %08x\n", regs_buff[1041]);
+ regs_buff[1042] = IXGBE_READ_REG(hw, IXGBE_PCS1GDBG1);
+ sbuf_printf(sb, "\tIXGBE_PCS1GDBG1\t %08x\n", regs_buff[1042]);
+ regs_buff[1043] = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ sbuf_printf(sb, "\tIXGBE_PCS1GANA\t %08x\n", regs_buff[1043]);
+ regs_buff[1044] = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+ sbuf_printf(sb, "\tIXGBE_PCS1GANLP\t %08x\n", regs_buff[1044]);
+ regs_buff[1045] = IXGBE_READ_REG(hw, IXGBE_PCS1GANNP);
+ sbuf_printf(sb, "\tIXGBE_PCS1GANNP\t %08x\n", regs_buff[1045]);
+ regs_buff[1046] = IXGBE_READ_REG(hw, IXGBE_PCS1GANLPNP);
+ sbuf_printf(sb, "\tIXGBE_PCS1GANLPNP\t %08x\n", regs_buff[1046]);
+ regs_buff[1047] = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+ sbuf_printf(sb, "\tIXGBE_HILREG0\t %08x\n", regs_buff[1047]);
+ regs_buff[1048] = IXGBE_READ_REG(hw, IXGBE_HLREG1);
+ sbuf_printf(sb, "\tIXGBE_HILREG1\t %08x\n", regs_buff[1048]);
+ regs_buff[1049] = IXGBE_READ_REG(hw, IXGBE_PAP);
+ sbuf_printf(sb, "\tIXGBE_PAP\t %08x\n", regs_buff[1049]);
+ regs_buff[1050] = IXGBE_READ_REG(hw, IXGBE_MACA);
+ sbuf_printf(sb, "\tIXGBE_MACA\t %08x\n", regs_buff[1050]);
+ regs_buff[1051] = IXGBE_READ_REG(hw, IXGBE_APAE);
+ sbuf_printf(sb, "\tIXGBE_APAE\t %08x\n", regs_buff[1051]);
+ regs_buff[1052] = IXGBE_READ_REG(hw, IXGBE_ARD);
+ sbuf_printf(sb, "\tIXGBE_ARD\t %08x\n", regs_buff[1052]);
+ regs_buff[1053] = IXGBE_READ_REG(hw, IXGBE_AIS);
+ sbuf_printf(sb, "\tIXGBE_AIS\t %08x\n", regs_buff[1053]);
+ regs_buff[1054] = IXGBE_READ_REG(hw, IXGBE_MSCA);
+ sbuf_printf(sb, "\tIXGBE_MSCA\t %08x\n", regs_buff[1054]);
+ regs_buff[1055] = IXGBE_READ_REG(hw, IXGBE_MSRWD);
+ sbuf_printf(sb, "\tIXGBE_MSRWD\t %08x\n", regs_buff[1055]);
+ regs_buff[1056] = IXGBE_READ_REG(hw, IXGBE_MLADD);
+ sbuf_printf(sb, "\tIXGBE_MLADD\t %08x\n", regs_buff[1056]);
+ regs_buff[1057] = IXGBE_READ_REG(hw, IXGBE_MHADD);
+ sbuf_printf(sb, "\tIXGBE_MHADD\t %08x\n", regs_buff[1057]);
+ regs_buff[1058] = IXGBE_READ_REG(hw, IXGBE_TREG);
+ sbuf_printf(sb, "\tIXGBE_TREG\t %08x\n", regs_buff[1058]);
+ regs_buff[1059] = IXGBE_READ_REG(hw, IXGBE_PCSS1);
+ sbuf_printf(sb, "\tIXGBE_PCSS1\t %08x\n", regs_buff[1059]);
+ regs_buff[1060] = IXGBE_READ_REG(hw, IXGBE_PCSS2);
+ sbuf_printf(sb, "\tIXGBE_PCSS2\t %08x\n", regs_buff[1060]);
+ regs_buff[1061] = IXGBE_READ_REG(hw, IXGBE_XPCSS);
+ sbuf_printf(sb, "\tIXGBE_XPCSS\t %08x\n", regs_buff[1061]);
+ regs_buff[1062] = IXGBE_READ_REG(hw, IXGBE_SERDESC);
+ sbuf_printf(sb, "\tIXGBE_SERDESC\t %08x\n", regs_buff[1062]);
+ regs_buff[1063] = IXGBE_READ_REG(hw, IXGBE_MACS);
+ sbuf_printf(sb, "\tIXGBE_MACS\t %08x\n", regs_buff[1063]);
+ regs_buff[1064] = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ sbuf_printf(sb, "\tIXGBE_AUTOC\t %08x\n", regs_buff[1064]);
+ regs_buff[1065] = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ sbuf_printf(sb, "\tIXGBE_LINKS\t %08x\n", regs_buff[1065]);
+ regs_buff[1066] = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+ sbuf_printf(sb, "\tIXGBE_AUTOC2\t %08x\n", regs_buff[1066]);
+ regs_buff[1067] = IXGBE_READ_REG(hw, IXGBE_AUTOC3);
+ sbuf_printf(sb, "\tIXGBE_AUTOC3\t %08x\n", regs_buff[1067]);
+ regs_buff[1068] = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+ sbuf_printf(sb, "\tIXGBE_ANLP1\t %08x\n", regs_buff[1068]);
+ regs_buff[1069] = IXGBE_READ_REG(hw, IXGBE_ANLP2);
+ sbuf_printf(sb, "\tIXGBE_ANLP2\t %08x\n", regs_buff[1069]);
+ regs_buff[1070] = IXGBE_READ_REG(hw, IXGBE_ATLASCTL);
+ sbuf_printf(sb, "\tIXGBE_ATLASCTL\t %08x\n", regs_buff[1070]);
+
+ /* Diagnostic */
+ sbuf_printf(sb, "\nDiagnostic\n");
+ regs_buff[1071] = IXGBE_READ_REG(hw, IXGBE_RDSTATCTL);
+ sbuf_printf(sb, "\tIXGBE_RDSTATCTL\t %08x\n", regs_buff[1071]);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[1072 + i] = IXGBE_READ_REG(hw, IXGBE_RDSTAT(i));
+ sbuf_printf(sb, "\tIXGBE_RDSTAT(%2d)\t %08x\n", i, regs_buff[1072+i]);
+ }
+ regs_buff[1080] = IXGBE_READ_REG(hw, IXGBE_RDHMPN);
+ sbuf_printf(sb, "\tIXGBE_RDHMPN\t %08x\n", regs_buff[1080]);
+ for (i = 0; i < 4; i++) {
+ regs_buff[1081 + i] = IXGBE_READ_REG(hw, IXGBE_RIC_DW(i));
+ sbuf_printf(sb, "\tIXGBE_RIC_DW(%2d)\t %08x\n", i, regs_buff[1081+i]);
+ }
+ regs_buff[1085] = IXGBE_READ_REG(hw, IXGBE_RDPROBE);
+ sbuf_printf(sb, "\tIXGBE_RDPROBE\t %08x\n", regs_buff[1085]);
+ /* regs_buff[1086] = IXGBE_READ_REG(hw, IXGBE_TDSTATCTL);
+ sbuf_printf(sb, "\tIXGBE_TDSTATCTL\t %08x\n", regs_buff[1086]); */
+ /* for (i = 0; i < adapter->num_queues; i++) {
+ regs_buff[1087 + i] = IXGBE_READ_REG(hw, IXGBE_TDSTAT(i));
+ sbuf_printf(sb, "\n\tIXGBE_TDSTAT(%2d)\t %08x\n", i, regs_buff[1087+i]);
+ } */
+ regs_buff[1095] = IXGBE_READ_REG(hw, IXGBE_TDHMPN);
+ sbuf_printf(sb, "\tIXGBE_TDHMPN\t %08x\n", regs_buff[1095]);
+
+ for (i = 0; i < 4; i++) {
+ regs_buff[1096 + i] = IXGBE_READ_REG(hw, IXGBE_TIC_DW(i));
+ sbuf_printf(sb, "\tIXGBE_TIC_DW(%2d)\t %08x\n", i, regs_buff[1096+i]);
+ }
+ regs_buff[1100] = IXGBE_READ_REG(hw, IXGBE_TDPROBE);
+ sbuf_printf(sb, "\tIXGBE_TDPROBE\t %08x\n", regs_buff[1100]);
+ regs_buff[1101] = IXGBE_READ_REG(hw, IXGBE_TXBUFCTRL);
+ sbuf_printf(sb, "\tIXGBE_TXBUFCTRL\t %08x\n", regs_buff[1101]);
+ regs_buff[1102] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA0);
+ sbuf_printf(sb, "\tIXGBE_TXBUFDATA0\t %08x\n", regs_buff[1102]);
+ regs_buff[1103] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA1);
+ sbuf_printf(sb, "\tIXGBE_TXBUFDATA1\t %08x\n", regs_buff[1103]);
+ regs_buff[1104] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA2);
+ sbuf_printf(sb, "\tIXGBE_TXBUFDATA2\t %08x\n", regs_buff[1104]);
+ regs_buff[1105] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA3);
+ sbuf_printf(sb, "\tIXGBE_TXBUFDATA3\t %08x\n", regs_buff[1105]);
+ regs_buff[1106] = IXGBE_READ_REG(hw, IXGBE_RXBUFCTRL);
+ sbuf_printf(sb, "\tIXGBE_RXBUFCTRL\t %08x\n", regs_buff[1106]);
+ regs_buff[1107] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA0);
+ sbuf_printf(sb, "\tIXGBE_RXBIFDATA0\t %08x\n", regs_buff[1107]);
+ regs_buff[1108] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA1);
+ sbuf_printf(sb, "\tIXGBE_RXBUFDATA1\t %08x\n", regs_buff[1108]);
+ regs_buff[1109] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA2);
+ sbuf_printf(sb, "\tIXGBE_RXBUFDATA2\t %08x\n", regs_buff[1109]);
+ regs_buff[1110] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA3);
+ sbuf_printf(sb, "\tIXGBE_RXBUFDATA3\t %08x\n", regs_buff[1110]);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ regs_buff[1111 + i] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i));
+ sbuf_printf(sb, "\tIXGBE_PCIE_DIAG(%2d)\t %08x\n", i,
+ regs_buff[1111+i]);
+ }
+ regs_buff[1119] = IXGBE_READ_REG(hw, IXGBE_RFVAL);
+ sbuf_printf(sb, "\tIXGBE_RFVAL\t %08x\n", regs_buff[1119]);
+ regs_buff[1120] = IXGBE_READ_REG(hw, IXGBE_MDFTC1);
+ sbuf_printf(sb, "\tIXGBE_MDFTC1\t %08x\n", regs_buff[1120]);
+ regs_buff[1121] = IXGBE_READ_REG(hw, IXGBE_MDFTC2);
+ sbuf_printf(sb, "\tIXGBE_MDFTC2\t %08x\n", regs_buff[1121]);
+ regs_buff[1122] = IXGBE_READ_REG(hw, IXGBE_MDFTFIFO1);
+ sbuf_printf(sb, "\tIXGBE_MDFTFIF01\t %08x\n", regs_buff[1122]);
+ regs_buff[1123] = IXGBE_READ_REG(hw, IXGBE_MDFTFIFO2);
+ sbuf_printf(sb, "\tIXGBE_MDFTFIF02\t %08x\n", regs_buff[1123]);
+ regs_buff[1124] = IXGBE_READ_REG(hw, IXGBE_MDFTS);
+ sbuf_printf(sb, "\tIXGBE_MDFTS\t %08x\n", regs_buff[1124]);
+ regs_buff[1125] = IXGBE_READ_REG(hw, IXGBE_PCIEECCCTL);
+ sbuf_printf(sb, "\tIXGBE_PCIEECCCTL\t %08x\n", regs_buff[1125]);
+ regs_buff[1126] = IXGBE_READ_REG(hw, IXGBE_PBTXECC);
+ sbuf_printf(sb, "\tIXGBE_PBTXECC\t %08x\n", regs_buff[1126]);
+ regs_buff[1127] = IXGBE_READ_REG(hw, IXGBE_PBRXECC);
+ sbuf_printf(sb, "\tIXGBE_PBRXECC\t %08x\n", regs_buff[1127]);
+
+ /* 82599 X540 specific registers */
+ regs_buff[1128] = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+
+ /* 82599 X540 specific DCB registers */
+ regs_buff[1129] = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
+ regs_buff[1130] = IXGBE_READ_REG(hw, IXGBE_RTTUP2TC);
+ for (i = 0; i < 4; i++) {
+ regs_buff[1131 + i] = IXGBE_READ_REG(hw, IXGBE_TXLLQ(i));
+ sbuf_printf(sb, "\tIXGBE_TXLLQ(%2d)\t %08x\n", i, regs_buff[1131+i]);
+ }
+ regs_buff[1135] = IXGBE_READ_REG(hw, IXGBE_RTTBCNRM);
+ /* same as RTTQCNRM */
+ sbuf_printf(sb, "\tIXGBE_RTTBCNRM\t %08x\n", regs_buff[1135]);
+ regs_buff[1136] = IXGBE_READ_REG(hw, IXGBE_RTTBCNRD);
+ /* same as RTTQCNRR */
+ sbuf_printf(sb, "\tIXGBE_RTTBCNRD\t %08x\n", regs_buff[1136]);
+#ifdef PRINT_QSET
+ for (j = 0; j < nrxd; j++) {
+ u32 staterr = le32toh(rxr->rx_base[j].wb.upper.status_error);
+ u32 length = le32toh(rxr->rx_base[j].wb.upper.length);
+ sbuf_printf(sb, "\tReceive Descriptor Address %d: %08lx Error:%d Length:%d\n", j, rxr->rx_base[j].read.pkt_addr, staterr, length);
+ }
+
+ for (j = 0; j < min(ntxd, 256); j++) {
+ struct ixgbe_tx_buf *buf = &txr->tx_buffers[j];
+ unsigned int *ptr = (unsigned int *)&txr->tx_base[j].read;
+
+ sbuf_printf(sb, "\tTXD[%03d] [0]: %08x [1]: %08x [2]: %08x [3]: %08x eop: %d DD=%d\n",
+ j, ptr[0], ptr[1], ptr[2], ptr[3], buf->eop,
+ buf->eop != -1 ? txr->tx_base[buf->eop].wb.status & IXGBE_TXD_STAT_DD : 0);
+
+ }
+#endif
+ /* X540 specific DCB registers
+ regs_buff[1137] = IXGBE_READ_REG(hw, IXGBE_RTTQCNCR);
+ regs_buff[1138] = IXGBE_READ_REG(hw, IXGBE_RTTQCNTG); */
+
+ rc = sbuf_finish(sb);
+ sbuf_delete(sb);
+ return(rc);
+}
Index: sys/dev/ixgbe/ixgbe_type.h
===================================================================
--- sys/dev/ixgbe/ixgbe_type.h
+++ sys/dev/ixgbe/ixgbe_type.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -107,11 +107,11 @@
#define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0
#define IXGBE_SUBDEV_ID_82599_ECNA_DP 0x0470
#define IXGBE_SUBDEV_ID_82599_SP_560FLR 0x211B
-#define IXGBE_SUBDEV_ID_82599_LOM_SFP 0x8976
#define IXGBE_SUBDEV_ID_82599_LOM_SNAP6 0x2159
#define IXGBE_SUBDEV_ID_82599_SFP_1OCP 0x000D
#define IXGBE_SUBDEV_ID_82599_SFP_2OCP 0x0008
-#define IXGBE_SUBDEV_ID_82599_SFP_LOM 0x06EE
+#define IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM1 0x8976
+#define IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM2 0x06EE
#define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A
#define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529
#define IXGBE_DEV_ID_82599_SFP_EM 0x1507
@@ -132,13 +132,27 @@
#define IXGBE_DEV_ID_X540T1 0x1560
#define IXGBE_DEV_ID_X550T 0x1563
#define IXGBE_DEV_ID_X550T1 0x15D1
+#define IXGBE_DEV_ID_X550EM_A_KR 0x15C2
+#define IXGBE_DEV_ID_X550EM_A_KR_L 0x15C3
+#define IXGBE_DEV_ID_X550EM_A_SFP_N 0x15C4
+#define IXGBE_DEV_ID_X550EM_A_SGMII 0x15C6
+#define IXGBE_DEV_ID_X550EM_A_SGMII_L 0x15C7
+#define IXGBE_DEV_ID_X550EM_A_10G_T 0x15C8
+#define IXGBE_DEV_ID_X550EM_A_QSFP 0x15CA
+#define IXGBE_DEV_ID_X550EM_A_QSFP_N 0x15CC
+#define IXGBE_DEV_ID_X550EM_A_SFP 0x15CE
+#define IXGBE_DEV_ID_X550EM_A_1G_T 0x15E4
+#define IXGBE_DEV_ID_X550EM_A_1G_T_L 0x15E5
#define IXGBE_DEV_ID_X550EM_X_KX4 0x15AA
#define IXGBE_DEV_ID_X550EM_X_KR 0x15AB
#define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC
#define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD
#define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE
+#define IXGBE_DEV_ID_X550EM_X_XFI 0x15B0
#define IXGBE_DEV_ID_X550_VF_HV 0x1564
#define IXGBE_DEV_ID_X550_VF 0x1565
+#define IXGBE_DEV_ID_X550EM_A_VF 0x15C5
+#define IXGBE_DEV_ID_X550EM_A_VF_HV 0x15B4
#define IXGBE_DEV_ID_X550EM_X_VF 0x15A8
#define IXGBE_DEV_ID_X550EM_X_VF_HV 0x15A9
@@ -157,6 +171,7 @@
#define IXGBE_I2CCTL_X540 IXGBE_I2CCTL_82599
#define IXGBE_I2CCTL_X550 0x15F5C
#define IXGBE_I2CCTL_X550EM_x IXGBE_I2CCTL_X550
+#define IXGBE_I2CCTL_X550EM_a IXGBE_I2CCTL_X550
#define IXGBE_I2CCTL_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2CCTL)
#define IXGBE_PHY_GPIO 0x00028
#define IXGBE_MAC_GPIO 0x00030
@@ -174,7 +189,8 @@
#define IXGBE_EEC_X540 IXGBE_EEC
#define IXGBE_EEC_X550 IXGBE_EEC
#define IXGBE_EEC_X550EM_x IXGBE_EEC
-#define IXGBE_EEC_BY_MAC(_hw) IXGBE_EEC
+#define IXGBE_EEC_X550EM_a 0x15FF8
+#define IXGBE_EEC_BY_MAC(_hw) IXGBE_BY_MAC((_hw), EEC)
#define IXGBE_EERD 0x10014
#define IXGBE_EEWR 0x10018
@@ -183,7 +199,8 @@
#define IXGBE_FLA_X540 IXGBE_FLA
#define IXGBE_FLA_X550 IXGBE_FLA
#define IXGBE_FLA_X550EM_x IXGBE_FLA
-#define IXGBE_FLA_BY_MAC(_hw) IXGBE_FLA
+#define IXGBE_FLA_X550EM_a 0x15F68
+#define IXGBE_FLA_BY_MAC(_hw) IXGBE_BY_MAC((_hw), FLA)
#define IXGBE_EEMNGCTL 0x10110
#define IXGBE_EEMNGDATA 0x10114
@@ -196,13 +213,15 @@
#define IXGBE_GRC_X540 IXGBE_GRC
#define IXGBE_GRC_X550 IXGBE_GRC
#define IXGBE_GRC_X550EM_x IXGBE_GRC
-#define IXGBE_GRC_BY_MAC(_hw) IXGBE_GRC
+#define IXGBE_GRC_X550EM_a 0x15F64
+#define IXGBE_GRC_BY_MAC(_hw) IXGBE_BY_MAC((_hw), GRC)
#define IXGBE_SRAMREL 0x10210
#define IXGBE_SRAMREL_X540 IXGBE_SRAMREL
#define IXGBE_SRAMREL_X550 IXGBE_SRAMREL
#define IXGBE_SRAMREL_X550EM_x IXGBE_SRAMREL
-#define IXGBE_SRAMREL_BY_MAC(_hw) IXGBE_SRAMREL
+#define IXGBE_SRAMREL_X550EM_a 0x15F6C
+#define IXGBE_SRAMREL_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SRAMREL)
#define IXGBE_PHYDBG 0x10218
@@ -218,36 +237,42 @@
#define IXGBE_I2C_CLK_IN_X540 IXGBE_I2C_CLK_IN
#define IXGBE_I2C_CLK_IN_X550 0x00004000
#define IXGBE_I2C_CLK_IN_X550EM_x IXGBE_I2C_CLK_IN_X550
+#define IXGBE_I2C_CLK_IN_X550EM_a IXGBE_I2C_CLK_IN_X550
#define IXGBE_I2C_CLK_IN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_CLK_IN)
#define IXGBE_I2C_CLK_OUT 0x00000002
#define IXGBE_I2C_CLK_OUT_X540 IXGBE_I2C_CLK_OUT
#define IXGBE_I2C_CLK_OUT_X550 0x00000200
#define IXGBE_I2C_CLK_OUT_X550EM_x IXGBE_I2C_CLK_OUT_X550
+#define IXGBE_I2C_CLK_OUT_X550EM_a IXGBE_I2C_CLK_OUT_X550
#define IXGBE_I2C_CLK_OUT_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_CLK_OUT)
#define IXGBE_I2C_DATA_IN 0x00000004
#define IXGBE_I2C_DATA_IN_X540 IXGBE_I2C_DATA_IN
#define IXGBE_I2C_DATA_IN_X550 0x00001000
#define IXGBE_I2C_DATA_IN_X550EM_x IXGBE_I2C_DATA_IN_X550
+#define IXGBE_I2C_DATA_IN_X550EM_a IXGBE_I2C_DATA_IN_X550
#define IXGBE_I2C_DATA_IN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_DATA_IN)
#define IXGBE_I2C_DATA_OUT 0x00000008
#define IXGBE_I2C_DATA_OUT_X540 IXGBE_I2C_DATA_OUT
#define IXGBE_I2C_DATA_OUT_X550 0x00000400
#define IXGBE_I2C_DATA_OUT_X550EM_x IXGBE_I2C_DATA_OUT_X550
+#define IXGBE_I2C_DATA_OUT_X550EM_a IXGBE_I2C_DATA_OUT_X550
#define IXGBE_I2C_DATA_OUT_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_DATA_OUT)
#define IXGBE_I2C_DATA_OE_N_EN 0
#define IXGBE_I2C_DATA_OE_N_EN_X540 IXGBE_I2C_DATA_OE_N_EN
#define IXGBE_I2C_DATA_OE_N_EN_X550 0x00000800
#define IXGBE_I2C_DATA_OE_N_EN_X550EM_x IXGBE_I2C_DATA_OE_N_EN_X550
+#define IXGBE_I2C_DATA_OE_N_EN_X550EM_a IXGBE_I2C_DATA_OE_N_EN_X550
#define IXGBE_I2C_DATA_OE_N_EN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_DATA_OE_N_EN)
#define IXGBE_I2C_BB_EN 0
#define IXGBE_I2C_BB_EN_X540 IXGBE_I2C_BB_EN
#define IXGBE_I2C_BB_EN_X550 0x00000100
#define IXGBE_I2C_BB_EN_X550EM_x IXGBE_I2C_BB_EN_X550
+#define IXGBE_I2C_BB_EN_X550EM_a IXGBE_I2C_BB_EN_X550
#define IXGBE_I2C_BB_EN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_BB_EN)
@@ -255,6 +280,7 @@
#define IXGBE_I2C_CLK_OE_N_EN_X540 IXGBE_I2C_CLK_OE_N_EN
#define IXGBE_I2C_CLK_OE_N_EN_X550 0x00002000
#define IXGBE_I2C_CLK_OE_N_EN_X550EM_x IXGBE_I2C_CLK_OE_N_EN_X550
+#define IXGBE_I2C_CLK_OE_N_EN_X550EM_a IXGBE_I2C_CLK_OE_N_EN_X550
#define IXGBE_I2C_CLK_OE_N_EN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_CLK_OE_N_EN)
#define IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT 500
@@ -522,6 +548,13 @@
#define IXGBE_PROXYFC 0x05F64 /* Proxying Filter Control Register */
#define IXGBE_VXLANCTRL 0x0000507C /* Rx filter VXLAN UDPPORT Register */
+/* masks for accessing VXLAN and GENEVE UDP ports */
+#define IXGBE_VXLANCTRL_VXLAN_UDPPORT_MASK 0x0000ffff /* VXLAN port */
+#define IXGBE_VXLANCTRL_GENEVE_UDPPORT_MASK 0xffff0000 /* GENEVE port */
+#define IXGBE_VXLANCTRL_ALL_UDPPORT_MASK 0xffffffff /* GENEVE/VXLAN */
+
+#define IXGBE_VXLANCTRL_GENEVE_UDPPORT_SHIFT 16
+
#define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */
/* Ext Flexible Host Filter Table */
#define IXGBE_FHFT_EXT(_n) (0x09800 + ((_n) * 0x100))
@@ -995,7 +1028,7 @@
#define IXGBE_FTFT 0x09400 /* 0x9400-0x97FC */
#define IXGBE_METF(_i) (0x05190 + ((_i) * 4)) /* 4 of these (0-3) */
#define IXGBE_MDEF_EXT(_i) (0x05160 + ((_i) * 4)) /* 8 of these (0-7) */
-#define IXGBE_LSWFW 0x15014
+#define IXGBE_LSWFW 0x15F14
#define IXGBE_BMCIP(_i) (0x05050 + ((_i) * 4)) /* 0x5050-0x505C */
#define IXGBE_BMCIPVAL 0x05060
#define IXGBE_BMCIP_IPADDR_TYPE 0x00000001
@@ -1037,36 +1070,64 @@
#define IXGBE_PCIEPIPEDAT 0x11008
#define IXGBE_GSCL_1 0x11010
#define IXGBE_GSCL_2 0x11014
+#define IXGBE_GSCL_1_X540 IXGBE_GSCL_1
+#define IXGBE_GSCL_2_X540 IXGBE_GSCL_2
#define IXGBE_GSCL_3 0x11018
#define IXGBE_GSCL_4 0x1101C
#define IXGBE_GSCN_0 0x11020
#define IXGBE_GSCN_1 0x11024
#define IXGBE_GSCN_2 0x11028
#define IXGBE_GSCN_3 0x1102C
+#define IXGBE_GSCN_0_X540 IXGBE_GSCN_0
+#define IXGBE_GSCN_1_X540 IXGBE_GSCN_1
+#define IXGBE_GSCN_2_X540 IXGBE_GSCN_2
+#define IXGBE_GSCN_3_X540 IXGBE_GSCN_3
#define IXGBE_FACTPS 0x10150
#define IXGBE_FACTPS_X540 IXGBE_FACTPS
+#define IXGBE_GSCL_1_X550 0x11800
+#define IXGBE_GSCL_2_X550 0x11804
+#define IXGBE_GSCL_1_X550EM_x IXGBE_GSCL_1_X550
+#define IXGBE_GSCL_2_X550EM_x IXGBE_GSCL_2_X550
+#define IXGBE_GSCN_0_X550 0x11820
+#define IXGBE_GSCN_1_X550 0x11824
+#define IXGBE_GSCN_2_X550 0x11828
+#define IXGBE_GSCN_3_X550 0x1182C
+#define IXGBE_GSCN_0_X550EM_x IXGBE_GSCN_0_X550
+#define IXGBE_GSCN_1_X550EM_x IXGBE_GSCN_1_X550
+#define IXGBE_GSCN_2_X550EM_x IXGBE_GSCN_2_X550
+#define IXGBE_GSCN_3_X550EM_x IXGBE_GSCN_3_X550
#define IXGBE_FACTPS_X550 IXGBE_FACTPS
#define IXGBE_FACTPS_X550EM_x IXGBE_FACTPS
-#define IXGBE_FACTPS_BY_MAC(_hw) IXGBE_FACTPS
+#define IXGBE_GSCL_1_X550EM_a IXGBE_GSCL_1_X550
+#define IXGBE_GSCL_2_X550EM_a IXGBE_GSCL_2_X550
+#define IXGBE_GSCN_0_X550EM_a IXGBE_GSCN_0_X550
+#define IXGBE_GSCN_1_X550EM_a IXGBE_GSCN_1_X550
+#define IXGBE_GSCN_2_X550EM_a IXGBE_GSCN_2_X550
+#define IXGBE_GSCN_3_X550EM_a IXGBE_GSCN_3_X550
+#define IXGBE_FACTPS_X550EM_a 0x15FEC
+#define IXGBE_FACTPS_BY_MAC(_hw) IXGBE_BY_MAC((_hw), FACTPS)
#define IXGBE_PCIEANACTL 0x11040
#define IXGBE_SWSM 0x10140
#define IXGBE_SWSM_X540 IXGBE_SWSM
#define IXGBE_SWSM_X550 IXGBE_SWSM
#define IXGBE_SWSM_X550EM_x IXGBE_SWSM
-#define IXGBE_SWSM_BY_MAC(_hw) IXGBE_SWSM
+#define IXGBE_SWSM_X550EM_a 0x15F70
+#define IXGBE_SWSM_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SWSM)
#define IXGBE_FWSM 0x10148
#define IXGBE_FWSM_X540 IXGBE_FWSM
#define IXGBE_FWSM_X550 IXGBE_FWSM
#define IXGBE_FWSM_X550EM_x IXGBE_FWSM
-#define IXGBE_FWSM_BY_MAC(_hw) IXGBE_FWSM
+#define IXGBE_FWSM_X550EM_a 0x15F74
+#define IXGBE_FWSM_BY_MAC(_hw) IXGBE_BY_MAC((_hw), FWSM)
#define IXGBE_SWFW_SYNC IXGBE_GSSR
#define IXGBE_SWFW_SYNC_X540 IXGBE_SWFW_SYNC
#define IXGBE_SWFW_SYNC_X550 IXGBE_SWFW_SYNC
#define IXGBE_SWFW_SYNC_X550EM_x IXGBE_SWFW_SYNC
-#define IXGBE_SWFW_SYNC_BY_MAC(_hw) IXGBE_SWFW_SYNC
+#define IXGBE_SWFW_SYNC_X550EM_a 0x15F78
+#define IXGBE_SWFW_SYNC_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SWFW_SYNC)
#define IXGBE_GSSR 0x10160
#define IXGBE_MREVID 0x11064
@@ -1079,6 +1140,10 @@
#define IXGBE_GSCL_6_82599 0x11034
#define IXGBE_GSCL_7_82599 0x11038
#define IXGBE_GSCL_8_82599 0x1103C
+#define IXGBE_GSCL_5_X540 IXGBE_GSCL_5_82599
+#define IXGBE_GSCL_6_X540 IXGBE_GSCL_6_82599
+#define IXGBE_GSCL_7_X540 IXGBE_GSCL_7_82599
+#define IXGBE_GSCL_8_X540 IXGBE_GSCL_8_82599
#define IXGBE_PHYADR_82599 0x11040
#define IXGBE_PHYDAT_82599 0x11044
#define IXGBE_PHYCTL_82599 0x11048
@@ -1089,10 +1154,24 @@
#define IXGBE_CIAD_82599 IXGBE_CIAD
#define IXGBE_CIAA_X540 IXGBE_CIAA
#define IXGBE_CIAD_X540 IXGBE_CIAD
+#define IXGBE_GSCL_5_X550 0x11810
+#define IXGBE_GSCL_6_X550 0x11814
+#define IXGBE_GSCL_7_X550 0x11818
+#define IXGBE_GSCL_8_X550 0x1181C
+#define IXGBE_GSCL_5_X550EM_x IXGBE_GSCL_5_X550
+#define IXGBE_GSCL_6_X550EM_x IXGBE_GSCL_6_X550
+#define IXGBE_GSCL_7_X550EM_x IXGBE_GSCL_7_X550
+#define IXGBE_GSCL_8_X550EM_x IXGBE_GSCL_8_X550
#define IXGBE_CIAA_X550 0x11508
#define IXGBE_CIAD_X550 0x11510
#define IXGBE_CIAA_X550EM_x IXGBE_CIAA_X550
#define IXGBE_CIAD_X550EM_x IXGBE_CIAD_X550
+#define IXGBE_GSCL_5_X550EM_a IXGBE_GSCL_5_X550
+#define IXGBE_GSCL_6_X550EM_a IXGBE_GSCL_6_X550
+#define IXGBE_GSCL_7_X550EM_a IXGBE_GSCL_7_X550
+#define IXGBE_GSCL_8_X550EM_a IXGBE_GSCL_8_X550
+#define IXGBE_CIAA_X550EM_a IXGBE_CIAA_X550
+#define IXGBE_CIAD_X550EM_a IXGBE_CIAD_X550
#define IXGBE_CIAA_BY_MAC(_hw) IXGBE_BY_MAC((_hw), CIAA)
#define IXGBE_CIAD_BY_MAC(_hw) IXGBE_BY_MAC((_hw), CIAD)
#define IXGBE_PICAUSE 0x110B0
@@ -1238,6 +1317,7 @@
#define IXGBE_XPCSS 0x04290
#define IXGBE_MFLCN 0x04294
#define IXGBE_SERDESC 0x04298
+#define IXGBE_MAC_SGMII_BUSY 0x04298
#define IXGBE_MACS 0x0429C
#define IXGBE_AUTOC 0x042A0
#define IXGBE_LINKS 0x042A4
@@ -1424,6 +1504,7 @@
#define IXGBE_CORECTL_WRITE_CMD 0x00010000
/* Device Type definitions for new protocol MDIO commands */
+#define IXGBE_MDIO_ZERO_DEV_TYPE 0x0
#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1
#define IXGBE_MDIO_PCS_DEV_TYPE 0x3
#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4
@@ -1489,6 +1570,7 @@
#define IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN 0x1 /* vendor alarm int enable */
#define IXGBE_MDIO_GLOBAL_STD_ALM2_INT 0x200 /* vendor alarm2 int mask */
#define IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN 0x4000 /* int high temp enable */
+#define IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN 0x0010 /* int dev fault enable */
#define IXGBE_MDIO_PMA_PMD_CONTROL_ADDR 0x0000 /* PMA/PMD Control Reg */
#define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */
#define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */
@@ -1548,16 +1630,17 @@
#define TN1010_PHY_ID 0x00A19410
#define TNX_FW_REV 0xB
#define X540_PHY_ID 0x01540200
-#define X550_PHY_ID1 0x01540220
#define X550_PHY_ID2 0x01540223
#define X550_PHY_ID3 0x01540221
#define X557_PHY_ID 0x01540240
+#define X557_PHY_ID2 0x01540250
#define AQ_FW_REV 0x20
#define QT2022_PHY_ID 0x0043A400
#define ATH_PHY_ID 0x03429050
/* PHY Types */
-#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0
+#define IXGBE_M88E1500_E_PHY_ID 0x01410DD0
+#define IXGBE_M88E1543_E_PHY_ID 0x01410EA0
/* Special PHY Init Routine */
#define IXGBE_PHY_INIT_OFFSET_NL 0x002B
@@ -1584,6 +1667,9 @@
#define IXGBE_SDP0_GPIEN_X550EM_x IXGBE_SDP0_GPIEN_X540
#define IXGBE_SDP1_GPIEN_X550EM_x IXGBE_SDP1_GPIEN_X540
#define IXGBE_SDP2_GPIEN_X550EM_x IXGBE_SDP2_GPIEN_X540
+#define IXGBE_SDP0_GPIEN_X550EM_a IXGBE_SDP0_GPIEN_X540
+#define IXGBE_SDP1_GPIEN_X550EM_a IXGBE_SDP1_GPIEN_X540
+#define IXGBE_SDP2_GPIEN_X550EM_a IXGBE_SDP2_GPIEN_X540
#define IXGBE_SDP0_GPIEN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SDP0_GPIEN)
#define IXGBE_SDP1_GPIEN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SDP1_GPIEN)
#define IXGBE_SDP2_GPIEN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SDP2_GPIEN)
@@ -1669,6 +1755,8 @@
#define IXGBE_VT_CTL_POOL_MASK (0x3F << IXGBE_VT_CTL_POOL_SHIFT)
/* VMOLR bitmasks */
+#define IXGBE_VMOLR_UPE 0x00400000 /* unicast promiscuous */
+#define IXGBE_VMOLR_VPE 0x00800000 /* VLAN promiscuous */
#define IXGBE_VMOLR_AUPE 0x01000000 /* accept untagged packets */
#define IXGBE_VMOLR_ROMPE 0x02000000 /* accept packets in MTA tbl */
#define IXGBE_VMOLR_ROPE 0x04000000 /* accept packets in UC tbl */
@@ -1774,6 +1862,9 @@
#define IXGBE_EICR_GPI_SDP0_X550EM_x IXGBE_EICR_GPI_SDP0_X540
#define IXGBE_EICR_GPI_SDP1_X550EM_x IXGBE_EICR_GPI_SDP1_X540
#define IXGBE_EICR_GPI_SDP2_X550EM_x IXGBE_EICR_GPI_SDP2_X540
+#define IXGBE_EICR_GPI_SDP0_X550EM_a IXGBE_EICR_GPI_SDP0_X540
+#define IXGBE_EICR_GPI_SDP1_X550EM_a IXGBE_EICR_GPI_SDP1_X540
+#define IXGBE_EICR_GPI_SDP2_X550EM_a IXGBE_EICR_GPI_SDP2_X540
#define IXGBE_EICR_GPI_SDP0_BY_MAC(_hw) IXGBE_BY_MAC((_hw), EICR_GPI_SDP0)
#define IXGBE_EICR_GPI_SDP1_BY_MAC(_hw) IXGBE_BY_MAC((_hw), EICR_GPI_SDP1)
#define IXGBE_EICR_GPI_SDP2_BY_MAC(_hw) IXGBE_BY_MAC((_hw), EICR_GPI_SDP2)
@@ -2104,6 +2195,7 @@
#define IXGBE_LINKS_SPEED_10G_82599 0x30000000
#define IXGBE_LINKS_SPEED_1G_82599 0x20000000
#define IXGBE_LINKS_SPEED_100_82599 0x10000000
+#define IXGBE_LINKS_SPEED_10_X550EM_A 0x00000000
#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
@@ -2149,6 +2241,7 @@
#define IXGBE_GSSR_FLASH_SM 0x0010
#define IXGBE_GSSR_NVM_UPDATE_SM 0x0200
#define IXGBE_GSSR_SW_MNG_SM 0x0400
+#define IXGBE_GSSR_TOKEN_SM 0x40000000 /* SW bit for shared access */
#define IXGBE_GSSR_SHARED_I2C_SM 0x1806 /* Wait for both phys and both I2Cs */
#define IXGBE_GSSR_I2C_MASK 0x1800
#define IXGBE_GSSR_NVM_PHY_MASK 0xF
@@ -2191,6 +2284,9 @@
#define IXGBE_PBANUM_PTR_GUARD 0xFAFA
#define IXGBE_EEPROM_CHECKSUM 0x3F
#define IXGBE_EEPROM_SUM 0xBABA
+#define IXGBE_EEPROM_CTRL_4 0x45
+#define IXGBE_EE_CTRL_4_INST_ID 0x10
+#define IXGBE_EE_CTRL_4_INST_ID_SHIFT 4
#define IXGBE_PCIE_ANALOG_PTR 0x03
#define IXGBE_ATLAS0_CONFIG_PTR 0x04
#define IXGBE_PHY_PTR 0x04
@@ -2218,7 +2314,8 @@
#define IXGBE_SAN_MAC_ADDR_PTR 0x28
#define IXGBE_DEVICE_CAPS 0x2C
-#define IXGBE_SERIAL_NUMBER_MAC_ADDR 0x11
+#define IXGBE_82599_SERIAL_NUMBER_MAC_ADDR 0x11
+#define IXGBE_X550_SERIAL_NUMBER_MAC_ADDR 0x04
#define IXGBE_PCIE_MSIX_82599_CAPS 0x72
#define IXGBE_MAX_MSIX_VECTORS_82599 0x40
#define IXGBE_PCIE_MSIX_82598_CAPS 0x62
@@ -2288,6 +2385,7 @@
#define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3
#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1
#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2
+#define IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR (1 << 7)
#define IXGBE_FW_LESM_PARAMETERS_PTR 0x2
#define IXGBE_FW_LESM_STATE_1 0x1
#define IXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */
@@ -2491,6 +2589,7 @@
#define IXGBE_MRQC_VMDQRSS64EN 0x0000000B /* VMDq2 64 pools w/ RSS */
#define IXGBE_MRQC_VMDQRT8TCEN 0x0000000C /* VMDq2/RT 16 pool 8 TC */
#define IXGBE_MRQC_VMDQRT4TCEN 0x0000000D /* VMDq2/RT 32 pool 4 TC */
+#define IXGBE_MRQC_L3L4TXSWEN 0x00008000 /* Enable L3/L4 Tx switch */
#define IXGBE_MRQC_RSS_FIELD_MASK 0xFFFF0000
#define IXGBE_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
#define IXGBE_MRQC_RSS_FIELD_IPV4 0x00020000
@@ -2662,6 +2761,7 @@
#define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */
#define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */
#define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */
+#define IXGBE_RXDADV_PKTTYPE_GENEVE 0x00000800 /* GENEVE hdr present */
#define IXGBE_RXDADV_PKTTYPE_VXLAN 0x00000800 /* VXLAN hdr present */
#define IXGBE_RXDADV_PKTTYPE_TUNNEL 0x00010000 /* Tunnel type */
#define IXGBE_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */
@@ -2750,7 +2850,7 @@
#define IXGBE_PVFPSRTYPE(P) (0x0EA00 + (4 * (P)))
#define IXGBE_PVFTDBAL(P) (0x06000 + (0x40 * (P)))
#define IXGBE_PVFTDBAH(P) (0x06004 + (0x40 * (P)))
-#define IXGBE_PVFTTDLEN(P) (0x06008 + (0x40 * (P)))
+#define IXGBE_PVFTDLEN(P) (0x06008 + (0x40 * (P)))
#define IXGBE_PVFTDH(P) (0x06010 + (0x40 * (P)))
#define IXGBE_PVFTDT(P) (0x06018 + (0x40 * (P)))
#define IXGBE_PVFTXDCTL(P) (0x06028 + (0x40 * (P)))
@@ -2905,6 +3005,7 @@
#define FW_CEM_UNUSED_VER 0x0
#define FW_CEM_MAX_RETRIES 3
#define FW_CEM_RESP_STATUS_SUCCESS 0x1
+#define FW_CEM_DRIVER_VERSION_SIZE 39 /* +9 would send 48 bytes to fw */
#define FW_READ_SHADOW_RAM_CMD 0x31
#define FW_READ_SHADOW_RAM_LEN 0x6
#define FW_WRITE_SHADOW_RAM_CMD 0x33
@@ -2917,13 +3018,77 @@
#define FW_DISABLE_RXEN_CMD 0xDE
#define FW_DISABLE_RXEN_LEN 0x1
#define FW_PHY_MGMT_REQ_CMD 0x20
+#define FW_PHY_TOKEN_REQ_CMD 0xA
+#define FW_PHY_TOKEN_REQ_LEN 2
+#define FW_PHY_TOKEN_REQ 0
+#define FW_PHY_TOKEN_REL 1
+#define FW_PHY_TOKEN_OK 1
+#define FW_PHY_TOKEN_RETRY 0x80
+#define FW_PHY_TOKEN_DELAY 5 /* milliseconds */
+#define FW_PHY_TOKEN_WAIT 5 /* seconds */
+#define FW_PHY_TOKEN_RETRIES ((FW_PHY_TOKEN_WAIT * 1000) / FW_PHY_TOKEN_DELAY)
#define FW_INT_PHY_REQ_CMD 0xB
#define FW_INT_PHY_REQ_LEN 10
#define FW_INT_PHY_REQ_READ 0
#define FW_INT_PHY_REQ_WRITE 1
+#define FW_PHY_ACT_REQ_CMD 5
+#define FW_PHY_ACT_DATA_COUNT 4
+#define FW_PHY_ACT_REQ_LEN (4 + 4 * FW_PHY_ACT_DATA_COUNT)
+#define FW_PHY_ACT_INIT_PHY 1
+#define FW_PHY_ACT_SETUP_LINK 2
+#define FW_PHY_ACT_LINK_SPEED_10 (1u << 0)
+#define FW_PHY_ACT_LINK_SPEED_100 (1u << 1)
+#define FW_PHY_ACT_LINK_SPEED_1G (1u << 2)
+#define FW_PHY_ACT_LINK_SPEED_2_5G (1u << 3)
+#define FW_PHY_ACT_LINK_SPEED_5G (1u << 4)
+#define FW_PHY_ACT_LINK_SPEED_10G (1u << 5)
+#define FW_PHY_ACT_LINK_SPEED_20G (1u << 6)
+#define FW_PHY_ACT_LINK_SPEED_25G (1u << 7)
+#define FW_PHY_ACT_LINK_SPEED_40G (1u << 8)
+#define FW_PHY_ACT_LINK_SPEED_50G (1u << 9)
+#define FW_PHY_ACT_LINK_SPEED_100G (1u << 10)
+#define FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT 16
+#define FW_PHY_ACT_SETUP_LINK_PAUSE_MASK (3u << \
+ FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT)
+#define FW_PHY_ACT_SETUP_LINK_PAUSE_NONE 0u
+#define FW_PHY_ACT_SETUP_LINK_PAUSE_TX 1u
+#define FW_PHY_ACT_SETUP_LINK_PAUSE_RX 2u
+#define FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX 3u
+#define FW_PHY_ACT_SETUP_LINK_LP (1u << 18)
+#define FW_PHY_ACT_SETUP_LINK_HP (1u << 19)
+#define FW_PHY_ACT_SETUP_LINK_EEE (1u << 20)
+#define FW_PHY_ACT_SETUP_LINK_AN (1u << 22)
+#define FW_PHY_ACT_SETUP_LINK_RSP_DOWN (1u << 0)
+#define FW_PHY_ACT_GET_LINK_INFO 3
+#define FW_PHY_ACT_GET_LINK_INFO_EEE (1u << 19)
+#define FW_PHY_ACT_GET_LINK_INFO_FC_TX (1u << 20)
+#define FW_PHY_ACT_GET_LINK_INFO_FC_RX (1u << 21)
+#define FW_PHY_ACT_GET_LINK_INFO_POWER (1u << 22)
+#define FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE (1u << 24)
+#define FW_PHY_ACT_GET_LINK_INFO_TEMP (1u << 25)
+#define FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX (1u << 28)
+#define FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX (1u << 29)
+#define FW_PHY_ACT_FORCE_LINK_DOWN 4
+#define FW_PHY_ACT_FORCE_LINK_DOWN_OFF (1u << 0)
+#define FW_PHY_ACT_PHY_SW_RESET 5
+#define FW_PHY_ACT_PHY_HW_RESET 6
+#define FW_PHY_ACT_GET_PHY_INFO 7
+#define FW_PHY_ACT_UD_2 0x1002
+#define FW_PHY_ACT_UD_2_10G_KR_EEE (1u << 6)
+#define FW_PHY_ACT_UD_2_10G_KX4_EEE (1u << 5)
+#define FW_PHY_ACT_UD_2_1G_KX_EEE (1u << 4)
+#define FW_PHY_ACT_UD_2_10G_T_EEE (1u << 3)
+#define FW_PHY_ACT_UD_2_1G_T_EEE (1u << 2)
+#define FW_PHY_ACT_UD_2_100M_TX_EEE (1u << 1)
+#define FW_PHY_ACT_RETRIES 50
+#define FW_PHY_INFO_SPEED_MASK 0xFFFu
+#define FW_PHY_INFO_ID_HI_MASK 0xFFFF0000u
+#define FW_PHY_INFO_ID_LO_MASK 0x0000FFFFu
/* Host Interface Command Structures */
+#pragma pack(push, 1)
+
struct ixgbe_hic_hdr {
u8 cmd;
u8 buf_len;
@@ -2964,6 +3129,16 @@
u16 pad2; /* end spacing to ensure length is mult. of dword2 */
};
+struct ixgbe_hic_drv_info2 {
+ struct ixgbe_hic_hdr hdr;
+ u8 port_num;
+ u8 ver_sub;
+ u8 ver_build;
+ u8 ver_min;
+ u8 ver_maj;
+ char driver_string[FW_CEM_DRIVER_VERSION_SIZE];
+};
+
/* These need to be dword aligned */
struct ixgbe_hic_read_shadow_ram {
union ixgbe_hic_hdr2 hdr;
@@ -2990,21 +3165,42 @@
u16 pad3;
};
+struct ixgbe_hic_phy_token_req {
+ struct ixgbe_hic_hdr hdr;
+ u8 port_number;
+ u8 command_type;
+ u16 pad;
+};
+
struct ixgbe_hic_internal_phy_req {
struct ixgbe_hic_hdr hdr;
u8 port_number;
u8 command_type;
- u16 address;
+ __be16 address;
u16 rsv1;
- u32 write_data;
+ __be32 write_data;
u16 pad;
};
struct ixgbe_hic_internal_phy_resp {
struct ixgbe_hic_hdr hdr;
- u32 read_data;
+ __be32 read_data;
};
+struct ixgbe_hic_phy_activity_req {
+ struct ixgbe_hic_hdr hdr;
+ u8 port_number;
+ u8 pad;
+ __le16 activity_id;
+ __be32 data[FW_PHY_ACT_DATA_COUNT];
+};
+
+struct ixgbe_hic_phy_activity_resp {
+ struct ixgbe_hic_hdr hdr;
+ __be32 data[FW_PHY_ACT_DATA_COUNT];
+};
+
+#pragma pack(pop)
/* Transmit Descriptor - Legacy */
struct ixgbe_legacy_tx_desc {
@@ -3130,6 +3326,7 @@
#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
+#define IXGBE_ADVTXD_TUCMD_L4T_RSV 0x00001800 /* RSV L4 Packet TYPE */
#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /* req Markers and CRC */
#define IXGBE_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
#define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
@@ -3152,12 +3349,14 @@
#define IXGBE_ADVTXD_TUNNEL_TYPE_SHIFT 16 /* Adv Tx Desc Tunnel Type shift */
#define IXGBE_ADVTXD_OUTERIPCS_SHIFT 17 /* Adv Tx Desc OUTERIPCS Shift */
#define IXGBE_ADVTXD_TUNNEL_TYPE_NVGRE 1 /* Adv Tx Desc Tunnel Type NVGRE */
-
+/* Adv Tx Desc OUTERIPCS Shift for X550EM_a */
+#define IXGBE_ADVTXD_OUTERIPCS_SHIFT_X550EM_a 26
/* Autonegotiation advertised speeds */
typedef u32 ixgbe_autoneg_advertised;
/* Link speed */
typedef u32 ixgbe_link_speed;
#define IXGBE_LINK_SPEED_UNKNOWN 0
+#define IXGBE_LINK_SPEED_10_FULL 0x0002
#define IXGBE_LINK_SPEED_100_FULL 0x0008
#define IXGBE_LINK_SPEED_1GB_FULL 0x0020
#define IXGBE_LINK_SPEED_2_5GB_FULL 0x0400
@@ -3170,23 +3369,25 @@
IXGBE_LINK_SPEED_10GB_FULL)
/* Physical layer type */
-typedef u32 ixgbe_physical_layer;
+typedef u64 ixgbe_physical_layer;
#define IXGBE_PHYSICAL_LAYER_UNKNOWN 0
-#define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001
-#define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002
-#define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x0004
-#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008
-#define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010
-#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020
-#define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x0040
-#define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x0080
-#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100
-#define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200
-#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400
-#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800
-#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000
-#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000
-#define IXGBE_PHYSICAL_LAYER_1000BASE_SX 0x4000
+#define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x00001
+#define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x00002
+#define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x00004
+#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x00008
+#define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x00010
+#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x00020
+#define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x00040
+#define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x00080
+#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x00100
+#define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x00200
+#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x00400
+#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x00800
+#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x01000
+#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x02000
+#define IXGBE_PHYSICAL_LAYER_1000BASE_SX 0x04000
+#define IXGBE_PHYSICAL_LAYER_10BASE_T 0x08000
+#define IXGBE_PHYSICAL_LAYER_2500BASE_KX 0x10000
/* Flow Control Data Sheet defined values
* Calculation and defines taken from 802.1bb Annex O
@@ -3391,8 +3592,10 @@
ixgbe_mac_X540_vf,
ixgbe_mac_X550,
ixgbe_mac_X550EM_x,
+ ixgbe_mac_X550EM_a,
ixgbe_mac_X550_vf,
ixgbe_mac_X550EM_x_vf,
+ ixgbe_mac_X550EM_a_vf,
ixgbe_num_macs
};
@@ -3403,6 +3606,7 @@
ixgbe_phy_aq,
ixgbe_phy_x550em_kr,
ixgbe_phy_x550em_kx4,
+ ixgbe_phy_x550em_xfi,
ixgbe_phy_x550em_ext_t,
ixgbe_phy_cu_unknown,
ixgbe_phy_qt,
@@ -3421,6 +3625,8 @@
ixgbe_phy_qsfp_intel,
ixgbe_phy_qsfp_unknown,
ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/
+ ixgbe_phy_sgmii,
+ ixgbe_phy_fw,
ixgbe_phy_generic
};
@@ -3536,7 +3742,8 @@
enum ixgbe_bus_type type;
u16 func;
- u16 lan_id;
+ u8 lan_id;
+ u16 instance_id;
};
/* Flow control parameters */
@@ -3658,7 +3865,7 @@
s32 (*clear_hw_cntrs)(struct ixgbe_hw *);
void (*enable_relaxed_ordering)(struct ixgbe_hw *);
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
- u32 (*get_supported_physical_layer)(struct ixgbe_hw *);
+ u64 (*get_supported_physical_layer)(struct ixgbe_hw *);
s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*set_san_mac_addr)(struct ixgbe_hw *, u8 *);
@@ -3676,6 +3883,7 @@
s32 (*enable_sec_rx_path)(struct ixgbe_hw *);
s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u32);
void (*release_swfw_sync)(struct ixgbe_hw *, u32);
+ void (*init_swfw_sync)(struct ixgbe_hw *);
s32 (*prot_autoc_read)(struct ixgbe_hw *, bool *, u32 *);
s32 (*prot_autoc_write)(struct ixgbe_hw *, u32, bool);
@@ -3698,6 +3906,7 @@
s32 (*led_off)(struct ixgbe_hw *, u32);
s32 (*blink_led_start)(struct ixgbe_hw *, u32);
s32 (*blink_led_stop)(struct ixgbe_hw *, u32);
+ s32 (*init_led_link_act)(struct ixgbe_hw *);
/* RAR, Multicast, VLAN */
s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32);
@@ -3715,8 +3924,9 @@
s32 (*enable_mc)(struct ixgbe_hw *);
s32 (*disable_mc)(struct ixgbe_hw *);
s32 (*clear_vfta)(struct ixgbe_hw *);
- s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
- s32 (*set_vlvf)(struct ixgbe_hw *, u32, u32, bool, bool *);
+ s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool, bool);
+ s32 (*set_vlvf)(struct ixgbe_hw *, u32, u32, bool, u32 *, u32,
+ bool);
s32 (*init_uta_tables)(struct ixgbe_hw *);
void (*set_mac_anti_spoofing)(struct ixgbe_hw *, bool, int);
void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int);
@@ -3724,9 +3934,15 @@
/* Flow Control */
s32 (*fc_enable)(struct ixgbe_hw *);
s32 (*setup_fc)(struct ixgbe_hw *);
+ void (*fc_autoneg)(struct ixgbe_hw *);
/* Manageability interface */
- s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
+ s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8, u16,
+ const char *);
+ s32 (*bypass_rw) (struct ixgbe_hw *hw, u32 cmd, u32 *status);
+ bool (*bypass_valid_rd) (u32 in_reg, u32 out_reg);
+ s32 (*bypass_set) (struct ixgbe_hw *hw, u32 cmd, u32 event, u32 action);
+ s32 (*bypass_rd_eep) (struct ixgbe_hw *hw, u32 addr, u8 *value);
void (*get_rtrup2tc)(struct ixgbe_hw *hw, u8 *map);
void (*disable_rx)(struct ixgbe_hw *hw);
void (*enable_rx)(struct ixgbe_hw *hw);
@@ -3765,22 +3981,30 @@
s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
void (*i2c_bus_clear)(struct ixgbe_hw *);
- s32 (*read_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val);
- s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
s32 (*check_overtemp)(struct ixgbe_hw *);
s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
s32 (*enter_lplu)(struct ixgbe_hw *);
s32 (*handle_lasi)(struct ixgbe_hw *hw);
- s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
- u16 *value);
- s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
- u16 value);
s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
u8 *value);
s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
u8 value);
};
+struct ixgbe_link_operations {
+ s32 (*read_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val);
+ s32 (*read_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 *val);
+ s32 (*write_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
+ s32 (*write_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+ u16 val);
+};
+
+struct ixgbe_link_info {
+ struct ixgbe_link_operations ops;
+ u8 addr;
+};
+
struct ixgbe_eeprom_info {
struct ixgbe_eeprom_operations ops;
enum ixgbe_eeprom_type type;
@@ -3824,6 +4048,7 @@
struct ixgbe_dmac_config dmac_config;
bool set_lben;
u32 max_link_up_time;
+ u8 led_link_act;
};
struct ixgbe_phy_info {
@@ -3839,6 +4064,8 @@
bool reset_disable;
ixgbe_autoneg_advertised autoneg_advertised;
ixgbe_link_speed speeds_supported;
+ ixgbe_link_speed eee_speeds_supported;
+ ixgbe_link_speed eee_speeds_advertised;
enum ixgbe_smart_speed smart_speed;
bool smart_speed_active;
bool multispeed_fiber;
@@ -3885,6 +4112,7 @@
struct ixgbe_addr_filter_info addr_ctrl;
struct ixgbe_fc_info fc;
struct ixgbe_phy_info phy;
+ struct ixgbe_link_info link;
struct ixgbe_eeprom_info eeprom;
struct ixgbe_bus_info bus;
struct ixgbe_mbx_info mbx;
@@ -3899,6 +4127,7 @@
bool force_full_reset;
bool allow_unsupported_sfp;
bool wol_enabled;
+ bool need_crosstalk_fix;
};
#define ixgbe_call_func(hw, func, params, error) \
@@ -3940,44 +4169,176 @@
#define IXGBE_ERR_INVALID_ARGUMENT -32
#define IXGBE_ERR_HOST_INTERFACE_COMMAND -33
#define IXGBE_ERR_OUT_OF_MEM -34
+#define IXGBE_BYPASS_FW_WRITE_FAILURE -35
#define IXGBE_ERR_FEATURE_NOT_SUPPORTED -36
#define IXGBE_ERR_EEPROM_PROTECTED_REGION -37
#define IXGBE_ERR_FDIR_CMD_INCOMPLETE -38
+#define IXGBE_ERR_FW_RESP_INVALID -39
+#define IXGBE_ERR_TOKEN_RETRY -40
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
+#define BYPASS_PAGE_CTL0 0x00000000
+#define BYPASS_PAGE_CTL1 0x40000000
+#define BYPASS_PAGE_CTL2 0x80000000
+#define BYPASS_PAGE_M 0xc0000000
+#define BYPASS_WE 0x20000000
+
+#define BYPASS_AUTO 0x0
+#define BYPASS_NOP 0x0
+#define BYPASS_NORM 0x1
+#define BYPASS_BYPASS 0x2
+#define BYPASS_ISOLATE 0x3
+
+#define BYPASS_EVENT_MAIN_ON 0x1
+#define BYPASS_EVENT_AUX_ON 0x2
+#define BYPASS_EVENT_MAIN_OFF 0x3
+#define BYPASS_EVENT_AUX_OFF 0x4
+#define BYPASS_EVENT_WDT_TO 0x5
+#define BYPASS_EVENT_USR 0x6
+
+#define BYPASS_MODE_OFF_M 0x00000003
+#define BYPASS_STATUS_OFF_M 0x0000000c
+#define BYPASS_AUX_ON_M 0x00000030
+#define BYPASS_MAIN_ON_M 0x000000c0
+#define BYPASS_MAIN_OFF_M 0x00000300
+#define BYPASS_AUX_OFF_M 0x00000c00
+#define BYPASS_WDTIMEOUT_M 0x00003000
+#define BYPASS_WDT_ENABLE_M 0x00004000
+#define BYPASS_WDT_VALUE_M 0x00070000
+
+#define BYPASS_MODE_OFF_SHIFT 0
+#define BYPASS_STATUS_OFF_SHIFT 2
+#define BYPASS_AUX_ON_SHIFT 4
+#define BYPASS_MAIN_ON_SHIFT 6
+#define BYPASS_MAIN_OFF_SHIFT 8
+#define BYPASS_AUX_OFF_SHIFT 10
+#define BYPASS_WDTIMEOUT_SHIFT 12
+#define BYPASS_WDT_ENABLE_SHIFT 14
+#define BYPASS_WDT_TIME_SHIFT 16
+
+#define BYPASS_WDT_1 0x0
+#define BYPASS_WDT_1_5 0x1
+#define BYPASS_WDT_2 0x2
+#define BYPASS_WDT_3 0x3
+#define BYPASS_WDT_4 0x4
+#define BYPASS_WDT_8 0x5
+#define BYPASS_WDT_16 0x6
+#define BYPASS_WDT_32 0x7
+#define BYPASS_WDT_OFF 0xffff
+
+#define BYPASS_CTL1_TIME_M 0x01ffffff
+#define BYPASS_CTL1_VALID_M 0x02000000
+#define BYPASS_CTL1_OFFTRST_M 0x04000000
+#define BYPASS_CTL1_WDT_PET_M 0x08000000
+
+#define BYPASS_CTL1_VALID 0x02000000
+#define BYPASS_CTL1_OFFTRST 0x04000000
+#define BYPASS_CTL1_WDT_PET 0x08000000
+
+#define BYPASS_CTL2_DATA_M 0x000000ff
+#define BYPASS_CTL2_OFFSET_M 0x0000ff00
+#define BYPASS_CTL2_RW_M 0x00010000
+#define BYPASS_CTL2_HEAD_M 0x0ff00000
+
+#define BYPASS_CTL2_OFFSET_SHIFT 8
+#define BYPASS_CTL2_HEAD_SHIFT 20
+
+#define BYPASS_CTL2_RW 0x00010000
+
+struct ixgbe_bypass_eeprom {
+ u32 logs;
+ u32 clear_off;
+ u8 actions;
+};
+
+#define BYPASS_MAX_LOGS 43
+#define BYPASS_LOG_SIZE 5
+#define BYPASS_LOG_LINE_SIZE 37
+
+#define BYPASS_EEPROM_VER_ADD 0x02
+
+#define BYPASS_LOG_TIME_M 0x01ffffff
+#define BYPASS_LOG_TIME_VALID_M 0x02000000
+#define BYPASS_LOG_HEAD_M 0x04000000
+#define BYPASS_LOG_CLEAR_M 0x08000000
+#define BYPASS_LOG_EVENT_M 0xf0000000
+#define BYPASS_LOG_ACTION_M 0x03
+
+#define BYPASS_LOG_EVENT_SHIFT 28
+#define BYPASS_LOG_CLEAR_SHIFT 24 /* bit offset */
+
#define IXGBE_FUSES0_GROUP(_i) (0x11158 + ((_i) * 4))
#define IXGBE_FUSES0_300MHZ (1 << 5)
-#define IXGBE_FUSES0_REV1 (1 << 6)
+#define IXGBE_FUSES0_REV_MASK (3 << 6)
#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010)
+#define IXGBE_KRM_LINK_S1(P) ((P) ? 0x8200 : 0x4200)
#define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C)
#define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C)
+#define IXGBE_KRM_AN_CNTL_4(P) ((P) ? 0x8238 : 0x4238)
+#define IXGBE_KRM_AN_CNTL_8(P) ((P) ? 0x8248 : 0x4248)
+#define IXGBE_KRM_PCS_KX_AN(P) ((P) ? 0x9918 : 0x5918)
+#define IXGBE_KRM_PCS_KX_AN_LP(P) ((P) ? 0x991C : 0x591C)
+#define IXGBE_KRM_SGMII_CTRL(P) ((P) ? 0x82A0 : 0x42A0)
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH(P) ((P) ? 0x836C : 0x436C)
#define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634)
#define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638)
#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00)
#define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P) ? 0x8E00 : 0x4E00)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20(P) ((P) ? 0x9054 : 0x5054)
#define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520)
#define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA ~(0x3 << 20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR (1u << 20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_LR (0x2 << 20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN (1u << 25)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN (1u << 26)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN (1u << 27)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10M ~(0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_100M (1u << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G (0x2 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G (0x3 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN (0x4 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_2_5G (0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK (0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART (1u << 31)
+
#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B (1 << 9)
#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS (1 << 11)
#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK (0x7 << 8)
#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G (2 << 8)
#define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G (4 << 8)
+#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN (1 << 12)
+#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN (1 << 13)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ (1 << 14)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC (1 << 15)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX (1 << 16)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR (1 << 18)
#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX (1 << 24)
#define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR (1 << 26)
+#define IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE (1 << 28)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE (1 << 29)
#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART (1 << 31)
#define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE (1 << 28)
#define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE (1 << 29)
+#define IXGBE_KRM_PCS_KX_AN_SYM_PAUSE (1 << 1)
+#define IXGBE_KRM_PCS_KX_AN_ASM_PAUSE (1 << 2)
+#define IXGBE_KRM_PCS_KX_AN_LP_SYM_PAUSE (1 << 2)
+#define IXGBE_KRM_PCS_KX_AN_LP_ASM_PAUSE (1 << 3)
+#define IXGBE_KRM_AN_CNTL_4_ECSR_AN37_OVER_73 (1 << 29)
+#define IXGBE_KRM_AN_CNTL_8_LINEAR (1 << 0)
+#define IXGBE_KRM_AN_CNTL_8_LIMITING (1 << 1)
+
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE (1 << 10)
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE (1 << 11)
+
+#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D (1 << 12)
+#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D (1 << 19)
#define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN (1 << 6)
#define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN (1 << 15)
@@ -4011,6 +4372,18 @@
#define IXGBE_SB_IOSF_TARGET_KR_PHY 0
#define IXGBE_NW_MNG_IF_SEL 0x00011178
-#define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24)
+#define IXGBE_NW_MNG_IF_SEL_MDIO_ACT (1u << 1)
+#define IXGBE_NW_MNG_IF_SEL_MDIO_IF_MODE (1u << 2)
+#define IXGBE_NW_MNG_IF_SEL_EN_SHARED_MDIO (1u << 13)
+#define IXGBE_NW_MNG_IF_SEL_PHY_SPEED_10M (1u << 17)
+#define IXGBE_NW_MNG_IF_SEL_PHY_SPEED_100M (1u << 18)
+#define IXGBE_NW_MNG_IF_SEL_PHY_SPEED_1G (1u << 19)
+#define IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G (1u << 20)
+#define IXGBE_NW_MNG_IF_SEL_PHY_SPEED_10G (1u << 21)
+#define IXGBE_NW_MNG_IF_SEL_SGMII_ENABLE (1u << 25)
+#define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24) /* X552 reg field only */
+#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT 3
+#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD \
+ (0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT)
#endif /* _IXGBE_TYPE_H_ */
Index: sys/dev/ixgbe/ixgbe_vf.h
===================================================================
--- sys/dev/ixgbe/ixgbe_vf.h
+++ sys/dev/ixgbe/ixgbe_vf.h
@@ -1,39 +1,39 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
/*$FreeBSD$*/
-#ifndef __IXGBE_VF_H__
-#define __IXGBE_VF_H__
+#ifndef _IXGBE_VF_H_
+#define _IXGBE_VF_H_
#define IXGBE_VF_IRQ_CLEAR_MASK 7
#define IXGBE_VF_MAX_TX_QUEUES 8
@@ -132,8 +132,10 @@
s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, ixgbe_mc_addr_itr,
bool clear);
-s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on);
-void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size);
+s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode);
+s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+ bool vlan_on, bool vlvf_bypass);
+s32 ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size);
int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api);
int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
unsigned int *default_tc);
Index: sys/dev/ixgbe/ixgbe_vf.c
===================================================================
--- sys/dev/ixgbe/ixgbe_vf.c
+++ sys/dev/ixgbe/ixgbe_vf.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -229,7 +229,9 @@
msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_NACK))
return IXGBE_ERR_INVALID_MAC_ADDR;
- memcpy(hw->mac.perm_addr, addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
+ if (msgbuf[0] == (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK))
+ memcpy(hw->mac.perm_addr, addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
+
hw->mac.mc_filter_type = msgbuf[IXGBE_VF_MC_TYPE_WORD];
return ret_val;
@@ -321,15 +323,16 @@
return vector;
}
-static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw,
- u32 *msg, u16 size)
+static s32 ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw, u32 *msg,
+ u32 *retmsg, u16 size)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- u32 retmsg[IXGBE_VFMAILBOX_SIZE];
s32 retval = mbx->ops.write_posted(hw, msg, size, 0);
- if (!retval)
- mbx->ops.read_posted(hw, retmsg, size, 0);
+ if (retval)
+ return retval;
+
+ return mbx->ops.read_posted(hw, retmsg, size, 0);
}
/**
@@ -343,7 +346,6 @@
s32 ixgbe_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr)
{
- struct ixgbe_mbx_info *mbx = &hw->mbx;
u32 msgbuf[3];
u8 *msg_addr = (u8 *)(&msgbuf[1]);
s32 ret_val;
@@ -352,17 +354,16 @@
memset(msgbuf, 0, 12);
msgbuf[0] = IXGBE_VF_SET_MAC_ADDR;
memcpy(msg_addr, addr, 6);
- ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0);
-
- if (!ret_val)
- ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
+ ret_val = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3);
msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
/* if nacked the address was rejected, use "perm_addr" */
if (!ret_val &&
- (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK)))
+ (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) {
ixgbe_get_mac_addr_vf(hw, hw->mac.addr);
+ return IXGBE_ERR_MBX;
+ }
return ret_val;
}
@@ -416,28 +417,65 @@
}
/**
+ * ixgbevf_update_xcast_mode - Update Multicast mode
+ * @hw: pointer to the HW structure
+ * @xcast_mode: new multicast mode
+ *
+ * Updates the Multicast Mode of VF.
+ **/
+s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode)
+{
+ u32 msgbuf[2];
+ s32 err;
+
+ switch (hw->api_version) {
+ case ixgbe_mbox_api_12:
+ /* New modes were introduced in 1.3 version */
+ if (xcast_mode > IXGBEVF_XCAST_MODE_ALLMULTI)
+ return IXGBE_ERR_FEATURE_NOT_SUPPORTED;
+ /* Fall through */
+ case ixgbe_mbox_api_13:
+ break;
+ default:
+ return IXGBE_ERR_FEATURE_NOT_SUPPORTED;
+ }
+
+ msgbuf[0] = IXGBE_VF_UPDATE_XCAST_MODE;
+ msgbuf[1] = xcast_mode;
+
+ err = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2);
+ if (err)
+ return err;
+
+ msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+ if (msgbuf[0] == (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_NACK))
+ return IXGBE_ERR_FEATURE_NOT_SUPPORTED;
+ return IXGBE_SUCCESS;
+}
+
+/**
* ixgbe_set_vfta_vf - Set/Unset vlan filter table address
* @hw: pointer to the HW structure
* @vlan: 12 bit VLAN ID
* @vind: unused by VF drivers
* @vlan_on: if TRUE then set bit, else clear bit
+ * @vlvf_bypass: boolean flag indicating updating default pool is okay
+ *
+ * Turn on/off specified VLAN in the VLAN filter table.
**/
-s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
+s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+ bool vlan_on, bool vlvf_bypass)
{
- struct ixgbe_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
s32 ret_val;
- UNREFERENCED_1PARAMETER(vind);
+ UNREFERENCED_2PARAMETER(vind, vlvf_bypass);
msgbuf[0] = IXGBE_VF_SET_VLAN;
msgbuf[1] = vlan;
/* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT;
- ret_val = mbx->ops.write_posted(hw, msgbuf, 2, 0);
- if (!ret_val)
- ret_val = mbx->ops.read_posted(hw, msgbuf, 1, 0);
-
+ ret_val = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2);
if (!ret_val && (msgbuf[0] & IXGBE_VT_MSGTYPE_ACK))
return IXGBE_SUCCESS;
@@ -484,8 +522,7 @@
s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr)
{
- struct ixgbe_mbx_info *mbx = &hw->mbx;
- u32 msgbuf[3];
+ u32 msgbuf[3], msgbuf_chk;
u8 *msg_addr = (u8 *)(&msgbuf[1]);
s32 ret_val;
@@ -498,18 +535,17 @@
*/
msgbuf[0] |= index << IXGBE_VT_MSGINFO_SHIFT;
msgbuf[0] |= IXGBE_VF_SET_MACVLAN;
+ msgbuf_chk = msgbuf[0];
if (addr)
memcpy(msg_addr, addr, 6);
- ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0);
- if (!ret_val)
- ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
+ ret_val = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3);
+ if (!ret_val) {
+ msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
- msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
-
- if (!ret_val)
- if (msgbuf[0] == (IXGBE_VF_SET_MACVLAN | IXGBE_VT_MSGTYPE_NACK))
- ret_val = IXGBE_ERR_OUT_OF_MEM;
+ if (msgbuf[0] == (msgbuf_chk | IXGBE_VT_MSGTYPE_NACK))
+ return IXGBE_ERR_OUT_OF_MEM;
+ }
return ret_val;
}
@@ -579,13 +615,29 @@
switch (links_reg & IXGBE_LINKS_SPEED_82599) {
case IXGBE_LINKS_SPEED_10G_82599:
*speed = IXGBE_LINK_SPEED_10GB_FULL;
+ if (hw->mac.type >= ixgbe_mac_X550) {
+ if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
+ *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
+ }
break;
case IXGBE_LINKS_SPEED_1G_82599:
*speed = IXGBE_LINK_SPEED_1GB_FULL;
break;
case IXGBE_LINKS_SPEED_100_82599:
*speed = IXGBE_LINK_SPEED_100_FULL;
+ if (hw->mac.type == ixgbe_mac_X550) {
+ if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
+ *speed = IXGBE_LINK_SPEED_5GB_FULL;
+ }
+ break;
+ case IXGBE_LINKS_SPEED_10_X550EM_A:
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
+ /* Since Reserved in older MAC's */
+ if (hw->mac.type >= ixgbe_mac_X550)
+ *speed = IXGBE_LINK_SPEED_10_FULL;
break;
+ default:
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
}
/* if the read failed it could just be a mailbox collision, best wait
@@ -622,13 +674,22 @@
* @hw: pointer to the HW structure
* @max_size: value to assign to max frame size
**/
-void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size)
+s32 ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size)
{
u32 msgbuf[2];
+ s32 retval;
msgbuf[0] = IXGBE_VF_SET_LPE;
msgbuf[1] = max_size;
- ixgbevf_write_msg_read_ack(hw, msgbuf, 2);
+
+ retval = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2);
+ if (retval)
+ return retval;
+ if ((msgbuf[0] & IXGBE_VF_SET_LPE) &&
+ (msgbuf[0] & IXGBE_VT_MSGTYPE_NACK))
+ return IXGBE_ERR_MBX;
+
+ return 0;
}
/**
@@ -645,11 +706,8 @@
msg[0] = IXGBE_VF_API_NEGOTIATE;
msg[1] = api;
msg[2] = 0;
- err = hw->mbx.ops.write_posted(hw, msg, 3, 0);
-
- if (!err)
- err = hw->mbx.ops.read_posted(hw, msg, 3, 0);
+ err = ixgbevf_write_msg_read_ack(hw, msg, msg, 3);
if (!err) {
msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
@@ -674,6 +732,8 @@
/* do nothing if API doesn't support ixgbevf_get_queues */
switch (hw->api_version) {
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
+ case ixgbe_mbox_api_13:
break;
default:
return 0;
@@ -682,11 +742,8 @@
/* Fetch queue configuration from the PF */
msg[0] = IXGBE_VF_GET_QUEUES;
msg[1] = msg[2] = msg[3] = msg[4] = 0;
- err = hw->mbx.ops.write_posted(hw, msg, 5, 0);
-
- if (!err)
- err = hw->mbx.ops.read_posted(hw, msg, 5, 0);
+ err = ixgbevf_write_msg_read_ack(hw, msg, msg, 5);
if (!err) {
msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
Index: sys/dev/ixgbe/ixgbe_x540.h
===================================================================
--- sys/dev/ixgbe/ixgbe_x540.h
+++ sys/dev/ixgbe/ixgbe_x540.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -44,7 +44,7 @@
bool link_up_wait_to_complete);
s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw);
-u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw);
+u64 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw);
s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw);
s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data);
@@ -60,6 +60,7 @@
s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask);
void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask);
+void ixgbe_init_swfw_sync_X540(struct ixgbe_hw *hw);
s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index);
Index: sys/dev/ixgbe/ixgbe_x540.c
===================================================================
--- sys/dev/ixgbe/ixgbe_x540.c
+++ sys/dev/ixgbe/ixgbe_x540.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -100,6 +100,7 @@
mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic;
mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X540;
mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X540;
+ mac->ops.init_swfw_sync = ixgbe_init_swfw_sync_X540;
mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic;
mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic;
@@ -122,6 +123,10 @@
mac->ops.setup_link = ixgbe_setup_mac_link_X540;
mac->ops.setup_rxpba = ixgbe_set_rxpba_generic;
mac->ops.check_link = ixgbe_check_mac_link_generic;
+ mac->ops.bypass_rw = ixgbe_bypass_rw_generic;
+ mac->ops.bypass_valid_rd = ixgbe_bypass_valid_rd_generic;
+ mac->ops.bypass_set = ixgbe_bypass_set_generic;
+ mac->ops.bypass_rd_eep = ixgbe_bypass_rd_eep_generic;
mac->mcft_size = IXGBE_X540_MC_TBL_SIZE;
@@ -269,12 +274,16 @@
/* Add the SAN MAC address to the RAR only if it's a valid address */
if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
- hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
- hw->mac.san_addr, 0, IXGBE_RAH_AV);
-
/* Save the SAN MAC RAR index */
hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
+ hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index,
+ hw->mac.san_addr, 0, IXGBE_RAH_AV);
+
+ /* clear VMDq pool/queue selection for this RAR */
+ hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index,
+ IXGBE_CLEAR_VMDQ_ALL);
+
/* Reserve the last RAR for the SAN MAC address */
hw->mac.num_rar_entries--;
}
@@ -317,9 +326,9 @@
*
* Determines physical layer capabilities of the current configuration.
**/
-u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
+u64 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
u16 ext_ability = 0;
DEBUGFUNC("ixgbe_get_supported_physical_layer_X540");
@@ -487,7 +496,6 @@
u16 length = 0;
u16 pointer = 0;
u16 word = 0;
- u16 checksum_last_word = IXGBE_EEPROM_CHECKSUM;
u16 ptr_start = IXGBE_PCIE_ANALOG_PTR;
/* Do not use hw->eeprom.ops.read because we do not want to take
@@ -497,14 +505,15 @@
DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540");
- /* Include 0x0-0x3F in the checksum */
- for (i = 0; i <= checksum_last_word; i++) {
+ /* Include 0x0 up to IXGBE_EEPROM_CHECKSUM; do not include the
+ * checksum itself
+ */
+ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
if (ixgbe_read_eerd_generic(hw, i, &word)) {
DEBUGOUT("EEPROM read failed\n");
return IXGBE_ERR_EEPROM;
}
- if (i != IXGBE_EEPROM_CHECKSUM)
- checksum += word;
+ checksum += word;
}
/* Include all data from pointers 0x3, 0x6-0xE. This excludes the
@@ -771,8 +780,10 @@
/* SW NVM semaphore bit is used for access to all
* SW_FW_SYNC bits (not just NVM)
*/
- if (ixgbe_get_swfw_sync_semaphore(hw))
+ if (ixgbe_get_swfw_sync_semaphore(hw)) {
+ DEBUGOUT("Failed to get NVM access and register semaphore, returning IXGBE_ERR_SWFW_SYNC\n");
return IXGBE_ERR_SWFW_SYNC;
+ }
swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
if (!(swfw_sync & (fwmask | swmask | hwmask))) {
@@ -780,7 +791,6 @@
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw),
swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
- msec_delay(5);
return IXGBE_SUCCESS;
}
/* Firmware currently using resource (fwmask), hardware
@@ -803,8 +813,10 @@
* of the requested resource(s) while ignoring the corresponding FW/HW
* bits in the SW_FW_SYNC register.
*/
- if (ixgbe_get_swfw_sync_semaphore(hw))
+ if (ixgbe_get_swfw_sync_semaphore(hw)) {
+ DEBUGOUT("Failed to get NVM sempahore and register semaphore while forcefully ignoring FW sempahore bit(s) and setting SW semaphore bit(s), returning IXGBE_ERR_SWFW_SYNC\n");
return IXGBE_ERR_SWFW_SYNC;
+ }
swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
if (swfw_sync & (fwmask | hwmask)) {
swfw_sync |= swmask;
@@ -857,7 +869,7 @@
IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
- msec_delay(5);
+ msec_delay(2);
}
/**
@@ -944,6 +956,25 @@
}
/**
+ * ixgbe_init_swfw_sync_X540 - Release hardware semaphore
+ * @hw: pointer to hardware structure
+ *
+ * This function reset hardware semaphore bits for a semaphore that may
+ * have be left locked due to a catastrophic failure.
+ **/
+void ixgbe_init_swfw_sync_X540(struct ixgbe_hw *hw)
+{
+ /* First try to grab the semaphore but we don't need to bother
+ * looking to see whether we got the lock or not since we do
+ * the same thing regardless of whether we got the lock or not.
+ * We got the lock - we release it.
+ * We timeout trying to get the lock - we force its release.
+ */
+ ixgbe_get_swfw_sync_semaphore(hw);
+ ixgbe_release_swfw_sync_semaphore(hw);
+}
+
+/**
* ixgbe_blink_led_start_X540 - Blink LED based on index.
* @hw: pointer to hardware structure
* @index: led number to blink
@@ -960,6 +991,9 @@
DEBUGFUNC("ixgbe_blink_led_start_X540");
+ if (index > 3)
+ return IXGBE_ERR_PARAM;
+
/*
* Link should be up in order for the blink bit in the LED control
* register to work. Force link and speed in the MAC if link is down.
@@ -994,6 +1028,9 @@
u32 macc_reg;
u32 ledctl_reg;
+ if (index > 3)
+ return IXGBE_ERR_PARAM;
+
DEBUGFUNC("ixgbe_blink_led_stop_X540");
/* Restore the LED to its default value. */
Index: sys/dev/ixgbe/ixgbe_x550.h
===================================================================
--- sys/dev/ixgbe/ixgbe_x550.h
+++ sys/dev/ixgbe/ixgbe_x550.h
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -56,12 +56,8 @@
u16 offset, u16 words, u16 *data);
s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset,
u16 *data);
-s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
- u16 *data);
s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
u16 data);
-s32 ixgbe_set_eee_X550(struct ixgbe_hw *hw, bool enable_eee);
-s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee);
void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable,
unsigned int pool);
void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
@@ -70,6 +66,14 @@
u32 device_type, u32 data);
s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u32 *data);
+s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
+ u8 build, u8 ver, u16 len, const char *str);
+s32 ixgbe_get_phy_token(struct ixgbe_hw *);
+s32 ixgbe_put_phy_token(struct ixgbe_hw *);
+s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u32 data);
+s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u32 *data);
void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw);
void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw);
void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap);
@@ -85,7 +89,7 @@
s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw);
s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw);
s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw);
-u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw);
+u64 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw);
void ixgbe_disable_rx_x550(struct ixgbe_hw *hw);
s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed);
s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw);
@@ -95,6 +99,19 @@
s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg_wait_to_complete);
+s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg_wait_to_complete);
+s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 *phy_data);
+s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 phy_data);
+s32 ixgbe_setup_fc_fiber_x550em_a(struct ixgbe_hw *hw);
+s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw);
+s32 ixgbe_setup_fc_sgmii_x550em_a(struct ixgbe_hw *hw);
+void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw);
+void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw);
+void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw);
s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw);
s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
Index: sys/dev/ixgbe/ixgbe_x550.c
===================================================================
--- sys/dev/ixgbe/ixgbe_x550.c
+++ sys/dev/ixgbe/ixgbe_x550.c
@@ -1,31 +1,31 @@
/******************************************************************************
- Copyright (c) 2001-2015, Intel Corporation
+ Copyright (c) 2001-2017, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -40,6 +40,9 @@
#include "ixgbe_phy.h"
static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed);
+static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
+static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
+static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw);
/**
* ixgbe_init_ops_X550 - Inits func ptrs and MAC type
@@ -60,7 +63,7 @@
mac->ops.dmac_config = ixgbe_dmac_config_X550;
mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550;
mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550;
- mac->ops.setup_eee = ixgbe_setup_eee_X550;
+ mac->ops.setup_eee = NULL;
mac->ops.set_source_address_pruning =
ixgbe_set_source_address_pruning_X550;
mac->ops.set_ethertype_anti_spoofing =
@@ -81,9 +84,16 @@
mac->ops.mdd_event = ixgbe_mdd_event_X550;
mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550;
mac->ops.disable_rx = ixgbe_disable_rx_x550;
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+ /* Manageability interface */
+ mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550;
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_X_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
hw->mac.ops.led_on = ixgbe_led_on_t_X550em;
hw->mac.ops.led_off = ixgbe_led_off_t_X550em;
+ break;
+ default:
+ break;
}
return ret_val;
}
@@ -98,7 +108,7 @@
**/
static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
{
- return ixgbe_read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, value);
+ return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
}
/**
@@ -111,7 +121,7 @@
**/
static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
{
- return ixgbe_write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, value);
+ return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
}
/**
@@ -323,6 +333,98 @@
}
/**
+ * ixgbe_read_phy_reg_mdi_22 - Read from a clause 22 PHY register without lock
+ * @hw: pointer to hardware structure
+ * @reg_addr: 32 bit address of PHY register to read
+ * @dev_type: always unused
+ * @phy_data: Pointer to read data from PHY register
+ */
+static s32 ixgbe_read_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 dev_type, u16 *phy_data)
+{
+ u32 i, data, command;
+ UNREFERENCED_1PARAMETER(dev_type);
+
+ /* Setup and write the read command */
+ command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+ IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC |
+ IXGBE_MSCA_MDI_COMMAND;
+
+ IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
+
+ /* Check every 10 usec to see if the access completed.
+ * The MDI Command bit will clear when the operation is
+ * complete
+ */
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
+ usec_delay(10);
+
+ command = IXGBE_READ_REG(hw, IXGBE_MSCA);
+ if (!(command & IXGBE_MSCA_MDI_COMMAND))
+ break;
+ }
+
+ if (command & IXGBE_MSCA_MDI_COMMAND) {
+ ERROR_REPORT1(IXGBE_ERROR_POLLING,
+ "PHY read command did not complete.\n");
+ return IXGBE_ERR_PHY;
+ }
+
+ /* Read operation is complete. Get the data from MSRWD */
+ data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
+ data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
+ *phy_data = (u16)data;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_write_phy_reg_mdi_22 - Write to a clause 22 PHY register without lock
+ * @hw: pointer to hardware structure
+ * @reg_addr: 32 bit PHY register to write
+ * @dev_type: always unused
+ * @phy_data: Data to write to the PHY register
+ */
+static s32 ixgbe_write_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 dev_type, u16 phy_data)
+{
+ u32 i, command;
+ UNREFERENCED_1PARAMETER(dev_type);
+
+ /* Put the data in the MDI single read and write data register*/
+ IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
+
+ /* Setup and write the write command */
+ command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) |
+ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+ IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
+ IXGBE_MSCA_MDI_COMMAND;
+
+ IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
+
+ /* Check every 10 usec to see if the access completed.
+ * The MDI Command bit will clear when the operation is
+ * complete
+ */
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
+ usec_delay(10);
+
+ command = IXGBE_READ_REG(hw, IXGBE_MSCA);
+ if (!(command & IXGBE_MSCA_MDI_COMMAND))
+ break;
+ }
+
+ if (command & IXGBE_MSCA_MDI_COMMAND) {
+ ERROR_REPORT1(IXGBE_ERROR_POLLING,
+ "PHY write cmd didn't complete\n");
+ return IXGBE_ERR_PHY;
+ }
+
+ return IXGBE_SUCCESS;
+}
+
+/**
* ixgbe_identify_phy_x550em - Get PHY type based on device id
* @hw: pointer to hardware structure
*
@@ -330,30 +432,180 @@
*/
static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
{
+ hw->mac.ops.set_lan_id(hw);
+
+ ixgbe_read_mng_if_sel_x550em(hw);
+
switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_A_SFP:
+ return ixgbe_identify_module_generic(hw);
case IXGBE_DEV_ID_X550EM_X_SFP:
/* set up for CS4227 usage */
- hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
ixgbe_setup_mux_ctl(hw);
ixgbe_check_cs4227(hw);
+ /* Fallthrough */
+ case IXGBE_DEV_ID_X550EM_A_SFP_N:
return ixgbe_identify_module_generic(hw);
break;
case IXGBE_DEV_ID_X550EM_X_KX4:
hw->phy.type = ixgbe_phy_x550em_kx4;
break;
+ case IXGBE_DEV_ID_X550EM_X_XFI:
+ hw->phy.type = ixgbe_phy_x550em_xfi;
+ break;
case IXGBE_DEV_ID_X550EM_X_KR:
+ case IXGBE_DEV_ID_X550EM_A_KR:
+ case IXGBE_DEV_ID_X550EM_A_KR_L:
hw->phy.type = ixgbe_phy_x550em_kr;
break;
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
case IXGBE_DEV_ID_X550EM_X_1G_T:
case IXGBE_DEV_ID_X550EM_X_10G_T:
return ixgbe_identify_phy_generic(hw);
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+ hw->phy.type = ixgbe_phy_fw;
+ hw->phy.ops.read_reg = NULL;
+ hw->phy.ops.write_reg = NULL;
+ if (hw->bus.lan_id)
+ hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
+ else
+ hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
+ break;
default:
break;
}
return IXGBE_SUCCESS;
}
+/**
+ * ixgbe_fw_phy_activity - Perform an activity on a PHY
+ * @hw: pointer to hardware structure
+ * @activity: activity to perform
+ * @data: Pointer to 4 32-bit words of data
+ */
+s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,
+ u32 (*data)[FW_PHY_ACT_DATA_COUNT])
+{
+ union {
+ struct ixgbe_hic_phy_activity_req cmd;
+ struct ixgbe_hic_phy_activity_resp rsp;
+ } hic;
+ u16 retries = FW_PHY_ACT_RETRIES;
+ s32 rc;
+ u16 i;
+
+ do {
+ memset(&hic, 0, sizeof(hic));
+ hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD;
+ hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN;
+ hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
+ hic.cmd.port_number = hw->bus.lan_id;
+ hic.cmd.activity_id = IXGBE_CPU_TO_LE16(activity);
+ for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
+ hic.cmd.data[i] = IXGBE_CPU_TO_BE32((*data)[i]);
+
+ rc = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd,
+ sizeof(hic.cmd),
+ IXGBE_HI_COMMAND_TIMEOUT,
+ TRUE);
+ if (rc != IXGBE_SUCCESS)
+ return rc;
+ if (hic.rsp.hdr.cmd_or_resp.ret_status ==
+ FW_CEM_RESP_STATUS_SUCCESS) {
+ for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i)
+ (*data)[i] = IXGBE_BE32_TO_CPU(hic.rsp.data[i]);
+ return IXGBE_SUCCESS;
+ }
+ usec_delay(20);
+ --retries;
+ } while (retries > 0);
+
+ return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+}
+
+static const struct {
+ u16 fw_speed;
+ ixgbe_link_speed phy_speed;
+} ixgbe_fw_map[] = {
+ { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },
+ { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },
+ { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },
+ { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },
+ { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },
+ { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },
+};
+
+/**
+ * ixgbe_get_phy_id_fw - Get the phy ID via firmware command
+ * @hw: pointer to hardware structure
+ *
+ * Returns error code
+ */
+static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)
+{
+ u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
+ u16 phy_speeds;
+ u16 phy_id_lo;
+ s32 rc;
+ u16 i;
+
+ rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);
+ if (rc)
+ return rc;
+
+ hw->phy.speeds_supported = 0;
+ phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;
+ for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
+ if (phy_speeds & ixgbe_fw_map[i].fw_speed)
+ hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
+ }
+ if (!hw->phy.autoneg_advertised)
+ hw->phy.autoneg_advertised = hw->phy.speeds_supported;
+
+ hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
+ phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
+ hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
+ hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
+ if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
+ return IXGBE_ERR_PHY_ADDR_INVALID;
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_identify_phy_fw - Get PHY type based on firmware command
+ * @hw: pointer to hardware structure
+ *
+ * Returns error code
+ */
+static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)
+{
+ if (hw->bus.lan_id)
+ hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
+ else
+ hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
+
+ hw->phy.type = ixgbe_phy_fw;
+ hw->phy.ops.read_reg = NULL;
+ hw->phy.ops.write_reg = NULL;
+ return ixgbe_get_phy_id_fw(hw);
+}
+
+/**
+ * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY
+ * @hw: pointer to hardware structure
+ *
+ * Returns error code
+ */
+s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)
+{
+ u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
+
+ setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;
+ return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);
+}
+
static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 *phy_data)
{
@@ -369,6 +621,68 @@
}
/**
+ * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ **/
+static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 *val)
+{
+ return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
+}
+
+/**
+ * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ **/
+static s32
+ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
+ u16 reg, u16 *val)
+{
+ return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ **/
+static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
+ u8 addr, u16 reg, u16 val)
+{
+ return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ **/
+static s32
+ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
+ u8 addr, u16 reg, u16 val)
+{
+ return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
+}
+
+/**
* ixgbe_init_ops_X550EM - Inits func ptrs and MAC type
* @hw: pointer to hardware structure
*
@@ -393,6 +707,12 @@
* the values being set in the x540 function.
*/
+ /* Bypass not supported in x550EM */
+ mac->ops.bypass_rw = NULL;
+ mac->ops.bypass_valid_rd = NULL;
+ mac->ops.bypass_set = NULL;
+ mac->ops.bypass_rd_eep = NULL;
+
/* FCOE not supported in x550EM */
mac->ops.get_san_mac_addr = NULL;
mac->ops.set_san_mac_addr = NULL;
@@ -411,10 +731,6 @@
hw->bus.type = ixgbe_bus_type_internal;
mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
- if (hw->mac.type == ixgbe_mac_X550EM_x) {
- mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
- mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
- }
mac->ops.get_media_type = ixgbe_get_media_type_X550em;
mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
@@ -428,15 +744,20 @@
else
mac->ops.setup_fc = ixgbe_setup_fc_X550em;
- mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em;
- mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em;
-
- if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR)
- mac->ops.setup_eee = NULL;
-
/* PHY */
phy->ops.init = ixgbe_init_phy_ops_X550em;
- phy->ops.identify = ixgbe_identify_phy_x550em;
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+ mac->ops.setup_fc = NULL;
+ phy->ops.identify = ixgbe_identify_phy_fw;
+ phy->ops.set_phy_power = NULL;
+ phy->ops.get_firmware_version = NULL;
+ break;
+ default:
+ phy->ops.identify = ixgbe_identify_phy_x550em;
+ }
+
if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
phy->ops.set_phy_power = NULL;
@@ -455,6 +776,183 @@
}
/**
+ * ixgbe_setup_fw_link - Setup firmware-controlled PHYs
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)
+{
+ u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };
+ s32 rc;
+ u16 i;
+
+ if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
+ return 0;
+
+ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+ ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
+ "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
+ }
+
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_full:
+ setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<
+ FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
+ break;
+ case ixgbe_fc_rx_pause:
+ setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<
+ FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
+ break;
+ case ixgbe_fc_tx_pause:
+ setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<
+ FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < sizeof(ixgbe_fw_map) / sizeof(ixgbe_fw_map[0]); ++i) {
+ if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)
+ setup[0] |= ixgbe_fw_map[i].fw_speed;
+ }
+ setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;
+
+ if (hw->phy.eee_speeds_advertised)
+ setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;
+
+ rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
+ if (rc)
+ return rc;
+ if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
+ return IXGBE_ERR_OVERTEMP;
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_fc_autoneg_fw _ Set up flow control for FW-controlled PHYs
+ * @hw: pointer to hardware structure
+ *
+ * Called at init time to set up flow control.
+ */
+static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
+{
+ if (hw->fc.requested_mode == ixgbe_fc_default)
+ hw->fc.requested_mode = ixgbe_fc_full;
+
+ return ixgbe_setup_fw_link(hw);
+}
+
+/**
+ * ixgbe_setup_eee_fw - Enable/disable EEE support
+ * @hw: pointer to the HW structure
+ * @enable_eee: boolean flag to enable EEE
+ *
+ * Enable/disable EEE based on enable_eee flag.
+ * This function controls EEE for firmware-based PHY implementations.
+ */
+static s32 ixgbe_setup_eee_fw(struct ixgbe_hw *hw, bool enable_eee)
+{
+ if (!!hw->phy.eee_speeds_advertised == enable_eee)
+ return IXGBE_SUCCESS;
+ if (enable_eee)
+ hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
+ else
+ hw->phy.eee_speeds_advertised = 0;
+ return hw->phy.ops.setup_link(hw);
+}
+
+/**
+* ixgbe_init_ops_X550EM_a - Inits func ptrs and MAC type
+* @hw: pointer to hardware structure
+*
+* Initialize the function pointers and for MAC type X550EM_a.
+* Does not touch the hardware.
+**/
+s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ s32 ret_val;
+
+ DEBUGFUNC("ixgbe_init_ops_X550EM_a");
+
+ /* Start with generic X550EM init */
+ ret_val = ixgbe_init_ops_X550EM(hw);
+
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
+ hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) {
+ mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
+ mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
+ } else {
+ mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a;
+ mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a;
+ }
+ mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a;
+ mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a;
+
+ switch (mac->ops.get_media_type(hw)) {
+ case ixgbe_media_type_fiber:
+ mac->ops.setup_fc = NULL;
+ mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
+ break;
+ case ixgbe_media_type_backplane:
+ mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
+ mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
+ break;
+ default:
+ break;
+ }
+
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+ mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
+ mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
+ mac->ops.setup_eee = ixgbe_setup_eee_fw;
+ hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
+ IXGBE_LINK_SPEED_1GB_FULL;
+ hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
+ break;
+ default:
+ break;
+ }
+
+ return ret_val;
+}
+
+/**
+* ixgbe_init_ops_X550EM_x - Inits func ptrs and MAC type
+* @hw: pointer to hardware structure
+*
+* Initialize the function pointers and for MAC type X550EM_x.
+* Does not touch the hardware.
+**/
+s32 ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_link_info *link = &hw->link;
+ s32 ret_val;
+
+ DEBUGFUNC("ixgbe_init_ops_X550EM_x");
+
+ /* Start with generic X550EM init */
+ ret_val = ixgbe_init_ops_X550EM(hw);
+
+ mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
+ mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
+ mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em;
+ mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em;
+ link->ops.read_link = ixgbe_read_i2c_combined_generic;
+ link->ops.read_link_unlocked = ixgbe_read_i2c_combined_generic_unlocked;
+ link->ops.write_link = ixgbe_write_i2c_combined_generic;
+ link->ops.write_link_unlocked =
+ ixgbe_write_i2c_combined_generic_unlocked;
+ link->addr = IXGBE_CS4227;
+
+
+ return ret_val;
+}
+
+/**
* ixgbe_dmac_config_X550
* @hw: pointer to hardware structure
*
@@ -517,6 +1015,7 @@
/* Configure DMA coalescing enabled */
switch (hw->mac.dmac_config.link_speed) {
+ case IXGBE_LINK_SPEED_10_FULL:
case IXGBE_LINK_SPEED_100_FULL:
pb_headroom = IXGBE_DMACRXT_100M;
break;
@@ -617,121 +1116,22 @@
}
/**
- * ixgbe_setup_eee_X550 - Enable/disable EEE support
- * @hw: pointer to the HW structure
- * @enable_eee: boolean flag to enable EEE
- *
- * Enable/disable EEE based on enable_eee flag.
- * Auto-negotiation must be started after BASE-T EEE bits in PHY register 7.3C
- * are modified.
- *
+ * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning
+ * @hw: pointer to hardware structure
+ * @enable: enable or disable source address pruning
+ * @pool: Rx pool to set source address pruning for
**/
-s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
+void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable,
+ unsigned int pool)
{
- u32 eeer;
- u16 autoneg_eee_reg;
- u32 link_reg;
- s32 status;
- u32 fuse;
-
- DEBUGFUNC("ixgbe_setup_eee_X550");
-
- eeer = IXGBE_READ_REG(hw, IXGBE_EEER);
- /* Enable or disable EEE per flag */
- if (enable_eee) {
- eeer |= (IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
-
- if (hw->mac.type == ixgbe_mac_X550) {
- /* Advertise EEE capability */
- hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg);
-
- autoneg_eee_reg |= (IXGBE_AUTO_NEG_10GBASE_EEE_ADVT |
- IXGBE_AUTO_NEG_1000BASE_EEE_ADVT |
- IXGBE_AUTO_NEG_100BASE_EEE_ADVT);
-
- hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_eee_reg);
- } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
- /* Not supported on first revision. */
- fuse = IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0));
- if (!(fuse & IXGBE_FUSES0_REV1))
- return IXGBE_SUCCESS;
-
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg);
- if (status != IXGBE_SUCCESS)
- return status;
+ u64 pfflp;
- link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR |
- IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX;
+ /* max rx pool is 63 */
+ if (pool > 63)
+ return;
- /* Don't advertise FEC capability when EEE enabled. */
- link_reg &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC;
-
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
- if (status != IXGBE_SUCCESS)
- return status;
- }
- } else {
- eeer &= ~(IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
-
- if (hw->mac.type == ixgbe_mac_X550) {
- /* Disable advertised EEE capability */
- hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg);
-
- autoneg_eee_reg &= ~(IXGBE_AUTO_NEG_10GBASE_EEE_ADVT |
- IXGBE_AUTO_NEG_1000BASE_EEE_ADVT |
- IXGBE_AUTO_NEG_100BASE_EEE_ADVT);
-
- hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_eee_reg);
- } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg);
- if (status != IXGBE_SUCCESS)
- return status;
-
- link_reg &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR |
- IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX);
-
- /* Advertise FEC capability when EEE is disabled. */
- link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC;
-
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
- if (status != IXGBE_SUCCESS)
- return status;
- }
- }
- IXGBE_WRITE_REG(hw, IXGBE_EEER, eeer);
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning
- * @hw: pointer to hardware structure
- * @enable: enable or disable source address pruning
- * @pool: Rx pool to set source address pruning for
- **/
-void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable,
- unsigned int pool)
-{
- u64 pfflp;
-
- /* max rx pool is 63 */
- if (pool > 63)
- return;
-
- pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
- pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
+ pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL);
+ pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32;
if (enable)
pfflp |= (1ULL << pool);
@@ -895,6 +1295,140 @@
}
/**
+ * ixgbe_get_phy_token - Get the token for shared phy access
+ * @hw: Pointer to hardware structure
+ */
+
+s32 ixgbe_get_phy_token(struct ixgbe_hw *hw)
+{
+ struct ixgbe_hic_phy_token_req token_cmd;
+ s32 status;
+
+ token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
+ token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
+ token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
+ token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
+ token_cmd.port_number = hw->bus.lan_id;
+ token_cmd.command_type = FW_PHY_TOKEN_REQ;
+ token_cmd.pad = 0;
+ status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
+ sizeof(token_cmd),
+ IXGBE_HI_COMMAND_TIMEOUT,
+ TRUE);
+ if (status) {
+ DEBUGOUT1("Issuing host interface command failed with Status = %d\n",
+ status);
+ return status;
+ }
+ if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
+ return IXGBE_SUCCESS;
+ if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) {
+ DEBUGOUT1("Host interface command returned 0x%08x , returning IXGBE_ERR_FW_RESP_INVALID\n",
+ token_cmd.hdr.cmd_or_resp.ret_status);
+ return IXGBE_ERR_FW_RESP_INVALID;
+ }
+
+ DEBUGOUT("Returning IXGBE_ERR_TOKEN_RETRY\n");
+ return IXGBE_ERR_TOKEN_RETRY;
+}
+
+/**
+ * ixgbe_put_phy_token - Put the token for shared phy access
+ * @hw: Pointer to hardware structure
+ */
+
+s32 ixgbe_put_phy_token(struct ixgbe_hw *hw)
+{
+ struct ixgbe_hic_phy_token_req token_cmd;
+ s32 status;
+
+ token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD;
+ token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN;
+ token_cmd.hdr.cmd_or_resp.cmd_resv = 0;
+ token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
+ token_cmd.port_number = hw->bus.lan_id;
+ token_cmd.command_type = FW_PHY_TOKEN_REL;
+ token_cmd.pad = 0;
+ status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd,
+ sizeof(token_cmd),
+ IXGBE_HI_COMMAND_TIMEOUT,
+ TRUE);
+ if (status)
+ return status;
+ if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
+ return IXGBE_SUCCESS;
+
+ DEBUGOUT("Put PHY Token host interface command failed");
+ return IXGBE_ERR_FW_RESP_INVALID;
+}
+
+/**
+ * ixgbe_write_iosf_sb_reg_x550a - Writes a value to specified register
+ * of the IOSF device
+ * @hw: pointer to hardware structure
+ * @reg_addr: 32 bit PHY register to write
+ * @device_type: 3 bit device type
+ * @data: Data to write to the register
+ **/
+s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u32 data)
+{
+ struct ixgbe_hic_internal_phy_req write_cmd;
+ s32 status;
+ UNREFERENCED_1PARAMETER(device_type);
+
+ memset(&write_cmd, 0, sizeof(write_cmd));
+ write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
+ write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
+ write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
+ write_cmd.port_number = hw->bus.lan_id;
+ write_cmd.command_type = FW_INT_PHY_REQ_WRITE;
+ write_cmd.address = IXGBE_CPU_TO_BE16(reg_addr);
+ write_cmd.write_data = IXGBE_CPU_TO_BE32(data);
+
+ status = ixgbe_host_interface_command(hw, (u32 *)&write_cmd,
+ sizeof(write_cmd),
+ IXGBE_HI_COMMAND_TIMEOUT, FALSE);
+
+ return status;
+}
+
+/**
+ * ixgbe_read_iosf_sb_reg_x550a - Reads specified register of the IOSF device
+ * @hw: pointer to hardware structure
+ * @reg_addr: 32 bit PHY register to write
+ * @device_type: 3 bit device type
+ * @data: Pointer to read data from the register
+ **/
+s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u32 *data)
+{
+ union {
+ struct ixgbe_hic_internal_phy_req cmd;
+ struct ixgbe_hic_internal_phy_resp rsp;
+ } hic;
+ s32 status;
+ UNREFERENCED_1PARAMETER(device_type);
+
+ memset(&hic, 0, sizeof(hic));
+ hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD;
+ hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN;
+ hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
+ hic.cmd.port_number = hw->bus.lan_id;
+ hic.cmd.command_type = FW_INT_PHY_REQ_READ;
+ hic.cmd.address = IXGBE_CPU_TO_BE16(reg_addr);
+
+ status = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd,
+ sizeof(hic.cmd),
+ IXGBE_HI_COMMAND_TIMEOUT, TRUE);
+
+ /* Extract the register value from the response. */
+ *data = IXGBE_BE32_TO_CPU(hic.rsp.read_data);
+
+ return status;
+}
+
+/**
* ixgbe_disable_mdd_X550
* @hw: pointer to hardware structure
*
@@ -1053,13 +1587,30 @@
switch (hw->device_id) {
case IXGBE_DEV_ID_X550EM_X_KR:
case IXGBE_DEV_ID_X550EM_X_KX4:
+ case IXGBE_DEV_ID_X550EM_X_XFI:
+ case IXGBE_DEV_ID_X550EM_A_KR:
+ case IXGBE_DEV_ID_X550EM_A_KR_L:
media_type = ixgbe_media_type_backplane;
break;
case IXGBE_DEV_ID_X550EM_X_SFP:
+ case IXGBE_DEV_ID_X550EM_A_SFP:
+ case IXGBE_DEV_ID_X550EM_A_SFP_N:
+ case IXGBE_DEV_ID_X550EM_A_QSFP:
+ case IXGBE_DEV_ID_X550EM_A_QSFP_N:
media_type = ixgbe_media_type_fiber;
break;
case IXGBE_DEV_ID_X550EM_X_1G_T:
case IXGBE_DEV_ID_X550EM_X_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
+ media_type = ixgbe_media_type_copper;
+ break;
+ case IXGBE_DEV_ID_X550EM_A_SGMII:
+ case IXGBE_DEV_ID_X550EM_A_SGMII_L:
+ media_type = ixgbe_media_type_backplane;
+ hw->phy.type = ixgbe_phy_sgmii;
+ break;
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
media_type = ixgbe_media_type_copper;
break;
default:
@@ -1153,6 +1704,191 @@
}
/**
+* ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
+* internal PHY
+* @hw: pointer to hardware structure
+**/
+static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
+{
+ s32 status;
+ u32 link_ctrl;
+
+ /* Restart auto-negotiation. */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
+
+ if (status) {
+ DEBUGOUT("Auto-negotiation did not complete\n");
+ return status;
+ }
+
+ link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
+
+ if (hw->mac.type == ixgbe_mac_X550EM_a) {
+ u32 flx_mask_st20;
+
+ /* Indicate to FW that AN restart has been asserted */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
+
+ if (status) {
+ DEBUGOUT("Auto-negotiation did not complete\n");
+ return status;
+ }
+
+ flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
+ }
+
+ return status;
+}
+
+/**
+ * ixgbe_setup_sgmii - Set up link for sgmii
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+ bool autoneg_wait)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ u32 lval, sval, flx_val;
+ s32 rc;
+
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
+ if (rc)
+ return rc;
+
+ lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
+ lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
+ lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
+ lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
+ lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+ rc = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
+ if (rc)
+ return rc;
+
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
+ if (rc)
+ return rc;
+
+ sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
+ sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
+ rc = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
+ if (rc)
+ return rc;
+
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
+ if (rc)
+ return rc;
+
+ flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
+ flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+
+ rc = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
+ if (rc)
+ return rc;
+
+ rc = ixgbe_restart_an_internal_phy_x550em(hw);
+ if (rc)
+ return rc;
+
+ return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
+}
+
+/**
+ * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+ bool autoneg_wait)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ u32 lval, sval, flx_val;
+ s32 rc;
+
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
+ if (rc)
+ return rc;
+
+ lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
+ lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
+ lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
+ lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
+ lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+ rc = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
+ if (rc)
+ return rc;
+
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
+ if (rc)
+ return rc;
+
+ sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
+ sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
+ rc = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
+ if (rc)
+ return rc;
+
+ rc = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
+ if (rc)
+ return rc;
+
+ rc = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
+ if (rc)
+ return rc;
+
+ flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
+ flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+ flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+
+ rc = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
+ if (rc)
+ return rc;
+
+ rc = ixgbe_restart_an_internal_phy_x550em(hw);
+
+ return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
+}
+
+/**
* ixgbe_init_mac_link_ops_X550em - init mac link function pointers
* @hw: pointer to hardware structure
*/
@@ -1171,13 +1907,37 @@
mac->ops.enable_tx_laser = NULL;
mac->ops.flap_tx_laser = NULL;
mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
- mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em;
mac->ops.set_rate_select_speed =
ixgbe_set_soft_rate_select_speed;
+
+ if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) ||
+ (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP))
+ mac->ops.setup_mac_link =
+ ixgbe_setup_mac_link_sfp_x550a;
+ else
+ mac->ops.setup_mac_link =
+ ixgbe_setup_mac_link_sfp_x550em;
break;
case ixgbe_media_type_copper:
- mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
- mac->ops.check_link = ixgbe_check_link_t_X550em;
+ if (hw->mac.type == ixgbe_mac_X550EM_a) {
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
+ hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
+ mac->ops.setup_link = ixgbe_setup_sgmii_fw;
+ mac->ops.check_link =
+ ixgbe_check_mac_link_generic;
+ } else {
+ mac->ops.setup_link =
+ ixgbe_setup_mac_link_t_X550em;
+ }
+ } else {
+ mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
+ mac->ops.check_link = ixgbe_check_link_t_X550em;
+ }
+ break;
+ case ixgbe_media_type_backplane:
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
+ hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
+ mac->ops.setup_link = ixgbe_setup_sgmii;
break;
default:
break;
@@ -1196,6 +1956,13 @@
{
DEBUGFUNC("ixgbe_get_link_capabilities_X550em");
+
+ if (hw->phy.type == ixgbe_phy_fw) {
+ *autoneg = TRUE;
+ *speed = hw->phy.speeds_supported;
+ return 0;
+ }
+
/* SFP */
if (hw->phy.media_type == ixgbe_media_type_fiber) {
@@ -1218,8 +1985,29 @@
else
*speed = IXGBE_LINK_SPEED_10GB_FULL;
} else {
- *speed = IXGBE_LINK_SPEED_10GB_FULL |
- IXGBE_LINK_SPEED_1GB_FULL;
+ switch (hw->phy.type) {
+ case ixgbe_phy_sgmii:
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ case ixgbe_phy_x550em_kr:
+ if (hw->mac.type == ixgbe_mac_X550EM_a) {
+ /* check different backplane modes */
+ if (hw->phy.nw_mng_if_sel &
+ IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
+ *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
+ break;
+ } else if (hw->device_id ==
+ IXGBE_DEV_ID_X550EM_A_KR_L) {
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ }
+ }
+ /* fall through */
+ default:
+ *speed = IXGBE_LINK_SPEED_10GB_FULL |
+ IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ }
*autoneg = TRUE;
}
@@ -1335,19 +2123,32 @@
status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
/* Enable link status change alarm */
- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
- if (status != IXGBE_SUCCESS)
- return status;
+ /* Enable the LASI interrupts on X552 devices to receive notifications
+ * of the link configurations of the external PHY and correspondingly
+ * support the configuration of the internal iXFI link, since iXFI does
+ * not support auto-negotiation. This is not required for X553 devices
+ * having KR support, which performs auto-negotiations and which is used
+ * as the internal link to the external PHY. Hence adding a check here
+ * to avoid enabling LASI interrupts for X553 devices.
+ */
+ if (hw->mac.type != ixgbe_mac_X550EM_a) {
+ status = hw->phy.ops.read_reg(hw,
+ IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
- reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
+ if (status != IXGBE_SUCCESS)
+ return status;
- status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
+ reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
- if (status != IXGBE_SUCCESS)
- return status;
+ status = hw->phy.ops.write_reg(hw,
+ IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
+
+ if (status != IXGBE_SUCCESS)
+ return status;
+ }
/* Enables high temperature failure alarm */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
@@ -1357,7 +2158,8 @@
if (status != IXGBE_SUCCESS)
return status;
- reg |= IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN;
+ reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN |
+ IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
@@ -1414,9 +2216,9 @@
s32 status;
u32 reg_val;
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status)
return status;
@@ -1432,13 +2234,102 @@
if (speed & IXGBE_LINK_SPEED_1GB_FULL)
reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
- /* Restart auto-negotiation. */
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
- return status;
+ if (hw->mac.type == ixgbe_mac_X550EM_a) {
+ /* Set lane mode to KR auto negotiation */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+
+ if (status)
+ return status;
+
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ }
+
+ return ixgbe_restart_an_internal_phy_x550em(hw);
+}
+
+/**
+ * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)
+{
+ u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
+ s32 rc;
+
+ if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))
+ return IXGBE_SUCCESS;
+
+ rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);
+ if (rc)
+ return rc;
+ memset(store, 0, sizeof(store));
+
+ rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);
+ if (rc)
+ return rc;
+
+ return ixgbe_setup_fw_link(hw);
+}
+
+/**
+ * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
+{
+ u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
+ s32 rc;
+
+ rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
+ if (rc)
+ return rc;
+
+ if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
+ ixgbe_shutdown_fw_phy(hw);
+ return IXGBE_ERR_OVERTEMP;
+ }
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register
+ * @hw: pointer to hardware structure
+ *
+ * Read NW_MNG_IF_SEL register and save field values, and check for valid field
+ * values.
+ **/
+static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw)
+{
+ /* Save NW management interface connected on board. This is used
+ * to determine internal PHY mode.
+ */
+ hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
+
+ /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set
+ * PHY address. This register field was has only been used for X552.
+ */
+ if (hw->mac.type == ixgbe_mac_X550EM_a &&
+ hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) {
+ hw->phy.addr = (hw->phy.nw_mng_if_sel &
+ IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
+ IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
+ }
+
+ return IXGBE_SUCCESS;
}
/**
@@ -1452,31 +2343,54 @@
s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
{
struct ixgbe_phy_info *phy = &hw->phy;
- ixgbe_link_speed speed;
s32 ret_val;
DEBUGFUNC("ixgbe_init_phy_ops_X550em");
hw->mac.ops.set_lan_id(hw);
+ ixgbe_read_mng_if_sel_x550em(hw);
if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
ixgbe_setup_mux_ctl(hw);
-
- /* Save NW management interface connected on board. This is used
- * to determine internal PHY mode.
- */
- phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
- if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) {
- speed = IXGBE_LINK_SPEED_10GB_FULL |
- IXGBE_LINK_SPEED_1GB_FULL;
- }
phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em;
}
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+ phy->ops.read_reg_mdi = ixgbe_read_phy_reg_mdi_22;
+ phy->ops.write_reg_mdi = ixgbe_write_phy_reg_mdi_22;
+ hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a;
+ hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a;
+ phy->ops.check_overtemp = ixgbe_check_overtemp_fw;
+ if (hw->bus.lan_id)
+ hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
+ else
+ hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
+
+ break;
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_SFP:
+ hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a;
+ hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a;
+ if (hw->bus.lan_id)
+ hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
+ else
+ hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM;
+ break;
+ case IXGBE_DEV_ID_X550EM_X_SFP:
+ /* set up for CS4227 usage */
+ hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
+ break;
+ default:
+ break;
+ }
+
/* Identify the PHY or SFP module */
ret_val = phy->ops.identify(hw);
- if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED ||
+ ret_val == IXGBE_ERR_PHY_ADDR_INVALID)
return ret_val;
/* Setup function pointers based on detected hardware */
@@ -1496,32 +2410,35 @@
phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
break;
+ case ixgbe_phy_x550em_xfi:
+ /* link is managed by HW */
+ phy->ops.setup_link = NULL;
+ phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
+ phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
+ break;
case ixgbe_phy_x550em_ext_t:
- /* Save NW management interface connected on board. This is used
- * to determine internal PHY mode
- */
- phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
-
/* If internal link mode is XFI, then setup iXFI internal link,
* else setup KR now.
*/
- if (!(phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
- phy->ops.setup_internal_link =
+ phy->ops.setup_internal_link =
ixgbe_setup_internal_phy_t_x550em;
- } else {
- speed = IXGBE_LINK_SPEED_10GB_FULL |
- IXGBE_LINK_SPEED_1GB_FULL;
- ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
- }
- /* setup SW LPLU only for first revision */
- if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw,
- IXGBE_FUSES0_GROUP(0))))
+ /* setup SW LPLU only for first revision of X550EM_x */
+ if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
+ !(IXGBE_FUSES0_REV_MASK &
+ IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
phy->ops.reset = ixgbe_reset_phy_t_X550em;
break;
+ case ixgbe_phy_sgmii:
+ phy->ops.setup_link = NULL;
+ break;
+ case ixgbe_phy_fw:
+ phy->ops.setup_link = ixgbe_setup_fw_link;
+ phy->ops.reset = ixgbe_reset_phy_fw;
+ break;
default:
break;
}
@@ -1529,6 +2446,38 @@
}
/**
+ * ixgbe_set_mdio_speed - Set MDIO clock speed
+ * @hw: pointer to hardware structure
+ */
+static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)
+{
+ u32 hlreg0;
+
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_X_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_SGMII:
+ case IXGBE_DEV_ID_X550EM_A_SGMII_L:
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
+ case IXGBE_DEV_ID_X550EM_A_SFP:
+ case IXGBE_DEV_ID_X550EM_A_QSFP:
+ /* Config MDIO clock speed before the first MDIO PHY access */
+ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+ hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+ break;
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+ /* Select fast MDIO clock speed for these devices */
+ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+ hlreg0 |= IXGBE_HLREG0_MDCSPD;
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
* ixgbe_reset_hw_X550em - Perform hardware reset
* @hw: pointer to hardware structure
*
@@ -1542,37 +2491,41 @@
s32 status;
u32 ctrl = 0;
u32 i;
- u32 hlreg0;
bool link_up = FALSE;
DEBUGFUNC("ixgbe_reset_hw_X550em");
/* Call adapter stop to disable Tx/Rx and clear interrupts */
status = hw->mac.ops.stop_adapter(hw);
- if (status != IXGBE_SUCCESS)
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT1("Failed to stop adapter, STATUS = %d\n", status);
return status;
-
+ }
/* flush pending Tx transactions */
ixgbe_clear_tx_pending(hw);
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
- /* Config MDIO clock speed before the first MDIO PHY access */
- hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
- hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
- IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
- }
+ ixgbe_set_mdio_speed(hw);
/* PHY ops must be identified and initialized prior to reset */
status = hw->phy.ops.init(hw);
- if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ if (status)
+ DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n",
+ status);
+
+ if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ DEBUGOUT("Returning from reset HW due to PHY init failure\n");
return status;
+ }
/* start the external PHY */
if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
status = ixgbe_init_ext_t_x550em(hw);
- if (status)
+ if (status) {
+ DEBUGOUT1("Failed to start the external PHY, STATUS = %d\n",
+ status);
return status;
+ }
}
/* Setup SFP module if there is one present. */
@@ -1585,8 +2538,10 @@
return status;
/* Reset PHY */
- if (!hw->phy.reset_disable && hw->phy.ops.reset)
- hw->phy.ops.reset(hw);
+ if (!hw->phy.reset_disable && hw->phy.ops.reset) {
+ if (hw->phy.ops.reset(hw) == IXGBE_ERR_OVERTEMP)
+ return IXGBE_ERR_OVERTEMP;
+ }
mac_reset_top:
/* Issue global reset to the MAC. Needs to be SW reset if link is up.
@@ -1639,9 +2594,14 @@
hw->mac.num_rar_entries = 128;
hw->mac.ops.init_rx_addrs(hw);
+ ixgbe_set_mdio_speed(hw);
+
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
ixgbe_setup_mux_ctl(hw);
+ if (status != IXGBE_SUCCESS)
+ DEBUGOUT1("Reset HW failed, STATUS = %d\n", status);
+
return status;
}
@@ -1691,11 +2651,16 @@
/**
* ixgbe_setup_kr_x550em - Configure the KR PHY.
* @hw: pointer to hardware structure
- *
- * Configures the integrated KR PHY.
**/
s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
{
+ /* leave link alone for 2.5G */
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
+ return IXGBE_SUCCESS;
+
+ if (ixgbe_check_reset_blocked(hw))
+ return 0;
+
return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
}
@@ -1727,113 +2692,200 @@
if (ret_val != IXGBE_SUCCESS)
return ret_val;
- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
- /* Configure CS4227 LINE side to 10G SR. */
- reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB +
- (hw->bus.lan_id << 12);
- reg_val = IXGBE_CS4227_SPEED_10G;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
+ /* Configure internal PHY for KR/KX. */
+ ixgbe_setup_kr_speed_x550em(hw, speed);
- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
- (hw->bus.lan_id << 12);
+ /* Configure CS4227 LINE side to proper mode. */
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
+ (hw->bus.lan_id << 12);
+ if (setup_linear)
+ reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+ else
reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
-
- /* Configure CS4227 for HOST connection rate then type. */
- reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB +
- (hw->bus.lan_id << 12);
- reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ?
- IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
-
- reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB +
- (hw->bus.lan_id << 12);
- if (setup_linear)
- reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
- else
- reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
-
- /* Setup XFI internal link. */
- ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
- } else {
- /* Configure internal PHY for KR/KX. */
- ixgbe_setup_kr_speed_x550em(hw, speed);
-
- /* Configure CS4227 LINE side to proper mode. */
- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
- (hw->bus.lan_id << 12);
- if (setup_linear)
- reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
- else
- reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
- }
+ ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
+ reg_val);
return ret_val;
}
/**
- * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
+ * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
* @hw: pointer to hardware structure
* @speed: the link speed to force
*
- * Configures the integrated KR PHY to use iXFI mode. Used to connect an
- * internal and external PHY at a specific speed, without autonegotiation.
+ * Configures the integrated PHY for native SFI mode. Used to connect the
+ * internal PHY directly to an SFP cage, without autonegotiation.
**/
-static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
{
+ struct ixgbe_mac_info *mac = &hw->mac;
s32 status;
u32 reg_val;
- /* Disable AN and force speed to 10G Serial. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ /* Disable all AN and force speed to 10G Serial. */
+ status = mac->ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
return status;
- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+ reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
/* Select forced link speed for internal PHY. */
switch (*speed) {
case IXGBE_LINK_SPEED_10GB_FULL:
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
break;
case IXGBE_LINK_SPEED_1GB_FULL:
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+ reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
break;
default:
- /* Other link speeds are not supported by internal KR PHY. */
+ /* Other link speeds are not supported by internal PHY. */
return IXGBE_ERR_LINK_SETUP;
}
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
+ status = mac->ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+ /* Toggle port SW reset by AN reset. */
+ status = ixgbe_restart_an_internal_phy_x550em(hw);
+
+ return status;
+}
+
+/**
+ * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP
+ * @hw: pointer to hardware structure
+ *
+ * Configure the the integrated PHY for SFP support.
+ **/
+s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg_wait_to_complete)
+{
+ s32 ret_val;
+ u16 reg_phy_ext;
+ bool setup_linear = FALSE;
+ u32 reg_slice, reg_phy_int, slice_offset;
+
+ UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
+
+ /* Check if SFP module is supported and linear */
+ ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
+
+ /* If no SFP module present, then return success. Return success since
+ * SFP not present error is not excepted in the setup MAC link flow.
+ */
+ if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
+ return IXGBE_SUCCESS;
+
+ if (ret_val != IXGBE_SUCCESS)
+ return ret_val;
+
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) {
+ /* Configure internal PHY for native SFI based on module type */
+ ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
+
+ if (ret_val != IXGBE_SUCCESS)
+ return ret_val;
+
+ reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
+ if (!setup_linear)
+ reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
+
+ ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
+
+ if (ret_val != IXGBE_SUCCESS)
+ return ret_val;
+
+ /* Setup SFI internal link. */
+ ret_val = ixgbe_setup_sfi_x550a(hw, &speed);
+ } else {
+ /* Configure internal PHY for KR/KX. */
+ ixgbe_setup_kr_speed_x550em(hw, speed);
+
+ if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) {
+ /* Find Address */
+ DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n");
+ return IXGBE_ERR_PHY_ADDR_INVALID;
+ }
+
+ /* Get external PHY SKU id */
+ ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
+ IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
+
+ if (ret_val != IXGBE_SUCCESS)
+ return ret_val;
+
+ /* When configuring quad port CS4223, the MAC instance is part
+ * of the slice offset.
+ */
+ if (reg_phy_ext == IXGBE_CS4223_SKU_ID)
+ slice_offset = (hw->bus.lan_id +
+ (hw->bus.instance_id << 1)) << 12;
+ else
+ slice_offset = hw->bus.lan_id << 12;
+
+ /* Configure CS4227/CS4223 LINE side to proper mode. */
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
+
+ ret_val = hw->phy.ops.read_reg(hw, reg_slice,
+ IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
+
+ if (ret_val != IXGBE_SUCCESS)
+ return ret_val;
+
+ reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
+ (IXGBE_CS4227_EDC_MODE_SR << 1));
+
+ if (setup_linear)
+ reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+ else
+ reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+ ret_val = hw->phy.ops.write_reg(hw, reg_slice,
+ IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
+
+ /* Flush previous write with a read */
+ ret_val = hw->phy.ops.read_reg(hw, reg_slice,
+ IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
+ }
+ return ret_val;
+}
+
+/**
+ * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
+ * @hw: pointer to hardware structure
+ *
+ * iXfI configuration needed for ixgbe_mac_X550EM_x devices.
+ **/
+static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ s32 status;
+ u32 reg_val;
/* Disable training protocol FSM. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
+ status = mac->ops.read_iosf_sb_reg(hw,
IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
return status;
reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
+ status = mac->ops.write_iosf_sb_reg(hw,
IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
if (status != IXGBE_SUCCESS)
return status;
/* Disable Flex from training TXFFE. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
+ status = mac->ops.read_iosf_sb_reg(hw,
IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
@@ -1841,12 +2893,12 @@
reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
+ status = mac->ops.write_iosf_sb_reg(hw,
IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
if (status != IXGBE_SUCCESS)
return status;
- status = ixgbe_read_iosf_sb_reg_x550(hw,
+ status = mac->ops.read_iosf_sb_reg(hw,
IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
@@ -1854,14 +2906,14 @@
reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
+ status = mac->ops.write_iosf_sb_reg(hw,
IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
if (status != IXGBE_SUCCESS)
return status;
/* Enable override for coefficients. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
+ status = mac->ops.read_iosf_sb_reg(hw,
IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
@@ -1870,22 +2922,68 @@
reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
+ status = mac->ops.write_iosf_sb_reg(hw,
IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
+ return status;
+}
- /* Toggle port SW reset by AN reset. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
+/**
+ * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
+ * @hw: pointer to hardware structure
+ * @speed: the link speed to force
+ *
+ * Configures the integrated KR PHY to use iXFI mode. Used to connect an
+ * internal and external PHY at a specific speed, without autonegotiation.
+ **/
+static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ s32 status;
+ u32 reg_val;
+
+ /* iXFI is only supported with X552 */
+ if (mac->type != ixgbe_mac_X550EM_x)
+ return IXGBE_ERR_LINK_SETUP;
+
+ /* Disable AN and force speed to 10G Serial. */
+ status = mac->ops.read_iosf_sb_reg(hw,
IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
return status;
- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
+
+ reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
+ reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
+
+ /* Select forced link speed for internal PHY. */
+ switch (*speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+ break;
+ default:
+ /* Other link speeds are not supported by internal KR PHY. */
+ return IXGBE_ERR_LINK_SETUP;
+ }
+
+ status = mac->ops.write_iosf_sb_reg(hw,
IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ /* Additional configuration needed for x550em_x */
+ if (hw->mac.type == ixgbe_mac_X550EM_x) {
+ status = ixgbe_setup_ixfi_x550em_x(hw);
+ if (status != IXGBE_SUCCESS)
+ return status;
+ }
+
+ /* Toggle port SW reset by AN reset. */
+ status = ixgbe_restart_an_internal_phy_x550em(hw);
return status;
}
@@ -1944,43 +3042,51 @@
if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
return IXGBE_ERR_CONFIG;
- /* If link is not up, then there is no setup necessary so return */
- status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
- if (status != IXGBE_SUCCESS)
- return status;
+ if (hw->mac.type == ixgbe_mac_X550EM_x &&
+ !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
+ /* If link is down, there is no setup necessary so return */
+ status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
+ if (status != IXGBE_SUCCESS)
+ return status;
- if (!link_up)
- return IXGBE_SUCCESS;
+ if (!link_up)
+ return IXGBE_SUCCESS;
- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &speed);
- if (status != IXGBE_SUCCESS)
- return status;
+ status = hw->phy.ops.read_reg(hw,
+ IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &speed);
+ if (status != IXGBE_SUCCESS)
+ return status;
- /* If link is not still up, then no setup is necessary so return */
- status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
- if (status != IXGBE_SUCCESS)
- return status;
- if (!link_up)
- return IXGBE_SUCCESS;
+ /* If link is still down - no setup is required so return */
+ status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
+ if (status != IXGBE_SUCCESS)
+ return status;
+ if (!link_up)
+ return IXGBE_SUCCESS;
- /* clear everything but the speed and duplex bits */
- speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
+ /* clear everything but the speed and duplex bits */
+ speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
- switch (speed) {
- case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
- force_speed = IXGBE_LINK_SPEED_10GB_FULL;
- break;
- case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
- force_speed = IXGBE_LINK_SPEED_1GB_FULL;
- break;
- default:
- /* Internal PHY does not support anything else */
- return IXGBE_ERR_INVALID_LINK_SETTINGS;
- }
+ switch (speed) {
+ case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
+ force_speed = IXGBE_LINK_SPEED_10GB_FULL;
+ break;
+ case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
+ force_speed = IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ default:
+ /* Internal PHY does not support anything else */
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
+ }
- return ixgbe_setup_ixfi_x550em(hw, &force_speed);
+ return ixgbe_setup_ixfi_x550em(hw, &force_speed);
+ } else {
+ speed = IXGBE_LINK_SPEED_10GB_FULL |
+ IXGBE_LINK_SPEED_1GB_FULL;
+ return ixgbe_setup_kr_speed_x550em(hw, speed);
+ }
}
/**
@@ -1995,57 +3101,57 @@
u32 reg_val;
/* Disable AN and force speed to 10G Serial. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
return status;
reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
if (status != IXGBE_SUCCESS)
return status;
/* Set near-end loopback clocks. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
return status;
reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B;
reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
if (status != IXGBE_SUCCESS)
return status;
/* Set loopback enable. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
return status;
reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
if (status != IXGBE_SUCCESS)
return status;
/* Training bypass. */
- status = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (status != IXGBE_SUCCESS)
return status;
reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS;
- status = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
return status;
}
@@ -2059,59 +3165,35 @@
*
* Reads a 16 bit word from the EEPROM using the hostif.
**/
-s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
- u16 *data)
-{
- s32 status;
- struct ixgbe_hic_read_shadow_ram buffer;
-
- DEBUGFUNC("ixgbe_read_ee_hostif_data_X550");
- buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
- buffer.hdr.req.buf_lenh = 0;
- buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
- buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
-
- /* convert offset from words to bytes */
- buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
- /* one word */
- buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
-
- status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
- sizeof(buffer),
- IXGBE_HI_COMMAND_TIMEOUT, FALSE);
-
- if (status)
- return status;
-
- *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
- FW_NVM_DATA_OFFSET);
-
- return 0;
-}
-
-/**
- * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
- * @hw: pointer to hardware structure
- * @offset: offset of word in the EEPROM to read
- * @data: word read from the EEPROM
- *
- * Reads a 16 bit word from the EEPROM using the hostif.
- **/
-s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset,
- u16 *data)
+s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
{
- s32 status = IXGBE_SUCCESS;
+ const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
+ struct ixgbe_hic_read_shadow_ram buffer;
+ s32 status;
DEBUGFUNC("ixgbe_read_ee_hostif_X550");
+ buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
+ buffer.hdr.req.buf_lenh = 0;
+ buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
+ buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
- IXGBE_SUCCESS) {
- status = ixgbe_read_ee_hostif_data_X550(hw, offset, data);
- hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
- } else {
- status = IXGBE_ERR_SWFW_SYNC;
+ /* convert offset from words to bytes */
+ buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
+ /* one word */
+ buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
+
+ status = hw->mac.ops.acquire_swfw_sync(hw, mask);
+ if (status)
+ return status;
+
+ status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
+ IXGBE_HI_COMMAND_TIMEOUT);
+ if (!status) {
+ *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
+ FW_NVM_DATA_OFFSET);
}
+ hw->mac.ops.release_swfw_sync(hw, mask);
return status;
}
@@ -2127,6 +3209,7 @@
s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
u16 offset, u16 words, u16 *data)
{
+ const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM;
struct ixgbe_hic_read_shadow_ram buffer;
u32 current_word = 0;
u16 words_to_read;
@@ -2136,11 +3219,12 @@
DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550");
/* Take semaphore for the entire operation. */
- status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ status = hw->mac.ops.acquire_swfw_sync(hw, mask);
if (status) {
DEBUGOUT("EEPROM read buffer - semaphore failed\n");
return status;
}
+
while (words) {
if (words > FW_MAX_READ_BUFFER_SIZE / 2)
words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
@@ -2156,10 +3240,8 @@
buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2);
buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2);
- status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
- sizeof(buffer),
- IXGBE_HI_COMMAND_TIMEOUT,
- FALSE);
+ status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
+ IXGBE_HI_COMMAND_TIMEOUT);
if (status) {
DEBUGOUT("Host interface command failed\n");
@@ -2184,7 +3266,7 @@
}
out:
- hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, mask);
return status;
}
@@ -2577,9 +3659,9 @@
*
* Determines physical layer capabilities of the current configuration.
**/
-u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
+u64 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
u16 ext_ability = 0;
DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em");
@@ -2588,6 +3670,21 @@
switch (hw->phy.type) {
case ixgbe_phy_x550em_kr:
+ if (hw->mac.type == ixgbe_mac_X550EM_a) {
+ if (hw->phy.nw_mng_if_sel &
+ IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) {
+ physical_layer =
+ IXGBE_PHYSICAL_LAYER_2500BASE_KX;
+ break;
+ } else if (hw->device_id ==
+ IXGBE_DEV_ID_X550EM_A_KR_L) {
+ physical_layer =
+ IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+ break;
+ }
+ }
+ /* fall through */
+ case ixgbe_phy_x550em_xfi:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
IXGBE_PHYSICAL_LAYER_1000BASE_KX;
break;
@@ -2604,6 +3701,17 @@
if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
break;
+ case ixgbe_phy_fw:
+ if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_1GB_FULL)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+ if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_100_FULL)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+ if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_10_FULL)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T;
+ break;
+ case ixgbe_phy_sgmii:
+ physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+ break;
default:
break;
}
@@ -2695,7 +3803,9 @@
bool link_up;
/* SW LPLU not required on later HW revisions. */
- if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))
+ if ((hw->mac.type == ixgbe_mac_X550EM_x) &&
+ (IXGBE_FUSES0_REV_MASK &
+ IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))))
return IXGBE_SUCCESS;
/* If blocked by MNG FW, then don't restart AN */
@@ -2879,10 +3989,13 @@
goto out;
}
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
- ret_val = ixgbe_read_iosf_sb_reg_x550(hw,
- IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X550EM_X_KR:
+ case IXGBE_DEV_ID_X550EM_A_KR:
+ case IXGBE_DEV_ID_X550EM_A_KR_L:
+ ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
if (ret_val != IXGBE_SUCCESS)
goto out;
reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
@@ -2891,12 +4004,18 @@
reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
if (asm_dir)
reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
- ret_val = ixgbe_write_iosf_sb_reg_x550(hw,
- IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+ ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
/* This device does not fully support AN. */
hw->fc.disable_fc_autoneg = TRUE;
+ break;
+ case IXGBE_DEV_ID_X550EM_X_XFI:
+ hw->fc.disable_fc_autoneg = TRUE;
+ break;
+ default:
+ break;
}
out:
@@ -2904,6 +4023,238 @@
}
/**
+ * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
+ * @hw: pointer to hardware structure
+ *
+ * Enable flow control according to IEEE clause 37.
+ **/
+void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
+{
+ u32 link_s1, lp_an_page_low, an_cntl_1;
+ s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ ixgbe_link_speed speed;
+ bool link_up;
+
+ /* AN should have completed when the cable was plugged in.
+ * Look for reasons to bail out. Bail out if:
+ * - FC autoneg is disabled, or if
+ * - link is not up.
+ */
+ if (hw->fc.disable_fc_autoneg) {
+ ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
+ "Flow control autoneg is disabled");
+ goto out;
+ }
+
+ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
+ if (!link_up) {
+ ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
+ goto out;
+ }
+
+ /* Check at auto-negotiation has completed */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LINK_S1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
+
+ if (status != IXGBE_SUCCESS ||
+ (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
+ DEBUGOUT("Auto-Negotiation did not complete\n");
+ status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ goto out;
+ }
+
+ /* Read the 10g AN autoc and LP ability registers and resolve
+ * local flow control settings accordingly
+ */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
+
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT("Auto-Negotiation did not complete\n");
+ goto out;
+ }
+
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
+
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT("Auto-Negotiation did not complete\n");
+ goto out;
+ }
+
+ status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
+ IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
+ IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
+ IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
+ IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
+
+out:
+ if (status == IXGBE_SUCCESS) {
+ hw->fc.fc_was_autonegged = TRUE;
+ } else {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ }
+}
+
+/**
+ * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
+ * @hw: pointer to hardware structure
+ *
+ **/
+void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
+{
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+}
+
+/**
+ * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37
+ * @hw: pointer to hardware structure
+ *
+ * Enable flow control according to IEEE clause 37.
+ **/
+void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
+{
+ s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
+ ixgbe_link_speed speed;
+ bool link_up;
+
+ /* AN should have completed when the cable was plugged in.
+ * Look for reasons to bail out. Bail out if:
+ * - FC autoneg is disabled, or if
+ * - link is not up.
+ */
+ if (hw->fc.disable_fc_autoneg) {
+ ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
+ "Flow control autoneg is disabled");
+ goto out;
+ }
+
+ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
+ if (!link_up) {
+ ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
+ goto out;
+ }
+
+ /* Check if auto-negotiation has completed */
+ status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
+ if (status != IXGBE_SUCCESS ||
+ !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
+ DEBUGOUT("Auto-Negotiation did not complete\n");
+ status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ goto out;
+ }
+
+ /* Negotiate the flow control */
+ status = ixgbe_negotiate_fc(hw, info[0], info[0],
+ FW_PHY_ACT_GET_LINK_INFO_FC_RX,
+ FW_PHY_ACT_GET_LINK_INFO_FC_TX,
+ FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
+ FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);
+
+out:
+ if (status == IXGBE_SUCCESS) {
+ hw->fc.fc_was_autonegged = TRUE;
+ } else {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ }
+}
+
+/**
+ * ixgbe_setup_fc_backplane_x550em_a - Set up flow control
+ * @hw: pointer to hardware structure
+ *
+ * Called at init time to set up flow control.
+ **/
+s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
+{
+ s32 status = IXGBE_SUCCESS;
+ u32 an_cntl = 0;
+
+ DEBUGFUNC("ixgbe_setup_fc_backplane_x550em_a");
+
+ /* Validate the requested mode */
+ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+ ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
+ "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
+ }
+
+ if (hw->fc.requested_mode == ixgbe_fc_default)
+ hw->fc.requested_mode = ixgbe_fc_full;
+
+ /* Set up the 1G and 10G flow control advertisement registers so the
+ * HW will be able to do FC autoneg once the cable is plugged in. If
+ * we link at 10G, the 1G advertisement is harmless and vice versa.
+ */
+ status = hw->mac.ops.read_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
+
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT("Auto-Negotiation did not complete\n");
+ return status;
+ }
+
+ /* The possible values of fc.requested_mode are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but
+ * we do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * other: Invalid.
+ */
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_none:
+ /* Flow control completely disabled by software override. */
+ an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
+ IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /* Tx Flow control is enabled, and Rx Flow control is
+ * disabled by software override.
+ */
+ an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
+ an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
+ break;
+ case ixgbe_fc_rx_pause:
+ /* Rx Flow control is enabled and Tx Flow control is
+ * disabled by software override. Since there really
+ * isn't a way to advertise that we are capable of RX
+ * Pause ONLY, we will advertise that we support both
+ * symmetric and asymmetric Rx PAUSE, as such we fall
+ * through to the fc_full statement. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ case ixgbe_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by SW override. */
+ an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
+ IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
+ break;
+ default:
+ ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
+ "Flow control param set incorrectly\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ status = hw->mac.ops.write_iosf_sb_reg(hw,
+ IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+ IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
+
+ /* Restart auto-negotiation. */
+ status = ixgbe_restart_an_internal_phy_x550em(hw);
+
+ return status;
+}
+
+/**
* ixgbe_set_mux - Set mux for port 1 access with CS4227
* @hw: pointer to hardware structure
* @state: set mux if 1, clear if 0
@@ -2964,6 +4315,133 @@
}
/**
+ * ixgbe_acquire_swfw_sync_X550a - Acquire SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to acquire
+ *
+ * Acquires the SWFW semaphore and get the shared phy token as needed
+ */
+static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
+{
+ u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
+ int retries = FW_PHY_TOKEN_RETRIES;
+ s32 status = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_acquire_swfw_sync_X550a");
+
+ while (--retries) {
+ status = IXGBE_SUCCESS;
+ if (hmask)
+ status = ixgbe_acquire_swfw_sync_X540(hw, hmask);
+ if (status) {
+ DEBUGOUT1("Could not acquire SWFW semaphore, Status = %d\n",
+ status);
+ return status;
+ }
+ if (!(mask & IXGBE_GSSR_TOKEN_SM))
+ return IXGBE_SUCCESS;
+
+ status = ixgbe_get_phy_token(hw);
+ if (status == IXGBE_ERR_TOKEN_RETRY)
+ DEBUGOUT1("Could not acquire PHY token, Status = %d\n",
+ status);
+
+ if (status == IXGBE_SUCCESS)
+ return IXGBE_SUCCESS;
+
+ if (hmask)
+ ixgbe_release_swfw_sync_X540(hw, hmask);
+
+ if (status != IXGBE_ERR_TOKEN_RETRY) {
+ DEBUGOUT1("Unable to retry acquiring the PHY token, Status = %d\n",
+ status);
+ return status;
+ }
+ }
+
+ DEBUGOUT1("Semaphore acquisition retries failed!: PHY ID = 0x%08X\n",
+ hw->phy.id);
+ return status;
+}
+
+/**
+ * ixgbe_release_swfw_sync_X550a - Release SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to release
+ *
+ * Releases the SWFW semaphore and puts the shared phy token as needed
+ */
+static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask)
+{
+ u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM;
+
+ DEBUGFUNC("ixgbe_release_swfw_sync_X550a");
+
+ if (mask & IXGBE_GSSR_TOKEN_SM)
+ ixgbe_put_phy_token(hw);
+
+ if (hmask)
+ ixgbe_release_swfw_sync_X540(hw, hmask);
+}
+
+/**
+ * ixgbe_read_phy_reg_x550a - Reads specified PHY register
+ * @hw: pointer to hardware structure
+ * @reg_addr: 32 bit address of PHY register to read
+ * @phy_data: Pointer to read data from PHY register
+ *
+ * Reads a value from a specified PHY register using the SWFW lock and PHY
+ * Token. The PHY Token is needed since the MDIO is shared between to MAC
+ * instances.
+ **/
+s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 *phy_data)
+{
+ s32 status;
+ u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
+
+ DEBUGFUNC("ixgbe_read_phy_reg_x550a");
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, mask))
+ return IXGBE_ERR_SWFW_SYNC;
+
+ status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
+
+ hw->mac.ops.release_swfw_sync(hw, mask);
+
+ return status;
+}
+
+/**
+ * ixgbe_write_phy_reg_x550a - Writes specified PHY register
+ * @hw: pointer to hardware structure
+ * @reg_addr: 32 bit PHY register to write
+ * @device_type: 5 bit device type
+ * @phy_data: Data to write to the PHY register
+ *
+ * Writes a value to specified PHY register using the SWFW lock and PHY Token.
+ * The PHY Token is needed since the MDIO is shared between to MAC instances.
+ **/
+s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
+ u32 device_type, u16 phy_data)
+{
+ s32 status;
+ u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM;
+
+ DEBUGFUNC("ixgbe_write_phy_reg_x550a");
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, mask) == IXGBE_SUCCESS) {
+ status = hw->phy.ops.write_reg_mdi(hw, reg_addr, device_type,
+ phy_data);
+ hw->mac.ops.release_swfw_sync(hw, mask);
+ } else {
+ status = IXGBE_ERR_SWFW_SYNC;
+ }
+
+ return status;
+}
+
+/**
* ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
* @hw: pointer to hardware structure
*
@@ -3018,8 +4496,10 @@
else
force_speed = IXGBE_LINK_SPEED_1GB_FULL;
- /* If internal link mode is XFI, then setup XFI internal link. */
- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
+ /* If X552 and internal link mode is XFI, then setup XFI internal link.
+ */
+ if (hw->mac.type == ixgbe_mac_X550EM_x &&
+ !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
if (status != IXGBE_SUCCESS)
@@ -3042,7 +4522,7 @@
bool *link_up, bool link_up_wait_to_complete)
{
u32 status;
- u16 autoneg_status;
+ u16 i, autoneg_status = 0;
if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
return IXGBE_ERR_CONFIG;
@@ -3055,21 +4535,18 @@
return status;
/* MAC link is up, so check external PHY link.
- * Read this twice back to back to indicate current status.
+ * X557 PHY. Link status is latching low, and can only be used to detect
+ * link drop, and not the current status of the link without performing
+ * back-to-back reads.
*/
- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_status);
-
- if (status != IXGBE_SUCCESS)
- return status;
-
- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_status);
+ for (i = 0; i < 2; i++) {
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &autoneg_status);
- if (status != IXGBE_SUCCESS)
- return status;
+ if (status != IXGBE_SUCCESS)
+ return status;
+ }
/* If external PHY link is not up, then indicate link not up */
if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
@@ -3143,3 +4620,63 @@
return IXGBE_SUCCESS;
}
+/**
+ * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware
+ * @hw: pointer to the HW structure
+ * @maj: driver version major number
+ * @min: driver version minor number
+ * @build: driver version build number
+ * @sub: driver version sub build number
+ * @len: length of driver_ver string
+ * @driver_ver: driver string
+ *
+ * Sends driver version number to firmware through the manageability
+ * block. On success return IXGBE_SUCCESS
+ * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
+ * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
+ u8 build, u8 sub, u16 len, const char *driver_ver)
+{
+ struct ixgbe_hic_drv_info2 fw_cmd;
+ s32 ret_val = IXGBE_SUCCESS;
+ int i;
+
+ DEBUGFUNC("ixgbe_set_fw_drv_ver_x550");
+
+ if ((len == 0) || (driver_ver == NULL) ||
+ (len > sizeof(fw_cmd.driver_string)))
+ return IXGBE_ERR_INVALID_ARGUMENT;
+
+ fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
+ fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
+ fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+ fw_cmd.port_num = (u8)hw->bus.func;
+ fw_cmd.ver_maj = maj;
+ fw_cmd.ver_min = min;
+ fw_cmd.ver_build = build;
+ fw_cmd.ver_sub = sub;
+ fw_cmd.hdr.checksum = 0;
+ memcpy(fw_cmd.driver_string, driver_ver, len);
+ fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
+ (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
+
+ for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
+ ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
+ sizeof(fw_cmd),
+ IXGBE_HI_COMMAND_TIMEOUT,
+ TRUE);
+ if (ret_val != IXGBE_SUCCESS)
+ continue;
+
+ if (fw_cmd.hdr.cmd_or_resp.ret_status ==
+ FW_CEM_RESP_STATUS_SUCCESS)
+ ret_val = IXGBE_SUCCESS;
+ else
+ ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+
+ break;
+ }
+
+ return ret_val;
+}
Index: sys/modules/ix/Makefile
===================================================================
--- sys/modules/ix/Makefile
+++ sys/modules/ix/Makefile
@@ -1,11 +1,12 @@
-#$FreeBSD$
+# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/ixgbe
KMOD = if_ix
-SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h
-SRCS += opt_inet.h opt_inet6.h opt_rss.h
-SRCS += if_ix.c ix_txrx.c ixgbe_osdep.c
+SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h
+SRCS += opt_inet.h opt_inet6.h opt_rss.h opt_iflib.h
+SRCS += if_ix.c if_bypass.c if_fdir.c if_sriov.c ix_txrx.c ixgbe_osdep.c
+SRCS += ixgbe_sysctl.c
# Shared source
SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c
SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c
Index: sys/modules/ixv/Makefile
===================================================================
--- sys/modules/ixv/Makefile
+++ sys/modules/ixv/Makefile
@@ -3,7 +3,7 @@
.PATH: ${SRCTOP}/sys/dev/ixgbe
KMOD = if_ixv
-SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h
+SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h
SRCS += opt_inet.h opt_inet6.h opt_rss.h
SRCS += if_ixv.c ix_txrx.c ixgbe_osdep.c
# Shared source

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 28, 12:43 PM (3 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15622981
Default Alt Text
D10293.id29244.diff (891 KB)

Event Timeline