aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJack F Vogel <jfv@FreeBSD.org>2009-12-07 21:30:54 +0000
committerJack F Vogel <jfv@FreeBSD.org>2009-12-07 21:30:54 +0000
commit2969bf0e467c14c149c45a81b6505ec443d15938 (patch)
treeeb771079f6b223fe24a5557c0c86f0cea1dbe80c /sys
parent406930fba4f38478e7a005d46e118c54775ffb37 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ixgbe/ixgbe.c1225
-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.c970
-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, 2506 insertions, 1265 deletions
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index d994529ea461..10a0e04df488 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,13 +548,40 @@ 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;
+ }
+
if ((adapter->msix > 1) && (ixgbe_enable_msix))
error = ixgbe_allocate_msix(adapter);
else
@@ -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;
+ i = first;
+ while (i != limit) {
+ rxbuf = &rxr->rx_buffers[i];
- rxbuf = &rxr->rx_buffers[i];
+ if (rxbuf->m_head == NULL) {
+ mh = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (mh == NULL)
+ goto failure;
+ } else /* reuse */
+ mh = rxbuf->m_head;
- /* 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;
+ mh->m_len = MHLEN;
+ mh->m_flags |= M_PKTHDR;
- 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;
+ }
- 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;
+ /*
+ ** 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);
+ /* 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);
+ /* 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;
+ }
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,18 +4721,40 @@ ixgbe_handle_msf(void *context, int pending)
struct adapter *adapter = context;
struct ixgbe_hw *hw = &adapter->hw;
u32 autoneg;
+ bool negotiate;
- 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);
+ 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
+
/**********************************************************************
*
* Update the board statistics counters.
@@ -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 848820a8e956..d52eed3a07e3 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 fb711c621ad5..12711b0a9b4d 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 c3d23afde550..97b655a26ac7 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;
- /* 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;
+ /* 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 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;
-}
-
-/**
- * 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);
+ DEBUGFUNC("ixgbe_get_device_caps_82599");
- 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 9c3356fff591..44644574860c 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 654f22f6c322..8ab78ad8720c 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 30c372d8a9b0..89e57d83dabb 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 0c535751880b..f0707e21a2e4 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 e1bbce08602d..151e63ff1f6a 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 daa37d910004..9bab98d29522 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 bfe73de25b12..39f3bc83f0a4 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 50345f4c2c1a..0b1011977094 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;
};