summaryrefslogtreecommitdiffstats
path: root/sys/dev/ixgbe
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2009-12-07 21:30:54 +0000
committerjfv <jfv@FreeBSD.org>2009-12-07 21:30:54 +0000
commitf615ab2eb39b672f5cd62249609001c3d4e81b88 (patch)
treeeb771079f6b223fe24a5557c0c86f0cea1dbe80c /sys/dev/ixgbe
parent37c0b1019a56f5828b614a8d77823ae72b9174b9 (diff)
downloadFreeBSD-src-f615ab2eb39b672f5cd62249609001c3d4e81b88.zip
FreeBSD-src-f615ab2eb39b672f5cd62249609001c3d4e81b88.tar.gz
Update driver to Intel version 2.0.7:
This adds new feature support for the 82599, a hardware assist to LRO, doing this required a large revamp to the RX cleanup code because the descriptor ring may not be processed out of order, this necessitated the elimination of global pointers. Additionally, the RX routine now does not refresh mbufs on every descriptor, rather it will do a range, and then update the hardware pointer at that time. These are performance oriented changes. The TX side now has a cleaner simpler watchdog algorithm as well, in TX cleanup a read of ticks is stored, that can then be compared in local_timer to determine if there is a hang. Various other cleanups along the way, thanks to all who have provided input and testing.
Diffstat (limited to 'sys/dev/ixgbe')
-rw-r--r--sys/dev/ixgbe/ixgbe.c1231
-rw-r--r--sys/dev/ixgbe/ixgbe.h52
-rw-r--r--sys/dev/ixgbe/ixgbe_82598.c240
-rw-r--r--sys/dev/ixgbe/ixgbe_82599.c857
-rw-r--r--sys/dev/ixgbe/ixgbe_api.c44
-rw-r--r--sys/dev/ixgbe/ixgbe_api.h6
-rw-r--r--sys/dev/ixgbe/ixgbe_common.c972
-rw-r--r--sys/dev/ixgbe/ixgbe_common.h27
-rw-r--r--sys/dev/ixgbe/ixgbe_osdep.h10
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.c221
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.h3
-rw-r--r--sys/dev/ixgbe/ixgbe_type.h116
12 files changed, 2510 insertions, 1269 deletions
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index d994529..10a0e04 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -46,7 +46,7 @@ int ixgbe_display_debug_stats = 0;
/*********************************************************************
* Driver version
*********************************************************************/
-char ixgbe_driver_version[] = "1.8.9";
+char ixgbe_driver_version[] = "2.0.7";
/*********************************************************************
* PCI Device ID Table
@@ -64,16 +64,19 @@ static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
{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_82598AT, 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_COMBO_BACKPLANE, 0, 0, 0},
/* required last entry */
{0, 0, 0, 0, 0}
};
@@ -102,7 +105,6 @@ static int ixgbe_mq_start_locked(struct ifnet *,
static void ixgbe_qflush(struct ifnet *);
#endif
static int ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
-static void ixgbe_watchdog(struct adapter *);
static void ixgbe_init(void *);
static void ixgbe_init_locked(struct adapter *);
static void ixgbe_stop(void *);
@@ -116,8 +118,8 @@ static int ixgbe_allocate_queues(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_hardware_init(struct adapter *);
static void ixgbe_setup_interface(device_t, struct adapter *);
+static void ixgbe_config_link(struct adapter *);
static int ixgbe_allocate_transmit_buffers(struct tx_ring *);
static int ixgbe_setup_transmit_structures(struct adapter *);
@@ -132,6 +134,7 @@ static int ixgbe_setup_receive_ring(struct rx_ring *);
static void ixgbe_initialize_receive_units(struct adapter *);
static void ixgbe_free_receive_structures(struct adapter *);
static void ixgbe_free_receive_buffers(struct rx_ring *);
+static void ixgbe_setup_hw_rsc(struct rx_ring *);
static void ixgbe_init_moderation(struct adapter *);
static void ixgbe_enable_intr(struct adapter *);
@@ -146,7 +149,7 @@ static void ixgbe_set_multi(struct adapter *);
static void ixgbe_print_hw_stats(struct adapter *);
static void ixgbe_print_debug_info(struct adapter *);
static void ixgbe_update_link_status(struct adapter *);
-static int ixgbe_get_buf(struct rx_ring *, int, u8);
+static int ixgbe_get_buf(struct rx_ring *, int, int);
static int ixgbe_xmit(struct tx_ring *, struct mbuf **);
static int ixgbe_sysctl_stats(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS);
@@ -186,6 +189,10 @@ static void ixgbe_handle_link(void *, int);
static void ixgbe_handle_msf(void *, int);
static void ixgbe_handle_mod(void *, int);
+#ifdef IXGBE_FDIR
+static void ixgbe_atr(struct tx_ring *, struct mbuf *);
+static void ixgbe_reinit_fdir(void *, int);
+#endif
/*********************************************************************
* FreeBSD Device Interface Entry Points
@@ -239,6 +246,15 @@ static int ixgbe_flow_control = ixgbe_fc_full;
TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
/*
+** 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;
+
+/*
* MSIX should be the default for best performance,
* but this allows it to be forced off for testing.
*/
@@ -271,7 +287,7 @@ TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd);
static int ixgbe_rxd = DEFAULT_RXD;
TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
-/* Total number of Interfaces - need for config sanity check */
+/* Keep running tab on them for sanity check */
static int ixgbe_total_ports;
/*
@@ -288,6 +304,27 @@ static u32 ixgbe_shadow_vfta[IXGBE_VFTA_SIZE];
*/
static int ixgbe_num_segs = IXGBE_82598_SCATTER;
+#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;
+/*
+** 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
+
/*********************************************************************
* Device identification routine
*
@@ -356,7 +393,7 @@ ixgbe_attach(device_t dev)
struct adapter *adapter;
struct ixgbe_hw *hw;
int error = 0;
- u16 pci_device_id;
+ u16 pci_device_id, csum;
u32 ctrl_ext;
INIT_DEBUGOUT("ixgbe_attach: begin");
@@ -376,10 +413,14 @@ ixgbe_attach(device_t dev)
case IXGBE_DEV_ID_82598EB_CX4 :
adapter->optics = IFM_10G_CX4;
break;
+ case IXGBE_DEV_ID_82598 :
case IXGBE_DEV_ID_82598AF_DUAL_PORT :
case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
case IXGBE_DEV_ID_82598AF_SINGLE_PORT :
+ case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM :
+ case IXGBE_DEV_ID_82598EB_SFP_LOM :
case IXGBE_DEV_ID_82598AT :
+ case IXGBE_DEV_ID_82598AT2 :
adapter->optics = IFM_10G_SR;
break;
case IXGBE_DEV_ID_82598EB_XF_LR :
@@ -390,10 +431,13 @@ ixgbe_attach(device_t dev)
ixgbe_num_segs = IXGBE_82599_SCATTER;
break;
case IXGBE_DEV_ID_82599_KX4 :
+ case IXGBE_DEV_ID_82599_KX4_MEZZ:
+ case IXGBE_DEV_ID_82599_CX4 :
adapter->optics = IFM_10G_CX4;
ixgbe_num_segs = IXGBE_82599_SCATTER;
break;
case IXGBE_DEV_ID_82599_XAUI_LOM :
+ case IXGBE_DEV_ID_82599_COMBO_BACKPLANE :
ixgbe_num_segs = IXGBE_82599_SCATTER;
default:
break;
@@ -504,10 +548,37 @@ ixgbe_attach(device_t dev)
goto err_late;
}
- /* Initialize the hardware */
- if (ixgbe_hardware_init(adapter)) {
- device_printf(dev,"Unable to initialize the hardware\n");
+ /* 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;
+ }
+
+ /* Pick up the smart speed setting */
+ if (hw->mac.type == ixgbe_mac_82599EB)
+ hw->phy.smart_speed = ixgbe_smart_speed;
+
+ /* Get Hardware Flow Control setting */
+ hw->fc.requested_mode = ixgbe_fc_full;
+ hw->fc.pause_time = IXGBE_FC_PAUSE;
+ hw->fc.low_water = IXGBE_FC_LO;
+ hw->fc.high_water = IXGBE_FC_HI;
+ hw->fc.send_xon = TRUE;
+
+ error = ixgbe_init_hw(hw);
+ if (error == 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");
+ } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ device_printf(dev,"Unsupported SFP+ Module\n");
+
+ if (error) {
error = EIO;
+ device_printf(dev,"Hardware Initialization Failure\n");
goto err_late;
}
@@ -529,10 +600,10 @@ ixgbe_attach(device_t dev)
adapter->cycles.mask = (u64)-1;
adapter->cycles.mult = 1;
adapter->cycles.shift = IXGBE_TSYNC_SHIFT;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TIMINCA, (1<<24) |
+ IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, (1<<24) |
IXGBE_TSYNC_CYCLE_TIME * IXGBE_TSYNC_SHIFT);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIML, 0x00000000);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIMH, 0xFF800000);
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0xFF800000);
// JFV - this is not complete yet
#endif
@@ -551,6 +622,24 @@ ixgbe_attach(device_t dev)
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
+ /* Print PCIE bus type/speed/width info */
+ ixgbe_get_bus_info(hw);
+ device_printf(dev,"PCI Express Bus: Speed %s %s\n",
+ ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s":
+ (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/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->bus.width <= ixgbe_bus_width_pcie_x4) {
+ 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 "
+ "PCI-Express slot is required.\n");
+ }
+
/* let hardware know driver is loaded */
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
@@ -616,6 +705,9 @@ ixgbe_detach(device_t dev)
taskqueue_drain(adapter->tq, &adapter->link_task);
taskqueue_drain(adapter->tq, &adapter->mod_task);
taskqueue_drain(adapter->tq, &adapter->msf_task);
+#ifdef IXGBE_FDIR
+ taskqueue_drain(adapter->tq, &adapter->fdir_task);
+#endif
taskqueue_free(adapter->tq);
}
@@ -700,8 +792,8 @@ ixgbe_start_locked(struct tx_ring *txr, struct ifnet * ifp)
/* Send a copy of the frame to the BPF listener */
ETHER_BPF_MTAP(ifp, m_head);
- /* Set timeout in case hardware has problems transmitting */
- txr->watchdog_timer = IXGBE_TX_TIMEOUT;
+ /* Set watchdog on */
+ txr->watchdog_check = TRUE;
}
return;
@@ -770,16 +862,17 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
/* If nothing queued go right to xmit */
if (drbr_empty(ifp, txr->br)) {
- if (ixgbe_xmit(txr, &m)) {
- if (m && (err = drbr_enqueue(ifp, txr->br, m)) != 0)
- return (err);
+ if ((err = ixgbe_xmit(txr, &m)) != 0) {
+ if (m != NULL)
+ err = drbr_enqueue(ifp, txr->br, m);
+ return (err);
} else {
/* Success, update stats */
drbr_stats_update(ifp, m->m_pkthdr.len, m->m_flags);
/* Send a copy of the frame to the BPF listener */
ETHER_BPF_MTAP(ifp, m);
/* Set the watchdog */
- txr->watchdog_timer = IXGBE_TX_TIMEOUT;
+ txr->watchdog_check = TRUE;
}
} else if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
@@ -796,11 +889,15 @@ process:
next = drbr_dequeue(ifp, txr->br);
if (next == NULL)
break;
- if (ixgbe_xmit(txr, &next))
+ if ((err = ixgbe_xmit(txr, &next)) != 0) {
+ if (next != NULL)
+ err = drbr_enqueue(ifp, txr->br, next);
break;
+ }
+ drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
ETHER_BPF_MTAP(ifp, next);
/* Set the watchdog */
- txr->watchdog_timer = IXGBE_TX_TIMEOUT;
+ txr->watchdog_check = TRUE;
}
if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD)
@@ -843,27 +940,10 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
{
struct adapter *adapter = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
-#ifdef INET
- struct ifaddr *ifa = (struct ifaddr *) data;
-#endif
int error = 0;
switch (command) {
- case SIOCSIFADDR:
-#ifdef INET
- IOCTL_DEBUGOUT("ioctl: SIOCxIFADDR (Get/Set Interface Addr)");
- if (ifa->ifa_addr->sa_family == AF_INET) {
- ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- IXGBE_CORE_LOCK(adapter);
- ixgbe_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- }
- arp_ifinit(ifp, ifa);
- } else
-#endif
- ether_ioctl(ifp, command, data);
- break;
+
case SIOCSIFMTU:
IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
@@ -919,7 +999,8 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_HWCSUM;
if (mask & IFCAP_TSO4)
ifp->if_capenable ^= IFCAP_TSO4;
- if (mask & IFCAP_LRO)
+ /* Only allow changing when using header split */
+ if ((mask & IFCAP_LRO) && (ixgbe_header_split))
ifp->if_capenable ^= IFCAP_LRO;
if (mask & IFCAP_VLAN_HWTAGGING)
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
@@ -948,84 +1029,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
}
/*********************************************************************
- * Watchdog entry point
- *
- * This routine is called by the local timer
- * to detect hardware hangs .
- *
- **********************************************************************/
-
-static void
-ixgbe_watchdog(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- struct tx_ring *txr = adapter->tx_rings;
- struct ixgbe_hw *hw = &adapter->hw;
- bool tx_hang = FALSE;
-
- IXGBE_CORE_LOCK_ASSERT(adapter);
-
- /*
- * The timer is set to 5 every time ixgbe_start() queues a packet.
- * Then ixgbe_txeof() keeps resetting to 5 as long as it cleans at
- * least one descriptor.
- * Finally, anytime all descriptors are clean the timer is
- * set to 0.
- */
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- u32 head, tail;
-
- IXGBE_TX_LOCK(txr);
- if (txr->watchdog_timer == 0 || --txr->watchdog_timer) {
- IXGBE_TX_UNLOCK(txr);
- continue;
- } else {
- head = IXGBE_READ_REG(hw, IXGBE_TDH(i));
- tail = IXGBE_READ_REG(hw, IXGBE_TDT(i));
- if (head == tail) { /* last minute check */
- IXGBE_TX_UNLOCK(txr);
- continue;
- }
- /* Well, seems something is really hung */
- tx_hang = TRUE;
- IXGBE_TX_UNLOCK(txr);
- break;
- }
- }
- if (tx_hang == FALSE)
- return;
-
- /*
- * If we are in this routine because of pause frames, then don't
- * reset the hardware.
- */
- if (IXGBE_READ_REG(hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) {
- txr = adapter->tx_rings; /* reset pointer */
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- IXGBE_TX_LOCK(txr);
- txr->watchdog_timer = IXGBE_TX_TIMEOUT;
- IXGBE_TX_UNLOCK(txr);
- }
- return;
- }
-
-
- device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", i,
- IXGBE_READ_REG(hw, IXGBE_TDH(i)),
- IXGBE_READ_REG(hw, IXGBE_TDT(i)));
- device_printf(dev,"TX(%d) desc avail = %d,"
- "Next TX to Clean = %d\n",
- i, txr->tx_avail, txr->next_tx_to_clean);
- }
- adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- adapter->watchdog_events++;
-
- ixgbe_init_locked(adapter);
-}
-
-/*********************************************************************
* Init entry point
*
* This routine is used in two ways. It is used by the stack as
@@ -1052,19 +1055,14 @@ ixgbe_init_locked(struct adapter *adapter)
hw = &adapter->hw;
mtx_assert(&adapter->core_mtx, MA_OWNED);
- ixgbe_stop(adapter);
-
/* Get the latest mac address, User can use a LAA */
- bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr,
+ bcopy(IF_LLADDR(adapter->ifp), hw->mac.addr,
IXGBE_ETH_LENGTH_OF_ADDRESS);
- ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, 1);
- adapter->hw.addr_ctrl.rar_used_count = 1;
+ ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
+ hw->addr_ctrl.rar_used_count = 1;
- /* Initialize the hardware */
- if (ixgbe_hardware_init(adapter)) {
- device_printf(dev, "Unable to initialize the hardware\n");
- return;
- }
+ /* Do a warm reset */
+ ixgbe_reset_hw(hw);
/* Prepare transmit descriptors and buffers */
if (ixgbe_setup_transmit_structures(adapter)) {
@@ -1102,7 +1100,7 @@ ixgbe_init_locked(struct adapter *adapter)
gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
- if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ if (hw->mac.type == ixgbe_mac_82599EB) {
gpie |= IXGBE_SDP1_GPIEN;
gpie |= IXGBE_SDP2_GPIEN;
}
@@ -1117,7 +1115,7 @@ ixgbe_init_locked(struct adapter *adapter)
gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
IXGBE_GPIE_OCD;
}
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_GPIE, gpie);
+ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
/* Set the various hardware offload abilities */
ifp->if_hwassist = 0;
@@ -1128,28 +1126,35 @@ ixgbe_init_locked(struct adapter *adapter)
/* Set MTU size */
if (ifp->if_mtu > ETHERMTU) {
- mhadd = IXGBE_READ_REG(&adapter->hw, IXGBE_MHADD);
+ mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
mhadd &= ~IXGBE_MHADD_MFS_MASK;
mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_MHADD, mhadd);
+ IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
}
/* Now enable all the queues */
for (int i = 0; i < adapter->num_queues; i++) {
- txdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(i));
+ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
txdctl |= IXGBE_TXDCTL_ENABLE;
/* Set WTHRESH to 8, burst writeback */
txdctl |= (8 << 16);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(i), txdctl);
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl);
}
for (int i = 0; i < adapter->num_queues; i++) {
- rxdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(i));
- /* PTHRESH set to 32 */
- rxdctl |= 0x0020;
+ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ /*
+ ** PTHRESH = 21
+ ** HTHRESH = 4
+ ** WTHRESH = 8
+ */
+ rxdctl &= ~0x3FFFFF;
+ rxdctl |= 0x080420;
+ }
rxdctl |= IXGBE_RXDCTL_ENABLE;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(i), rxdctl);
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), rxdctl);
for (k = 0; k < 10; k++) {
if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)) &
IXGBE_RXDCTL_ENABLE)
@@ -1166,7 +1171,7 @@ ixgbe_init_locked(struct adapter *adapter)
/* Enable Receive engine */
rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ if (hw->mac.type == ixgbe_mac_82598EB)
rxctrl |= IXGBE_RXCTRL_DMBYPS;
rxctrl |= IXGBE_RXCTRL_RXEN;
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
@@ -1181,7 +1186,11 @@ ixgbe_init_locked(struct adapter *adapter)
ixgbe_set_ivar(adapter, 0, 0, 1);
}
- ixgbe_enable_intr(adapter);
+#ifdef IXGBE_FDIR
+ /* Init Flow director */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
+#endif
/*
** Check on any SFP devices that
@@ -1194,14 +1203,12 @@ ixgbe_init_locked(struct adapter *adapter)
ixgbe_detach(dev);
return;
}
- if (ixgbe_is_sfp(hw)) {
- if (hw->phy.multispeed_fiber) {
- hw->mac.ops.setup_sfp(hw);
- taskqueue_enqueue(adapter->tq, &adapter->msf_task);
- } else
- taskqueue_enqueue(adapter->tq, &adapter->mod_task);
- } else
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+
+ /* Config/Enable Link */
+ ixgbe_config_link(adapter);
+
+ /* And now turn on interrupts */
+ ixgbe_enable_intr(adapter);
/* Now inform the stack we're ready */
ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -1269,7 +1276,7 @@ ixgbe_disable_queue(struct adapter *adapter, u32 vector)
}
static inline void
-ixgbe_rearm_rx_queues(struct adapter *adapter, u64 queues)
+ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
{
u32 mask;
@@ -1464,11 +1471,25 @@ ixgbe_msix_link(void *arg)
taskqueue_enqueue(adapter->tq, &adapter->link_task);
if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+#ifdef IXGBE_FDIR
+ if (reg_eicr & IXGBE_EICR_FLOW_DIR) {
+ /* This is probably overkill :) */
+ if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
+ return;
+ /* Clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR);
+ /* Turn off the interface */
+ adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ taskqueue_enqueue(adapter->tq, &adapter->fdir_task);
+ } else
+#endif
if (reg_eicr & IXGBE_EICR_ECC) {
device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! "
"Please Reboot!!\n");
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
- } else if (reg_eicr & IXGBE_EICR_GPI_SDP1) {
+ } else
+
+ if (reg_eicr & IXGBE_EICR_GPI_SDP1) {
/* Clear the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
taskqueue_enqueue(adapter->tq, &adapter->msf_task);
@@ -1553,11 +1574,9 @@ ixgbe_init_moderation(struct adapter *adapter)
}
/* TX irq moderation rate is fixed */
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
+ for (int i = 0; i < adapter->num_queues; i++, txr++)
IXGBE_WRITE_REG(&adapter->hw,
IXGBE_EITR(txr->msix), ixgbe_ave_latency);
- txr->watchdog_timer = FALSE;
- }
/* RX moderation will be adapted over time, set default */
for (int i = 0; i < adapter->num_queues; i++, rxr++) {
@@ -1633,7 +1652,6 @@ ixgbe_media_change(struct ifnet * ifp)
switch (IFM_SUBTYPE(ifm->ifm_media)) {
case IFM_AUTO:
- adapter->hw.mac.autoneg = TRUE;
adapter->hw.phy.autoneg_advertised =
IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_10GB_FULL;
break;
@@ -1690,7 +1708,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
* used because it will contain the index of
* the one we tell the hardware to report back
*/
- first = txr->next_avail_tx_desc;
+ first = txr->next_avail_desc;
txbuf = &txr->tx_buffers[first];
txbuf_mapped = txbuf;
map = txbuf->map;
@@ -1767,12 +1785,22 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
cmd_type_len |= IXGBE_ADVTXD_MAC_TSTAMP;
#endif
+#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;
+ }
+ }
+#endif
/* Record payload length */
if (paylen == 0)
olinfo_status |= m_head->m_pkthdr.len <<
IXGBE_ADVTXD_PAYLEN_SHIFT;
- i = txr->next_avail_tx_desc;
+ i = txr->next_avail_desc;
for (j = 0; j < nsegs; j++) {
bus_size_t seglen;
bus_addr_t segaddr;
@@ -1798,7 +1826,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
txd->read.cmd_type_len |=
htole32(IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS);
txr->tx_avail -= nsegs;
- txr->next_avail_tx_desc = i;
+ txr->next_avail_desc = i;
txbuf->m_head = m_head;
txbuf->map = map;
@@ -1939,7 +1967,7 @@ ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
* Timer routine
*
* This routine checks for link status,updates statistics,
- * and runs the watchdog timer.
+ * and runs the watchdog check.
*
**********************************************************************/
@@ -1948,6 +1976,9 @@ ixgbe_local_timer(void *arg)
{
struct adapter *adapter = arg;
struct ifnet *ifp = adapter->ifp;
+ device_t dev = adapter->dev;
+ struct tx_ring *txr = adapter->tx_rings;
+ bool tx_hung = FALSE;
mtx_assert(&adapter->core_mtx, MA_OWNED);
@@ -1962,16 +1993,31 @@ ixgbe_local_timer(void *arg)
ixgbe_print_hw_stats(adapter);
}
/*
- * Each tick we check the watchdog
- * to protect against hardware hangs.
- */
- ixgbe_watchdog(adapter);
-
+ ** Check for time since any descriptor was cleaned
+ */
+ for (int i = 0; i < adapter->num_queues; i++, txr++) {
+ if (txr->watchdog_check == FALSE)
+ continue;
+ if ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG) {
+ tx_hung = TRUE;
+ goto hung;
+ }
+ }
out:
- /* Trigger an RX interrupt on all queues */
- ixgbe_rearm_rx_queues(adapter, adapter->rx_mask);
-
callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
+ return;
+
+hung:
+ device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
+ device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", txr->me,
+ IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(txr->me)),
+ IXGBE_READ_REG(&adapter->hw, IXGBE_TDT(txr->me)));
+ device_printf(dev,"TX(%d) desc avail = %d,"
+ "Next TX to Clean = %d\n",
+ txr->me, txr->tx_avail, txr->next_to_clean);
+ adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ adapter->watchdog_events++;
+ ixgbe_init_locked(adapter);
}
/*
@@ -2004,7 +2050,7 @@ ixgbe_update_link_status(struct adapter *adapter)
adapter->link_active = FALSE;
for (int i = 0; i < adapter->num_queues;
i++, txr++)
- txr->watchdog_timer = FALSE;
+ txr->watchdog_check = FALSE;
}
}
@@ -2113,6 +2159,9 @@ ixgbe_allocate_legacy(struct adapter *adapter)
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 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",
@@ -2242,6 +2291,9 @@ ixgbe_allocate_msix(struct adapter *adapter)
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 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",
@@ -2432,65 +2484,15 @@ mem:
/*********************************************************************
*
- * Initialize the hardware to a configuration as specified by the
- * adapter structure. The controller is reset, the EEPROM is
- * verified, the MAC address is set, then the shared initialization
- * routines are called.
- *
- **********************************************************************/
-static int
-ixgbe_hardware_init(struct adapter *adapter)
-{
- device_t dev = adapter->dev;
- u32 ret;
- u16 csum;
-
- csum = 0;
- /* Issue a global reset */
- adapter->hw.adapter_stopped = FALSE;
- ixgbe_stop_adapter(&adapter->hw);
-
- /* 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");
- return (EIO);
- }
-
- /* Get Hardware Flow Control setting */
- adapter->hw.fc.requested_mode = ixgbe_fc_full;
- adapter->hw.fc.pause_time = IXGBE_FC_PAUSE;
- adapter->hw.fc.low_water = IXGBE_FC_LO;
- adapter->hw.fc.high_water = IXGBE_FC_HI;
- adapter->hw.fc.send_xon = TRUE;
-
- ret = ixgbe_init_hw(&adapter->hw);
- if (ret == 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");
- } else if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,"Unsupported SFP+ Module\n");
- return (EIO);
- } else if (ret != 0 ) {
- device_printf(dev,"Hardware Initialization Failure\n");
- return (EIO);
- }
-
- return (0);
-}
-
-/*********************************************************************
- *
* Setup networking device structure and register an interface.
*
**********************************************************************/
static void
ixgbe_setup_interface(device_t dev, struct adapter *adapter)
{
- struct ifnet *ifp;
struct ixgbe_hw *hw = &adapter->hw;
+ struct ifnet *ifp;
+
INIT_DEBUGOUT("ixgbe_setup_interface: begin");
ifp = adapter->ifp = if_alloc(IFT_ETHER);
@@ -2522,17 +2524,12 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
- ifp->if_capabilities |= IFCAP_JUMBO_MTU | IFCAP_LRO;
+ ifp->if_capabilities |= IFCAP_JUMBO_MTU;
+ if (ixgbe_header_split)
+ ifp->if_capabilities |= IFCAP_LRO;
ifp->if_capenable = ifp->if_capabilities;
- if (hw->device_id == IXGBE_DEV_ID_82598AT)
- ixgbe_setup_link_speed(hw, (IXGBE_LINK_SPEED_10GB_FULL |
- IXGBE_LINK_SPEED_1GB_FULL), TRUE, TRUE);
- else
- ixgbe_setup_link_speed(hw, IXGBE_LINK_SPEED_10GB_FULL,
- TRUE, FALSE);
-
/*
* Specify the media types supported by this adapter and register
* callbacks to update media and link information
@@ -2549,7 +2546,51 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
}
ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
+ return;
+}
+static void
+ixgbe_config_link(struct adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 autoneg, err = 0;
+ bool sfp, negotiate;
+
+ 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_tw_tyco:
+ case ixgbe_phy_tw_unknown:
+ sfp = TRUE;
+ default:
+ sfp = FALSE;
+ }
+
+ if (sfp) {
+ if (hw->phy.multispeed_fiber) {
+ hw->mac.ops.setup_sfp(hw);
+ taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+ } else
+ taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+ } else {
+ if (hw->mac.ops.check_link)
+ err = ixgbe_check_link(hw, &autoneg,
+ &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,
+ negotiate, adapter->link_up);
+ }
+out:
return;
}
@@ -2833,8 +2874,8 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr)
bzero((void *)txr->tx_base,
(sizeof(union ixgbe_adv_tx_desc)) * adapter->num_tx_desc);
/* Reset indices */
- txr->next_avail_tx_desc = 0;
- txr->next_tx_to_clean = 0;
+ txr->next_avail_desc = 0;
+ txr->next_to_clean = 0;
/* Free any existing tx buffers. */
txbuf = txr->tx_buffers;
@@ -2850,6 +2891,12 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr)
txbuf->eop_index = -1;
}
+#ifdef IXGBE_FDIR
+ /* Set the rate at which we sample packets */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ txr->atr_sample = atr_sample_rate;
+#endif
+
/* Set number of descriptors available */
txr->tx_avail = adapter->num_tx_desc;
@@ -2888,6 +2935,7 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
for (int i = 0; i < adapter->num_queues; i++, txr++) {
u64 tdba = txr->txdma.dma_paddr;
+ u32 txctrl;
IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i),
(tdba & 0x00000000ffffffffULL));
@@ -2901,15 +2949,43 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
/* Setup Transmit Descriptor Cmd Settings */
txr->txd_cmd = IXGBE_TXD_CMD_IFCS;
+ txr->watchdog_check = FALSE;
+
+ /* Disable Head Writeback */
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
+ break;
+ case ixgbe_mac_82599EB:
+ default:
+ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
+ break;
+ }
+ txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
+ break;
+ case ixgbe_mac_82599EB:
+ default:
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), txctrl);
+ break;
+ }
- txr->watchdog_timer = 0;
}
if (hw->mac.type == ixgbe_mac_82599EB) {
- u32 dmatxctl;
+ 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_MTQC_64Q_1PB);
+ rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
+ IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
}
return;
@@ -3009,7 +3085,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
u16 etype;
u8 ipproto = 0;
bool offload = TRUE;
- int ctxd = txr->next_avail_tx_desc;
+ int ctxd = txr->next_avail_desc;
u16 vtag = 0;
@@ -3099,7 +3175,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
/* We've consumed the first desc, adjust counters */
if (++ctxd == adapter->num_tx_desc)
ctxd = 0;
- txr->next_avail_tx_desc = ctxd;
+ txr->next_avail_desc = ctxd;
--txr->tx_avail;
return (offload);
@@ -3140,7 +3216,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr))
return FALSE;
- ctxd = txr->next_avail_tx_desc;
+ ctxd = txr->next_avail_desc;
tx_buffer = &txr->tx_buffers[ctxd];
TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];
@@ -3188,10 +3264,88 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
ctxd = 0;
txr->tx_avail--;
- txr->next_avail_tx_desc = ctxd;
+ txr->next_avail_desc = ctxd;
return TRUE;
}
+#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)
+{
+ struct adapter *adapter = txr->adapter;
+ struct ixgbe_atr_input atr_input;
+ struct ip *ip;
+ struct tcphdr *th;
+ struct udphdr *uh;
+ struct ether_vlan_header *eh;
+ int ehdrlen, ip_hlen;
+ u16 etype, vlan_id, src_port, dst_port, flex_bytes;
+ u32 src_ipv4_addr, dst_ipv4_addr;
+ u8 l4type = 0, ipproto = 0;
+
+ eh = mtod(mp, struct ether_vlan_header *);
+ if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
+ ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+ else
+ ehdrlen = ETHER_HDR_LEN;
+ etype = ntohs(eh->evl_proto);
+
+ /* Only handling IPv4 */
+ if (etype != ETHERTYPE_IP)
+ return;
+
+ ip = (struct ip *)(mp->m_data + ehdrlen);
+ ipproto = ip->ip_p;
+ ip_hlen = ip->ip_hl << 2;
+ src_port = dst_port = 0;
+
+ /* check if we're UDP or TCP */
+ switch (ipproto) {
+ case IPPROTO_TCP:
+ th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
+ src_port = th->th_sport;
+ dst_port = th->th_dport;
+ l4type |= IXGBE_ATR_L4TYPE_TCP;
+ break;
+ case IPPROTO_UDP:
+ uh = (struct udphdr *)((caddr_t)ip + ip_hlen);
+ src_port = uh->uh_sport;
+ dst_port = uh->uh_dport;
+ l4type |= IXGBE_ATR_L4TYPE_UDP;
+ break;
+ default:
+ return;
+ }
+
+ memset(&atr_input, 0, sizeof(struct ixgbe_atr_input));
+
+ vlan_id = htole16(mp->m_pkthdr.ether_vtag);
+ src_ipv4_addr = ip->ip_src.s_addr;
+ dst_ipv4_addr = ip->ip_dst.s_addr;
+ flex_bytes = etype;
+
+ ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id);
+ ixgbe_atr_set_src_port_82599(&atr_input, dst_port);
+ ixgbe_atr_set_dst_port_82599(&atr_input, src_port);
+ ixgbe_atr_set_flex_byte_82599(&atr_input, flex_bytes);
+ ixgbe_atr_set_l4type_82599(&atr_input, l4type);
+ /* src and dst are inverted, think how the receiver sees them */
+ ixgbe_atr_set_src_ipv4_82599(&atr_input, dst_ipv4_addr);
+ ixgbe_atr_set_dst_ipv4_82599(&atr_input, src_ipv4_addr);
+
+ /* This assumes the Rx queue and Tx queue are bound to the same CPU */
+ ixgbe_fdir_add_signature_filter_82599(&adapter->hw,
+ &atr_input, txr->msix);
+}
+#endif
/**********************************************************************
*
@@ -3203,10 +3357,9 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
static boolean_t
ixgbe_txeof(struct tx_ring *txr)
{
- struct adapter * adapter = txr->adapter;
+ struct adapter *adapter = txr->adapter;
struct ifnet *ifp = adapter->ifp;
- u32 first, last, done, num_avail;
- u32 cleaned = 0;
+ u32 first, last, done;
struct ixgbe_tx_buf *tx_buffer;
struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc;
@@ -3215,17 +3368,15 @@ ixgbe_txeof(struct tx_ring *txr)
if (txr->tx_avail == adapter->num_tx_desc)
return FALSE;
- num_avail = txr->tx_avail;
- first = txr->next_tx_to_clean;
-
+ first = txr->next_to_clean;
tx_buffer = &txr->tx_buffers[first];
/* For cleanup we just use legacy struct */
tx_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first];
last = tx_buffer->eop_index;
if (last == -1)
return FALSE;
-
eop_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last];
+
/*
** Get the index of the first descriptor
** BEYOND the EOP and call that 'done'.
@@ -3247,7 +3398,7 @@ ixgbe_txeof(struct tx_ring *txr)
tx_desc->upper.data = 0;
tx_desc->lower.data = 0;
tx_desc->buffer_addr = 0;
- num_avail++; cleaned++;
+ ++txr->tx_avail;
if (tx_buffer->m_head) {
ifp->if_opackets++;
@@ -3261,6 +3412,7 @@ ixgbe_txeof(struct tx_ring *txr)
tx_buffer->map = NULL;
}
tx_buffer->eop_index = -1;
+ txr->watchdog_time = ticks;
if (++first == adapter->num_tx_desc)
first = 0;
@@ -3283,7 +3435,7 @@ ixgbe_txeof(struct tx_ring *txr)
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- txr->next_tx_to_clean = first;
+ txr->next_to_clean = first;
/*
* If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that
@@ -3291,98 +3443,101 @@ ixgbe_txeof(struct tx_ring *txr)
* clear the timeout. Otherwise, if some descriptors have been freed,
* restart the timeout.
*/
- if (num_avail > IXGBE_TX_CLEANUP_THRESHOLD) {
+ if (txr->tx_avail > IXGBE_TX_CLEANUP_THRESHOLD) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- /* If all are clean turn off the timer */
- if (num_avail == adapter->num_tx_desc) {
- txr->watchdog_timer = 0;
- txr->tx_avail = num_avail;
+ if (txr->tx_avail == adapter->num_tx_desc) {
+ txr->watchdog_check = FALSE;
return FALSE;
}
}
- /* Some were cleaned, so reset timer */
- if (cleaned)
- txr->watchdog_timer = IXGBE_TX_TIMEOUT;
- txr->tx_avail = num_avail;
return TRUE;
}
/*********************************************************************
*
- * Get a buffer from system mbuf buffer pool.
+ * Refresh mbuf buffers for a range of descriptors
*
**********************************************************************/
static int
-ixgbe_get_buf(struct rx_ring *rxr, int i, u8 clean)
+ixgbe_get_buf(struct rx_ring *rxr, int first, int limit)
{
struct adapter *adapter = rxr->adapter;
bus_dma_segment_t seg[2];
struct ixgbe_rx_buf *rxbuf;
struct mbuf *mh, *mp;
bus_dmamap_t map;
- int nsegs, error;
- int merr = 0;
-
+ int i, nsegs, error;
- rxbuf = &rxr->rx_buffers[i];
+ i = first;
+ while (i != limit) {
+ rxbuf = &rxr->rx_buffers[i];
- /* First get our header and payload mbuf */
- if (clean & IXGBE_CLEAN_HDR) {
- mh = m_gethdr(M_DONTWAIT, MT_DATA);
- if (mh == NULL)
- goto remap;
- } else /* reuse */
- mh = rxr->rx_buffers[i].m_head;
+ if (rxbuf->m_head == NULL) {
+ mh = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (mh == NULL)
+ goto failure;
+ } else /* reuse */
+ mh = rxbuf->m_head;
+
+ mh->m_len = MHLEN;
+ mh->m_flags |= M_PKTHDR;
+
+ if (rxbuf->m_pack == NULL) {
+ mp = m_getjcl(M_DONTWAIT, MT_DATA,
+ M_PKTHDR, adapter->rx_mbuf_sz);
+ if (mp == NULL)
+ goto failure;
+ mp->m_len = adapter->rx_mbuf_sz;
+ mp->m_flags &= ~M_PKTHDR;
+ } else { /* reusing */
+ mp = rxbuf->m_pack;
+ mp->m_len = adapter->rx_mbuf_sz;
+ mp->m_flags &= ~M_PKTHDR;
+ }
- mh->m_len = MHLEN;
- mh->m_flags |= M_PKTHDR;
+ /*
+ ** Need to create a chain for the following
+ ** dmamap call at this point.
+ */
+ mh->m_next = mp;
+ mh->m_pkthdr.len = mh->m_len + mp->m_len;
- if (clean & IXGBE_CLEAN_PKT) {
- mp = m_getjcl(M_DONTWAIT, MT_DATA,
- M_PKTHDR, adapter->rx_mbuf_sz);
- if (mp == NULL)
- goto remap;
- mp->m_len = adapter->rx_mbuf_sz;
- mp->m_flags &= ~M_PKTHDR;
- } else { /* reusing */
- mp = rxr->rx_buffers[i].m_pack;
- mp->m_len = adapter->rx_mbuf_sz;
- mp->m_flags &= ~M_PKTHDR;
- }
- /*
- ** Need to create a chain for the following
- ** dmamap call at this point.
- */
- mh->m_next = mp;
- mh->m_pkthdr.len = mh->m_len + mp->m_len;
+ /* Get the memory mapping */
+ error = bus_dmamap_load_mbuf_sg(rxr->rxtag,
+ rxr->spare_map, mh, seg, &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ printf("GET BUF: dmamap load failure - %d\n", error);
+ m_free(mh);
+ return (error);
+ }
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->rxtag,
- rxr->spare_map, mh, seg, &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("GET BUF: dmamap load failure - %d\n", error);
- m_free(mh);
- return (error);
+ /* Unload old mapping and update buffer struct */
+ if (rxbuf->m_head != NULL)
+ bus_dmamap_unload(rxr->rxtag, rxbuf->map);
+ map = rxbuf->map;
+ rxbuf->map = rxr->spare_map;
+ rxr->spare_map = map;
+ rxbuf->m_head = mh;
+ rxbuf->m_pack = mp;
+ bus_dmamap_sync(rxr->rxtag,
+ rxbuf->map, BUS_DMASYNC_PREREAD);
+
+ /* Update descriptor */
+ rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr);
+ rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr);
+
+ /* Calculate next index */
+ if (++i == adapter->num_rx_desc)
+ i = 0;
}
- /* Unload old mapping and update buffer struct */
- if (rxbuf->m_head != NULL)
- bus_dmamap_unload(rxr->rxtag, rxbuf->map);
- map = rxbuf->map;
- rxbuf->map = rxr->spare_map;
- rxr->spare_map = map;
- rxbuf->m_head = mh;
- rxbuf->m_pack = mp;
- bus_dmamap_sync(rxr->rxtag,
- rxbuf->map, BUS_DMASYNC_PREREAD);
-
- /* Update descriptor */
- rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr);
- rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr);
-
return (0);
+failure:
+ panic("GET BUF: ENOBUFS\n");
+
+#if 0
/*
** If we get here, we have an mbuf resource
** issue, so we discard the incoming packet
@@ -3415,9 +3570,9 @@ remap:
rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr);
return (merr);
+#endif
}
-
/*********************************************************************
*
* Allocate memory for rx_buffer structures. Since we use one
@@ -3491,6 +3646,62 @@ fail:
return (error);
}
+
+/*
+** 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.
+ *
+ **********************************************************************/
+static void
+ixgbe_setup_hw_rsc(struct rx_ring *rxr)
+{
+ struct adapter *adapter = rxr->adapter;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 rscctrl, rdrxctl;
+
+ rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+ rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
+ rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
+ 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 (adapter->rx_mbuf_sz == MCLBYTES)
+ rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
+ else /* using 4K clusters */
+ rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
+ 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;
+}
+
+
/*********************************************************************
*
* Initialize a receive ring and its buffers.
@@ -3503,8 +3714,9 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr)
struct ifnet *ifp;
device_t dev;
struct ixgbe_rx_buf *rxbuf;
+ bus_dma_segment_t seg[2];
struct lro_ctrl *lro = &rxr->lro;
- int j, rsize;
+ int rsize, nsegs, error;
adapter = rxr->adapter;
ifp = adapter->ifp;
@@ -3533,48 +3745,74 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr)
}
}
- /* Now refresh the mbufs */
- for (j = 0; j < adapter->num_rx_desc; j++) {
- if (ixgbe_get_buf(rxr, j, IXGBE_CLEAN_ALL) == ENOBUFS) {
- rxr->rx_buffers[j].m_head = NULL;
- rxr->rx_buffers[j].m_pack = NULL;
- rxr->rx_base[j].read.hdr_addr = 0;
- rxr->rx_base[j].read.pkt_addr = 0;
- goto fail;
- }
+ /* Now replenish the mbufs */
+ for (int j = 0; j != adapter->num_rx_desc; ++j) {
+
+ rxbuf = &rxr->rx_buffers[j];
+ rxbuf->m_head = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (rxbuf->m_head == NULL)
+ panic("RX ring hdr initialization failed!\n");
+ rxbuf->m_head->m_len = MHLEN;
+ rxbuf->m_head->m_flags |= M_PKTHDR;
+ rxbuf->m_head->m_pkthdr.len = rxbuf->m_head->m_len;
+
+ rxbuf->m_pack = m_getjcl(M_DONTWAIT, MT_DATA,
+ M_PKTHDR, adapter->rx_mbuf_sz);
+ if (rxbuf->m_pack == NULL)
+ panic("RX ring pkt initialization failed!\n");
+ rxbuf->m_pack->m_len = adapter->rx_mbuf_sz;
+ rxbuf->m_head->m_next = rxbuf->m_pack;
+ rxbuf->m_head->m_pkthdr.len += rxbuf->m_pack->m_len;
+
+ /* Get the memory mapping */
+ error = bus_dmamap_load_mbuf_sg(rxr->rxtag,
+ rxbuf->map, rxbuf->m_head, seg,
+ &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0)
+ panic("RX ring dma initialization failed!\n");
+ bus_dmamap_sync(rxr->rxtag,
+ rxbuf->map, BUS_DMASYNC_PREREAD);
+
+ /* Update descriptor */
+ rxr->rx_base[j].read.hdr_addr = htole64(seg[0].ds_addr);
+ rxr->rx_base[j].read.pkt_addr = htole64(seg[1].ds_addr);
}
+
/* Setup our descriptor indices */
rxr->next_to_check = 0;
- rxr->last_cleaned = 0;
+ rxr->last_refreshed = 0;
rxr->lro_enabled = FALSE;
/* Use header split if configured */
if (ixgbe_header_split)
rxr->hdr_split = TRUE;
+ else
+ ifp->if_capabilities &= ~IFCAP_LRO;
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/*
- ** Now set up the LRO interface, we
- ** also only do head split when LRO
- ** is enabled, since so often they
- ** are undesireable in similar setups.
+ ** Now set up the LRO interface:
+ ** 82598 uses software LRO, the
+ ** 82599 on the other hand uses a
+ ** hardware assist to do the same.
+ ** We only do LRO when header split
+ ** is enabled, its simpler that way.
*/
- if (ifp->if_capenable & IFCAP_LRO) {
+ if ((ifp->if_capenable & IFCAP_LRO) && (rxr->hdr_split)) {
int err = tcp_lro_init(lro);
- if (err) {
- INIT_DEBUGOUT("LRO Initialization failed!\n");
- goto fail;
- }
- INIT_DEBUGOUT("RX LRO Initialized\n");
+ if (err)
+ panic("LRO Initialization failed!\n");
+ INIT_DEBUGOUT("RX Soft LRO Initialized\n");
rxr->lro_enabled = TRUE;
lro->ifp = adapter->ifp;
+ ixgbe_setup_hw_rsc(rxr);
}
return (0);
-
+#if 0
fail:
/*
* We need to clean up any buffers allocated
@@ -3591,6 +3829,7 @@ fail:
}
}
return (ENOBUFS);
+#endif
}
/*********************************************************************
@@ -3844,7 +4083,7 @@ ixgbe_rxeof(struct rx_ring *rxr, int count)
struct ifnet *ifp = adapter->ifp;
struct lro_ctrl *lro = &rxr->lro;
struct lro_entry *queued;
- int i;
+ int i, processed = 0;
u32 staterr;
union ixgbe_adv_rx_desc *cur;
@@ -3865,31 +4104,69 @@ ixgbe_rxeof(struct rx_ring *rxr, int count)
while ((staterr & IXGBE_RXD_STAT_DD) && (count != 0) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- struct mbuf *sendmp, *mh, *mp;
- u16 hlen, plen, hdr, vtag;
- u8 dopayload, accept_frame, eop;
+ struct mbuf *sendmp, *mh, *mp, *nh, *np;
+ struct ixgbe_rx_buf *nxtbuf;
+ u32 rsc;
+ u16 hlen, plen, hdr, nextp, vtag;
+ bool accept_frame, eop;
- accept_frame = 1;
- hlen = plen = vtag = 0;
- sendmp = mh = mp = NULL;
+ accept_frame = TRUE;
+ hlen = plen = rsc = nextp = 0;
+ sendmp = mh = mp = nh = np = NULL;
/* Sync the buffers */
bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[i].map,
BUS_DMASYNC_POSTREAD);
+ mh = rxr->rx_buffers[i].m_head;
+ mp = rxr->rx_buffers[i].m_pack;
+ vtag = le16toh(cur->wb.upper.vlan);
+ eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);
+
+ if (!eop) {
+ /*
+ ** 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 current.
+ ** 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 (rxr->hw_rsc == TRUE) {
+ rsc = ixgbe_rsc_count(cur);
+ rxr->rsc_num += (rsc - 1);
+ }
+ if (rsc) {
+ nextp = ((staterr &
+ IXGBE_RXDADV_NEXTP_MASK) >>
+ IXGBE_RXDADV_NEXTP_SHIFT);
+ } else {
+ nextp = i + 1;
+ if (nextp == adapter->num_rx_desc)
+ nextp = 0;
+ }
+ nxtbuf = &rxr->rx_buffers[nextp];
+ prefetch(nxtbuf);
+ }
/*
** The way the hardware is configured to
** split, it will ONLY use the header buffer
** when header split is enabled, otherwise we
- ** get normal behavior, ie, both header and
- ** payload are DMA'd into the payload buffer.
+ ** get legacy behavior, ie, both header and
+ ** payload are DMA'd into JUST the payload buffer.
+ **
+ ** Rather than using the fmp/lmp global pointers
+ ** we now keep the head of a packet chain in the
+ ** m_nextpkt pointer and pass this along from one
+ ** descriptor to the next, until we get EOP.
**
- ** The fmp test is to catch the case where a
- ** packet spans multiple descriptors, in that
- ** case only the first header is valid.
*/
- if ((rxr->hdr_split) && (rxr->fmp == NULL)){
+ if ((rxr->hdr_split) && (mh->m_nextpkt == NULL)) {
hdr = le16toh(cur->
wb.lower.lo_dword.hs_rss.hdr_info);
hlen = (hdr & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
@@ -3897,182 +4174,168 @@ ixgbe_rxeof(struct rx_ring *rxr, int count)
if (hlen > IXGBE_RX_HDR)
hlen = IXGBE_RX_HDR;
plen = le16toh(cur->wb.upper.length);
- /* Handle the header mbuf */
- mh = rxr->rx_buffers[i].m_head;
mh->m_len = hlen;
- dopayload = IXGBE_CLEAN_HDR;
+ mh->m_flags |= M_PKTHDR;
+ mh->m_next = NULL;
+ mh->m_pkthdr.len = mh->m_len;
+ /* Null this so getbuf replenishes */
+ rxr->rx_buffers[i].m_head = NULL;
/*
** Get the payload length, this
** could be zero if its a small
** packet.
*/
if (plen) {
- mp = rxr->rx_buffers[i].m_pack;
mp->m_len = plen;
mp->m_next = NULL;
mp->m_flags &= ~M_PKTHDR;
mh->m_next = mp;
- mh->m_flags |= M_PKTHDR;
- dopayload = IXGBE_CLEAN_ALL;
+ mh->m_pkthdr.len += mp->m_len;
+ /* Null this so getbuf replenishes */
+ rxr->rx_buffers[i].m_pack = NULL;
rxr->rx_split_packets++;
- } else { /* small packets */
- mh->m_flags &= ~M_PKTHDR;
- mh->m_next = NULL;
+ }
+ /* Setup the forward chain */
+ if (eop == 0) {
+ nh = rxr->rx_buffers[nextp].m_head;
+ np = rxr->rx_buffers[nextp].m_pack;
+ nh->m_nextpkt = mh;
+ if (plen)
+ mp->m_next = np;
+ else
+ mh->m_next = np;
+ } else {
+ sendmp = mh;
+ if (staterr & IXGBE_RXD_STAT_VP) {
+ sendmp->m_pkthdr.ether_vtag = vtag;
+ sendmp->m_flags |= M_VLANTAG;
+ }
}
} else {
/*
** Either no header split, or a
** secondary piece of a fragmented
- ** split packet.
+ ** packet.
*/
- mh = rxr->rx_buffers[i].m_pack;
- mh->m_flags |= M_PKTHDR;
- mh->m_len = le16toh(cur->wb.upper.length);
- dopayload = IXGBE_CLEAN_PKT;
+ mp->m_len = le16toh(cur->wb.upper.length);
+ rxr->rx_buffers[i].m_pack = NULL;
+ /* stored head pointer */
+ sendmp = mh->m_nextpkt;
+ if (sendmp != NULL) {
+ sendmp->m_pkthdr.len += mp->m_len;
+ sendmp->m_nextpkt = NULL;
+ } else {
+ /* first desc of a non-ps chain */
+ sendmp = mp;
+ sendmp->m_flags |= M_PKTHDR;
+ sendmp->m_pkthdr.len = mp->m_len;
+ if (staterr & IXGBE_RXD_STAT_VP) {
+ sendmp->m_pkthdr.ether_vtag = vtag;
+ sendmp->m_flags |= M_VLANTAG;
+ }
+ }
+ /* Carry head forward */
+ if (eop == 0) {
+ nh = rxr->rx_buffers[nextp].m_head;
+ np = rxr->rx_buffers[nextp].m_pack;
+ nh->m_nextpkt = sendmp;
+ mp->m_next = np;
+ sendmp = NULL;
+ }
+ mh->m_nextpkt = NULL;
}
- if (staterr & IXGBE_RXD_STAT_EOP) {
- count--;
- eop = 1;
- } else
- eop = 0;
-
-#ifdef IXGBE_IEEE1588
- This code needs to be converted to work here
- -----------------------------------------------------
- if (unlikely(staterr & IXGBE_RXD_STAT_TS)) {
- u64 regval;
- u64 ns;
-// Create an mtag and set it up
- struct skb_shared_hwtstamps *shhwtstamps =
- skb_hwtstamps(skb);
-
- rd32(IXGBE_TSYNCRXCTL) & IXGBE_TSYNCRXCTL_VALID),
- "igb: no RX time stamp available for time stamped packet");
- regval = rd32(IXGBE_RXSTMPL);
- regval |= (u64)rd32(IXGBE_RXSTMPH) << 32;
-// Do time conversion from the register
- ns = timecounter_cyc2time(&adapter->clock, regval);
- clocksync_update(&adapter->sync, ns);
- memset(shhwtstamps, 0, sizeof(*shhwtstamps));
- shhwtstamps->hwtstamp = ns_to_ktime(ns);
- shhwtstamps->syststamp =
- clocksync_hw2sys(&adapter->sync, ns);
- }
-#endif
-
if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)
- accept_frame = 0;
+ accept_frame = FALSE;
if (accept_frame) {
- /*
- ** Save the vlan id, because get_buf will
- ** clobber the writeback descriptor...
- */
- vtag = le16toh(cur->wb.upper.vlan);
- if (ixgbe_get_buf(rxr, i, dopayload) != 0) {
- ifp->if_iqdrops++;
- goto discard;
- }
- /* Initial frame - setup */
- if (rxr->fmp == NULL) {
- mh->m_flags |= M_PKTHDR;
- mh->m_pkthdr.len = mh->m_len;
- rxr->fmp = mh; /* Store the first mbuf */
- rxr->lmp = mh;
- if (mp) { /* Add payload if split */
- mh->m_pkthdr.len += mp->m_len;
- rxr->lmp = mh->m_next;
- }
- } else {
- /* Chain mbuf's together */
- mh->m_flags &= ~M_PKTHDR;
- rxr->lmp->m_next = mh;
- rxr->lmp = rxr->lmp->m_next;
- rxr->fmp->m_pkthdr.len += mh->m_len;
- }
-
+ ++processed;
if (eop) {
- rxr->fmp->m_pkthdr.rcvif = ifp;
+ --count;
+ sendmp->m_pkthdr.rcvif = ifp;
ifp->if_ipackets++;
rxr->rx_packets++;
/* capture data for AIM */
- rxr->bytes += rxr->fmp->m_pkthdr.len;
+ rxr->bytes += sendmp->m_pkthdr.len;
rxr->rx_bytes += rxr->bytes;
if (ifp->if_capenable & IFCAP_RXCSUM)
- ixgbe_rx_checksum(staterr, rxr->fmp);
+ ixgbe_rx_checksum(staterr, sendmp);
else
- rxr->fmp->m_pkthdr.csum_flags = 0;
- if (staterr & IXGBE_RXD_STAT_VP) {
- rxr->fmp->m_pkthdr.ether_vtag = vtag;
- rxr->fmp->m_flags |= M_VLANTAG;
- }
+ sendmp->m_pkthdr.csum_flags = 0;
#if __FreeBSD_version >= 800000
- rxr->fmp->m_pkthdr.flowid = curcpu;
- rxr->fmp->m_flags |= M_FLOWID;
+ /* Get the RSS Hash */
+ sendmp->m_pkthdr.flowid =
+ le16toh(cur->wb.lower.hi_dword.rss);
+ sendmp->m_flags |= M_FLOWID;
#endif
- sendmp = rxr->fmp;
- rxr->fmp = NULL;
- rxr->lmp = NULL;
}
} else {
ifp->if_ierrors++;
-discard:
/* Reuse loaded DMA map and just update mbuf chain */
- if (hlen) {
- mh = rxr->rx_buffers[i].m_head;
- mh->m_len = MHLEN;
- mh->m_next = NULL;
- }
- mp = rxr->rx_buffers[i].m_pack;
+ mh->m_len = MHLEN;
+ mh->m_flags |= M_PKTHDR;
+ mh->m_next = NULL;
mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz;
mp->m_data = mp->m_ext.ext_buf;
+ if (mp->m_next) { /* Free chain */
+ sendmp = mp->m_next;
+ m_free(sendmp);
+ }
mp->m_next = NULL;
if (adapter->max_frame_size <=
(MCLBYTES - ETHER_ALIGN))
m_adj(mp, ETHER_ALIGN);
- if (rxr->fmp != NULL) {
- /* handles the whole chain */
- m_freem(rxr->fmp);
- rxr->fmp = NULL;
- rxr->lmp = NULL;
- }
sendmp = NULL;
}
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- rxr->last_cleaned = i; /* for updating tail */
-
+ rxr->last_refreshed = i; /* for updating tail */
if (++i == adapter->num_rx_desc)
i = 0;
+ /* Prefetch next descriptor */
+ cur = &rxr->rx_base[i];
+ prefetch(cur);
/*
** Now send up to the stack,
- ** note the the value of next_to_check
- ** is safe because we keep the RX lock
- ** thru this call.
+ ** note that the RX lock is
+ ** held thru this call.
*/
if (sendmp != NULL) {
/*
** Send to the stack if:
- ** - LRO not enabled, or
- ** - no LRO resources, or
- ** - lro enqueue fails
+ ** - Soft LRO not enabled, or
+ ** - no Soft LRO resources, or
+ ** - soft lro enqueue fails
*/
if ((!rxr->lro_enabled) ||
((!lro->lro_cnt) || (tcp_lro_rx(lro, sendmp, 0))))
(*ifp->if_input)(ifp, sendmp);
}
- /* Get next descriptor */
- cur = &rxr->rx_base[i];
+ /* Replenish every 8 max */
+ if (processed == 8) {
+ ixgbe_get_buf(rxr, rxr->next_to_check, i);
+ processed = 0;
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_RDT(rxr->me), rxr->last_refreshed);
+ rxr->next_to_check = i;
+ }
+
+ /* Next iteration */
staterr = cur->wb.upper.status_error;
}
- rxr->next_to_check = i;
- /* Advance the IXGB's Receive Queue "Tail Pointer" */
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), rxr->last_cleaned);
+ /* Replenish remaining work */
+ if (processed != 0) {
+ ixgbe_get_buf(rxr, rxr->next_to_check, i);
+ processed = 0;
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_RDT(rxr->me), rxr->last_refreshed);
+ }
+
+ rxr->next_to_check = i;
/*
* Flush any outstanding LRO work
@@ -4090,7 +4353,7 @@ discard:
** then schedule another interrupt.
*/
if (staterr & IXGBE_RXD_STAT_DD) {
- ixgbe_rearm_rx_queues(adapter, (u64)(1 << rxr->msix));
+ ixgbe_rearm_queues(adapter, (u64)(1 << rxr->msix));
return TRUE;
}
@@ -4244,6 +4507,9 @@ ixgbe_enable_intr(struct adapter *adapter)
mask |= IXGBE_EIMS_ECC;
mask |= IXGBE_EIMS_GPI_SDP1;
mask |= IXGBE_EIMS_GPI_SDP2;
+#ifdef IXGBE_FDIR
+ mask |= IXGBE_EIMS_FLOW_DIR;
+#endif
}
IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
@@ -4435,7 +4701,12 @@ ixgbe_handle_mod(void *context, int pending)
"Unsupported SFP+ module type was detected.\n");
return;
}
- hw->mac.ops.setup_sfp(hw);
+ err = hw->mac.ops.setup_sfp(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev,
+ "Setup failure - unsupported SFP+ module type.\n");
+ return;
+ }
taskqueue_enqueue(adapter->tq, &adapter->msf_task);
return;
}
@@ -4450,17 +4721,39 @@ ixgbe_handle_msf(void *context, int pending)
struct adapter *adapter = context;
struct ixgbe_hw *hw = &adapter->hw;
u32 autoneg;
-
- if (hw->mac.ops.get_link_capabilities)
- hw->mac.ops.get_link_capabilities(hw, &autoneg,
- &hw->mac.autoneg);
- if (hw->mac.ops.setup_link_speed)
- hw->mac.ops.setup_link_speed(hw, autoneg, TRUE, TRUE);
- ixgbe_check_link(&adapter->hw,
- &adapter->link_speed, &adapter->link_up, 0);
+ bool negotiate;
+
+ 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, negotiate, TRUE);
+#if 0
+ ixgbe_check_link(&adapter->hw, &speed, &adapter->link_up, 0);
ixgbe_update_link_status(adapter);
+#endif
+ return;
+}
+
+#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->fdir_reinit != 1) /* Shouldn't happen */
+ return;
+ ixgbe_reinit_fdir_tables_82599(&adapter->hw);
+ adapter->fdir_reinit = 0;
+ /* Restart the interface */
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
return;
}
+#endif
/**********************************************************************
*
@@ -4482,12 +4775,12 @@ ixgbe_update_stats_counters(struct adapter *adapter)
mp = IXGBE_READ_REG(hw, IXGBE_MPC(i));
/* missed_rx tallies misses for the gprc workaround */
missed_rx += mp;
+ /* global total per queue */
adapter->stats.mpc[i] += mp;
/* Running comprehensive total for stats display */
total_missed_rx += adapter->stats.mpc[i];
if (hw->mac.type == ixgbe_mac_82598EB)
- adapter->stats.rnbc[i] +=
- IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+ adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
}
/* Hardware workaround, gprc counts missed packets */
@@ -4508,7 +4801,7 @@ ixgbe_update_stats_counters(struct adapter *adapter)
adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
/* 82598 only has a counter in the high register */
adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
- adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
+ adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
}
@@ -4653,6 +4946,8 @@ ixgbe_print_debug_info(struct adapter *adapter)
rxr->me, lro->lro_queued);
device_printf(dev,"RX(%d) LRO Flushed= %d\n",
rxr->me, lro->lro_flushed);
+ device_printf(dev,"RX(%d) HW LRO Merges= %lu\n",
+ rxr->me, (long)rxr->rsc_num);
}
for (int i = 0; i < adapter->num_queues; i++, txr++) {
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index 848820a..d52eed3 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -134,9 +134,11 @@
#define MAX_LOOP 10
/*
- * This parameter controls the duration of transmit watchdog timer.
+ * This is the max watchdog interval, ie. the time that can
+ * pass between any two TX clean operations, such only happening
+ * when the TX hardware is functioning.
*/
-#define IXGBE_TX_TIMEOUT 5 /* set to 5 seconds */
+#define IXGBE_WATCHDOG (10 * hz)
/*
* This parameters control when the driver calls the routine to reclaim
@@ -148,7 +150,7 @@
#define IXGBE_MAX_FRAME_SIZE 0x3F00
/* Flow control constants */
-#define IXGBE_FC_PAUSE 0x680
+#define IXGBE_FC_PAUSE 0xFFFF
#define IXGBE_FC_HI 0x20000
#define IXGBE_FC_LO 0x10000
@@ -174,7 +176,7 @@
#define MSIX_82599_BAR 4
#define IXGBE_TSO_SIZE 65535
#define IXGBE_TX_BUFFER_SIZE ((u32) 1514)
-#define IXGBE_RX_HDR 128
+#define IXGBE_RX_HDR 256
#define IXGBE_VFTA_SIZE 128
#define IXGBE_BR_SIZE 4096
#define CSUM_OFFLOAD 7 /* Bits in csum flags */
@@ -253,14 +255,15 @@ struct tx_ring {
struct mtx tx_mtx;
u32 me;
u32 msix;
- u32 watchdog_timer;
+ bool watchdog_check;
+ int watchdog_time;
union ixgbe_adv_tx_desc *tx_base;
volatile u32 tx_hwb;
struct ixgbe_dma_alloc txdma;
struct task tx_task;
struct taskqueue *tq;
- u32 next_avail_tx_desc;
- u32 next_tx_to_clean;
+ u32 next_avail_desc;
+ u32 next_to_clean;
struct ixgbe_tx_buf *tx_buffers;
volatile u16 tx_avail;
u32 txd_cmd;
@@ -272,7 +275,10 @@ struct tx_ring {
/* Interrupt resources */
void *tag;
struct resource *res;
-
+#ifdef IXGBE_FDIR
+ u16 atr_sample;
+ u16 atr_count;
+#endif
/* Soft Stats */
u32 no_tx_desc_avail;
u32 no_tx_desc_late;
@@ -297,13 +303,12 @@ struct rx_ring {
struct lro_ctrl lro;
bool lro_enabled;
bool hdr_split;
- unsigned int last_cleaned;
+ bool hw_rsc;
+ unsigned int last_refreshed;
unsigned int next_to_check;
struct ixgbe_rx_buf *rx_buffers;
bus_dma_tag_t rxtag;
bus_dmamap_t spare_map;
- struct mbuf *fmp;
- struct mbuf *lmp;
char mtx_name[16];
u32 bytes; /* Used for AIM calc */
@@ -318,6 +323,10 @@ struct rx_ring {
u64 rx_split_packets;
u64 rx_packets;
u64 rx_bytes;
+ u64 rsc_num;
+#ifdef IXGBE_FDIR
+ u64 flm;
+#endif
};
/* Our adapter structure */
@@ -349,21 +358,16 @@ struct adapter {
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
- u32 num_vlans;
+ u16 num_vlans;
u16 num_queues;
/* Info about the board itself */
- u32 part_num;
u32 optics;
bool link_active;
u16 max_frame_size;
u32 link_speed;
bool link_up;
u32 linkvec;
- u32 tx_int_delay;
- u32 tx_abs_int_delay;
- u32 rx_int_delay;
- u32 rx_abs_int_delay;
/* Mbuf cluster size */
u32 rx_mbuf_sz;
@@ -373,6 +377,10 @@ struct adapter {
struct task link_task; /* Link tasklet */
struct task mod_task; /* SFP tasklet */
struct task msf_task; /* Multispeed Fiber tasklet */
+#ifdef IXGBE_FDIR
+ int fdir_reinit;
+ struct task fdir_task;
+#endif
struct taskqueue *tq;
/*
@@ -423,12 +431,12 @@ struct adapter {
#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_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_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)
diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c
index fb711c6..12711b0 100644
--- a/sys/dev/ixgbe/ixgbe_82598.c
+++ b/sys/dev/ixgbe/ixgbe_82598.c
@@ -44,20 +44,21 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
bool *autoneg);
static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw);
s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num);
-static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw);
+static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw,
+ bool autoneg_wait_to_complete);
static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
ixgbe_link_speed *speed, bool *link_up,
bool link_up_wait_to_complete);
-static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
-static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw);
-static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw);
+s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan,
@@ -70,7 +71,50 @@ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
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);
+static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw);
+/**
+ * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
+ * @hw: pointer to the HW structure
+ *
+ * The defaults for 82598 should be in the range of 50us to 50ms,
+ * however the hardware default for these parts is 500us to 1ms which is less
+ * than the 10ms recommended by the pci-e spec. To address this we need to
+ * increase the value to either 10ms to 250ms for capability version 1 config,
+ * or 16ms to 55ms for version 2.
+ **/
+void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
+{
+ u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
+ u16 pcie_devctl2;
+
+ /* only take action if timeout value is defaulted to 0 */
+ if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
+ goto out;
+
+ /*
+ * if capababilities version is type 1 we can write the
+ * timeout of 10ms to 250ms through the GCR register
+ */
+ if (!(gcr & IXGBE_GCR_CAP_VER2)) {
+ gcr |= IXGBE_GCR_CMPL_TMOUT_10ms;
+ goto out;
+ }
+
+ /*
+ * for version 2 capabilities we need to write the config space
+ * directly in order to set the completion timeout value for
+ * 16ms to 55ms
+ */
+ pcie_devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2);
+ pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
+ IXGBE_WRITE_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
+out:
+ /* disable completion timeout resend */
+ gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND;
+ IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr);
+}
/**
* ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
@@ -83,6 +127,8 @@ u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw)
{
u32 msix_count = 18;
+ DEBUGFUNC("ixgbe_get_pcie_msix_count_82598");
+
if (hw->mac.msix_vectors_from_pcie) {
msix_count = IXGBE_READ_PCIE_WORD(hw,
IXGBE_PCIE_MSIX_82598_CAPS);
@@ -108,6 +154,8 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw)
struct ixgbe_phy_info *phy = &hw->phy;
s32 ret_val;
+ DEBUGFUNC("ixgbe_init_ops_82598");
+
ret_val = ixgbe_init_phy_ops_generic(hw);
ret_val = ixgbe_init_ops_generic(hw);
@@ -115,6 +163,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw)
phy->ops.init = &ixgbe_init_phy_ops_82598;
/* MAC */
+ mac->ops.start_hw = &ixgbe_start_hw_82598;
mac->ops.reset_hw = &ixgbe_reset_hw_82598;
mac->ops.get_media_type = &ixgbe_get_media_type_82598;
mac->ops.get_supported_physical_layer =
@@ -145,7 +194,6 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw)
/* Link */
mac->ops.check_link = &ixgbe_check_mac_link_82598;
mac->ops.setup_link = &ixgbe_setup_mac_link_82598;
- mac->ops.setup_link_speed = &ixgbe_setup_mac_link_speed_82598;
mac->ops.get_link_capabilities =
&ixgbe_get_link_capabilities_82598;
@@ -168,6 +216,7 @@ s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
s32 ret_val = IXGBE_SUCCESS;
u16 list_offset, data_offset;
+ DEBUGFUNC("ixgbe_init_phy_ops_82598");
/* Identify the PHY */
phy->ops.identify(hw);
@@ -175,21 +224,20 @@ s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
/* Overwrite the link function pointers if copper PHY */
if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
- mac->ops.setup_link_speed =
- &ixgbe_setup_copper_link_speed_82598;
mac->ops.get_link_capabilities =
&ixgbe_get_copper_link_capabilities_generic;
}
switch (hw->phy.type) {
case ixgbe_phy_tn:
+ phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
phy->ops.check_link = &ixgbe_check_phy_link_tnx;
phy->ops.get_firmware_version =
&ixgbe_get_phy_firmware_version_tnx;
break;
case ixgbe_phy_aq:
phy->ops.get_firmware_version =
- &ixgbe_get_phy_firmware_version_aq;
+ &ixgbe_get_phy_firmware_version_generic;
break;
case ixgbe_phy_nl:
phy->ops.reset = &ixgbe_reset_phy_nl;
@@ -221,6 +269,46 @@ out:
}
/**
+ * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx
+ * @hw: pointer to hardware structure
+ *
+ * Starts the hardware using the generic start_hw function.
+ * Then set pcie completion timeout
+ **/
+s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
+{
+ u32 regval;
+ u32 i;
+ s32 ret_val = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_start_hw_82598");
+
+ ret_val = ixgbe_start_hw_generic(hw);
+
+ /* Disable relaxed ordering */
+ for (i = 0; ((i < hw->mac.max_tx_queues) &&
+ (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
+ regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
+ regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval);
+ }
+
+ for (i = 0; ((i < hw->mac.max_rx_queues) &&
+ (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
+ regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
+ regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
+ IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
+ }
+
+ /* set the completion timeout for interface */
+ if (ret_val == IXGBE_SUCCESS)
+ ixgbe_set_pcie_completion_timeout(hw);
+
+ return ret_val;
+}
+
+/**
* ixgbe_get_link_capabilities_82598 - Determines link capabilities
* @hw: pointer to hardware structure
* @speed: pointer to link speed
@@ -235,6 +323,8 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
s32 status = IXGBE_SUCCESS;
u32 autoc = 0;
+ DEBUGFUNC("ixgbe_get_link_capabilities_82598");
+
/*
* Determine link capabilities based on the stored value of AUTOC,
* which represents EEPROM defaults. If AUTOC value has not been
@@ -289,6 +379,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
{
enum ixgbe_media_type media_type;
+ DEBUGFUNC("ixgbe_get_media_type_82598");
+
/* Detect if there is a copper PHY attached. */
if (hw->phy.type == ixgbe_phy_cu_unknown ||
hw->phy.type == ixgbe_phy_tn ||
@@ -306,15 +398,18 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
break;
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
- case IXGBE_DEV_ID_82598EB_CX4:
- case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
case IXGBE_DEV_ID_82598EB_XF_LR:
case IXGBE_DEV_ID_82598EB_SFP_LOM:
media_type = ixgbe_media_type_fiber;
break;
+ case IXGBE_DEV_ID_82598EB_CX4:
+ case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
+ media_type = ixgbe_media_type_cx4;
+ break;
case IXGBE_DEV_ID_82598AT:
+ case IXGBE_DEV_ID_82598AT2:
media_type = ixgbe_media_type_copper;
break;
default:
@@ -338,9 +433,23 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
u32 fctrl_reg;
u32 rmcs_reg;
u32 reg;
+ u32 link_speed = 0;
+ bool link_up;
DEBUGFUNC("ixgbe_fc_enable_82598");
+ /*
+ * On 82598 backplane having FC on causes resets while doing
+ * KX, so turn off here.
+ */
+ hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE);
+ if (link_up &&
+ link_speed == IXGBE_LINK_SPEED_1GB_FULL &&
+ hw->mac.ops.get_media_type(hw) == ixgbe_media_type_backplane) {
+ hw->fc.disable_fc_autoneg = TRUE;
+ hw->fc.requested_mode = ixgbe_fc_none;
+ }
+
/* Negotiate the fc mode to use */
ret_val = ixgbe_fc_autoneg(hw);
if (ret_val)
@@ -394,7 +503,7 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
- ret_val = -IXGBE_ERR_CONFIG;
+ ret_val = IXGBE_ERR_CONFIG;
goto out;
break;
}
@@ -433,26 +542,29 @@ out:
}
/**
- * ixgbe_setup_mac_link_82598 - Configures MAC link settings
+ * ixgbe_start_mac_link_82598 - Configures MAC link settings
* @hw: pointer to hardware structure
*
* Configures link settings based on values in the ixgbe_hw struct.
* Restarts the link. Performs autonegotiation if needed.
**/
-static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
+static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw,
+ bool autoneg_wait_to_complete)
{
u32 autoc_reg;
u32 links_reg;
u32 i;
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_start_mac_link_82598");
+
/* Restart link */
autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
/* Only poll for autoneg to complete if specified to do so */
- if (hw->phy.autoneg_wait_to_complete) {
+ if (autoneg_wait_to_complete) {
if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
IXGBE_AUTOC_LMS_KX4_AN ||
(autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
@@ -494,6 +606,8 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
u32 i;
u16 link_reg, adapt_comp_reg;
+ DEBUGFUNC("ixgbe_check_mac_link_82598");
+
/*
* SERDES PHY requires us to read link status from undocumented
* register 0xC79F. Bit 0 set indicates link is up/ready; clear
@@ -558,17 +672,22 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
else
*speed = IXGBE_LINK_SPEED_1GB_FULL;
+ if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == TRUE) &&
+ (ixgbe_validate_link_ready(hw) != IXGBE_SUCCESS))
+ *link_up = FALSE;
+
/* if link is down, zero out the current_mode */
if (*link_up == FALSE) {
hw->fc.current_mode = ixgbe_fc_none;
hw->fc.fc_was_autonegged = FALSE;
}
+
out:
return IXGBE_SUCCESS;
}
/**
- * ixgbe_setup_mac_link_speed_82598 - Set MAC link speed
+ * ixgbe_setup_mac_link_82598 - Set MAC link speed
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
@@ -576,7 +695,7 @@ out:
*
* Set the link speed in the AUTOC register and restarts link.
**/
-static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete)
{
@@ -586,6 +705,8 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
u32 autoc = curr_autoc;
u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
+ DEBUGFUNC("ixgbe_setup_mac_link_82598");
+
/* Check to see if speed passed in is supported. */
ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg);
speed &= link_capabilities;
@@ -606,14 +727,13 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
}
if (status == IXGBE_SUCCESS) {
- hw->phy.autoneg_wait_to_complete = autoneg_wait_to_complete;
-
/*
* Setup and restart the link based on the new values in
* ixgbe_hw This will write the AUTOC register based on the new
* stored values
*/
- status = ixgbe_setup_mac_link_82598(hw);
+ status = ixgbe_start_mac_link_82598(hw,
+ autoneg_wait_to_complete);
}
return status;
@@ -621,29 +741,7 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
/**
- * ixgbe_setup_copper_link_82598 - Setup copper link settings
- * @hw: pointer to hardware structure
- *
- * Configures link settings based on values in the ixgbe_hw struct.
- * Restarts the link. Performs autonegotiation if needed. Restart
- * phy and wait for autonegotiate to finish. Then synchronize the
- * MAC and PHY.
- **/
-static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw)
-{
- s32 status;
-
- /* Restart autonegotiation on PHY */
- status = hw->phy.ops.setup_link(hw);
-
- /* Set up MAC */
- ixgbe_setup_mac_link_82598(hw);
-
- return status;
-}
-
-/**
- * ixgbe_setup_copper_link_speed_82598 - Set the PHY autoneg advertised field
+ * ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
@@ -651,18 +749,20 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw)
*
* Sets the link speed in the AUTOC register in the MAC and restarts link.
**/
-static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete)
{
s32 status;
+ DEBUGFUNC("ixgbe_setup_copper_link_82598");
+
/* Setup the PHY according to input speed */
status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
autoneg_wait_to_complete);
/* Set up MAC */
- ixgbe_setup_mac_link_82598(hw);
+ ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
return status;
}
@@ -685,6 +785,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
u32 autoc;
u8 analog_val;
+ DEBUGFUNC("ixgbe_reset_hw_82598");
+
/* Call adapter stop to disable tx/rx and clear interrupts */
hw->mac.ops.stop_adapter(hw);
@@ -811,6 +913,8 @@ s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
{
u32 rar_high;
+ DEBUGFUNC("ixgbe_set_vmdq_82598");
+
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
rar_high &= ~IXGBE_RAH_VIND_MASK;
rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK);
@@ -861,6 +965,8 @@ s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
u32 bits;
u32 vftabyte;
+ DEBUGFUNC("ixgbe_set_vfta_82598");
+
if (vlan > 4095)
return IXGBE_ERR_PARAM;
@@ -903,6 +1009,8 @@ static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw)
u32 offset;
u32 vlanbyte;
+ DEBUGFUNC("ixgbe_clear_vfta_82598");
+
for (offset = 0; offset < hw->mac.vft_size; offset++)
IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
@@ -926,6 +1034,8 @@ s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val)
{
u32 atlas_ctl;
+ DEBUGFUNC("ixgbe_read_analog_reg8_82598");
+
IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL,
IXGBE_ATLASCTL_WRITE_CMD | (reg << 8));
IXGBE_WRITE_FLUSH(hw);
@@ -948,6 +1058,8 @@ s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
{
u32 atlas_ctl;
+ DEBUGFUNC("ixgbe_write_analog_reg8_82598");
+
atlas_ctl = (reg << 8) | val;
IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl);
IXGBE_WRITE_FLUSH(hw);
@@ -973,6 +1085,8 @@ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u16 sfp_stat = 0;
u32 i;
+ DEBUGFUNC("ixgbe_read_i2c_eeprom_82598");
+
if (hw->phy.type == ixgbe_phy_nl) {
/*
* NetLogic phy SDA/SCL registers are at addresses 0xC30A to
@@ -1032,6 +1146,8 @@ u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
u16 ext_ability = 0;
+ DEBUGFUNC("ixgbe_get_supported_physical_layer_82598");
+
hw->phy.ops.identify(hw);
/* Copper PHY must be checked before AUTOC LMS to determine correct
@@ -1128,6 +1244,8 @@ void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw)
struct ixgbe_bus_info *bus = &hw->bus;
u16 pci_gen, pci_ctrl2;
+ DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie_82598");
+
ixgbe_set_lan_id_multi_port_pcie(hw);
/* check if LAN0 is disabled */
@@ -1146,4 +1264,38 @@ void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw)
}
}
+/**
+ * ixgbe_validate_link_ready - Function looks for phy link
+ * @hw: pointer to hardware structure
+ *
+ * Function indicates success when phy link is available. If phy is not ready
+ * within 5 seconds of MAC indicating link, the function returns error.
+ **/
+static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw)
+{
+ u32 timeout;
+ u16 an_reg;
+
+ if (hw->device_id != IXGBE_DEV_ID_82598AT2)
+ return IXGBE_SUCCESS;
+
+ for (timeout = 0;
+ timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) {
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &an_reg);
+
+ if ((an_reg & IXGBE_MII_AUTONEG_COMPLETE) &&
+ (an_reg & IXGBE_MII_AUTONEG_LINK_UP))
+ break;
+
+ msec_delay(100);
+ }
+
+ if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) {
+ DEBUGOUT("Link was indicated but link is down\n");
+ return IXGBE_ERR_LINK_SETUP;
+ }
+
+ return IXGBE_SUCCESS;
+}
diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c
index c3d23af..97b655a 100644
--- a/sys/dev/ixgbe/ixgbe_82599.c
+++ b/sys/dev/ixgbe/ixgbe_82599.c
@@ -37,39 +37,30 @@
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
-u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw);
s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw);
s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *autoneg);
enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw);
-s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw);
-s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete);
-s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw);
-s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw,
- ixgbe_link_speed *speed,
- bool *link_up, bool link_up_wait_to_complete);
-s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw,
+s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed, bool autoneg,
+ bool autoneg_wait_to_complete);
+s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
+ bool autoneg_wait_to_complete);
+s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
-static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw);
-static s32 ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw);
void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw);
s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw);
-s32 ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
-s32 ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
-s32 ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
-s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan,
- u32 vind, bool vlan_on);
-s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw);
-s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw);
s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw);
@@ -77,14 +68,9 @@ 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);
s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval);
-s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw,
- u16 *san_mac_offset);
-s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr);
-s32 ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps);
static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
-
void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
@@ -93,15 +79,14 @@ void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
if (hw->phy.multispeed_fiber) {
/* Set up dual speed SFP+ support */
- mac->ops.setup_link =
- &ixgbe_setup_mac_link_multispeed_fiber;
- mac->ops.setup_link_speed =
- &ixgbe_setup_mac_link_speed_multispeed_fiber;
+ mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
} else {
- mac->ops.setup_link =
- &ixgbe_setup_mac_link_82599;
- mac->ops.setup_link_speed =
- &ixgbe_setup_mac_link_speed_82599;
+ if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) &&
+ (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
+ hw->phy.smart_speed == ixgbe_smart_speed_on))
+ mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed;
+ else
+ mac->ops.setup_link = &ixgbe_setup_mac_link_82599;
}
}
@@ -135,8 +120,6 @@ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
/* If copper media, overwrite with copper function pointers */
if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
mac->ops.setup_link = &ixgbe_setup_copper_link_82599;
- mac->ops.setup_link_speed =
- &ixgbe_setup_copper_link_speed_82599;
mac->ops.get_link_capabilities =
&ixgbe_get_copper_link_capabilities_generic;
}
@@ -144,13 +127,14 @@ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
/* Set necessary function pointers based on phy type */
switch (hw->phy.type) {
case ixgbe_phy_tn:
+ phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
phy->ops.check_link = &ixgbe_check_phy_link_tnx;
phy->ops.get_firmware_version =
&ixgbe_get_phy_firmware_version_tnx;
break;
case ixgbe_phy_aq:
phy->ops.get_firmware_version =
- &ixgbe_get_phy_firmware_version_aq;
+ &ixgbe_get_phy_firmware_version_generic;
break;
default:
break;
@@ -204,30 +188,6 @@ setup_sfp_out:
}
/**
- * ixgbe_get_pcie_msix_count_82599 - Gets MSI-X vector count
- * @hw: pointer to hardware structure
- *
- * Read PCIe configuration space, and get the MSI-X vector count from
- * the capabilities table.
- **/
-u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw)
-{
- u32 msix_count = 64;
-
- if (hw->mac.msix_vectors_from_pcie) {
- msix_count = IXGBE_READ_PCIE_WORD(hw,
- IXGBE_PCIE_MSIX_82599_CAPS);
- msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
-
- /* MSI-X count is zero-based in HW, so increment to give
- * proper value */
- msix_count++;
- }
-
- return msix_count;
-}
-
-/**
* ixgbe_init_ops_82599 - Inits func ptrs and MAC type
* @hw: pointer to hardware structure
*
@@ -241,6 +201,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
struct ixgbe_phy_info *phy = &hw->phy;
s32 ret_val;
+ DEBUGFUNC("ixgbe_init_ops_82599");
+
ret_val = ixgbe_init_phy_ops_generic(hw);
ret_val = ixgbe_init_ops_generic(hw);
@@ -257,23 +219,24 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82599;
mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82599;
mac->ops.start_hw = &ixgbe_start_hw_rev_1_82599;
- mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_82599;
- mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_82599;
+ mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic;
+ mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic;
mac->ops.get_device_caps = &ixgbe_get_device_caps_82599;
+ mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic;
/* RAR, Multicast, VLAN */
- mac->ops.set_vmdq = &ixgbe_set_vmdq_82599;
- mac->ops.clear_vmdq = &ixgbe_clear_vmdq_82599;
- mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_82599;
+ mac->ops.set_vmdq = &ixgbe_set_vmdq_generic;
+ mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic;
+ mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic;
mac->rar_highwater = 1;
- mac->ops.set_vfta = &ixgbe_set_vfta_82599;
- mac->ops.clear_vfta = &ixgbe_clear_vfta_82599;
- mac->ops.init_uta_tables = &ixgbe_init_uta_tables_82599;
+ mac->ops.set_vfta = &ixgbe_set_vfta_generic;
+ mac->ops.clear_vfta = &ixgbe_clear_vfta_generic;
+ mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic;
mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_82599;
/* Link */
mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599;
- mac->ops.check_link = &ixgbe_check_mac_link_82599;
+ mac->ops.check_link = &ixgbe_check_mac_link_generic;
ixgbe_init_mac_link_ops_82599(hw);
mac->mcft_size = 128;
@@ -281,7 +244,7 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
mac->num_rar_entries = 128;
mac->max_tx_queues = 128;
mac->max_rx_queues = 128;
- mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw);
+ mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
return ret_val;
@@ -302,6 +265,8 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
s32 status = IXGBE_SUCCESS;
u32 autoc = 0;
+ DEBUGFUNC("ixgbe_get_link_capabilities_82599");
+
/*
* Determine link capabilities based on the stored value of AUTOC,
* which represents EEPROM defaults. If AUTOC value has not
@@ -387,6 +352,8 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
{
enum ixgbe_media_type media_type;
+ DEBUGFUNC("ixgbe_get_media_type_82599");
+
/* Detect if there is a copper PHY attached. */
if (hw->phy.type == ixgbe_phy_cu_unknown ||
hw->phy.type == ixgbe_phy_tn ||
@@ -397,6 +364,8 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
switch (hw->device_id) {
case IXGBE_DEV_ID_82599_KX4:
+ case IXGBE_DEV_ID_82599_KX4_MEZZ:
+ case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
case IXGBE_DEV_ID_82599_XAUI_LOM:
/* Default device ID is mezzanine card KX/KX4 */
media_type = ixgbe_media_type_backplane;
@@ -405,7 +374,7 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
media_type = ixgbe_media_type_fiber;
break;
case IXGBE_DEV_ID_82599_CX4:
- media_type = ixgbe_media_type_fiber;
+ media_type = ixgbe_media_type_cx4;
break;
default:
media_type = ixgbe_media_type_unknown;
@@ -416,19 +385,22 @@ out:
}
/**
- * ixgbe_setup_mac_link_82599 - Setup MAC link settings
+ * ixgbe_start_mac_link_82599 - Setup MAC link settings
* @hw: pointer to hardware structure
*
* Configures link settings based on values in the ixgbe_hw struct.
* Restarts the link. Performs autonegotiation if needed.
**/
-s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw)
+s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
+ bool autoneg_wait_to_complete)
{
u32 autoc_reg;
u32 links_reg;
u32 i;
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_start_mac_link_82599");
+
/* Restart link */
autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
@@ -436,7 +408,7 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
/* Only poll for autoneg to complete if specified to do so */
- if (hw->phy.autoneg_wait_to_complete) {
+ if (autoneg_wait_to_complete) {
if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
IXGBE_AUTOC_LMS_KX4_KX_KR ||
(autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
@@ -464,27 +436,7 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw)
}
/**
- * ixgbe_setup_mac_link_multispeed_fiber - Setup MAC link settings
- * @hw: pointer to hardware structure
- *
- * Configures link settings based on values in the ixgbe_hw struct.
- * Restarts the link for multi-speed fiber at 1G speed, if link
- * fails at 10G.
- * Performs autonegotiation if needed.
- **/
-s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw)
-{
- s32 status = IXGBE_SUCCESS;
- ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_82599_AUTONEG;
- DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
-
- status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw,
- link_speed, TRUE, true);
- return status;
-}
-
-/**
- * ixgbe_setup_mac_link_speed_multispeed_fiber - Set MAC link speed
+ * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
@@ -492,7 +444,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw)
*
* Set the link speed in the AUTOC register and restarts link.
**/
-s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete)
{
@@ -505,22 +457,15 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
bool link_up = FALSE;
bool negotiation;
+ DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
+
/* Mask off requested but non-supported speeds */
status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation);
if (status != IXGBE_SUCCESS)
- goto out;
+ return status;
speed &= link_speed;
- /* Set autoneg_advertised value based on input link speed */
- hw->phy.autoneg_advertised = 0;
-
- if (speed & IXGBE_LINK_SPEED_10GB_FULL)
- hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
-
- if (speed & IXGBE_LINK_SPEED_1GB_FULL)
- hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
-
/*
* When the driver changes the link speeds that it can support,
* it sets autotry_restart to TRUE to indicate that we need to
@@ -542,7 +487,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
/* 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)
- goto out;
+ return status;
if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
goto out;
@@ -554,11 +499,11 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
/* Allow module to change analog characteristics (1G->10G) */
msec_delay(40);
- status = ixgbe_setup_mac_link_speed_82599(
+ status = ixgbe_setup_mac_link_82599(
hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg,
autoneg_wait_to_complete);
if (status != IXGBE_SUCCESS)
- goto out;
+ return status;
/* Flap the tx laser if it has not already been done */
if (hw->mac.autotry_restart) {
@@ -575,7 +520,11 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
hw->mac.autotry_restart = FALSE;
}
- /* The controller may take up to 500ms at 10g to acquire link */
+ /*
+ * Wait for the controller to acquire link. Per IEEE 802.3ap,
+ * Section 73.10.2, we may have to wait up to 500ms if KR is
+ * attempted. 82599 uses the same timing for 10g SFI.
+ */
for (i = 0; i < 5; i++) {
/* Wait for the link partner to also set speed */
msec_delay(100);
@@ -584,7 +533,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
status = ixgbe_check_link(hw, &link_speed,
&link_up, FALSE);
if (status != IXGBE_SUCCESS)
- goto out;
+ return status;
if (link_up)
goto out;
@@ -599,7 +548,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
/* 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)
- goto out;
+ return status;
if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
goto out;
@@ -612,11 +561,11 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
/* Allow module to change analog characteristics (10G->1G) */
msec_delay(40);
- status = ixgbe_setup_mac_link_speed_82599(
+ status = ixgbe_setup_mac_link_82599(
hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg,
autoneg_wait_to_complete);
if (status != IXGBE_SUCCESS)
- goto out;
+ return status;
/* Flap the tx laser if it has not already been done */
if (hw->mac.autotry_restart) {
@@ -639,7 +588,7 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
/* If we have link, just jump out */
status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
if (status != IXGBE_SUCCESS)
- goto out;
+ return status;
if (link_up)
goto out;
@@ -651,67 +600,134 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
* single highest speed that the user requested.
*/
if (speedcnt > 1)
- status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw,
+ status = ixgbe_setup_mac_link_multispeed_fiber(hw,
highest_link_speed, autoneg, autoneg_wait_to_complete);
out:
+ /* Set autoneg_advertised value based on input link speed */
+ hw->phy.autoneg_advertised = 0;
+
+ if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
return status;
}
/**
- * ixgbe_check_mac_link_82599 - Determine link and speed status
+ * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed
* @hw: pointer to hardware structure
- * @speed: pointer to link speed
- * @link_up: TRUE when link is up
- * @link_up_wait_to_complete: bool used to wait for link up or not
+ * @speed: new link speed
+ * @autoneg: TRUE if autonegotiation enabled
+ * @autoneg_wait_to_complete: TRUE when waiting for completion is needed
*
- * Reads the links register to determine if link is up and the current speed
+ * Implements the Intel SmartSpeed algorithm.
**/
-s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
- bool *link_up, bool link_up_wait_to_complete)
+s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed, bool autoneg,
+ bool autoneg_wait_to_complete)
{
- u32 links_reg;
- u32 i;
+ s32 status = IXGBE_SUCCESS;
+ ixgbe_link_speed link_speed;
+ s32 i, j;
+ bool link_up = FALSE;
+ u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
- if (link_up_wait_to_complete) {
- for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
- if (links_reg & IXGBE_LINKS_UP) {
- *link_up = TRUE;
- break;
- } else {
- *link_up = FALSE;
- }
+ DEBUGFUNC("ixgbe_setup_mac_link_smartspeed");
+
+ /* Set autoneg_advertised value based on input link speed */
+ hw->phy.autoneg_advertised = 0;
+
+ if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
+ if (speed & IXGBE_LINK_SPEED_100_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
+
+ /*
+ * Implement Intel SmartSpeed algorithm. SmartSpeed will reduce the
+ * autoneg advertisement if link is unable to be established at the
+ * highest negotiated rate. This can sometimes happen due to integrity
+ * issues with the physical media connection.
+ */
+
+ /* First, try to get link with full advertisement */
+ hw->phy.smart_speed_active = FALSE;
+ for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
+ status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
+ autoneg_wait_to_complete);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ /*
+ * Wait for the controller to acquire link. Per IEEE 802.3ap,
+ * Section 73.10.2, we may have to wait up to 500ms if KR is
+ * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per
+ * Table 9 in the AN MAS.
+ */
+ for (i = 0; i < 5; i++) {
msec_delay(100);
- links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+
+ /* If we have link, just jump out */
+ status = ixgbe_check_link(hw, &link_speed, &link_up,
+ FALSE);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ if (link_up)
+ goto out;
}
- } else {
- if (links_reg & IXGBE_LINKS_UP)
- *link_up = TRUE;
- else
- *link_up = FALSE;
}
- if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
- IXGBE_LINKS_SPEED_10G_82599)
- *speed = IXGBE_LINK_SPEED_10GB_FULL;
- else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
- IXGBE_LINKS_SPEED_1G_82599)
- *speed = IXGBE_LINK_SPEED_1GB_FULL;
- else
- *speed = IXGBE_LINK_SPEED_100_FULL;
+ /*
+ * We didn't get link. If we advertised KR plus one of KX4/KX
+ * (or BX4/BX), then disable KR and try again.
+ */
+ if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) ||
+ ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0))
+ goto out;
+
+ /* Turn SmartSpeed on to disable KR support */
+ hw->phy.smart_speed_active = TRUE;
+ status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
+ autoneg_wait_to_complete);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ /*
+ * Wait for the controller to acquire link. 600ms will allow for
+ * the AN link_fail_inhibit_timer as well for multiple cycles of
+ * parallel detect, both 10g and 1g. This allows for the maximum
+ * connect attempts as defined in the AN MAS table 73-7.
+ */
+ for (i = 0; i < 6; i++) {
+ msec_delay(100);
- /* if link is down, zero out the current_mode */
- if (*link_up == FALSE) {
- hw->fc.current_mode = ixgbe_fc_none;
- hw->fc.fc_was_autonegged = FALSE;
+ /* If we have link, just jump out */
+ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ if (link_up)
+ goto out;
}
- return IXGBE_SUCCESS;
+ /* We didn't get link. Turn SmartSpeed back off. */
+ hw->phy.smart_speed_active = FALSE;
+ status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
+ autoneg_wait_to_complete);
+
+out:
+ return status;
}
/**
- * ixgbe_setup_mac_link_speed_82599 - Set MAC link speed
+ * ixgbe_setup_mac_link_82599 - Set MAC link speed
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
@@ -719,7 +735,7 @@ s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
*
* Set the link speed in the AUTOC register and restarts link.
**/
-s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw,
+s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete)
{
@@ -735,6 +751,8 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw,
u32 i;
ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
+ DEBUGFUNC("ixgbe_setup_mac_link_82599");
+
/* Check to see if speed passed in is supported. */
status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg);
if (status != IXGBE_SUCCESS)
@@ -761,7 +779,8 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw,
if (speed & IXGBE_LINK_SPEED_10GB_FULL)
if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
autoc |= IXGBE_AUTOC_KX4_SUPP;
- if (orig_autoc & IXGBE_AUTOC_KR_SUPP)
+ if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) &&
+ (hw->phy.smart_speed_active == FALSE))
autoc |= IXGBE_AUTOC_KR_SUPP;
if (speed & IXGBE_LINK_SPEED_1GB_FULL)
autoc |= IXGBE_AUTOC_KX_SUPP;
@@ -823,26 +842,7 @@ out:
}
/**
- * ixgbe_setup_copper_link_82599 - Setup copper link settings
- * @hw: pointer to hardware structure
- *
- * Restarts the link on PHY and then MAC. Performs autonegotiation if needed.
- **/
-static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw)
-{
- s32 status;
-
- /* Restart autonegotiation on PHY */
- status = hw->phy.ops.setup_link(hw);
-
- /* Set up MAC */
- ixgbe_setup_mac_link_82599(hw);
-
- return status;
-}
-
-/**
- * ixgbe_setup_copper_link_speed_82599 - Set the PHY autoneg advertised field
+ * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
@@ -850,18 +850,20 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw)
*
* Restarts link on PHY and MAC based on settings passed in.
**/
-static s32 ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete)
{
s32 status;
+ DEBUGFUNC("ixgbe_setup_copper_link_82599");
+
/* Setup the PHY according to input speed */
status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
autoneg_wait_to_complete);
/* Set up MAC */
- ixgbe_setup_mac_link_82599(hw);
+ ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete);
return status;
}
@@ -881,6 +883,8 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
u32 autoc;
u32 autoc2;
+ DEBUGFUNC("ixgbe_reset_hw_82599");
+
/* Call adapter stop to disable tx/rx and clear interrupts */
hw->mac.ops.stop_adapter(hw);
@@ -892,7 +896,6 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
goto reset_hw_out;
-
/* Setup SFP module if there is one present. */
if (hw->phy.sfp_setup_needed) {
status = hw->mac.ops.setup_sfp(hw);
@@ -942,8 +945,6 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
msec_delay(50);
-
-
/*
* Store the original AUTOC/AUTOC2 values if they have not been
* stored off yet. Otherwise restore the stored original
@@ -994,311 +995,15 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
hw->mac.num_rar_entries--;
}
+ /* Store the alternative WWNN/WWPN prefix */
+ hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
+ &hw->mac.wwpn_prefix);
+
reset_hw_out:
return status;
}
/**
- * ixgbe_insert_mac_addr_82599 - Find a RAR for this mac address
- * @hw: pointer to hardware structure
- * @addr: Address to put into receive address register
- * @vmdq: VMDq pool to assign
- *
- * Puts an ethernet address into a receive address register, or
- * finds the rar that it is aleady in; adds to the pool list
- **/
-s32 ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
-{
- static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF;
- u32 first_empty_rar = NO_EMPTY_RAR_FOUND;
- u32 rar;
- u32 rar_low, rar_high;
- u32 addr_low, addr_high;
-
- /* swap bytes for HW little endian */
- addr_low = addr[0] | (addr[1] << 8)
- | (addr[2] << 16)
- | (addr[3] << 24);
- addr_high = addr[4] | (addr[5] << 8);
-
- /*
- * Either find the mac_id in rar or find the first empty space.
- * rar_highwater points to just after the highest currently used
- * rar in order to shorten the search. It grows when we add a new
- * rar to the top.
- */
- for (rar = 0; rar < hw->mac.rar_highwater; rar++) {
- rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
-
- if (((IXGBE_RAH_AV & rar_high) == 0)
- && first_empty_rar == NO_EMPTY_RAR_FOUND) {
- first_empty_rar = rar;
- } else if ((rar_high & 0xFFFF) == addr_high) {
- rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar));
- if (rar_low == addr_low)
- break; /* found it already in the rars */
- }
- }
-
- if (rar < hw->mac.rar_highwater) {
- /* already there so just add to the pool bits */
- ixgbe_set_vmdq(hw, rar, vmdq);
- } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
- /* stick it into first empty RAR slot we found */
- rar = first_empty_rar;
- ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
- } else if (rar == hw->mac.rar_highwater) {
- /* add it to the top of the list and inc the highwater mark */
- ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
- hw->mac.rar_highwater++;
- } else if (rar >= hw->mac.num_rar_entries) {
- return IXGBE_ERR_INVALID_MAC_ADDR;
- }
-
- /*
- * If we found rar[0], make sure the default pool bit (we use pool 0)
- * remains cleared to be sure default pool packets will get delivered
- */
- if (rar == 0)
- ixgbe_clear_vmdq(hw, rar, 0);
-
- return rar;
-}
-
-/**
- * ixgbe_clear_vmdq_82599 - Disassociate a VMDq pool index from a rx address
- * @hw: pointer to hardware struct
- * @rar: receive address register index to disassociate
- * @vmdq: VMDq pool index to remove from the rar
- **/
-s32 ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
-{
- u32 mpsar_lo, mpsar_hi;
- u32 rar_entries = hw->mac.num_rar_entries;
-
- if (rar < rar_entries) {
- mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
- mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
-
- if (!mpsar_lo && !mpsar_hi)
- goto done;
-
- if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
- if (mpsar_lo) {
- IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
- mpsar_lo = 0;
- }
- if (mpsar_hi) {
- IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
- mpsar_hi = 0;
- }
- } else if (vmdq < 32) {
- mpsar_lo &= ~(1 << vmdq);
- IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
- } else {
- mpsar_hi &= ~(1 << (vmdq - 32));
- IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
- }
-
- /* was that the last pool using this rar? */
- if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
- hw->mac.ops.clear_rar(hw, rar);
- } else {
- DEBUGOUT1("RAR index %d is out of range.\n", rar);
- }
-
-done:
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_set_vmdq_82599 - Associate a VMDq pool index with a rx address
- * @hw: pointer to hardware struct
- * @rar: receive address register index to associate with a VMDq index
- * @vmdq: VMDq pool index
- **/
-s32 ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
-{
- u32 mpsar;
- u32 rar_entries = hw->mac.num_rar_entries;
-
- if (rar < rar_entries) {
- if (vmdq < 32) {
- mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
- mpsar |= 1 << vmdq;
- IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
- } else {
- mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
- mpsar |= 1 << (vmdq - 32);
- IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
- }
- } else {
- DEBUGOUT1("RAR index %d is out of range.\n", rar);
- }
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_set_vfta_82599 - 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
- *
- * Turn on/off specified VLAN in the VLAN filter table.
- **/
-s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on)
-{
- u32 regindex;
- u32 bitindex;
- u32 bits;
- u32 first_empty_slot;
- u32 vt;
-
- if (vlan > 4095)
- return IXGBE_ERR_PARAM;
-
- /*
- * this is a 2 part operation - first the VFTA, then the
- * VLVF and VLVFB if VT Mode is set
- */
-
- /* Part 1
- * The VFTA is a bitstring made up of 128 32-bit registers
- * that enable the particular VLAN id, much like the MTA:
- * bits[11-5]: which register
- * bits[4-0]: which bit in the register
- */
- regindex = (vlan >> 5) & 0x7F;
- bitindex = vlan & 0x1F;
- bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
- if (vlan_on)
- bits |= (1 << bitindex);
- else
- bits &= ~(1 << bitindex);
- IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits);
-
-
- /* Part 2
- * If VT Mode is set
- * Either vlan_on
- * make sure the vlan is in VLVF
- * set the vind bit in the matching VLVFB
- * 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) {
- /* find the vlanid or the first empty slot */
- first_empty_slot = 0;
-
- for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
- bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
- if (!bits && !first_empty_slot)
- first_empty_slot = regindex;
- else if ((bits & 0x0FFF) == vlan)
- break;
- }
-
- if (regindex >= IXGBE_VLVF_ENTRIES) {
- if (first_empty_slot)
- regindex = first_empty_slot;
- else {
- DEBUGOUT("No space in VLVF.\n");
- goto out;
- }
- }
-
-
- if (vlan_on) {
- /* set the pool bit */
- if (vind < 32) {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB(regindex*2));
- bits |= (1 << vind);
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB(regindex*2),
- bits);
- } else {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB((regindex*2)+1));
- bits |= (1 << vind);
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB((regindex*2)+1),
- bits);
- }
- } else {
- /* clear the pool bit */
- if (vind < 32) {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB(regindex*2));
- bits &= ~(1 << vind);
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB(regindex*2),
- bits);
- bits |= IXGBE_READ_REG(hw,
- IXGBE_VLVFB((regindex*2)+1));
- } else {
- bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB((regindex*2)+1));
- bits &= ~(1 << vind);
- IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB((regindex*2)+1),
- bits);
- bits |= IXGBE_READ_REG(hw,
- IXGBE_VLVFB(regindex*2));
- }
- }
-
- if (bits)
- IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex),
- (IXGBE_VLVF_VIEN | vlan));
- else
- IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0);
- }
-out:
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_clear_vfta_82599 - Clear VLAN filter table
- * @hw: pointer to hardware structure
- *
- * Clears the VLAN filer table, and the VMDq index associated with the filter
- **/
-s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw)
-{
- u32 offset;
-
- for (offset = 0; offset < hw->mac.vft_size; offset++)
- IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
-
- for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
- IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
- IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0);
- IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0);
- }
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_init_uta_tables_82599 - Initialize the Unicast Table Array
- * @hw: pointer to hardware structure
- **/
-s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw)
-{
- int i;
- DEBUGOUT(" Clearing UTA\n");
-
- for (i = 0; i < 128; i++)
- IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
-
- return IXGBE_SUCCESS;
-}
-
-/**
* ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
* @hw: pointer to hardware structure
**/
@@ -1308,6 +1013,8 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
+ DEBUGFUNC("ixgbe_reinit_fdir_tables_82599");
+
/*
* Before starting reinitialization process,
* FDIRCMD.CMD must be zero.
@@ -1384,6 +1091,8 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
u32 pbsize;
int i;
+ DEBUGFUNC("ixgbe_init_fdir_signature_82599");
+
/*
* Before enabling Flow Director, the Rx Packet Buffer size
* must be reduced. The new value is the current size minus
@@ -1474,6 +1183,8 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
u32 pbsize;
int i;
+ DEBUGFUNC("ixgbe_init_fdir_perfect_82599");
+
/*
* Before enabling Flow Director, the Rx Packet Buffer size
* must be reduced. The new value is the current size minus
@@ -1609,6 +1320,8 @@ u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key)
u16 hash_result = 0;
int i, j, k, h;
+ DEBUGFUNC("ixgbe_atr_compute_hash_82599");
+
/*
* Initialize the fill member to prevent warnings
* on some compilers
@@ -1687,6 +1400,8 @@ u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key)
**/
s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
{
+ DEBUGFUNC("ixgbe_atr_set_vlan_id_82599");
+
input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8;
input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff;
@@ -1700,6 +1415,8 @@ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
**/
s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
{
+ DEBUGFUNC("ixgbe_atr_set_src_ipv4_82599");
+
input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24;
input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] =
(src_addr >> 16) & 0xff;
@@ -1717,6 +1434,8 @@ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
**/
s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
{
+ DEBUGFUNC("ixgbe_atr_set_dst_ipv4_82599");
+
input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24;
input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] =
(dst_addr >> 16) & 0xff;
@@ -1739,6 +1458,8 @@ s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
u32 src_addr_1, u32 src_addr_2,
u32 src_addr_3, u32 src_addr_4)
{
+ DEBUGFUNC("ixgbe_atr_set_src_ipv6_82599");
+
input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff;
input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] =
(src_addr_4 >> 8) & 0xff;
@@ -1782,6 +1503,8 @@ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
u32 dst_addr_1, u32 dst_addr_2,
u32 dst_addr_3, u32 dst_addr_4)
{
+ DEBUGFUNC("ixgbe_atr_set_dst_ipv6_82599");
+
input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff;
input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] =
(dst_addr_4 >> 8) & 0xff;
@@ -1820,6 +1543,8 @@ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
**/
s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
{
+ DEBUGFUNC("ixgbe_atr_set_src_port_82599");
+
input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8;
input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff;
@@ -1833,6 +1558,8 @@ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
**/
s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port)
{
+ DEBUGFUNC("ixgbe_atr_set_dst_port_82599");
+
input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8;
input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff;
@@ -1846,6 +1573,8 @@ s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port)
**/
s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
{
+ DEBUGFUNC("ixgbe_atr_set_flex_byte_82599");
+
input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8;
input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff;
@@ -1859,6 +1588,8 @@ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
**/
s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool)
{
+ DEBUGFUNC("ixgbe_atr_set_vm_pool_82599");
+
input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
return IXGBE_SUCCESS;
@@ -1871,6 +1602,8 @@ s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool)
**/
s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type)
{
+ DEBUGFUNC("ixgbe_atr_set_l4type_82599");
+
input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type;
return IXGBE_SUCCESS;
@@ -1883,6 +1616,8 @@ s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type)
**/
s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan)
{
+ DEBUGFUNC("ixgbe_atr_get_vlan_id_82599");
+
*vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET];
*vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8;
@@ -1896,6 +1631,8 @@ s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan)
**/
s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr)
{
+ DEBUGFUNC("ixgbe_atr_get_src_ipv4_82599");
+
*src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET];
*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8;
*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16;
@@ -1911,6 +1648,8 @@ s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr)
**/
s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr)
{
+ DEBUGFUNC("ixgbe_atr_get_dst_ipv4_82599");
+
*dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET];
*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8;
*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16;
@@ -1931,6 +1670,8 @@ s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
u32 *src_addr_1, u32 *src_addr_2,
u32 *src_addr_3, u32 *src_addr_4)
{
+ DEBUGFUNC("ixgbe_atr_get_src_ipv6_82599");
+
*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12];
*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8;
*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16;
@@ -1966,6 +1707,8 @@ s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
u32 *dst_addr_1, u32 *dst_addr_2,
u32 *dst_addr_3, u32 *dst_addr_4)
{
+ DEBUGFUNC("ixgbe_atr_get_dst_ipv6_82599");
+
*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12];
*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8;
*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16;
@@ -2001,6 +1744,8 @@ s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
**/
s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port)
{
+ DEBUGFUNC("ixgbe_atr_get_src_port_82599");
+
*src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8;
*src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1];
@@ -2019,6 +1764,8 @@ s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port)
**/
s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port)
{
+ DEBUGFUNC("ixgbe_atr_get_dst_port_82599");
+
*dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8;
*dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1];
@@ -2032,6 +1779,8 @@ s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port)
**/
s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte)
{
+ DEBUGFUNC("ixgbe_atr_get_flex_byte_82599");
+
*flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET];
*flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8;
@@ -2045,6 +1794,8 @@ s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte)
**/
s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool)
{
+ DEBUGFUNC("ixgbe_atr_get_vm_pool_82599");
+
*vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET];
return IXGBE_SUCCESS;
@@ -2057,6 +1808,8 @@ s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool)
**/
s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type)
{
+ DEBUGFUNC("ixgbe_atr_get_l4type__82599");
+
*l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET];
return IXGBE_SUCCESS;
@@ -2078,6 +1831,8 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
u16 bucket_hash, sig_hash;
u8 l4type;
+ DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
+
bucket_hash = ixgbe_atr_compute_hash_82599(input,
IXGBE_ATR_BUCKET_HASH_KEY);
@@ -2149,6 +1904,8 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
u16 bucket_hash;
u8 l4type;
+ DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599");
+
/* Get our input values */
ixgbe_atr_get_l4type_82599(input, &l4type);
@@ -2237,6 +1994,8 @@ s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val)
{
u32 core_ctl;
+ DEBUGFUNC("ixgbe_read_analog_reg8_82599");
+
IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD |
(reg << 8));
IXGBE_WRITE_FLUSH(hw);
@@ -2259,6 +2018,8 @@ s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val)
{
u32 core_ctl;
+ DEBUGFUNC("ixgbe_write_analog_reg8_82599");
+
core_ctl = (reg << 8) | val;
IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl);
IXGBE_WRITE_FLUSH(hw);
@@ -2277,18 +2038,35 @@ s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val)
**/
s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw)
{
- u32 q_num;
+ u32 i;
+ u32 regval;
s32 ret_val = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_start_hw_rev_1__82599");
+
ret_val = ixgbe_start_hw_generic(hw);
/* Clear the rate limiters */
- for (q_num = 0; q_num < hw->mac.max_tx_queues; q_num++) {
- IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, q_num);
+ for (i = 0; i < hw->mac.max_tx_queues; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i);
IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0);
}
IXGBE_WRITE_FLUSH(hw);
+ /* Disable relaxed ordering */
+ for (i = 0; i < hw->mac.max_tx_queues; i++) {
+ regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
+ regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
+ }
+
+ for (i = 0; i < hw->mac.max_rx_queues; i++) {
+ regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
+ regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
+ IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+ IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
+ }
+
/* We need to run link autotry after the driver loads */
hw->mac.autotry_restart = TRUE;
@@ -2309,6 +2087,8 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
{
s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+ DEBUGFUNC("ixgbe_identify_phy_82599");
+
/* Detect PHY if not unknown - returns success if already detected. */
status = ixgbe_identify_phy_generic(hw);
if (status != IXGBE_SUCCESS)
@@ -2343,6 +2123,8 @@ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
u16 ext_ability = 0;
u8 comp_codes_10g = 0;
+ DEBUGFUNC("ixgbe_get_support_physical_layer_82599");
+
hw->phy.ops.identify(hw);
if (hw->phy.type == ixgbe_phy_tn ||
@@ -2446,6 +2228,8 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
int i;
int secrxreg;
+ DEBUGFUNC("ixgbe_enable_rx_dma_82599");
+
/*
* Workaround for 82599 silicon errata when enabling the Rx datapath.
* If traffic is incoming before we enable the Rx unit, it could hang
@@ -2488,119 +2272,14 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
**/
s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps)
{
- hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
-
- return IXGBE_SUCCESS;
-}
+ DEBUGFUNC("ixgbe_get_device_caps_82599");
-/**
- * ixgbe_get_san_mac_addr_offset_82599 - SAN MAC address offset for 82599
- * @hw: pointer to hardware structure
- * @san_mac_offset: SAN MAC address offset
- *
- * This function will read the EEPROM location for the SAN MAC address
- * pointer, and returns the value at that location. This is used in both
- * get and set mac_addr routines.
- **/
-s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw,
- u16 *san_mac_offset)
-{
- /*
- * First read the EEPROM pointer to see if the MAC addresses are
- * available.
- */
- hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset);
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_get_san_mac_addr_82599 - SAN MAC address retrieval for 82599
- * @hw: pointer to hardware structure
- * @san_mac_addr: SAN MAC address
- *
- * Reads the SAN MAC address from the EEPROM, if it's available. This is
- * per-port, so set_lan_id() must be called before reading the addresses.
- * set_lan_id() is called by identify_sfp(), but this cannot be relied
- * upon for non-SFP connections, so we must call it here.
- **/
-s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr)
-{
- u16 san_mac_data, san_mac_offset;
- u8 i;
-
- /*
- * First read the EEPROM pointer to see if the MAC addresses are
- * available. If they're not, no point in calling set_lan_id() here.
- */
- ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset);
-
- if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
- /*
- * No addresses available in this EEPROM. It's not an
- * error though, so just wipe the local address and return.
- */
- for (i = 0; i < 6; i++)
- san_mac_addr[i] = 0xFF;
-
- goto san_mac_addr_out;
- }
-
- /* make sure we know which port we need to program */
- hw->mac.ops.set_lan_id(hw);
- /* apply the port offset to the address offset */
- (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
- (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
- for (i = 0; i < 3; i++) {
- hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data);
- san_mac_addr[i * 2] = (u8)(san_mac_data);
- san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
- san_mac_offset++;
- }
+ hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
-san_mac_addr_out:
return IXGBE_SUCCESS;
}
/**
- * ixgbe_set_san_mac_addr_82599 - Write the SAN MAC address to the EEPROM
- * @hw: pointer to hardware structure
- * @san_mac_addr: SAN MAC address
- *
- * Write a SAN MAC address to the EEPROM.
- **/
-s32 ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr)
-{
- s32 status = IXGBE_SUCCESS;
- u16 san_mac_data, san_mac_offset;
- u8 i;
-
- /* Look for SAN mac address pointer. If not defined, return */
- ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset);
-
- if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
- status = IXGBE_ERR_NO_SAN_ADDR_PTR;
- goto san_mac_addr_out;
- }
-
- /* Make sure we know which port we need to write */
- hw->mac.ops.set_lan_id(hw);
- /* Apply the port offset to the address offset */
- (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
- (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
-
- for (i = 0; i < 3; i++) {
- san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8);
- san_mac_data |= (u16)(san_mac_addr[i * 2]);
- hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data);
- san_mac_offset++;
- }
-
-san_mac_addr_out:
- return status;
-}
-
-/**
* ixgbe_verify_fw_version_82599 - verify fw version for 82599
* @hw: pointer to hardware structure
*
@@ -2616,6 +2295,8 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
u16 fw_offset, fw_ptp_cfg_offset;
u16 fw_version = 0;
+ DEBUGFUNC("ixgbe_verify_fw_version_82599");
+
/* firmware check is only necessary for SFI devices */
if (hw->phy.media_type != ixgbe_media_type_fiber) {
status = IXGBE_SUCCESS;
diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c
index 9c3356f..4464457 100644
--- a/sys/dev/ixgbe/ixgbe_api.c
+++ b/sys/dev/ixgbe/ixgbe_api.c
@@ -54,6 +54,8 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
{
s32 status;
+ DEBUGFUNC("ixgbe_init_shared_code");
+
/*
* Set the mac type
*/
@@ -94,6 +96,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AT:
+ case IXGBE_DEV_ID_82598AT2:
case IXGBE_DEV_ID_82598EB_CX4:
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
@@ -103,7 +106,9 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
hw->mac.type = ixgbe_mac_82598EB;
break;
case IXGBE_DEV_ID_82599_KX4:
+ case IXGBE_DEV_ID_82599_KX4_MEZZ:
case IXGBE_DEV_ID_82599_XAUI_LOM:
+ case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
case IXGBE_DEV_ID_82599_SFP:
case IXGBE_DEV_ID_82599_CX4:
hw->mac.type = ixgbe_mac_82599EB;
@@ -244,6 +249,23 @@ s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps)
}
/**
+ * ixgbe_get_wwn_prefix - Get alternative WWNN/WWPN prefix from the EEPROM
+ * @hw: pointer to hardware structure
+ * @wwnn_prefix: the alternative WWNN prefix
+ * @wwpn_prefix: the alternative WWPN prefix
+ *
+ * This function will read the EEPROM from the alternative SAN MAC address
+ * block to check the support for the alternative WWNN/WWPN prefix support.
+ **/
+s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix,
+ u16 *wwpn_prefix)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.get_wwn_prefix,
+ (hw, wwnn_prefix, wwpn_prefix),
+ IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
* ixgbe_get_bus_info - Set PCI bus info
* @hw: pointer to hardware structure
*
@@ -439,19 +461,6 @@ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
}
/**
- * ixgbe_setup_link - Configure link settings
- * @hw: pointer to hardware structure
- *
- * Configures link settings based on values in the ixgbe_hw struct.
- * Restarts the link. Performs autonegotiation if needed.
- **/
-s32 ixgbe_setup_link(struct ixgbe_hw *hw)
-{
- return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw),
- IXGBE_NOT_IMPLEMENTED);
-}
-
-/**
* ixgbe_check_link - Get link and speed status
* @hw: pointer to hardware structure
*
@@ -466,18 +475,19 @@ s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
}
/**
- * ixgbe_setup_link_speed - Set link speed
+ * ixgbe_setup_link - Set link speed
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
*
- * Set the link speed and restarts the link.
+ * Configures link settings. Restarts the link.
+ * Performs autonegotiation if needed.
**/
-s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete)
{
- return ixgbe_call_func(hw, hw->mac.ops.setup_link_speed, (hw, speed,
+ return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw, speed,
autoneg, autoneg_wait_to_complete),
IXGBE_NOT_IMPLEMENTED);
}
diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h
index 654f22f..8ab78ad 100644
--- a/sys/dev/ixgbe/ixgbe_api.h
+++ b/sys/dev/ixgbe/ixgbe_api.h
@@ -67,8 +67,7 @@ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
-s32 ixgbe_setup_link(struct ixgbe_hw *hw);
-s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg, bool autoneg_wait_to_complete);
s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up, bool link_up_wait_to_complete);
@@ -97,6 +96,7 @@ s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func);
s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, ixgbe_mc_addr_itr func);
+void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr_list, u32 vmdq);
s32 ixgbe_enable_mc(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc(struct ixgbe_hw *hw);
s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
@@ -164,6 +164,8 @@ 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, u16 mask);
void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask);
+s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix,
+ u16 *wwpn_prefix);
#endif /* _IXGBE_API_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c
index 30c372d..89e57d8 100644
--- a/sys/dev/ixgbe/ixgbe_common.c
+++ b/sys/dev/ixgbe/ixgbe_common.c
@@ -35,7 +35,6 @@
#include "ixgbe_common.h"
#include "ixgbe_api.h"
-static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw);
static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
@@ -47,9 +46,11 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
-static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
+static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
+ u16 *san_mac_offset);
+s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
/**
* ixgbe_init_ops_generic - Inits function ptrs
@@ -63,17 +64,20 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
struct ixgbe_mac_info *mac = &hw->mac;
u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ DEBUGFUNC("ixgbe_init_ops_generic");
+
/* EEPROM */
eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic;
/* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
if (eec & (1 << 8))
- eeprom->ops.read = &ixgbe_read_eeprom_generic;
+ eeprom->ops.read = &ixgbe_read_eerd_generic;
else
eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic;
eeprom->ops.write = &ixgbe_write_eeprom_generic;
eeprom->ops.validate_checksum =
&ixgbe_validate_eeprom_checksum_generic;
eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic;
+ eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic;
/* MAC */
mac->ops.init_hw = &ixgbe_init_hw_generic;
@@ -117,7 +121,6 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
/* Link */
mac->ops.get_link_capabilities = NULL;
mac->ops.setup_link = NULL;
- mac->ops.setup_link_speed = NULL;
mac->ops.check_link = NULL;
return IXGBE_SUCCESS;
@@ -137,6 +140,8 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
u32 ctrl_ext;
s32 ret_val = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_start_hw_generic");
+
/* Set the media type */
hw->phy.media_type = hw->mac.ops.get_media_type(hw);
@@ -177,6 +182,8 @@ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
{
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_init_hw_generic");
+
/* Reset the hardware */
status = hw->mac.ops.reset_hw(hw);
@@ -199,6 +206,8 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
{
u16 i = 0;
+ DEBUGFUNC("ixgbe_clear_hw_cntrs_generic");
+
IXGBE_READ_REG(hw, IXGBE_CRCERRS);
IXGBE_READ_REG(hw, IXGBE_ILLERRC);
IXGBE_READ_REG(hw, IXGBE_ERRBC);
@@ -324,6 +333,8 @@ s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
u32 rar_low;
u16 i;
+ DEBUGFUNC("ixgbe_get_mac_addr_generic");
+
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0));
rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0));
@@ -347,6 +358,8 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
struct ixgbe_mac_info *mac = &hw->mac;
u16 link_status;
+ DEBUGFUNC("ixgbe_get_bus_info_generic");
+
hw->bus.type = ixgbe_bus_type_pci_express;
/* Get the negotiated link width and speed from PCI config space */
@@ -399,6 +412,8 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
struct ixgbe_bus_info *bus = &hw->bus;
u32 reg;
+ 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;
@@ -424,6 +439,8 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
u32 reg_val;
u16 i;
+ DEBUGFUNC("ixgbe_stop_adapter_generic");
+
/*
* Set the adapter_stopped flag so other driver functions stop touching
* the hardware
@@ -472,6 +489,8 @@ s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
{
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ DEBUGFUNC("ixgbe_led_on_generic");
+
/* 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);
@@ -490,6 +509,8 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
{
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ DEBUGFUNC("ixgbe_led_off_generic");
+
/* 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);
@@ -512,6 +533,8 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
u32 eec;
u16 eeprom_size;
+ DEBUGFUNC("ixgbe_init_eeprom_params_generic");
+
if (eeprom->type == ixgbe_eeprom_uninitialized) {
eeprom->type = ixgbe_eeprom_none;
/* Set default semaphore delay to 10ms which is a well
@@ -533,7 +556,7 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
IXGBE_EEC_SIZE_SHIFT);
eeprom->word_size = 1 << (eeprom_size +
- IXGBE_EEPROM_WORD_SIZE_SHIFT);
+ IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT);
}
if (eec & IXGBE_EEC_ADDR_SIZE)
@@ -562,6 +585,8 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
s32 status;
u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
+ DEBUGFUNC("ixgbe_write_eeprom_generic");
+
hw->eeprom.ops.init_params(hw);
if (offset >= hw->eeprom.word_size) {
@@ -629,6 +654,8 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 word_in;
u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
+ DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic");
+
hw->eeprom.ops.init_params(hw);
if (offset >= hw->eeprom.word_size) {
@@ -675,18 +702,20 @@ out:
}
/**
- * ixgbe_read_eeprom_generic - Read EEPROM word using EERD
+ * ixgbe_read_eerd_generic - Read EEPROM word using EERD
* @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 EERD register.
**/
-s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
+s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
{
u32 eerd;
s32 status;
+ DEBUGFUNC("ixgbe_read_eerd_generic");
+
hw->eeprom.ops.init_params(hw);
if (offset >= hw->eeprom.word_size) {
@@ -694,15 +723,15 @@ s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
goto out;
}
- eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) +
- IXGBE_EEPROM_READ_REG_START;
+ eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) +
+ IXGBE_EEPROM_RW_REG_START;
IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
- status = ixgbe_poll_eeprom_eerd_done(hw);
+ status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
if (status == IXGBE_SUCCESS)
*data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
- IXGBE_EEPROM_READ_REG_DATA);
+ IXGBE_EEPROM_RW_REG_DATA);
else
DEBUGOUT("Eeprom read timed out\n");
@@ -711,20 +740,28 @@ out:
}
/**
- * ixgbe_poll_eeprom_eerd_done - Poll EERD status
+ * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
* @hw: pointer to hardware structure
+ * @ee_reg: EEPROM flag for polling
*
- * Polls the status bit (bit 1) of the EERD to determine when the read is done.
+ * Polls the status bit (bit 1) of the EERD or EEWR to determine when the
+ * read or write is done respectively.
**/
-static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw)
+s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
{
u32 i;
u32 reg;
s32 status = IXGBE_ERR_EEPROM;
- for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) {
- reg = IXGBE_READ_REG(hw, IXGBE_EERD);
- if (reg & IXGBE_EEPROM_READ_REG_DONE) {
+ DEBUGFUNC("ixgbe_poll_eerd_eewr_done");
+
+ for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
+ if (ee_reg == IXGBE_NVM_POLL_READ)
+ reg = IXGBE_READ_REG(hw, IXGBE_EERD);
+ else
+ reg = IXGBE_READ_REG(hw, IXGBE_EEWR);
+
+ if (reg & IXGBE_EEPROM_RW_REG_DONE) {
status = IXGBE_SUCCESS;
break;
}
@@ -746,6 +783,8 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
u32 eec;
u32 i;
+ DEBUGFUNC("ixgbe_acquire_eeprom");
+
if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS)
status = IXGBE_ERR_SWFW_SYNC;
@@ -798,6 +837,8 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
u32 i;
u32 swsm;
+ DEBUGFUNC("ixgbe_get_eeprom_semaphore");
+
/* Get SMBI software semaphore between device drivers first */
for (i = 0; i < timeout; i++) {
/*
@@ -860,6 +901,8 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
{
u32 swsm;
+ DEBUGFUNC("ixgbe_release_eeprom_semaphore");
+
swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
@@ -878,6 +921,8 @@ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
u16 i;
u8 spi_stat_reg;
+ DEBUGFUNC("ixgbe_ready_eeprom");
+
/*
* Read "Status Register" repeatedly until the LSB is cleared. The
* EEPROM will signal that the command has been completed by clearing
@@ -915,6 +960,8 @@ static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
{
u32 eec;
+ DEBUGFUNC("ixgbe_standby_eeprom");
+
eec = IXGBE_READ_REG(hw, IXGBE_EEC);
/* Toggle CS to flush commands */
@@ -941,6 +988,8 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
u32 mask;
u32 i;
+ DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
+
eec = IXGBE_READ_REG(hw, IXGBE_EEC);
/*
@@ -993,6 +1042,8 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
u32 i;
u16 data = 0;
+ DEBUGFUNC("ixgbe_shift_in_eeprom_bits");
+
/*
* In order to read a register from the EEPROM, we need to shift
* 'count' bits in from the EEPROM. Bits are "shifted in" by raising
@@ -1027,6 +1078,8 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
**/
static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
{
+ DEBUGFUNC("ixgbe_raise_eeprom_clk");
+
/*
* Raise the clock input to the EEPROM
* (setting the SK bit), then delay
@@ -1044,6 +1097,8 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
**/
static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
{
+ DEBUGFUNC("ixgbe_lower_eeprom_clk");
+
/*
* Lower the clock input to the EEPROM (clearing the SK bit), then
* delay
@@ -1062,6 +1117,8 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
{
u32 eec;
+ DEBUGFUNC("ixgbe_release_eeprom");
+
eec = IXGBE_READ_REG(hw, IXGBE_EEC);
eec |= IXGBE_EEC_CS; /* Pull CS high */
@@ -1083,10 +1140,10 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
}
/**
- * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
+ * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
* @hw: pointer to hardware structure
**/
-static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
+u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
{
u16 i;
u16 j;
@@ -1095,6 +1152,8 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
u16 pointer = 0;
u16 word = 0;
+ DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic");
+
/* Include 0x0-0x3F in the checksum */
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) {
@@ -1141,6 +1200,8 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
u16 checksum;
u16 read_checksum = 0;
+ DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic");
+
/*
* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
@@ -1149,7 +1210,7 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status == IXGBE_SUCCESS) {
- checksum = ixgbe_calc_eeprom_checksum(hw);
+ checksum = hw->eeprom.ops.calc_checksum(hw);
hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
@@ -1179,6 +1240,8 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
s32 status;
u16 checksum;
+ DEBUGFUNC("ixgbe_update_eeprom_checksum_generic");
+
/*
* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
@@ -1187,7 +1250,7 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status == IXGBE_SUCCESS) {
- checksum = ixgbe_calc_eeprom_checksum(hw);
+ checksum = hw->eeprom.ops.calc_checksum(hw);
status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
checksum);
} else {
@@ -1207,6 +1270,8 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr)
{
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_validate_mac_addr");
+
/* Make sure it is not a multicast address */
if (IXGBE_IS_MULTICAST(mac_addr)) {
DEBUGOUT("MAC address is multicast\n");
@@ -1240,6 +1305,8 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 rar_low, rar_high;
u32 rar_entries = hw->mac.num_rar_entries;
+ DEBUGFUNC("ixgbe_set_rar_generic");
+
/* setup VMDq pool selection before this RAR gets enabled */
hw->mac.ops.set_vmdq(hw, index, vmdq);
@@ -1286,6 +1353,8 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
u32 rar_high;
u32 rar_entries = hw->mac.num_rar_entries;
+ DEBUGFUNC("ixgbe_clear_rar_generic");
+
/* Make sure we are using a valid rar index range */
if (index < rar_entries) {
/*
@@ -1321,6 +1390,8 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
u32 i;
u32 rar_entries = hw->mac.num_rar_entries;
+ DEBUGFUNC("ixgbe_init_rx_addrs_generic");
+
/*
* If the current mac address is valid, assume it is a software override
* to the permanent address.
@@ -1383,6 +1454,8 @@ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
u32 rar_entries = hw->mac.num_rar_entries;
u32 rar;
+ DEBUGFUNC("ixgbe_add_uc_addr");
+
DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
@@ -1426,6 +1499,8 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
u32 fctrl;
u32 vmdq;
+ DEBUGFUNC("ixgbe_update_uc_addr_list_generic");
+
/*
* Clear accounting of old secondary address list,
* don't count RAR[0]
@@ -1435,10 +1510,10 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
hw->addr_ctrl.overflow_promisc = 0;
/* Zero out the other receive addresses */
- DEBUGOUT1("Clearing RAR[1-%d]\n", hw->addr_ctrl.rar_used_count);
- for (i = 1; i <= hw->addr_ctrl.rar_used_count; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+ DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1);
+ for (i = 0; i < uc_addr_in_use; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
}
/* Add the new addresses */
@@ -1486,6 +1561,8 @@ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
{
u32 vector = 0;
+ DEBUGFUNC("ixgbe_mta_vector");
+
switch (hw->mac.mc_filter_type) {
case 0: /* use bits [47:36] of the address */
vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
@@ -1524,6 +1601,8 @@ void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
u32 vector_reg;
u32 mta_reg;
+ DEBUGFUNC("ixgbe_set_mta");
+
hw->addr_ctrl.mta_in_use++;
vector = ixgbe_mta_vector(hw, mc_addr);
@@ -1563,6 +1642,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 i;
u32 vmdq;
+ DEBUGFUNC("ixgbe_update_mc_addr_list_generic");
+
/*
* Set the new number of MC addresses that we are being requested to
* use.
@@ -1600,6 +1681,8 @@ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
{
struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
+ DEBUGFUNC("ixgbe_enable_mc_generic");
+
if (a->mta_in_use > 0)
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
hw->mac.mc_filter_type);
@@ -1617,6 +1700,8 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
{
struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
+ DEBUGFUNC("ixgbe_disable_mc_generic");
+
if (a->mta_in_use > 0)
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
@@ -1692,7 +1777,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
- ret_val = -IXGBE_ERR_CONFIG;
+ ret_val = IXGBE_ERR_CONFIG;
goto out;
break;
}
@@ -1761,6 +1846,7 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
s32 ret_val = IXGBE_SUCCESS;
ixgbe_link_speed speed;
u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+ u32 links2, anlp1_reg, autoc_reg, links;
bool link_up;
DEBUGFUNC("ixgbe_fc_autoneg");
@@ -1769,27 +1855,68 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
* 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
- * - we don't have multispeed fiber, or if
- * - we're not running at 1G, or if
- * - link is not up, or if
- * - link is up but AN did not complete, or if
- * - link is up and AN completed but timed out
+ * - link is not up.
*
- * Since we're being called from an LSC, link is already know to be up.
+ * Since we're being called from an LSC, link is already known to be up.
* So use link_up_wait_to_complete=FALSE.
*/
hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
- linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-
- if (hw->fc.disable_fc_autoneg ||
- !hw->phy.multispeed_fiber ||
- (speed != IXGBE_LINK_SPEED_1GB_FULL) ||
- !link_up ||
- ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
- ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+
+ if (hw->fc.disable_fc_autoneg || (!link_up)) {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+
+ /*
+ * On backplane, bail out if
+ * - backplane autoneg was not completed, or if
+ * - we are 82599 and link partner is not AN enabled
+ */
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ links = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+
+ if (hw->mac.type == ixgbe_mac_82599EB) {
+ links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
+ if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+ }
+ }
+
+ /*
+ * On multispeed fiber at 1g, bail out if
+ * - link is up but AN did not complete, or if
+ * - link is up and AN completed but timed out
+ */
+ if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) {
+ linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+ if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+ ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ goto out;
+ }
+ }
+
+ /*
+ * Bail out on
+ * - copper or CX4 adapters
+ * - fiber adapters running at 10gig
+ */
+ if ((hw->phy.media_type == ixgbe_media_type_copper) ||
+ (hw->phy.media_type == ixgbe_media_type_cx4) ||
+ ((hw->phy.media_type == ixgbe_media_type_fiber) &&
+ (speed == IXGBE_LINK_SPEED_10GB_FULL))) {
hw->fc.fc_was_autonegged = FALSE;
hw->fc.current_mode = hw->fc.requested_mode;
- DEBUGOUT("Autoneg FC was skipped.\n");
goto out;
}
@@ -1797,41 +1924,85 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
* Read the AN advertisement and LP ability registers and resolve
* local flow control settings accordingly
*/
- pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
- pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
- if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+ if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
+ (hw->phy.media_type != ixgbe_media_type_backplane)) {
+ pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+ if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+ /*
+ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_full) {
+ hw->fc.current_mode = ixgbe_fc_full;
+ DEBUGOUT("Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control=RX PAUSE frames only\n");
+ }
+ } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+ hw->fc.current_mode = ixgbe_fc_tx_pause;
+ DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
+ } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+ !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_none;
+ DEBUGOUT("Flow Control = NONE.\n");
+ }
+ }
+
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
/*
- * Now we need to check if the user selected Rx ONLY
- * of pause frames. In this case, we had to advertise
- * FULL flow control because we could not advertise RX
- * ONLY. Hence, we must now check to see if we need to
- * turn OFF the TRANSMISSION of PAUSE frames.
+ * Read the 10g AN autoc and LP ability registers and resolve
+ * local flow control settings accordingly
*/
- if (hw->fc.requested_mode == ixgbe_fc_full) {
- hw->fc.current_mode = ixgbe_fc_full;
- DEBUGOUT("Flow Control = FULL.\n");
- } else {
+ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+
+ if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) {
+ /*
+ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_full) {
+ hw->fc.current_mode = ixgbe_fc_full;
+ DEBUGOUT("Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control=RX PAUSE frames only\n");
+ }
+ } else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+ (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
+ hw->fc.current_mode = ixgbe_fc_tx_pause;
+ DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
+ } else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+ (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+ !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+ (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
hw->fc.current_mode = ixgbe_fc_rx_pause;
DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_none;
+ DEBUGOUT("Flow Control = NONE.\n");
}
- } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
- hw->fc.current_mode = ixgbe_fc_tx_pause;
- DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
- } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
- !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
- (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
- hw->fc.current_mode = ixgbe_fc_rx_pause;
- DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
- } else {
- hw->fc.current_mode = ixgbe_fc_none;
- DEBUGOUT("Flow Control = NONE.\n");
}
-
/* Record that current_mode is the result of a successful autoneg */
hw->fc.fc_was_autonegged = TRUE;
@@ -1850,6 +2021,8 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
s32 ret_val = IXGBE_SUCCESS;
u32 reg;
+ DEBUGFUNC("ixgbe_setup_fc");
+
/* Validate the packetbuf configuration */
if (packetbuf_num < 0 || packetbuf_num > 7) {
@@ -1933,7 +2106,7 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
- ret_val = -IXGBE_ERR_CONFIG;
+ ret_val = IXGBE_ERR_CONFIG;
goto out;
break;
}
@@ -1941,9 +2114,6 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
- /* Enable and restart autoneg to inform the link partner */
- reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
-
/* Disable AN timeout */
if (hw->fc.strict_ieee)
reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
@@ -1951,6 +2121,65 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+ /*
+ * Set up the 10G flow control advertisement registers so the HW
+ * can do fc autoneg once the cable is plugged in. If we end up
+ * using 1g instead, this is harmless.
+ */
+ reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+ /*
+ * 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. */
+ reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_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. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /*
+ * Tx Flow control is enabled, and Rx Flow control is
+ * disabled by software override.
+ */
+ reg |= (IXGBE_AUTOC_ASM_PAUSE);
+ reg &= ~(IXGBE_AUTOC_SYM_PAUSE);
+ break;
+ case ixgbe_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by SW override. */
+ reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+ break;
+ default:
+ DEBUGOUT("Flow control param set incorrectly\n");
+ ret_val = IXGBE_ERR_CONFIG;
+ goto out;
+ break;
+ }
+ /*
+ * AUTOC restart handles negotiation of 1G and 10G. There is
+ * no need to set the PCS1GCTL register.
+ */
+ reg |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg);
+ DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
+
out:
return ret_val;
}
@@ -1971,6 +2200,8 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
u32 number_of_queues;
s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+ DEBUGFUNC("ixgbe_disable_pcie_master");
+
/* Disable the receive unit by stopping each queue */
number_of_queues = hw->mac.max_rx_queues;
for (i = 0; i < number_of_queues; i++) {
@@ -2012,13 +2243,15 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
u32 fwmask = mask << 5;
s32 timeout = 200;
+ DEBUGFUNC("ixgbe_acquire_swfw_sync");
+
while (timeout) {
/*
* SW EEPROM semaphore bit is used for access to all
* SW_FW_SYNC/GSSR bits (not just EEPROM)
*/
if (ixgbe_get_eeprom_semaphore(hw))
- return -IXGBE_ERR_SWFW_SYNC;
+ return IXGBE_ERR_SWFW_SYNC;
gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
if (!(gssr & (fwmask | swmask)))
@@ -2035,7 +2268,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
if (!timeout) {
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
- return -IXGBE_ERR_SWFW_SYNC;
+ return IXGBE_ERR_SWFW_SYNC;
}
gssr |= swmask;
@@ -2058,6 +2291,8 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
u32 gssr;
u32 swmask = mask;
+ DEBUGFUNC("ixgbe_release_swfw_sync");
+
ixgbe_get_eeprom_semaphore(hw);
gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
@@ -2076,6 +2311,8 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
**/
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
{
+ DEBUGFUNC("ixgbe_enable_rx_dma_generic");
+
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
return IXGBE_SUCCESS;
@@ -2093,6 +2330,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ DEBUGFUNC("ixgbe_blink_led_start_generic");
+
/*
* Link must be up to auto-blink the LEDs;
* Force it if link is down.
@@ -2125,6 +2364,8 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ DEBUGFUNC("ixgbe_blink_led_stop_generic");
+
autoc_reg &= ~IXGBE_AUTOC_FLU;
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
@@ -2139,3 +2380,582 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
return IXGBE_SUCCESS;
}
+/**
+ * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
+ * @hw: pointer to hardware structure
+ * @san_mac_offset: SAN MAC address offset
+ *
+ * This function will read the EEPROM location for the SAN MAC address
+ * pointer, and returns the value at that location. This is used in both
+ * get and set mac_addr routines.
+ **/
+static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
+ u16 *san_mac_offset)
+{
+ DEBUGFUNC("ixgbe_get_san_mac_addr_offset");
+
+ /*
+ * First read the EEPROM pointer to see if the MAC addresses are
+ * available.
+ */
+ hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM
+ * @hw: pointer to hardware structure
+ * @san_mac_addr: SAN MAC address
+ *
+ * Reads the SAN MAC address from the EEPROM, if it's available. This is
+ * per-port, so set_lan_id() must be called before reading the addresses.
+ * set_lan_id() is called by identify_sfp(), but this cannot be relied
+ * upon for non-SFP connections, so we must call it here.
+ **/
+s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
+{
+ u16 san_mac_data, san_mac_offset;
+ u8 i;
+
+ DEBUGFUNC("ixgbe_get_san_mac_addr_generic");
+
+ /*
+ * First read the EEPROM pointer to see if the MAC addresses are
+ * available. If they're not, no point in calling set_lan_id() here.
+ */
+ ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
+
+ if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
+ /*
+ * No addresses available in this EEPROM. It's not an
+ * error though, so just wipe the local address and return.
+ */
+ for (i = 0; i < 6; i++)
+ san_mac_addr[i] = 0xFF;
+
+ goto san_mac_addr_out;
+ }
+
+ /* make sure we know which port we need to program */
+ hw->mac.ops.set_lan_id(hw);
+ /* apply the port offset to the address offset */
+ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
+ (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
+ for (i = 0; i < 3; i++) {
+ hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data);
+ san_mac_addr[i * 2] = (u8)(san_mac_data);
+ san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
+ san_mac_offset++;
+ }
+
+san_mac_addr_out:
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM
+ * @hw: pointer to hardware structure
+ * @san_mac_addr: SAN MAC address
+ *
+ * Write a SAN MAC address to the EEPROM.
+ **/
+s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
+{
+ s32 status = IXGBE_SUCCESS;
+ u16 san_mac_data, san_mac_offset;
+ u8 i;
+
+ DEBUGFUNC("ixgbe_set_san_mac_addr_generic");
+
+ /* Look for SAN mac address pointer. If not defined, return */
+ ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
+
+ if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
+ status = IXGBE_ERR_NO_SAN_ADDR_PTR;
+ goto san_mac_addr_out;
+ }
+
+ /* Make sure we know which port we need to write */
+ hw->mac.ops.set_lan_id(hw);
+ /* Apply the port offset to the address offset */
+ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
+ (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
+
+ for (i = 0; i < 3; i++) {
+ san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8);
+ san_mac_data |= (u16)(san_mac_addr[i * 2]);
+ hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data);
+ san_mac_offset++;
+ }
+
+san_mac_addr_out:
+ return status;
+}
+
+/**
+ * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count
+ * @hw: pointer to hardware structure
+ *
+ * Read PCIe configuration space, and get the MSI-X vector count from
+ * the capabilities table.
+ **/
+u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
+{
+ u32 msix_count = 64;
+
+ DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
+ if (hw->mac.msix_vectors_from_pcie) {
+ msix_count = IXGBE_READ_PCIE_WORD(hw,
+ IXGBE_PCIE_MSIX_82599_CAPS);
+ msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
+
+ /* MSI-X count is zero-based in HW, so increment to give
+ * proper value */
+ msix_count++;
+ }
+
+ return msix_count;
+}
+
+/**
+ * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address
+ * @hw: pointer to hardware structure
+ * @addr: Address to put into receive address register
+ * @vmdq: VMDq pool to assign
+ *
+ * Puts an ethernet address into a receive address register, or
+ * finds the rar that it is aleady in; adds to the pool list
+ **/
+s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
+{
+ static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF;
+ u32 first_empty_rar = NO_EMPTY_RAR_FOUND;
+ u32 rar;
+ u32 rar_low, rar_high;
+ u32 addr_low, addr_high;
+
+ DEBUGFUNC("ixgbe_insert_mac_addr_generic");
+
+ /* swap bytes for HW little endian */
+ addr_low = addr[0] | (addr[1] << 8)
+ | (addr[2] << 16)
+ | (addr[3] << 24);
+ addr_high = addr[4] | (addr[5] << 8);
+
+ /*
+ * Either find the mac_id in rar or find the first empty space.
+ * rar_highwater points to just after the highest currently used
+ * rar in order to shorten the search. It grows when we add a new
+ * rar to the top.
+ */
+ for (rar = 0; rar < hw->mac.rar_highwater; rar++) {
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+
+ if (((IXGBE_RAH_AV & rar_high) == 0)
+ && first_empty_rar == NO_EMPTY_RAR_FOUND) {
+ first_empty_rar = rar;
+ } else if ((rar_high & 0xFFFF) == addr_high) {
+ rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar));
+ if (rar_low == addr_low)
+ break; /* found it already in the rars */
+ }
+ }
+
+ if (rar < hw->mac.rar_highwater) {
+ /* already there so just add to the pool bits */
+ ixgbe_set_vmdq(hw, rar, vmdq);
+ } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
+ /* stick it into first empty RAR slot we found */
+ rar = first_empty_rar;
+ ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
+ } else if (rar == hw->mac.rar_highwater) {
+ /* add it to the top of the list and inc the highwater mark */
+ ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
+ hw->mac.rar_highwater++;
+ } else if (rar >= hw->mac.num_rar_entries) {
+ return IXGBE_ERR_INVALID_MAC_ADDR;
+ }
+
+ /*
+ * If we found rar[0], make sure the default pool bit (we use pool 0)
+ * remains cleared to be sure default pool packets will get delivered
+ */
+ if (rar == 0)
+ ixgbe_clear_vmdq(hw, rar, 0);
+
+ return rar;
+}
+
+/**
+ * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address
+ * @hw: pointer to hardware struct
+ * @rar: receive address register index to disassociate
+ * @vmdq: VMDq pool index to remove from the rar
+ **/
+s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
+{
+ u32 mpsar_lo, mpsar_hi;
+ u32 rar_entries = hw->mac.num_rar_entries;
+
+ DEBUGFUNC("ixgbe_clear_vmdq_generic");
+
+ if (rar < rar_entries) {
+ mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+ mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+
+ if (!mpsar_lo && !mpsar_hi)
+ goto done;
+
+ if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
+ if (mpsar_lo) {
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
+ mpsar_lo = 0;
+ }
+ if (mpsar_hi) {
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
+ mpsar_hi = 0;
+ }
+ } else if (vmdq < 32) {
+ mpsar_lo &= ~(1 << vmdq);
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
+ } else {
+ mpsar_hi &= ~(1 << (vmdq - 32));
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
+ }
+
+ /* was that the last pool using this rar? */
+ if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
+ hw->mac.ops.clear_rar(hw, rar);
+ } else {
+ DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ }
+
+done:
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address
+ * @hw: pointer to hardware struct
+ * @rar: receive address register index to associate with a VMDq index
+ * @vmdq: VMDq pool index
+ **/
+s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
+{
+ u32 mpsar;
+ u32 rar_entries = hw->mac.num_rar_entries;
+
+ DEBUGFUNC("ixgbe_set_vmdq_generic");
+
+ if (rar < rar_entries) {
+ if (vmdq < 32) {
+ mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+ mpsar |= 1 << vmdq;
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
+ } else {
+ mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+ mpsar |= 1 << (vmdq - 32);
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
+ }
+ } else {
+ DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ }
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
+ * @hw: pointer to hardware structure
+ **/
+s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
+{
+ int i;
+
+ DEBUGFUNC("ixgbe_init_uta_tables_generic");
+ DEBUGOUT(" Clearing UTA\n");
+
+ for (i = 0; i < 128; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot
+ * @hw: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ *
+ * return the VLVF index where this VLAN id should be placed
+ *
+ **/
+s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
+{
+ u32 bits = 0;
+ u32 first_empty_slot = 0;
+ s32 regindex;
+
+ /*
+ * 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++) {
+ bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
+ if (!bits && !(first_empty_slot))
+ 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 {
+ DEBUGOUT("No space in VLVF.\n");
+ regindex = -1;
+ }
+ }
+
+ return regindex;
+}
+
+/**
+ * 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
+ *
+ * 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)
+{
+ s32 regindex;
+ u32 bitindex;
+ u32 bits;
+ u32 vt;
+
+ DEBUGFUNC("ixgbe_set_vfta_generic");
+
+ if (vlan > 4095)
+ return IXGBE_ERR_PARAM;
+
+ /*
+ * this is a 2 part operation - first the VFTA, then the
+ * VLVF and VLVFB if VT Mode is set
+ */
+
+ /* Part 1
+ * The VFTA is a bitstring made up of 128 32-bit registers
+ * that enable the particular VLAN id, much like the MTA:
+ * bits[11-5]: which register
+ * bits[4-0]: which bit in the register
+ */
+ regindex = (vlan >> 5) & 0x7F;
+ bitindex = vlan & 0x1F;
+ bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
+ if (vlan_on)
+ bits |= (1 << bitindex);
+ else
+ bits &= ~(1 << bitindex);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits);
+
+
+ /* Part 2
+ * If VT Mode is set
+ * Either vlan_on
+ * make sure the vlan is in VLVF
+ * set the vind bit in the matching VLVFB
+ * 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) {
+ if (vlan == 0) {
+ regindex = 0;
+ } else {
+ regindex = ixgbe_find_vlvf_slot(hw, vlan);
+ if (regindex < 0)
+ goto out;
+ }
+
+ if (vlan_on) {
+ /* set the pool bit */
+ if (vind < 32) {
+ bits = IXGBE_READ_REG(hw,
+ IXGBE_VLVFB(regindex*2));
+ bits |= (1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB(regindex*2),
+ bits);
+ } else {
+ bits = IXGBE_READ_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1));
+ bits |= (1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1),
+ bits);
+ }
+ } else {
+ /* clear the pool bit */
+ if (vind < 32) {
+ bits = IXGBE_READ_REG(hw,
+ IXGBE_VLVFB(regindex*2));
+ bits &= ~(1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB(regindex*2),
+ bits);
+ bits |= IXGBE_READ_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1));
+ } else {
+ bits = IXGBE_READ_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1));
+ bits &= ~(1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1),
+ bits);
+ bits |= IXGBE_READ_REG(hw,
+ IXGBE_VLVFB(regindex*2));
+ }
+ }
+
+ if (bits)
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex),
+ (IXGBE_VLVF_VIEN | vlan));
+ else
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0);
+ }
+out:
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_clear_vfta_generic - Clear VLAN filter table
+ * @hw: pointer to hardware structure
+ *
+ * Clears the VLAN filer table, and the VMDq index associated with the filter
+ **/
+s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
+{
+ u32 offset;
+
+ DEBUGFUNC("ixgbe_clear_vfta_generic");
+
+ for (offset = 0; offset < hw->mac.vft_size; offset++)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
+
+ for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0);
+ }
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_check_mac_link_generic - Determine link and speed status
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @link_up: TRUE when link is up
+ * @link_up_wait_to_complete: bool used to wait for link up or not
+ *
+ * Reads the links register to determine if link is up and the current speed
+ **/
+s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+ bool *link_up, bool link_up_wait_to_complete)
+{
+ u32 links_reg;
+ u32 i;
+
+ DEBUGFUNC("ixgbe_check_mac_link_generic");
+
+ links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ if (link_up_wait_to_complete) {
+ for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+ if (links_reg & IXGBE_LINKS_UP) {
+ *link_up = TRUE;
+ break;
+ } else {
+ *link_up = FALSE;
+ }
+ msec_delay(100);
+ links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ }
+ } else {
+ if (links_reg & IXGBE_LINKS_UP)
+ *link_up = TRUE;
+ else
+ *link_up = FALSE;
+ }
+
+ if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+ IXGBE_LINKS_SPEED_10G_82599)
+ *speed = IXGBE_LINK_SPEED_10GB_FULL;
+ else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+ IXGBE_LINKS_SPEED_1G_82599)
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ else
+ *speed = IXGBE_LINK_SPEED_100_FULL;
+
+ /* if link is down, zero out the current_mode */
+ if (*link_up == FALSE) {
+ hw->fc.current_mode = ixgbe_fc_none;
+ hw->fc.fc_was_autonegged = FALSE;
+ }
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
+ * the EEPROM
+ * @hw: pointer to hardware structure
+ * @wwnn_prefix: the alternative WWNN prefix
+ * @wwpn_prefix: the alternative WWPN prefix
+ *
+ * This function will read the EEPROM from the alternative SAN MAC address
+ * block to check the support for the alternative WWNN/WWPN prefix support.
+ **/
+s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
+ u16 *wwpn_prefix)
+{
+ u16 offset, caps;
+ u16 alt_san_mac_blk_offset;
+
+ DEBUGFUNC("ixgbe_get_wwn_prefix_generic");
+
+ /* clear output first */
+ *wwnn_prefix = 0xFFFF;
+ *wwpn_prefix = 0xFFFF;
+
+ /* check if alternative SAN MAC is supported */
+ hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
+ &alt_san_mac_blk_offset);
+
+ if ((alt_san_mac_blk_offset == 0) ||
+ (alt_san_mac_blk_offset == 0xFFFF))
+ goto wwn_prefix_out;
+
+ /* check capability in alternative san mac address block */
+ offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
+ hw->eeprom.ops.read(hw, offset, &caps);
+ if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
+ goto wwn_prefix_out;
+
+ /* get the corresponding prefix for WWNN/WWPN */
+ offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
+ hw->eeprom.ops.read(hw, offset, wwnn_prefix);
+
+ offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
+ hw->eeprom.ops.read(hw, offset, wwpn_prefix);
+
+wwn_prefix_out:
+ return IXGBE_SUCCESS;
+}
diff --git a/sys/dev/ixgbe/ixgbe_common.h b/sys/dev/ixgbe/ixgbe_common.h
index 0c53575..f0707e2 100644
--- a/sys/dev/ixgbe/ixgbe_common.h
+++ b/sys/dev/ixgbe/ixgbe_common.h
@@ -42,6 +42,8 @@
IXGBE_WRITE_REG(hw, reg + 4, (u32) (value >> 32)); \
} while (0)
+u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw);
+
s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw);
@@ -57,12 +59,14 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
-s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
+s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 *data);
+u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
+s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr);
@@ -73,7 +77,6 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
ixgbe_mc_addr_itr func);
s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func);
-void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
@@ -87,9 +90,25 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask);
s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
-s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val);
-s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
+s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr);
+s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr);
+
+s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
+s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
+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);
+s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
+
+s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *link_up, bool link_up_wait_to_complete);
+
+s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
+ u16 *wwpn_prefix);
+
#endif /* IXGBE_COMMON */
diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h
index e1bbce0..151e63f 100644
--- a/sys/dev/ixgbe/ixgbe_osdep.h
+++ b/sys/dev/ixgbe/ixgbe_osdep.h
@@ -110,6 +110,16 @@ typedef boolean_t bool;
#endif
#endif
+#if defined(__i386__) || defined(__amd64__)
+static __inline
+void prefetch(void *x)
+{
+ __asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x));
+}
+#else
+#define prefetch(x)
+#endif
+
struct ixgbe_osdep
{
bus_space_tag_t mem_bus_space_tag;
diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c
index daa37d9..9bab98d 100644
--- a/sys/dev/ixgbe/ixgbe_phy.c
+++ b/sys/dev/ixgbe/ixgbe_phy.c
@@ -59,6 +59,8 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw)
{
struct ixgbe_phy_info *phy = &hw->phy;
+ DEBUGFUNC("ixgbe_init_phy_ops_generic");
+
/* PHY */
phy->ops.identify = &ixgbe_identify_phy_generic;
phy->ops.reset = &ixgbe_reset_phy_generic;
@@ -67,7 +69,7 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw)
phy->ops.setup_link = &ixgbe_setup_phy_link_generic;
phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic;
phy->ops.check_link = NULL;
- phy->ops.get_firmware_version = NULL;
+ phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_generic;
phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_generic;
phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_generic;
phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic;
@@ -91,6 +93,8 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
u32 phy_addr;
u16 ext_ability = 0;
+ DEBUGFUNC("ixgbe_identify_phy_generic");
+
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)) {
@@ -138,6 +142,8 @@ bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr)
u16 phy_id = 0;
bool valid = FALSE;
+ DEBUGFUNC("ixgbe_validate_phy_addr");
+
hw->phy.addr = phy_addr;
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id);
@@ -159,6 +165,8 @@ s32 ixgbe_get_phy_id(struct ixgbe_hw *hw)
u16 phy_id_high = 0;
u16 phy_id_low = 0;
+ DEBUGFUNC("ixgbe_get_phy_id");
+
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&phy_id_high);
@@ -183,6 +191,8 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
{
enum ixgbe_phy_type phy_type;
+ DEBUGFUNC("ixgbe_get_phy_type_from_id");
+
switch (phy_id) {
case TN1010_PHY_ID:
phy_type = ixgbe_phy_tn;
@@ -215,6 +225,8 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
u16 ctrl = 0;
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_reset_phy_generic");
+
if (hw->phy.type == ixgbe_phy_unknown)
status = ixgbe_identify_phy_generic(hw);
@@ -262,6 +274,8 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
s32 status = IXGBE_SUCCESS;
u16 gssr;
+ DEBUGFUNC("ixgbe_read_phy_reg_generic");
+
if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
gssr = IXGBE_GSSR_PHY1_SM;
else
@@ -359,6 +373,8 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
s32 status = IXGBE_SUCCESS;
u16 gssr;
+ DEBUGFUNC("ixgbe_write_phy_reg_generic");
+
if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
gssr = IXGBE_GSSR_PHY1_SM;
else
@@ -437,10 +453,10 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
}
/**
- * ixgbe_setup_phy_link_generic - Set and restart autoneg
- * @hw: pointer to hardware structure
+ * ixgbe_setup_phy_link_generic - Set and restart autoneg
+ * @hw: pointer to hardware structure
*
- * Restart autonegotiation and PHY and waits for completion.
+ * Restart autonegotiation and PHY and waits for completion.
**/
s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
{
@@ -448,23 +464,59 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
u32 time_out;
u32 max_time_out = 10;
u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+ bool autoneg = FALSE;
+ ixgbe_link_speed speed;
- /*
- * Set advertisement settings in PHY based on autoneg_advertised
- * settings. If autoneg_advertised = 0, then advertise default values
- * tnx devices cannot be "forced" to a autoneg 10G and fail. But can
- * for a 1G.
- */
- hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
+ DEBUGFUNC("ixgbe_setup_phy_link_generic");
- if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL)
- autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */
- else
- autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */
+ ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
- hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
+ 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);
+
+ autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE;
+ if (hw->phy.autoneg_advertised & 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);
+ }
+
+ 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);
+
+ 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);
+ }
+
+ 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);
+
+ autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE;
+ if (hw->phy.autoneg_advertised & 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);
+ }
/* Restart PHY autonegotiation and wait for completion */
hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
@@ -489,8 +541,10 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
}
}
- if (time_out == max_time_out)
+ if (time_out == max_time_out) {
status = IXGBE_ERR_LINK_SETUP;
+ DEBUGOUT("ixgbe_setup_phy_link_generic: time out");
+ }
return status;
}
@@ -509,6 +563,8 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
UNREFERENCED_PARAMETER(autoneg);
UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+ DEBUGFUNC("ixgbe_setup_phy_link_speed_generic");
+
/*
* Clear autoneg_advertised and set new values based on input link
* speed.
@@ -545,6 +601,8 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
s32 status = IXGBE_ERR_LINK_SETUP;
u16 speed_ability;
+ DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
+
*speed = 0;
*autoneg = TRUE;
@@ -581,6 +639,8 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
u16 phy_speed = 0;
u16 phy_data = 0;
+ DEBUGFUNC("ixgbe_check_phy_link_tnx");
+
/* Initialize speed and link to default case */
*link_up = FALSE;
*speed = IXGBE_LINK_SPEED_10GB_FULL;
@@ -613,6 +673,102 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
}
/**
+ * ixgbe_setup_phy_link_tnx - Set and restart autoneg
+ * @hw: pointer to hardware structure
+ *
+ * Restart autonegotiation and PHY and waits for completion.
+ **/
+s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
+{
+ s32 status = IXGBE_SUCCESS;
+ u32 time_out;
+ u32 max_time_out = 10;
+ u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+ bool autoneg = FALSE;
+ ixgbe_link_speed speed;
+
+ DEBUGFUNC("ixgbe_setup_phy_link_tnx");
+
+ 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);
+
+ autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE;
+ if (hw->phy.autoneg_advertised & 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);
+ }
+
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+ /* Set or unset auto-negotiation 1G advertisement */
+ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &autoneg_reg);
+
+ autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
+ autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+
+ hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_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);
+
+ autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE;
+ if (hw->phy.autoneg_advertised & 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);
+ }
+
+ /* Restart PHY autonegotiation and wait for completion */
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
+
+ autoneg_reg |= IXGBE_MII_RESTART;
+
+ hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
+
+ /* Wait for autonegotiation to finish */
+ for (time_out = 0; time_out < max_time_out; time_out++) {
+ usec_delay(10);
+ /* Restart PHY autonegotiation and wait for completion */
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &autoneg_reg);
+
+ autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
+ if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) {
+ break;
+ }
+ }
+
+ if (time_out == max_time_out) {
+ status = IXGBE_ERR_LINK_SETUP;
+ DEBUGOUT("ixgbe_setup_phy_link_tnx: time out");
+ }
+
+ return status;
+}
+
+
+/**
* ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
* @hw: pointer to hardware structure
* @firmware_version: pointer to the PHY Firmware Version
@@ -622,6 +778,8 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
{
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_get_phy_firmware_version_tnx");
+
status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
firmware_version);
@@ -631,15 +789,17 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
/**
- * ixgbe_get_phy_firmware_version_aq - Gets the PHY Firmware Version
+ * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version
* @hw: pointer to hardware structure
* @firmware_version: pointer to the PHY Firmware Version
**/
-s32 ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw,
+s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
u16 *firmware_version)
{
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_get_phy_firmware_version_generic");
+
status = hw->phy.ops.read_reg(hw, AQ_FW_REV,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
firmware_version);
@@ -660,6 +820,8 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
s32 ret_val = IXGBE_SUCCESS;
u32 i;
+ DEBUGFUNC("ixgbe_reset_phy_nl");
+
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
@@ -762,6 +924,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
u8 cable_tech = 0;
u16 enforce_sfp = 0;
+ DEBUGFUNC("ixgbe_identify_sfp_module_generic");
+
if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
hw->phy.sfp_type = ixgbe_sfp_type_not_present;
status = IXGBE_ERR_SFP_NOT_PRESENT;
@@ -850,6 +1014,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
(comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
hw->phy.multispeed_fiber = TRUE;
+
/* Determine PHY vendor */
if (hw->phy.type != ixgbe_phy_nl) {
hw->phy.id = identifier;
@@ -944,6 +1109,8 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
{
u16 sfp_id;
+ DEBUGFUNC("ixgbe_get_sfp_init_sequence_offsets");
+
if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
return IXGBE_ERR_SFP_NOT_SUPPORTED;
@@ -1370,6 +1537,8 @@ static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
s32 status;
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ DEBUGFUNC("ixgbe_clock_in_i2c_bit");
+
status = ixgbe_raise_i2c_clk(hw, &i2cctl);
/* Minimum high period of clock is 4us */
@@ -1398,6 +1567,8 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
s32 status;
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ DEBUGFUNC("ixgbe_clock_out_i2c_bit");
+
status = ixgbe_set_i2c_data(hw, &i2cctl, data);
if (status == IXGBE_SUCCESS) {
status = ixgbe_raise_i2c_clk(hw, &i2cctl);
@@ -1429,6 +1600,8 @@ static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
{
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_raise_i2c_clk");
+
*i2cctl |= IXGBE_I2C_CLK_OUT;
IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
@@ -1449,6 +1622,8 @@ static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
{
+ DEBUGFUNC("ixgbe_lower_i2c_clk");
+
*i2cctl &= ~IXGBE_I2C_CLK_OUT;
IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
@@ -1469,6 +1644,8 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
{
s32 status = IXGBE_SUCCESS;
+ DEBUGFUNC("ixgbe_set_i2c_data");
+
if (data)
*i2cctl |= IXGBE_I2C_DATA_OUT;
else
@@ -1500,6 +1677,8 @@ static bool ixgbe_get_i2c_data(u32 *i2cctl)
{
bool data;
+ DEBUGFUNC("ixgbe_get_i2c_data");
+
if (*i2cctl & IXGBE_I2C_DATA_IN)
data = 1;
else
diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h
index bfe73de..39f3bc8 100644
--- a/sys/dev/ixgbe/ixgbe_phy.h
+++ b/sys/dev/ixgbe/ixgbe_phy.h
@@ -108,9 +108,10 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *link_up);
+s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw);
s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
u16 *firmware_version);
-s32 ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw,
+s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
u16 *firmware_version);
s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h
index 50345f4..0b10119 100644
--- a/sys/dev/ixgbe/ixgbe_type.h
+++ b/sys/dev/ixgbe/ixgbe_type.h
@@ -47,6 +47,7 @@
#define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
#define IXGBE_DEV_ID_82598AT 0x10C8
+#define IXGBE_DEV_ID_82598AT2 0x150B
#define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
@@ -54,6 +55,8 @@
#define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1
#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
#define IXGBE_DEV_ID_82599_KX4 0x10F7
+#define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514
+#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
#define IXGBE_DEV_ID_82599_CX4 0x10F9
#define IXGBE_DEV_ID_82599_SFP 0x10FB
#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC
@@ -74,6 +77,7 @@
/* NVM Registers */
#define IXGBE_EEC 0x10010
#define IXGBE_EERD 0x10014
+#define IXGBE_EEWR 0x10018
#define IXGBE_FLA 0x1001C
#define IXGBE_EEMNGCTL 0x10110
#define IXGBE_EEMNGDATA 0x10114
@@ -352,7 +356,7 @@
#define IXGBE_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */
#define IXGBE_WUFC_FLX_FILTERS 0x000F0000 /* Mask for 4 flex filters */
#define IXGBE_WUFC_EXT_FLX_FILTERS 0x00300000 /* Mask for Ext. flex filters */
-#define IXGBE_WUFC_ALL_FILTERS 0x003F00FF /* Mask for all 6 wakeup filters*/
+#define IXGBE_WUFC_ALL_FILTERS 0x003F00FF /* Mask for all wakeup filters */
#define IXGBE_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */
/* Wake Up Status */
@@ -703,6 +707,7 @@
#define IXGBE_MREVID 0x11064
#define IXGBE_DCA_ID 0x11070
#define IXGBE_DCA_CTRL 0x11074
+#define IXGBE_SWFW_SYNC IXGBE_GSSR
/* PCI-E registers 82599-Specific */
#define IXGBE_GCR_EXT 0x11050
@@ -725,6 +730,12 @@
#define IXGBE_ECC_STATUS_82599 0x110E0
#define IXGBE_BAR_CTRL_82599 0x110F4
+/* PCI Express Control */
+#define IXGBE_GCR_CMPL_TMOUT_MASK 0x0000F000
+#define IXGBE_GCR_CMPL_TMOUT_10ms 0x00001000
+#define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000
+#define IXGBE_GCR_CAP_VER2 0x00040000
+
/* Time Sync Registers */
#define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */
#define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */
@@ -848,12 +859,16 @@
#define IXGBE_MPVC 0x04318
#define IXGBE_SGMIIC 0x04314
+/* Copper Pond 2 link timeout */
+#define IXGBE_VALIDATE_LINK_READY_TIMEOUT 50
+
/* Omer CORECTL */
#define IXGBE_CORECTL 0x014F00
/* BARCTRL */
-#define IXGBE_BARCTRL 0x110F4
-#define IXGBE_BARCTRL_FLSIZE 0x0700
-#define IXGBE_BARCTRL_CSRSIZE 0x2000
+#define IXGBE_BARCTRL 0x110F4
+#define IXGBE_BARCTRL_FLSIZE 0x0700
+#define IXGBE_BARCTRL_FLSIZE_SHIFT 8
+#define IXGBE_BARCTRL_CSRSIZE 0x2000
/* RSCCTL Bit Masks */
#define IXGBE_RSCCTL_RSCEN 0x01
@@ -1013,10 +1028,18 @@
/* MII clause 22/28 definitions */
#define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800
-#define IXGBE_MII_SPEED_SELECTION_REG 0x10
-#define IXGBE_MII_RESTART 0x200
-#define IXGBE_MII_AUTONEG_COMPLETE 0x20
-#define IXGBE_MII_AUTONEG_REG 0x0
+#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */
+#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */
+#define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */
+#define IXGBE_MII_AUTONEG_ADVERTISE_REG 0x10 /* 100M Advertisement */
+#define IXGBE_MII_10GBASE_T_ADVERTISE 0x1000 /* full duplex, bit:12*/
+#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/
+#define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/
+#define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */
+#define IXGBE_MII_RESTART 0x200
+#define IXGBE_MII_AUTONEG_COMPLETE 0x20
+#define IXGBE_MII_AUTONEG_LINK_UP 0x04
+#define IXGBE_MII_AUTONEG_REG 0x0
#define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0
#define IXGBE_MAX_PHY_ADDR 32
@@ -1408,6 +1431,8 @@
#define IXGBE_AUTOC_KX4_SUPP 0x80000000
#define IXGBE_AUTOC_KX_SUPP 0x40000000
#define IXGBE_AUTOC_PAUSE 0x30000000
+#define IXGBE_AUTOC_ASM_PAUSE 0x20000000
+#define IXGBE_AUTOC_SYM_PAUSE 0x10000000
#define IXGBE_AUTOC_RF 0x08000000
#define IXGBE_AUTOC_PD_TMR 0x06000000
#define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000
@@ -1476,6 +1501,8 @@
#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
+#define IXGBE_LINKS2_AN_SUPPORTED 0x00000040
+
/* PCS1GLSTA Bit Masks */
#define IXGBE_PCS1GLSTA_LINK_OK 1
#define IXGBE_PCS1GLSTA_SYNK_OK 0x10
@@ -1496,12 +1523,18 @@
#define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000
#define IXGBE_PCS1GLCTL_AN_RESTART 0x20000
+/* ANLP1 Bit Masks */
+#define IXGBE_ANLP1_PAUSE 0x0C00
+#define IXGBE_ANLP1_SYM_PAUSE 0x0400
+#define IXGBE_ANLP1_ASM_PAUSE 0x0800
+
/* SW Semaphore Register bitmasks */
#define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
#define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
#define IXGBE_SWSM_WMNG 0x00000004 /* Wake MNG Clock */
+#define IXGBE_SWFW_REGSMP 0x80000000 /* Register Semaphore bit 31 */
-/* GSSR definitions */
+/* SW_FW_SYNC/GSSR definitions */
#define IXGBE_GSSR_EEP_SM 0x0001
#define IXGBE_GSSR_PHY0_SM 0x0002
#define IXGBE_GSSR_PHY1_SM 0x0004
@@ -1521,20 +1554,24 @@
#define IXGBE_EEC_GNT 0x00000080 /* EEPROM Access Grant */
#define IXGBE_EEC_PRES 0x00000100 /* EEPROM Present */
#define IXGBE_EEC_ARD 0x00000200 /* EEPROM Auto Read Done */
+#define IXGBE_EEC_FLUP 0x00800000 /* Flash update command */
+#define IXGBE_EEC_FLUDONE 0x04000000 /* Flash update done */
/* EEPROM Addressing bits based on type (0-small, 1-large) */
#define IXGBE_EEC_ADDR_SIZE 0x00000400
#define IXGBE_EEC_SIZE 0x00007800 /* EEPROM Size */
-#define IXGBE_EEC_SIZE_SHIFT 11
-#define IXGBE_EEPROM_WORD_SIZE_SHIFT 6
-#define IXGBE_EEPROM_OPCODE_BITS 8
+#define IXGBE_EEC_SIZE_SHIFT 11
+#define IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT 6
+#define IXGBE_EEPROM_OPCODE_BITS 8
/* Checksum and EEPROM pointers */
#define IXGBE_EEPROM_CHECKSUM 0x3F
#define IXGBE_EEPROM_SUM 0xBABA
#define IXGBE_PCIE_ANALOG_PTR 0x03
#define IXGBE_ATLAS0_CONFIG_PTR 0x04
+#define IXGBE_PHY_PTR 0x04
#define IXGBE_ATLAS1_CONFIG_PTR 0x05
+#define IXGBE_OPTION_ROM_PTR 0x05
#define IXGBE_PCIE_GENERAL_PTR 0x06
#define IXGBE_PCIE_CONFIG0_PTR 0x07
#define IXGBE_PCIE_CONFIG1_PTR 0x08
@@ -1577,10 +1614,12 @@
#define IXGBE_EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */
/* EEPROM Read Register */
-#define IXGBE_EEPROM_READ_REG_DATA 16 /* data offset in EEPROM read reg */
-#define IXGBE_EEPROM_READ_REG_DONE 2 /* Offset to READ done bit */
-#define IXGBE_EEPROM_READ_REG_START 1 /* First bit to start operation */
-#define IXGBE_EEPROM_READ_ADDR_SHIFT 2 /* Shift to the address bits */
+#define IXGBE_EEPROM_RW_REG_DATA 16 /* data offset in EEPROM read reg */
+#define IXGBE_EEPROM_RW_REG_DONE 2 /* Offset to READ done bit */
+#define IXGBE_EEPROM_RW_REG_START 1 /* First bit to start operation */
+#define IXGBE_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
+#define IXGBE_NVM_POLL_WRITE 1 /* Flag for polling for write complete */
+#define IXGBE_NVM_POLL_READ 0 /* Flag for polling for read complete */
#define IXGBE_ETH_LENGTH_OF_ADDRESS 6
@@ -1588,10 +1627,12 @@
#define IXGBE_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
#endif
-#ifndef IXGBE_EERD_ATTEMPTS
-/* Number of 5 microseconds we wait for EERD read to complete */
-#define IXGBE_EERD_ATTEMPTS 100000
-#endif
+/* Number of 5 microseconds we wait for EERD read and
+ * EERW write to complete */
+#define IXGBE_EERD_EEWR_ATTEMPTS 100000
+
+/* # attempts we wait for flush update to complete */
+#define IXGBE_FLUDONE_ATTEMPTS 20000
#define IXGBE_PCIE_CTRL2 0x5 /* PCIe Control 2 Offset */
#define IXGBE_PCIE_CTRL2_DUMMY_ENABLE 0x8 /* Dummy Function Enable */
@@ -1604,9 +1645,18 @@
#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2
#define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4
#define IXGBE_FW_PATCH_VERSION_4 0x7
+#define IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR 0x27 /* Alt. SAN MAC block */
+#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET 0x0 /* Alt. SAN MAC capability */
+#define IXGBE_ALT_SAN_MAC_ADDR_PORT0_OFFSET 0x1 /* Alt. SAN MAC 0 offset */
+#define IXGBE_ALT_SAN_MAC_ADDR_PORT1_OFFSET 0x4 /* Alt. SAN MAC 1 offset */
+#define IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET 0x7 /* Alt. WWNN prefix offset */
+#define IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET 0x8 /* Alt. WWPN prefix offset */
+#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_SANMAC 0x0 /* Alt. SAN MAC exists */
+#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt. WWN base exists */
/* PCI Bus Info */
#define IXGBE_PCI_LINK_STATUS 0xB2
+#define IXGBE_PCI_DEVICE_CONTROL2 0xC8
#define IXGBE_PCI_LINK_WIDTH 0x3F0
#define IXGBE_PCI_LINK_WIDTH_1 0x10
#define IXGBE_PCI_LINK_WIDTH_2 0x20
@@ -1617,6 +1667,7 @@
#define IXGBE_PCI_LINK_SPEED_5000 0x2
#define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E
#define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80
+#define IXGBE_PCI_DEVICE_CONTROL2_16ms 0x0005
/* Number of 100 microseconds we wait for PCI Express master disable */
#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
@@ -2210,6 +2261,7 @@ struct ixgbe_atr_input {
enum ixgbe_eeprom_type {
ixgbe_eeprom_uninitialized = 0,
ixgbe_eeprom_spi,
+ ixgbe_flash,
ixgbe_eeprom_none /* No NVM support */
};
@@ -2269,6 +2321,7 @@ enum ixgbe_media_type {
ixgbe_media_type_fiber,
ixgbe_media_type_copper,
ixgbe_media_type_backplane,
+ ixgbe_media_type_cx4,
ixgbe_media_type_virtual
};
@@ -2281,6 +2334,14 @@ enum ixgbe_fc_mode {
ixgbe_fc_default
};
+/* Smart Speed Settings */
+#define IXGBE_SMARTSPEED_MAX_RETRIES 3
+enum ixgbe_smart_speed {
+ ixgbe_smart_speed_auto = 0,
+ ixgbe_smart_speed_on,
+ ixgbe_smart_speed_off
+};
+
/* PCI bus types */
enum ixgbe_bus_type {
ixgbe_bus_type_unknown = 0,
@@ -2434,6 +2495,7 @@ struct ixgbe_eeprom_operations {
s32 (*write)(struct ixgbe_hw *, u16, u16);
s32 (*validate_checksum)(struct ixgbe_hw *, u16 *);
s32 (*update_checksum)(struct ixgbe_hw *);
+ u16 (*calc_checksum)(struct ixgbe_hw *);
};
struct ixgbe_mac_operations {
@@ -2447,6 +2509,7 @@ struct ixgbe_mac_operations {
s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*set_san_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*get_device_caps)(struct ixgbe_hw *, u16 *);
+ s32 (*get_wwn_prefix)(struct ixgbe_hw *, u16 *, u16 *);
s32 (*stop_adapter)(struct ixgbe_hw *);
s32 (*get_bus_info)(struct ixgbe_hw *);
void (*set_lan_id)(struct ixgbe_hw *);
@@ -2458,9 +2521,7 @@ struct ixgbe_mac_operations {
void (*release_swfw_sync)(struct ixgbe_hw *, u16);
/* Link */
- s32 (*setup_link)(struct ixgbe_hw *);
- s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool,
- bool);
+ s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool);
s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool);
s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
bool *);
@@ -2525,6 +2586,10 @@ struct ixgbe_mac_info {
u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
u8 san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
+ /* prefix for World Wide Node Name (WWNN) */
+ u16 wwnn_prefix;
+ /* prefix for World Wide Port Name (WWPN) */
+ u16 wwpn_prefix;
s32 mc_filter_type;
u32 mcft_size;
u32 vft_size;
@@ -2537,8 +2602,6 @@ struct ixgbe_mac_info {
u32 orig_autoc;
u32 orig_autoc2;
bool orig_link_settings_stored;
- bool autoneg;
- bool autoneg_succeeded;
bool autotry_restart;
};
@@ -2553,7 +2616,8 @@ struct ixgbe_phy_info {
enum ixgbe_media_type media_type;
bool reset_disable;
ixgbe_autoneg_advertised autoneg_advertised;
- bool autoneg_wait_to_complete;
+ enum ixgbe_smart_speed smart_speed;
+ bool smart_speed_active;
bool multispeed_fiber;
};
OpenPOWER on IntegriCloud