summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2011-06-10 12:46:36 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2011-06-10 12:46:36 +0000
commitede3ae71faaa64d8a260366efbfa6669a1a8898a (patch)
tree19da36ebabdeb9dfc35c109712cf84715463ca39 /sys
parent1067402c5d83af16fa9c9f95adef20db70eff0e3 (diff)
Monster update of ix(4). This brings ix(4) close to what is currently
in FreeBSD. This seems to fix a lot of problems on 82599 based cards including the VLAN problems and the corrupted receives. Putting this in now to work on it in tree since a few additional things need to be merged. Tested by myself, deraadt@ and jsg@ on both 98er and 99er cards. OK jsg@, deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_ix.c1453
-rw-r--r--sys/dev/pci/if_ix.h207
-rw-r--r--sys/dev/pci/ixgbe.c1875
-rw-r--r--sys/dev/pci/ixgbe.h60
-rw-r--r--sys/dev/pci/ixgbe_82598.c210
-rw-r--r--sys/dev/pci/ixgbe_82599.c1386
-rw-r--r--sys/dev/pci/ixgbe_phy.c247
-rw-r--r--sys/dev/pci/ixgbe_type.h405
8 files changed, 3897 insertions, 1946 deletions
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c
index 8a2d5488ba5..41a295c2dfc 100644
--- a/sys/dev/pci/if_ix.c
+++ b/sys/dev/pci/if_ix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ix.c,v 1.51 2011/04/15 15:12:27 chl Exp $ */
+/* $OpenBSD: if_ix.c,v 1.52 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -55,6 +55,7 @@ const struct pci_matchid ixgbe_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82598AF_DUAL },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82598AF },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82598AT },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82598AT2 },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82598AT_DUAL },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82598EB_CX4 },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82598EB_CX4_DUAL },
@@ -66,9 +67,15 @@ const struct pci_matchid ixgbe_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_KX4_MEZZ },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_XAUI },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_COMBO_BACKPLANE },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_BPLANE_FCOE },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_CX4 },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_T3_LOM },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP },
- { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_EM }
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_EM },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_FCOE }
+#if 0
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599VF }
+#endif
};
/*********************************************************************
@@ -91,8 +98,8 @@ int ixgbe_allocate_legacy(struct ix_softc *);
int ixgbe_allocate_queues(struct ix_softc *);
void ixgbe_free_pci_resources(struct ix_softc *);
void ixgbe_local_timer(void *);
-int ixgbe_hardware_init(struct ix_softc *);
void ixgbe_setup_interface(struct ix_softc *);
+void ixgbe_config_link(struct ix_softc *sc);
int ixgbe_allocate_transmit_buffers(struct tx_ring *);
int ixgbe_setup_transmit_structures(struct ix_softc *);
@@ -113,8 +120,8 @@ void ixgbe_enable_intr(struct ix_softc *);
void ixgbe_disable_intr(struct ix_softc *);
void ixgbe_update_stats_counters(struct ix_softc *);
int ixgbe_txeof(struct tx_ring *);
-int ixgbe_rxeof(struct rx_ring *, int);
-void ixgbe_rx_checksum(struct ix_softc *, uint32_t, struct mbuf *);
+int ixgbe_rxeof(struct ix_queue *, int);
+void ixgbe_rx_checksum(uint32_t, struct mbuf *, uint32_t);
void ixgbe_set_promisc(struct ix_softc *);
void ixgbe_disable_promisc(struct ix_softc *);
void ixgbe_set_multi(struct ix_softc *);
@@ -124,7 +131,6 @@ void ixgbe_print_hw_stats(struct ix_softc *);
void ixgbe_update_link_status(struct ix_softc *);
int ixgbe_get_buf(struct rx_ring *, int);
int ixgbe_encap(struct tx_ring *, struct mbuf *);
-void ixgbe_enable_hw_vlans(struct ix_softc * sc);
int ixgbe_dma_malloc(struct ix_softc *, bus_size_t,
struct ixgbe_dma_alloc *, int);
void ixgbe_dma_free(struct ix_softc *, struct ixgbe_dma_alloc *);
@@ -134,8 +140,18 @@ void ixgbe_set_ivar(struct ix_softc *, uint8_t, uint8_t, int8_t);
void ixgbe_configure_ivars(struct ix_softc *);
uint8_t *ixgbe_mc_array_itr(struct ixgbe_hw *, uint8_t **, uint32_t *);
+void ixgbe_setup_vlan_hw_support(struct ix_softc *);
+
+/* Support for pluggable optic modules */
+int ixgbe_sfp_probe(struct ix_softc *);
+void ixgbe_setup_optics(struct ix_softc *);
+
/* Legacy (single vector interrupt handler */
int ixgbe_legacy_irq(void *);
+void ixgbe_enable_queue(struct ix_softc *, uint32_t);
+void ixgbe_disable_queue(struct ix_softc *, uint32_t);
+void ixgbe_rearm_queue(struct ix_softc *, uint32_t);
+void ixgbe_handle_que(void *, int);
/*********************************************************************
* OpenBSD Device Interface Entry Points
@@ -155,7 +171,7 @@ int ixgbe_smart_speed = ixgbe_smart_speed_on;
* Device identification routine
*
* ixgbe_probe determines if the driver should be loaded on
- * sc based on PCI vendor/device id of the sc.
+ * adapter based on PCI vendor/device id of the adapter.
*
* return 0 on success, positive on failure
*********************************************************************/
@@ -204,7 +220,6 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux)
ixgbe_identify_hardware(sc);
/* Indicate to RX setup to use Jumbo Clusters */
- sc->bigbufs = FALSE;
sc->num_tx_desc = DEFAULT_TXD;
sc->num_rx_desc = DEFAULT_RXD;
sc->rx_process_limit = 100; // XXX
@@ -217,11 +232,31 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux)
if (ixgbe_allocate_queues(sc))
goto err_out;
+ /* Allocate multicast array memory. */
+ sc->mta = malloc(sizeof(uint8_t) * IXGBE_ETH_LENGTH_OF_ADDRESS *
+ MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
+ if (sc->mta == 0) {
+ printf(": Can not allocate multicast setup array\n");
+ goto err_late;
+ }
+
/* Initialize the shared code */
- if (hw->mac.type == ixgbe_mac_82598EB)
- error = ixgbe_init_ops_82598(&sc->hw);
- else
- error = ixgbe_init_ops_82599(&sc->hw);
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ error = ixgbe_init_ops_82598(hw);
+ break;
+ case ixgbe_mac_82599EB:
+ error = ixgbe_init_ops_82599(hw);
+ break;
+#if 0
+ case ixgbe_mac_82599_vf:
+ error = ixgbe_init_ops_vf(hw);
+ break;
+#endif
+ default:
+ error = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
+ break;
+ }
if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
/*
* No optics in this port, set up
@@ -232,25 +267,18 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux)
error = 0;
} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
printf(": Unsupported SFP+ module detected!\n");
- error = EIO;
goto err_late;
} else if (error) {
printf(": Unable to initialize the shared code\n");
- error = EIO;
goto err_late;
}
/* Make sure we have a good EEPROM before we read from it */
if (sc->hw.eeprom.ops.validate_checksum(&sc->hw, &csum) < 0) {
printf(": The EEPROM Checksum Is Not Valid\n");
- error = EIO;
goto err_late;
}
- /* Pick up the smart speed setting */
- if (sc->hw.mac.type == ixgbe_mac_82599EB)
- sc->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;
@@ -288,6 +316,9 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux)
/* Initialize statistics */
ixgbe_update_stats_counters(sc);
+ /* Print PCIE bus type/speed/width info */
+ hw->mac.ops.get_bus_info(hw);
+
/* let hardware know driver is loaded */
ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
@@ -303,6 +334,7 @@ err_late:
ixgbe_free_receive_structures(sc);
err_out:
ixgbe_free_pci_resources(sc);
+ free(sc->mta, M_DEVBUF);
}
/*********************************************************************
@@ -339,6 +371,7 @@ ixgbe_detach(struct device *self, int flags)
ixgbe_free_transmit_structures(sc);
ixgbe_free_receive_structures(sc);
+ free(sc->mta, M_DEVBUF);
return (0);
}
@@ -404,7 +437,7 @@ ixgbe_start_locked(struct tx_ring *txr, struct ifnet * ifp)
*/
if (post)
IXGBE_WRITE_REG(&sc->hw, IXGBE_TDT(txr->me),
- txr->next_avail_tx_desc);
+ txr->next_avail_desc);
}
@@ -423,8 +456,8 @@ ixgbe_start(struct ifnet *ifp)
* and appropriate logic here to deal with
* it. -jfv
*/
- if (sc->num_tx_queues > 1)
- queue = (curcpu % sc->num_tx_queues);
+ if (sc->num_queues > 1)
+ queue = (curcpu % sc->num_queues);
#endif
txr = &sc->tx_rings[queue];
@@ -542,7 +575,7 @@ ixgbe_watchdog(struct ifnet * ifp)
* Finally, anytime all descriptors are clean the timer is
* set to 0.
*/
- for (i = 0; i < sc->num_tx_queues; i++, txr++) {
+ for (i = 0; i < sc->num_queues; i++, txr++) {
if (txr->watchdog_timer == 0 || --txr->watchdog_timer)
continue;
else {
@@ -558,7 +591,7 @@ ixgbe_watchdog(struct ifnet * ifp)
* reset the hardware.
*/
if (IXGBE_READ_REG(hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) {
- for (i = 0; i < sc->num_tx_queues; i++, txr++)
+ for (i = 0; i < sc->num_queues; i++, txr++)
txr->watchdog_timer = IXGBE_TX_TIMEOUT;
ifp->if_timer = IXGBE_TX_TIMEOUT;
return;
@@ -566,12 +599,12 @@ ixgbe_watchdog(struct ifnet * ifp)
printf("%s: Watchdog timeout -- resetting\n", ifp->if_xname);
- for (i = 0; i < sc->num_tx_queues; i++, txr++) {
+ for (i = 0; i < sc->num_queues; i++, txr++) {
printf("%s: Queue(%d) tdh = %d, hw tdt = %d\n", ifp->if_xname, i,
IXGBE_READ_REG(hw, IXGBE_TDH(i)),
IXGBE_READ_REG(hw, IXGBE_TDT(i)));
printf("%s: TX(%d) desc avail = %d, Next TX to Clean = %d\n", ifp->if_xname,
- i, txr->tx_avail, txr->next_tx_to_clean);
+ i, txr->tx_avail, txr->next_to_clean);
}
ifp->if_flags &= ~IFF_RUNNING;
sc->watchdog_events++;
@@ -598,7 +631,7 @@ ixgbe_init(void *arg)
struct ix_softc *sc = (struct ix_softc *)arg;
struct ifnet *ifp = &sc->arpcom.ac_if;
struct rx_ring *rxr = sc->rx_rings;
- uint32_t k, txdctl, rxdctl, mhadd, gpie;
+ uint32_t k, txdctl, rxdctl, rxctrl, mhadd, gpie;
int err;
int i, s;
@@ -608,18 +641,15 @@ ixgbe_init(void *arg)
ixgbe_stop(sc);
+ /* reprogram the RAR[0] in case user changed it. */
+ ixgbe_hw(&sc->hw, set_rar, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV);
+
/* Get the latest mac address, User can use a LAA */
bcopy(sc->arpcom.ac_enaddr, sc->hw.mac.addr,
IXGBE_ETH_LENGTH_OF_ADDRESS);
ixgbe_hw(&sc->hw, set_rar, 0, sc->hw.mac.addr, 0, 1);
sc->hw.addr_ctrl.rar_used_count = 1;
- /* Do a warm reset */
- sc->hw.mac.ops.reset_hw(&sc->hw);
-
- if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING)
- ixgbe_enable_hw_vlans(sc);
-
/* Prepare transmit descriptors and buffers */
if (ixgbe_setup_transmit_structures(sc)) {
printf("%s: Could not setup transmit structures\n",
@@ -629,21 +659,26 @@ ixgbe_init(void *arg)
return;
}
+ ixgbe_hw0(&sc->hw, init_hw);
ixgbe_initialize_transmit_units(sc);
/* Setup Multicast table */
ixgbe_set_multi(sc);
- /*
- * If we are resetting MTU smaller than 2K
- * drop to small RX buffers
- */
- if (sc->max_frame_size <= MCLBYTES)
- sc->bigbufs = FALSE;
+ /* Determine the correct buffer size for jumbo/headersplit */
+ if (sc->max_frame_size <= 2048)
+ sc->rx_mbuf_sz = MCLBYTES;
+ else if (sc->max_frame_size <= 4096)
+ sc->rx_mbuf_sz = 4096;
+ else if (sc->max_frame_size <= 9216)
+ sc->rx_mbuf_sz = 9216;
+ else
+ sc->rx_mbuf_sz = 16 * 1024;
/* Prepare receive descriptors and buffers */
if (ixgbe_setup_receive_structures(sc)) {
- printf("%s: Could not setup receive structures\n", ifp->if_xname);
+ printf("%s: Could not setup receive structures\n",
+ ifp->if_xname);
ixgbe_stop(sc);
splx(s);
return;
@@ -654,20 +689,14 @@ ixgbe_init(void *arg)
gpie = IXGBE_READ_REG(&sc->hw, IXGBE_GPIE);
- if (sc->hw.mac.type == ixgbe_mac_82599EB) {
- gpie |= IXGBE_SDP1_GPIEN;
+ /* Enable Fan Failure Interrupt */
+ gpie |= IXGBE_SDP1_GPIEN;
+
+ /* Add for Thermal detection */
+ if (sc->hw.mac.type == ixgbe_mac_82599EB)
gpie |= IXGBE_SDP2_GPIEN;
- /*
- * Set LL interval to max to reduce the number of low latency
- * interrupts hitting the card when the ring is getting full.
- */
- gpie |= 0xf << IXGBE_GPIE_LLI_DELAY_SHIFT;
- }
- /* Enable Fan Failure Interrupt */
- if (sc->hw.phy.media_type == ixgbe_media_type_copper)
- gpie |= IXGBE_SDP1_GPIEN;
- if (sc->msix) {
+ if (sc->msix > 1) {
/* Enable Enhanced MSIX mode */
gpie |= IXGBE_GPIE_MSIX_MODE;
gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
@@ -685,7 +714,7 @@ ixgbe_init(void *arg)
/* Now enable all the queues */
- for (i = 0; i < sc->num_tx_queues; i++) {
+ for (i = 0; i < sc->num_queues; i++) {
txdctl = IXGBE_READ_REG(&sc->hw, IXGBE_TXDCTL(i));
txdctl |= IXGBE_TXDCTL_ENABLE;
/* Set WTHRESH to 8, burst writeback */
@@ -693,11 +722,16 @@ ixgbe_init(void *arg)
IXGBE_WRITE_REG(&sc->hw, IXGBE_TXDCTL(i), txdctl);
}
- for (i = 0; i < sc->num_rx_queues; i++) {
+ for (i = 0; i < sc->num_queues; i++) {
rxdctl = IXGBE_READ_REG(&sc->hw, IXGBE_RXDCTL(i));
if (sc->hw.mac.type == ixgbe_mac_82598EB) {
- /* PTHRESH set to 32 */
- rxdctl |= 0x0020;
+ /*
+ * PTHRESH = 21
+ * HTHRESH = 4
+ * WTHRESH = 8
+ */
+ rxdctl &= ~0x3FFFFF;
+ rxdctl |= 0x080420;
}
rxdctl |= IXGBE_RXDCTL_ENABLE;
IXGBE_WRITE_REG(&sc->hw, IXGBE_RXDCTL(i), rxdctl);
@@ -708,34 +742,68 @@ ixgbe_init(void *arg)
else
msec_delay(1);
}
- IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(i), rxr->last_rx_desc_filled);
+ /* XXX wmb() : memory barrier */
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(i), rxr->last_desc_filled);
}
+ /* Set up VLAN support and filter */
+ ixgbe_setup_vlan_hw_support(sc);
+
+ /* Enable Receive engine */
+ rxctrl = IXGBE_READ_REG(&sc->hw, IXGBE_RXCTRL);
+ if (sc->hw.mac.type == ixgbe_mac_82598EB)
+ rxctrl |= IXGBE_RXCTRL_DMBYPS;
+ rxctrl |= IXGBE_RXCTRL_RXEN;
+ ixgbe_hw(&sc->hw, enable_rx_dma, rxctrl);
+
timeout_add_sec(&sc->timer, 1);
#ifdef MSI
/* Set up MSI/X routing */
- if (ixgbe_enable_msix)
+ if (ixgbe_enable_msix) {
ixgbe_configure_ivars(sc);
- else /* Simple settings for Legacy/MSI */
+ /* Set up auto-mask */
+ if (sc->hw.mac.type == ixgbe_mac_82598EB)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
+ else {
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
+ }
+ } else /* Simple settings for Legacy/MSI */
#else
{
ixgbe_set_ivar(sc, 0, 0, 0);
ixgbe_set_ivar(sc, 0, 0, 1);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
}
#endif
+#ifdef IXGBE_FDIR
+ /* Init Flow director */
+ if (sc->hw.mac.type != ixgbe_mac_82598EB)
+ ixgbe_init_fdir_signature_82599(&sc->hw, fdir_pballoc);
+#endif
+
/*
* Check on any SFP devices that
* need to be kick-started
*/
- err = sc->hw.phy.ops.identify(&sc->hw);
- if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- printf("Unsupported SFP+ module type was detected.\n");
- splx(s);
- return;
- }
+ if (sc->hw.phy.type == ixgbe_phy_none) {
+ err = sc->hw.phy.ops.identify(&sc->hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ printf("Unsupported SFP+ module type was detected.\n");
+ splx(s);
+ return;
+ }
+ }
+
+ /* Set moderation on the Link interrupt */
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(sc->linkvec), IXGBE_LINK_ITR);
+
+ /* Config/Enable Link */
+ ixgbe_config_link(sc);
+ /* And now turn on interrupts */
ixgbe_enable_intr(sc);
/* Now inform the stack we're ready */
@@ -745,6 +813,92 @@ ixgbe_init(void *arg)
splx(s);
}
+/*
+ * MSIX Interrupt Handlers
+ */
+void
+ixgbe_enable_queue(struct ix_softc *sc, uint32_t vector)
+{
+ uint64_t queue = 1ULL << vector;
+ uint32_t mask;
+
+ if (sc->hw.mac.type == ixgbe_mac_82598EB) {
+ mask = (IXGBE_EIMS_RTX_QUEUE & queue);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS, mask);
+ } else {
+ mask = (queue & 0xFFFFFFFF);
+ if (mask)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS_EX(0), mask);
+ mask = (queue >> 32);
+ if (mask)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS_EX(1), mask);
+ }
+}
+
+void
+ixgbe_disable_queue(struct ix_softc *sc, uint32_t vector)
+{
+ uint64_t queue = 1ULL << vector;
+ uint32_t mask;
+
+ if (sc->hw.mac.type == ixgbe_mac_82598EB) {
+ mask = (IXGBE_EIMS_RTX_QUEUE & queue);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, mask);
+ } else {
+ mask = (queue & 0xFFFFFFFF);
+ if (mask)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(0), mask);
+ mask = (queue >> 32);
+ if (mask)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(1), mask);
+ }
+}
+
+void
+ixgbe_rearm_queue(struct ix_softc *sc, uint32_t vector)
+{
+ uint64_t queue = 1ULL << vector;
+ uint32_t mask;
+
+ if (sc->hw.mac.type == ixgbe_mac_82598EB) {
+ mask = (IXGBE_EIMS_RTX_QUEUE & queue);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EICS, mask);
+ } else {
+ mask = (queue & 0xFFFFFFFF);
+ if (mask)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EICS_EX(0), mask);
+ mask = (queue >> 32);
+ if (mask)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EICS_EX(1), mask);
+ }
+}
+
+void
+ixgbe_handle_que(void *context, int pending)
+{
+ struct ix_queue *que = context;
+ struct ix_softc *sc = que->sc;
+ struct tx_ring *txr = que->txr;
+ struct ifnet *ifp = &que->sc->arpcom.ac_if;
+
+ if (ifp->if_flags & IFF_RUNNING) {
+ ixgbe_rxeof(que, -1 /* XXX sc->rx_process_limit */);
+ ixgbe_txeof(txr);
+
+ if (ixgbe_rxfill(que->rxr)) {
+ /* Advance the Rx Queue "Tail Pointer" */
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(que->rxr->me),
+ que->rxr->last_desc_filled);
+ }
+
+ if (!IFQ_IS_EMPTY(&ifp->if_snd))
+ ixgbe_start_locked(txr, ifp);
+ }
+
+ /* Reenable this interrupt */
+ ixgbe_enable_queue(que->sc, que->msix);
+}
+
/*********************************************************************
*
* Legacy Interrupt Service routine
@@ -755,19 +909,22 @@ int
ixgbe_legacy_irq(void *arg)
{
struct ix_softc *sc = (struct ix_softc *)arg;
+ struct ix_queue *que = sc->queues;
struct ifnet *ifp = &sc->arpcom.ac_if;
struct tx_ring *txr = sc->tx_rings;
- struct rx_ring *rxr = sc->rx_rings;
struct ixgbe_hw *hw = &sc->hw;
uint32_t reg_eicr;
int refill = 0;
reg_eicr = IXGBE_READ_REG(&sc->hw, IXGBE_EICR);
- if (reg_eicr == 0)
+ if (reg_eicr == 0) {
+ ixgbe_enable_intr(sc);
return (0);
+ }
+ ++que->irqs;
if (ifp->if_flags & IFF_RUNNING) {
- ixgbe_rxeof(rxr, -1);
+ ixgbe_rxeof(que, -1);
ixgbe_txeof(txr);
refill = 1;
}
@@ -775,7 +932,7 @@ ixgbe_legacy_irq(void *arg)
/* Check for fan failure */
if ((hw->phy.media_type == ixgbe_media_type_copper) &&
(reg_eicr & IXGBE_EICR_GPI_SDP1)) {
- printf("%s: \nCRITICAL: FAN FAILURE!! "
+ printf("\n%s: CRITICAL: FAN FAILURE!! "
"REPLACE IMMEDIATELY!!\n", ifp->if_xname);
IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS,
IXGBE_EICR_GPI_SDP1);
@@ -788,15 +945,16 @@ ixgbe_legacy_irq(void *arg)
timeout_add_sec(&sc->timer, 1);
}
- if (refill && ixgbe_rxfill(rxr)) {
+ if (refill && ixgbe_rxfill(que->rxr)) {
/* Advance the Rx Queue "Tail Pointer" */
- IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(rxr->me),
- rxr->last_rx_desc_filled);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(que->rxr->me),
+ que->rxr->last_desc_filled);
}
if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
ixgbe_start_locked(txr, ifp);
+ ixgbe_enable_intr(sc);
return (1);
}
@@ -863,9 +1021,9 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head)
struct ix_softc *sc = txr->sc;
uint32_t olinfo_status = 0, cmd_type_len = 0;
int i, j, error;
- int first;
+ int first, last = 0;
bus_dmamap_t map;
- struct ixgbe_tx_buf *txbuf, *txbuf_mapped;
+ struct ixgbe_tx_buf *txbuf;
union ixgbe_adv_tx_desc *txd = NULL;
uint32_t paylen = 0;
@@ -878,6 +1036,7 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head)
cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
#endif
+#if 0
/*
* Force a cleanup if number of TX descriptors
* available is below the threshold. If it fails
@@ -887,19 +1046,19 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head)
ixgbe_txeof(txr);
/* Make sure things have improved */
if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
- txr->no_tx_desc_avail++;
+ txr->no_desc_avail++;
return (ENOBUFS);
}
}
+#endif
/*
* Important to capture the first descriptor
* used because it will contain the index of
* the one we tell the hardware to report back
*/
- first = txr->next_avail_tx_desc;
+ first = txr->next_avail_desc;
txbuf = &txr->tx_buffers[first];
- txbuf_mapped = txbuf;
map = txbuf->map;
/*
@@ -907,7 +1066,7 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head)
*/
error = bus_dmamap_load_mbuf(txr->txdma.dma_tag, map,
m_head, BUS_DMA_NOWAIT);
-
+ /* XXX EFBIG */
if (error == ENOMEM) {
sc->no_tx_dma_setup++;
return (error);
@@ -918,7 +1077,7 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head)
/* Make certain there are enough descriptors */
if (map->dm_nsegs > txr->tx_avail - 2) {
- txr->no_tx_desc_avail++;
+ txr->no_desc_avail++;
error = ENOBUFS;
goto xmit_fail;
}
@@ -945,7 +1104,7 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head)
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 < map->dm_nsegs; j++) {
txbuf = &txr->tx_buffers[i];
txd = &txr->tx_base[i];
@@ -954,26 +1113,30 @@ ixgbe_encap(struct tx_ring *txr, struct mbuf *m_head)
txd->read.cmd_type_len = htole32(txr->txd_cmd |
cmd_type_len | map->dm_segs[j].ds_len);
txd->read.olinfo_status = htole32(olinfo_status);
+ last = i; /* descriptor that will get completion IRQ */
if (++i == sc->num_tx_desc)
i = 0;
txbuf->m_head = NULL;
+ txbuf->eop_index = -1;
}
txd->read.cmd_type_len |=
htole32(IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS);
txr->tx_avail -= map->dm_nsegs;
- txr->next_avail_tx_desc = i;
+ txr->next_avail_desc = i;
txbuf->m_head = m_head;
- txbuf_mapped->map = txbuf->map;
+ /* swap maps because last tx descriptor is tracking all the data */
+ txr->tx_buffers[first].map = txbuf->map;
txbuf->map = map;
bus_dmamap_sync(txr->txdma.dma_tag, map, 0, map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
/* Set the index of the descriptor that will be marked done */
txbuf = &txr->tx_buffers[first];
+ txbuf->eop_index = last;
++txr->tx_packets;
return (0);
@@ -1010,9 +1173,7 @@ ixgbe_disable_promisc(struct ix_softc * sc)
uint32_t reg_rctl;
reg_rctl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
-
- reg_rctl &= (~IXGBE_FCTRL_UPE);
- reg_rctl &= (~IXGBE_FCTRL_MPE);
+ reg_rctl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, reg_rctl);
return;
@@ -1025,13 +1186,11 @@ ixgbe_disable_promisc(struct ix_softc * sc)
* This routine is called whenever multicast address list is updated.
*
**********************************************************************/
-#define IXGBE_RAR_ENTRIES 16
-
void
ixgbe_set_multi(struct ix_softc *sc)
{
uint32_t fctrl;
- uint8_t mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];
+ uint8_t *mta;
uint8_t *update_ptr;
struct ether_multi *enm;
struct ether_multistep step;
@@ -1040,6 +1199,10 @@ ixgbe_set_multi(struct ix_softc *sc)
IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
+ mta = sc->mta;
+ bzero(mta, sizeof(uint8_t) * IXGBE_ETH_LENGTH_OF_ADDRESS *
+ MAX_NUM_MULTICAST_ADDRESSES);
+
fctrl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
if (ifp->if_flags & IFF_PROMISC)
@@ -1111,15 +1274,20 @@ ixgbe_local_timer(void *arg)
s = splnet();
+ /* Check for pluggable optics */
+ if (sc->sfp_probe)
+ if (!ixgbe_sfp_probe(sc))
+ goto out; /* Nothing to do */
+
ixgbe_update_link_status(sc);
ixgbe_update_stats_counters(sc);
+out:
#ifdef IX_DEBUG
if ((ifp->if_flags & (IFF_RUNNING|IFF_DEBUG)) ==
(IFF_RUNNING|IFF_DEBUG))
ixgbe_print_hw_stats(sc);
#endif
-
timeout_add_sec(&sc->timer, 1);
splx(s);
@@ -1162,7 +1330,7 @@ ixgbe_update_link_status(struct ix_softc *sc)
} else {
ifp->if_baudrate = 0;
ifp->if_timer = 0;
- for (i = 0; i < sc->num_tx_queues; i++)
+ for (i = 0; i < sc->num_queues; i++)
txr[i].watchdog_timer = FALSE;
}
@@ -1194,11 +1362,15 @@ ixgbe_stop(void *arg)
ixgbe_hw0(&sc->hw, reset_hw);
sc->hw.adapter_stopped = FALSE;
ixgbe_hw0(&sc->hw, stop_adapter);
+ /* Turn off the laser */
+ if (sc->hw.phy.multispeed_fiber)
+ ixgbe_hw0(&sc->hw, disable_tx_laser);
timeout_del(&sc->timer);
/* reprogram the RAR[0] in case user changed it. */
ixgbe_hw(&sc->hw, set_rar, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV);
+ /* Should we really clear all structures on stop? */
ixgbe_free_transmit_structures(sc);
ixgbe_free_receive_structures(sc);
}
@@ -1246,8 +1418,9 @@ ixgbe_identify_hardware(struct ix_softc *sc)
sc->hw.mac.type = ixgbe_mac_82598EB;
sc->optics = IFM_10G_LR;
break;
- case PCI_PRODUCT_INTEL_82598AT_DUAL:
case PCI_PRODUCT_INTEL_82598AT:
+ case PCI_PRODUCT_INTEL_82598AT2:
+ case PCI_PRODUCT_INTEL_82598AT_DUAL:
sc->hw.mac.type = ixgbe_mac_82598EB;
sc->optics = IFM_10G_T;
break;
@@ -1257,19 +1430,34 @@ ixgbe_identify_hardware(struct ix_softc *sc)
break;
case PCI_PRODUCT_INTEL_82599_SFP:
case PCI_PRODUCT_INTEL_82599_SFP_EM:
+ case PCI_PRODUCT_INTEL_82599_SFP_FCOE:
sc->hw.mac.type = ixgbe_mac_82599EB;
sc->optics = IFM_10G_SR;
+ sc->hw.phy.smart_speed = ixgbe_smart_speed;
break;
case PCI_PRODUCT_INTEL_82599_KX4:
case PCI_PRODUCT_INTEL_82599_KX4_MEZZ:
case PCI_PRODUCT_INTEL_82599_CX4:
sc->hw.mac.type = ixgbe_mac_82599EB;
sc->optics = IFM_10G_CX4;
+ sc->hw.phy.smart_speed = ixgbe_smart_speed;
+ break;
+ case PCI_PRODUCT_INTEL_82599_T3_LOM:
+ sc->hw.mac.type = ixgbe_mac_82599EB;
+ sc->optics = IFM_10G_T;
+ sc->hw.phy.smart_speed = ixgbe_smart_speed;
break;
case PCI_PRODUCT_INTEL_82599_XAUI:
case PCI_PRODUCT_INTEL_82599_COMBO_BACKPLANE:
+ case PCI_PRODUCT_INTEL_82599_BPLANE_FCOE:
sc->hw.mac.type = ixgbe_mac_82599EB;
sc->optics = IFM_AUTO;
+ sc->hw.phy.smart_speed = ixgbe_smart_speed;
+ break;
+ case PCI_PRODUCT_INTEL_82599VF:
+ sc->hw.mac.type = ixgbe_mac_82599_vf;
+ sc->optics = IFM_AUTO;
+ sc->hw.phy.smart_speed = ixgbe_smart_speed;
break;
default:
sc->optics = IFM_AUTO;
@@ -1279,6 +1467,50 @@ ixgbe_identify_hardware(struct ix_softc *sc)
/*********************************************************************
*
+ * Determine optic type
+ *
+ **********************************************************************/
+void
+ixgbe_setup_optics(struct ix_softc *sc)
+{
+ struct ixgbe_hw *hw = &sc->hw;
+ int layer;
+
+ layer = ixgbe_hw(hw, get_supported_physical_layer);
+ switch (layer) {
+ case IXGBE_PHYSICAL_LAYER_10GBASE_T:
+ sc->optics = IFM_10G_T;
+ break;
+ case IXGBE_PHYSICAL_LAYER_1000BASE_T:
+ sc->optics = IFM_1000_T;
+ break;
+ case IXGBE_PHYSICAL_LAYER_10GBASE_LR:
+ case IXGBE_PHYSICAL_LAYER_10GBASE_LRM:
+ sc->optics = IFM_10G_LR;
+ break;
+ case IXGBE_PHYSICAL_LAYER_10GBASE_SR:
+ sc->optics = IFM_10G_SR;
+ break;
+ case IXGBE_PHYSICAL_LAYER_10GBASE_KX4:
+ case IXGBE_PHYSICAL_LAYER_10GBASE_CX4:
+ sc->optics = IFM_10G_CX4;
+ break;
+ case IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU:
+ sc->optics = IFM_10G_SFP_CU;
+ break;
+ case IXGBE_PHYSICAL_LAYER_1000BASE_KX:
+ case IXGBE_PHYSICAL_LAYER_10GBASE_KR:
+ case IXGBE_PHYSICAL_LAYER_10GBASE_XAUI:
+ case IXGBE_PHYSICAL_LAYER_UNKNOWN:
+ default:
+ sc->optics = IFM_ETHER | IFM_AUTO;
+ break;
+ }
+ return;
+}
+
+/*********************************************************************
+ *
* Setup the Legacy or MSI Interrupt handler
*
**********************************************************************/
@@ -1292,20 +1524,25 @@ ixgbe_allocate_legacy(struct ix_softc *sc)
pci_chipset_tag_t pc = pa->pa_pc;
pci_intr_handle_t ih;
- /* Legacy RID at 0 */
- if (sc->msix == 0)
- sc->rid[0] = 0;
-
/* We allocate a single interrupt resource */
- if (pci_intr_map(pa, &ih)) {
+ if (/* pci_intr_map_msi(pa, &ih) != 0 && */
+ pci_intr_map(pa, &ih) != 0) {
printf(": couldn't map interrupt\n");
return (ENXIO);
}
+#if 0
+ /* XXX */
+ /* Tasklets for Link, SFP and Multispeed Fiber */
+ TASK_INIT(&sc->link_task, 0, ixgbe_handle_link, sc);
+ TASK_INIT(&sc->mod_task, 0, ixgbe_handle_mod, sc);
+ TASK_INIT(&sc->msf_task, 0, ixgbe_handle_msf, sc);
+#endif
+
intrstr = pci_intr_string(pc, ih);
- sc->tag[0] = pci_intr_establish(pc, ih, IPL_NET,
+ sc->tag = pci_intr_establish(pc, ih, IPL_NET,
ixgbe_legacy_irq, sc, ifp->if_xname);
- if (sc->tag[0] == NULL) {
+ if (sc->tag == NULL) {
printf(": couldn't establish interrupt");
if (intrstr != NULL)
printf(" at %s", intrstr);
@@ -1314,6 +1551,9 @@ ixgbe_allocate_legacy(struct ix_softc *sc)
}
printf(": %s", intrstr);
+ /* For simplicity in the handlers */
+ sc->que_mask = IXGBE_EIMS_ENABLE_MASK;
+
return (0);
}
@@ -1322,7 +1562,7 @@ ixgbe_allocate_pci_resources(struct ix_softc *sc)
{
struct ixgbe_osdep *os = &sc->osdep;
struct pci_attach_args *pa = os->os_pa;
- int val, i;
+ int val;
val = pci_conf_read(pa->pa_pc, pa->pa_tag, PCIR_BAR(0));
if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM &&
@@ -1338,24 +1578,14 @@ ixgbe_allocate_pci_resources(struct ix_softc *sc)
}
sc->hw.hw_addr = (uint8_t *)os->os_membase;
- /*
- * Init the resource arrays
- */
- for (i = 0; i < IXGBE_MSGS; i++) {
- sc->rid[i] = i + 1; /* MSI/X RID starts at 1 */
- sc->tag[i] = NULL;
- sc->res[i] = NULL;
- }
-
/* Legacy defaults */
- sc->num_tx_queues = 1;
- sc->num_rx_queues = 1;
+ sc->num_queues = 1;
+ sc->hw.back = os;
#ifdef notyet
- /* Now setup MSI or MSI/X */
+ /* Now setup MSI or MSI/X, return us the number of supported vectors. */
sc->msix = ixgbe_setup_msix(sc);
#endif
- sc->hw.back = os;
return (0);
}
@@ -1365,10 +1595,20 @@ ixgbe_free_pci_resources(struct ix_softc * sc)
{
struct ixgbe_osdep *os = &sc->osdep;
struct pci_attach_args *pa = os->os_pa;
+ struct ix_queue *que = sc->queues;
+ int i;
- if (sc->tag[0])
- pci_intr_disestablish(pa->pa_pc, sc->tag[0]);
- sc->tag[0] = NULL;
+
+ /* Release all msix queue resources: */
+ for (i = 0; i < sc->num_queues; i++, que++) {
+ if (que->tag)
+ pci_intr_disestablish(pa->pa_pc, que->tag);
+ que->tag = NULL;
+ }
+
+ if (sc->tag)
+ pci_intr_disestablish(pa->pa_pc, sc->tag);
+ sc->tag = NULL;
if (os->os_membase != 0)
bus_space_unmap(os->os_memt, os->os_memh, os->os_memsize);
os->os_membase = 0;
@@ -1378,52 +1618,6 @@ ixgbe_free_pci_resources(struct ix_softc * sc)
/*********************************************************************
*
- * Initialize the hardware to a configuration as specified by the
- * sc structure. The controller is reset, the EEPROM is
- * verified, the MAC address is set, then the shared initialization
- * routines are called.
- *
- **********************************************************************/
-int
-ixgbe_hardware_init(struct ix_softc *sc)
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- uint16_t csum;
-
- csum = 0;
- /* Issue a global reset */
- sc->hw.adapter_stopped = FALSE;
- ixgbe_hw0(&sc->hw, stop_adapter);
-
- /* Make sure we have a good EEPROM before we read from it */
- if (ixgbe_ee(&sc->hw, validate_checksum, &csum) < 0) {
- printf("%s: The EEPROM Checksum Is Not Valid\n", ifp->if_xname);
- return (EIO);
- }
-
- /* Pick up the smart speed setting */
- if (sc->hw.mac.type == ixgbe_mac_82599EB)
- sc->hw.phy.smart_speed = ixgbe_smart_speed;
-
- /* Get Hardware Flow Control setting */
- sc->hw.fc.requested_mode = ixgbe_fc_full;
- sc->hw.fc.pause_time = IXGBE_FC_PAUSE;
- sc->hw.fc.low_water = IXGBE_FC_LO;
- sc->hw.fc.high_water = IXGBE_FC_HI;
- sc->hw.fc.send_xon = TRUE;
-
- if (ixgbe_hw0(&sc->hw, init_hw) != 0) {
- printf("%s: Hardware Initialization Failed", ifp->if_xname);
- return (EIO);
- }
- bcopy(sc->hw.mac.addr, sc->arpcom.ac_enaddr,
- IXGBE_ETH_LENGTH_OF_ADDRESS);
-
- return (0);
-}
-
-/*********************************************************************
- *
* Setup networking device structure and register an interface.
*
**********************************************************************/
@@ -1488,6 +1682,50 @@ ixgbe_setup_interface(struct ix_softc *sc)
return;
}
+void
+ixgbe_config_link(struct ix_softc *sc)
+{
+ uint32_t autoneg, err = 0;
+ int sfp, negotiate;
+
+ switch (sc->hw.phy.type) {
+ case ixgbe_phy_sfp_avago:
+ case ixgbe_phy_sfp_ftl:
+ case ixgbe_phy_sfp_intel:
+ case ixgbe_phy_sfp_unknown:
+ case ixgbe_phy_sfp_passive_tyco:
+ case ixgbe_phy_sfp_passive_unknown:
+ sfp = 1;
+ break;
+ default:
+ sfp = 0;
+ break;
+ }
+
+ if (sfp) {
+ if (&sc->hw.phy.multispeed_fiber) {
+ sc->hw.mac.ops.setup_sfp(&sc->hw);
+ ixgbe_hw0(&sc->hw, enable_tx_laser);
+ /* XXX taskqueue_enqueue(sc->tq, &sc->msf_task); */
+ } /* else */
+ /* XXX taskqueue_enqueue(sc->tq, &sc->mod_task); */
+ } else {
+ if (sc->hw.mac.ops.check_link)
+ err = sc->hw.mac.ops.check_link(&sc->hw, &autoneg,
+ &sc->link_up, FALSE);
+ if (err)
+ return;
+ if (sc->hw.mac.ops.setup_link)
+ err = sc->hw.mac.ops.setup_link(&sc->hw, autoneg,
+ negotiate, sc->link_up);
+ }
+ return;
+}
+
+
+/********************************************************************
+ * Manage DMA'able memory.
+ *******************************************************************/
int
ixgbe_dma_malloc(struct ix_softc *sc, bus_size_t size,
struct ixgbe_dma_alloc *dma, int mapflags)
@@ -1573,26 +1811,33 @@ int
ixgbe_allocate_queues(struct ix_softc *sc)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct ix_queue *que;
struct tx_ring *txr;
struct rx_ring *rxr;
- int rsize, tsize, error = IXGBE_SUCCESS;
+ int rsize, tsize;
int txconf = 0, rxconf = 0, i;
- /* First allocate the TX ring struct memory */
+ /* First allocate the top level queue structs */
+ if (!(sc->queues =
+ (struct ix_queue *) malloc(sizeof(struct ix_queue) *
+ sc->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
+ printf("%s: Unable to allocate queue memory\n", ifp->if_xname);
+ goto fail;
+ }
+
+ /* Then allocate the TX ring struct memory */
if (!(sc->tx_rings =
(struct tx_ring *) malloc(sizeof(struct tx_ring) *
- sc->num_tx_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
+ sc->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
printf("%s: Unable to allocate TX ring memory\n", ifp->if_xname);
- error = ENOMEM;
goto fail;
}
/* Next allocate the RX */
if (!(sc->rx_rings =
(struct rx_ring *) malloc(sizeof(struct rx_ring) *
- sc->num_rx_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
+ sc->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
printf("%s: Unable to allocate RX ring memory\n", ifp->if_xname);
- error = ENOMEM;
goto rx_fail;
}
@@ -1605,7 +1850,7 @@ ixgbe_allocate_queues(struct ix_softc *sc)
* possibility that things fail midcourse and we need to
* undo memory gracefully
*/
- for (i = 0; i < sc->num_tx_queues; i++, txconf++) {
+ for (i = 0; i < sc->num_queues; i++, txconf++) {
/* Set up some basics */
txr = &sc->tx_rings[i];
txr->sc = sc;
@@ -1618,21 +1863,10 @@ ixgbe_allocate_queues(struct ix_softc *sc)
&txr->txdma, BUS_DMA_NOWAIT)) {
printf("%s: Unable to allocate TX Descriptor memory\n",
ifp->if_xname);
- error = ENOMEM;
goto err_tx_desc;
}
txr->tx_base = (union ixgbe_adv_tx_desc *)txr->txdma.dma_vaddr;
bzero((void *)txr->tx_base, tsize);
-
- if (ixgbe_dma_malloc(sc, sizeof(uint32_t),
- &txr->txwbdma, BUS_DMA_NOWAIT)) {
- printf("%s: Unable to allocate TX Write Back memory\n",
- ifp->if_xname);
- error = ENOMEM;
- goto err_tx_desc;
- }
- txr->tx_hwb = (uint32_t *)txr->txwbdma.dma_vaddr;
- *txr->tx_hwb = 0;
}
/*
@@ -1640,7 +1874,7 @@ ixgbe_allocate_queues(struct ix_softc *sc)
*/
rsize = roundup2(sc->num_rx_desc *
sizeof(union ixgbe_adv_rx_desc), 4096);
- for (i = 0; i < sc->num_rx_queues; i++, rxconf++) {
+ for (i = 0; i < sc->num_queues; i++, rxconf++) {
rxr = &sc->rx_rings[i];
/* Set up some basics */
rxr->sc = sc;
@@ -1653,13 +1887,22 @@ ixgbe_allocate_queues(struct ix_softc *sc)
&rxr->rxdma, BUS_DMA_NOWAIT)) {
printf("%s: Unable to allocate RxDescriptor memory\n",
ifp->if_xname);
- error = ENOMEM;
goto err_rx_desc;
}
rxr->rx_base = (union ixgbe_adv_rx_desc *)rxr->rxdma.dma_vaddr;
bzero((void *)rxr->rx_base, rsize);
}
+ /*
+ * Finally set up the queue holding structs
+ */
+ for (i = 0; i < sc->num_queues; i++) {
+ que = &sc->queues[i];
+ que->sc = sc;
+ que->txr = &sc->tx_rings[i];
+ que->rxr = &sc->rx_rings[i];
+ }
+
return (0);
err_rx_desc:
@@ -1668,7 +1911,6 @@ err_rx_desc:
err_tx_desc:
for (txr = sc->tx_rings; txconf > 0; txr++, txconf--) {
ixgbe_dma_free(sc, &txr->txdma);
- ixgbe_dma_free(sc, &txr->txwbdma);
}
free(sc->rx_rings, M_DEVBUF);
sc->rx_rings = NULL;
@@ -1676,7 +1918,7 @@ rx_fail:
free(sc->tx_rings, M_DEVBUF);
sc->tx_rings = NULL;
fail:
- return (error);
+ return (ENOMEM);
}
/*********************************************************************
@@ -1754,8 +1996,8 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr)
(sizeof(union ixgbe_adv_tx_desc)) * sc->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;
/* Set number of descriptors available */
txr->tx_avail = sc->num_tx_desc;
@@ -1778,7 +2020,7 @@ ixgbe_setup_transmit_structures(struct ix_softc *sc)
struct tx_ring *txr = sc->tx_rings;
int i, error;
- for (i = 0; i < sc->num_tx_queues; i++, txr++) {
+ for (i = 0; i < sc->num_queues; i++, txr++) {
if ((error = ixgbe_setup_transmit_ring(txr)) != 0)
goto fail;
}
@@ -1801,12 +2043,12 @@ ixgbe_initialize_transmit_units(struct ix_softc *sc)
struct tx_ring *txr;
struct ixgbe_hw *hw = &sc->hw;
int i;
- uint64_t tdba, txhwb;
+ uint64_t tdba;
uint32_t txctrl;
/* Setup the Base and Length of the Tx Descriptor Ring */
- for (i = 0; i < sc->num_tx_queues; i++) {
+ for (i = 0; i < sc->num_queues; i++) {
txr = &sc->tx_rings[i];
/* Setup descriptor base address */
@@ -1817,13 +2059,14 @@ ixgbe_initialize_transmit_units(struct ix_softc *sc)
IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i),
sc->num_tx_desc * sizeof(struct ixgbe_legacy_tx_desc));
- /* Setup for Head WriteBack */
- txhwb = txr->txwbdma.dma_map->dm_segs[0].ds_addr;
- txhwb |= IXGBE_TDWBAL_HEAD_WB_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_TDWBAL(i),
- (txhwb & 0x00000000ffffffffULL));
- IXGBE_WRITE_REG(hw, IXGBE_TDWBAH(i),
- (txhwb >> 32));
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+ IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);
+
+ /* Setup Transmit Descriptor Cmd Settings */
+ txr->txd_cmd = IXGBE_TXD_CMD_IFCS;
+ txr->queue_status = IXGBE_QUEUE_IDLE;
+ txr->watchdog_timer = 0;
/* Disable Head Writeback */
switch (hw->mac.type) {
@@ -1845,15 +2088,6 @@ ixgbe_initialize_transmit_units(struct ix_softc *sc)
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), txctrl);
break;
}
-
- /* Setup the HW Tx Head and Tail descriptor pointers */
- IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);
-
- /* Setup Transmit Descriptor Cmd Settings */
- txr->txd_cmd = IXGBE_TXD_CMD_IFCS;
-
- txr->watchdog_timer = 0;
}
ifp->if_timer = 0;
@@ -1885,7 +2119,7 @@ ixgbe_free_transmit_structures(struct ix_softc *sc)
struct tx_ring *txr = sc->tx_rings;
int i;
- for (i = 0; i < sc->num_tx_queues; i++, txr++) {
+ for (i = 0; i < sc->num_queues; i++, txr++) {
ixgbe_free_transmit_buffers(txr);
}
}
@@ -1927,10 +2161,8 @@ ixgbe_free_transmit_buffers(struct tx_ring *txr)
}
}
- if (txr->tx_buffers != NULL) {
+ if (txr->tx_buffers != NULL)
free(txr->tx_buffers, M_DEVBUF);
- txr->tx_buffers = NULL;
- }
txr->tx_buffers = NULL;
txr->txtag = NULL;
}
@@ -1957,12 +2189,13 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
int ehdrlen, ip_hlen = 0;
uint16_t etype;
int offload = TRUE;
- int ctxd = txr->next_avail_tx_desc;
+ int ctxd = txr->next_avail_desc;
#if NVLAN > 0
struct ether_vlan_header *eh;
#else
struct ether_header *eh;
#endif
+ uint16_t vtag = 0;
if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) == 0)
offload = FALSE;
@@ -1976,8 +2209,8 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
*/
#if NVLAN > 0
if (mp->m_flags & M_VLANTAG) {
- vlan_macip_lens |=
- htole16(mp->m_pkthdr.ether_vtag) << IXGBE_ADVTXD_VLAN_SHIFT;
+ vtag = htole16(mp->m_pkthdr.ether_vtag);
+ vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT);
} else
#endif
if (offload == FALSE)
@@ -2005,47 +2238,48 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
/* Set the ether header length */
vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
- type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
- if (offload == TRUE) {
- switch (etype) {
- case ETHERTYPE_IP:
- ip = (struct ip *)(mp->m_data + ehdrlen);
- ip_hlen = ip->ip_hl << 2;
- if (mp->m_len < ehdrlen + ip_hlen)
- return FALSE; /* failure */
- ipproto = ip->ip_p;
- if (mp->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
- break;
+ switch (etype) {
+ case ETHERTYPE_IP:
+ ip = (struct ip *)(mp->m_data + ehdrlen);
+ ip_hlen = ip->ip_hl << 2;
+ if (mp->m_len < ehdrlen + ip_hlen)
+ return FALSE; /* failure */
+ ipproto = ip->ip_p;
+ if (mp->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
+ break;
#ifdef notyet
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
- ip_hlen = sizeof(struct ip6_hdr);
- if (mp->m_len < ehdrlen + ip_hlen)
- return FALSE; /* failure */
- ipproto = ip6->ip6_nxt;
- if (mp->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
- break;
+ case ETHERTYPE_IPV6:
+ ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
+ ip_hlen = sizeof(struct ip6_hdr);
+ if (mp->m_len < ehdrlen + ip_hlen)
+ return FALSE; /* failure */
+ ipproto = ip6->ip6_nxt;
+ if (mp->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
+ break;
#endif
- default:
- offload = FALSE;
- break;
- }
+ default:
+ offload = FALSE;
+ break;
+ }
- vlan_macip_lens |= ip_hlen;
+ vlan_macip_lens |= ip_hlen;
+ type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
- switch (ipproto) {
- case IPPROTO_TCP:
- if (mp->m_pkthdr.csum_flags & M_TCP_CSUM_OUT)
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
- break;
- case IPPROTO_UDP:
- if (mp->m_pkthdr.csum_flags & M_UDP_CSUM_OUT)
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
- break;
- }
+ switch (ipproto) {
+ case IPPROTO_TCP:
+ if (mp->m_pkthdr.csum_flags & M_TCP_CSUM_OUT)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ break;
+ case IPPROTO_UDP:
+ if (mp->m_pkthdr.csum_flags & M_UDP_CSUM_OUT)
+ type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
+ break;
+ default:
+ offload = FALSE;
+ break;
}
/* Now copy bits into descriptor */
@@ -2055,11 +2289,12 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
TXD->mss_l4len_idx = htole32(0);
tx_buffer->m_head = NULL;
+ tx_buffer->eop_index = -1;
/* We've consumed the first desc, adjust counters */
if (++ctxd == sc->num_tx_desc)
ctxd = 0;
- txr->next_avail_tx_desc = ctxd;
+ txr->next_avail_desc = ctxd;
--txr->tx_avail;
return (offload);
@@ -2113,7 +2348,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, uint32_t *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];
@@ -2162,7 +2397,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, uint32_t *paylen)
ctxd = 0;
txr->tx_avail--;
- txr->next_avail_tx_desc = ctxd;
+ txr->next_avail_desc = ctxd;
return TRUE;
}
@@ -2187,41 +2422,48 @@ ixgbe_txeof(struct tx_ring *txr)
{
struct ix_softc *sc = txr->sc;
struct ifnet *ifp = &sc->arpcom.ac_if;
- uint first, last, done, num_avail;
+ uint32_t first, last, done, processed;
struct ixgbe_tx_buf *tx_buffer;
- struct ixgbe_legacy_tx_desc *tx_desc;
+ struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc;
- if (txr->tx_avail == sc->num_tx_desc)
+ if (txr->tx_avail == sc->num_tx_desc) {
+ txr->queue_status = IXGBE_QUEUE_IDLE;
return FALSE;
+ }
- num_avail = txr->tx_avail;
- first = txr->next_tx_to_clean;
-
+ processed = 0;
+ 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 HWB */
- bus_dmamap_sync(txr->txwbdma.dma_tag, txr->txwbdma.dma_map,
- 0, txr->txwbdma.dma_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
- done = *txr->tx_hwb;
+ /*
+ * Get the index of the first descriptor
+ * BEYOND the EOP and call that 'done'.
+ * I do this so the comparison in the
+ * inner while loop below can be simple
+ */
+ if (++last == sc->num_tx_desc) last = 0;
+ done = last;
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
0, txr->txdma.dma_map->dm_mapsize,
BUS_DMASYNC_POSTREAD);
- while (TRUE) {
- /* We clean the range til last head write back */
+ while (eop_desc->upper.fields.status & IXGBE_TXD_STAT_DD) {
+ /* We clean the range of the packet */
while (first != done) {
tx_desc->upper.data = 0;
tx_desc->lower.data = 0;
tx_desc->buffer_addr = 0;
- num_avail++;
+ ++txr->tx_avail;
+ ++processed;
if (tx_buffer->m_head) {
- ifp->if_opackets++;
bus_dmamap_sync(txr->txdma.dma_tag,
tx_buffer->map,
0, tx_buffer->map->dm_mapsize,
@@ -2231,6 +2473,7 @@ ixgbe_txeof(struct tx_ring *txr)
m_freem(tx_buffer->m_head);
tx_buffer->m_head = NULL;
}
+ tx_buffer->eop_index = -1;
if (++first == sc->num_tx_desc)
first = 0;
@@ -2239,13 +2482,17 @@ ixgbe_txeof(struct tx_ring *txr)
tx_desc = (struct ixgbe_legacy_tx_desc *)
&txr->tx_base[first];
}
+ ++txr->packets;
+ ++ifp->if_opackets;
/* See if there is more work now */
- last = done;
- bus_dmamap_sync(txr->txwbdma.dma_tag, txr->txwbdma.dma_map,
- 0, txr->txwbdma.dma_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
- done = *txr->tx_hwb;
- if (last == done)
+ last = tx_buffer->eop_index;
+ if (last != -1) {
+ eop_desc =
+ (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last];
+ /* Get next done point */
+ if (++last == sc->num_tx_desc) last = 0;
+ done = last;
+ } else
break;
}
@@ -2253,7 +2500,7 @@ ixgbe_txeof(struct tx_ring *txr)
0, txr->txdma.dma_map->dm_mapsize,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- txr->next_tx_to_clean = first;
+ txr->next_to_clean = first;
/*
* If we have enough room, clear IFF_OACTIVE to tell the stack that
@@ -2261,25 +2508,22 @@ 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_flags &= ~IFF_OACTIVE;
/* If all are clean turn off the timer */
- if (num_avail == sc->num_tx_desc) {
+ if (txr->tx_avail == sc->num_tx_desc) {
ifp->if_timer = 0;
txr->watchdog_timer = 0;
- txr->tx_avail = num_avail;
return FALSE;
}
/* Some were cleaned, so reset timer */
- else if (num_avail != txr->tx_avail) {
+ else if (processed) {
ifp->if_timer = IXGBE_TX_TIMEOUT;
txr->watchdog_timer = IXGBE_TX_TIMEOUT;
}
}
- txr->tx_avail = num_avail;
-
return TRUE;
}
@@ -2292,47 +2536,73 @@ int
ixgbe_get_buf(struct rx_ring *rxr, int i)
{
struct ix_softc *sc = rxr->sc;
- struct mbuf *m;
- int error;
- int size = MCLBYTES;
struct ixgbe_rx_buf *rxbuf;
+ struct mbuf *mh, *mp;
+ int error;
union ixgbe_adv_rx_desc *rxdesc;
size_t dsize = sizeof(union ixgbe_adv_rx_desc);
rxbuf = &rxr->rx_buffers[i];
rxdesc = &rxr->rx_base[i];
-
- if (rxbuf->m_head != NULL) {
+ if (rxbuf->m_head != NULL || rxbuf->m_pack) {
printf("%s: ixgbe_get_buf: slot %d already has an mbuf\n",
sc->dev.dv_xname, i);
return (ENOBUFS);
}
- m = MCLGETI(NULL, M_DONTWAIT, &sc->arpcom.ac_if, size);
- if (!m) {
- sc->mbuf_cluster_failed++;
+ /* needed in any case so prealocate since this one will fail for sure */
+ mp = MCLGETI(NULL, M_DONTWAIT, &sc->arpcom.ac_if, sc->rx_mbuf_sz);
+ if (!mp) {
+ sc->mbuf_packet_failed++;
return (ENOBUFS);
}
- m->m_len = m->m_pkthdr.len = size;
- if (sc->max_frame_size <= (size - ETHER_ALIGN))
- m_adj(m, ETHER_ALIGN);
- error = bus_dmamap_load_mbuf(rxr->rxdma.dma_tag, rxbuf->map,
- m, BUS_DMA_NOWAIT);
+ if (rxr->hdr_split == FALSE)
+ goto no_split;
+
+ mh = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (mh == NULL)
+ return (ENOBUFS);
+
+ mh->m_pkthdr.len = mh->m_len = MHLEN;
+ mh->m_len = MHLEN;
+ /* always offset header buffers */
+ m_adj(mh, ETHER_ALIGN);
+
+ error = bus_dmamap_load_mbuf(rxr->rxdma.dma_tag, rxbuf->hmap,
+ mh, BUS_DMA_NOWAIT);
+ if (error) {
+ m_freem(mh);
+ return (error);
+ }
+ bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->hmap,
+ 0, rxbuf->hmap->dm_mapsize, BUS_DMASYNC_PREREAD);
+ rxbuf->m_head = mh;
+
+ rxdesc->read.hdr_addr = htole64(rxbuf->hmap->dm_segs[0].ds_addr);
+
+no_split:
+ mp->m_len = mp->m_pkthdr.len = sc->rx_mbuf_sz;
+ /* only adjust if this is not a split header */
+ if (rxr->hdr_split == FALSE &&
+ sc->max_frame_size <= (sc->rx_mbuf_sz - ETHER_ALIGN))
+ m_adj(mp, ETHER_ALIGN);
+
+ error = bus_dmamap_load_mbuf(rxr->rxdma.dma_tag, rxbuf->pmap,
+ mp, BUS_DMA_NOWAIT);
if (error) {
- m_freem(m);
+ m_freem(mp);
return (error);
}
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->map,
- 0, rxbuf->map->dm_mapsize, BUS_DMASYNC_PREREAD);
- rxbuf->m_head = m;
+ bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->pmap,
+ 0, rxbuf->pmap->dm_mapsize, BUS_DMASYNC_PREREAD);
+ rxbuf->m_pack = mp;
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
dsize * i, dsize, BUS_DMASYNC_POSTWRITE);
- bzero(rxdesc, dsize);
- rxdesc->read.pkt_addr = htole64(rxbuf->map->dm_segs[0].ds_addr);
+ rxdesc->read.pkt_addr = htole64(rxbuf->pmap->dm_segs[0].ds_addr);
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
dsize * i, dsize, BUS_DMASYNC_PREWRITE);
@@ -2356,7 +2626,7 @@ ixgbe_allocate_receive_buffers(struct rx_ring *rxr)
struct ix_softc *sc = rxr->sc;
struct ifnet *ifp = &sc->arpcom.ac_if;
struct ixgbe_rx_buf *rxbuf;
- int i, bsize, error, size = MCLBYTES;
+ int i, bsize, error;
bsize = sizeof(struct ixgbe_rx_buf) * sc->num_rx_desc;
if (!(rxr->rx_buffers = (struct ixgbe_rx_buf *) malloc(bsize,
@@ -2366,18 +2636,23 @@ ixgbe_allocate_receive_buffers(struct rx_ring *rxr)
error = ENOMEM;
goto fail;
}
- rxr->rxtag = rxr->rxdma.dma_tag;
rxbuf = rxr->rx_buffers;
for (i = 0; i < sc->num_rx_desc; i++, rxbuf++) {
- error = bus_dmamap_create(rxr->rxdma.dma_tag, size, 1,
- size, 0, BUS_DMA_NOWAIT, &rxbuf->map);
+ error = bus_dmamap_create(rxr->rxdma.dma_tag, MSIZE, 1,
+ MSIZE, 0, BUS_DMA_NOWAIT, &rxbuf->hmap);
+ if (error) {
+ printf("%s: Unable to create Head DMA map\n",
+ ifp->if_xname);
+ goto fail;
+ }
+ error = bus_dmamap_create(rxr->rxdma.dma_tag, 16 * 1024, 1,
+ 16 * 1024, 0, BUS_DMA_NOWAIT, &rxbuf->pmap);
if (error) {
- printf("%s: Unable to create Rx DMA map\n",
+ printf("%s: Unable to create Pack DMA map\n",
ifp->if_xname);
goto fail;
}
- rxbuf->m_head = NULL;
}
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, 0,
rxr->rxdma.dma_map->dm_mapsize,
@@ -2410,7 +2685,7 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr)
/* Setup our descriptor indices */
rxr->next_to_check = 0;
- rxr->last_rx_desc_filled = sc->num_rx_desc - 1;
+ rxr->last_desc_filled = sc->num_rx_desc - 1;
rxr->rx_ndescs = 0;
ixgbe_rxfill(rxr);
@@ -2430,7 +2705,7 @@ ixgbe_rxfill(struct rx_ring *rxr)
int post = 0;
int i;
- i = rxr->last_rx_desc_filled;
+ i = rxr->last_desc_filled;
while (rxr->rx_ndescs < sc->num_rx_desc) {
if (++i == sc->num_rx_desc)
i = 0;
@@ -2438,7 +2713,7 @@ ixgbe_rxfill(struct rx_ring *rxr)
if (ixgbe_get_buf(rxr, i) != 0)
break;
- rxr->last_rx_desc_filled = i;
+ rxr->last_desc_filled = i;
post = 1;
}
@@ -2456,7 +2731,7 @@ ixgbe_setup_receive_structures(struct ix_softc *sc)
struct rx_ring *rxr = sc->rx_rings;
int i;
- for (i = 0; i < sc->num_rx_queues; i++, rxr++)
+ for (i = 0; i < sc->num_queues; i++, rxr++)
if (ixgbe_setup_receive_ring(rxr))
goto fail;
@@ -2472,15 +2747,16 @@ fail:
* Enable receive unit.
*
**********************************************************************/
+#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
+
void
ixgbe_initialize_receive_units(struct ix_softc *sc)
{
struct rx_ring *rxr = sc->rx_rings;
struct ifnet *ifp = &sc->arpcom.ac_if;
- uint32_t rxctrl, fctrl, srrctl, rxcsum;
- uint32_t reta, mrqc, hlreg, linkvec;
+ uint32_t bufsz, rxctrl, fctrl, srrctl, rxcsum;
+ uint32_t reta, mrqc = 0, hlreg;
uint32_t random[10];
- uint32_t llimod = 0;
int i;
/*
@@ -2494,8 +2770,11 @@ ixgbe_initialize_receive_units(struct ix_softc *sc)
/* Enable broadcasts */
fctrl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
fctrl |= IXGBE_FCTRL_BAM;
+ fctrl |= IXGBE_FCTRL_DPF;
+ fctrl |= IXGBE_FCTRL_PMCF;
IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl);
+ /* Set for Jumbo Frames? */
hlreg = IXGBE_READ_REG(&sc->hw, IXGBE_HLREG0);
if (ifp->if_mtu > ETHERMTU)
hlreg |= IXGBE_HLREG0_JUMBOEN;
@@ -2503,28 +2782,11 @@ ixgbe_initialize_receive_units(struct ix_softc *sc)
hlreg &= ~IXGBE_HLREG0_JUMBOEN;
IXGBE_WRITE_REG(&sc->hw, IXGBE_HLREG0, hlreg);
- srrctl = IXGBE_READ_REG(&sc->hw, IXGBE_SRRCTL(0));
- srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
- srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
- if (sc->bigbufs)
- srrctl |= 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- else
- srrctl |= 2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
- IXGBE_WRITE_REG(&sc->hw, IXGBE_SRRCTL(0), srrctl);
-
- /* Set Queue moderation rate */
- if (sc->hw.mac.type == ixgbe_mac_82599EB)
- llimod = IXGBE_EITR_LLI_MOD;
- for (i = 0; i < IXGBE_MSGS; i++)
- IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(i), DEFAULT_ITR | llimod);
-
- /* Set Link moderation lower */
- linkvec = sc->num_tx_queues + sc->num_rx_queues;
- IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(linkvec), LINK_ITR);
+ bufsz = sc->rx_mbuf_sz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- for (i = 0; i < sc->num_rx_queues; i++, rxr++) {
+ for (i = 0; i < sc->num_queues; i++, rxr++) {
uint64_t rdba = rxr->rxdma.dma_map->dm_segs[0].ds_addr;
+
/* Setup the Base and Length of the Rx Descriptor Ring */
IXGBE_WRITE_REG(&sc->hw, IXGBE_RDBAL(i),
(rdba & 0x00000000ffffffffULL));
@@ -2532,46 +2794,58 @@ ixgbe_initialize_receive_units(struct ix_softc *sc)
IXGBE_WRITE_REG(&sc->hw, IXGBE_RDLEN(i),
sc->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
+ /* Set up the SRRCTL register */
+ srrctl = IXGBE_READ_REG(&sc->hw, IXGBE_SRRCTL(i));
+ srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
+ srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
+ srrctl |= bufsz;
+ if (rxr->hdr_split) {
+ /* Use a standard mbuf for the header */
+ srrctl |= ((IXGBE_RX_HDR <<
+ IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT)
+ & IXGBE_SRRCTL_BSIZEHDR_MASK);
+ srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+ } else
+ srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_SRRCTL(i), srrctl);
+
/* Setup the HW Rx Head and Tail Descriptor Pointers */
IXGBE_WRITE_REG(&sc->hw, IXGBE_RDH(i), 0);
- IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(i),
- rxr->last_rx_desc_filled);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_RDT(i), 0);
+ }
+
+ if (sc->hw.mac.type != ixgbe_mac_82598EB) {
+ uint32_t psrtype = IXGBE_PSRTYPE_TCPHDR |
+ IXGBE_PSRTYPE_UDPHDR |
+ IXGBE_PSRTYPE_IPV4HDR |
+ IXGBE_PSRTYPE_IPV6HDR;
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_PSRTYPE(0), psrtype);
}
rxcsum = IXGBE_READ_REG(&sc->hw, IXGBE_RXCSUM);
- if (sc->num_rx_queues > 1) {
+ /* Setup RSS */
+ if (sc->num_queues > 1) {
+ int j;
+ reta = 0;
/* set up random bits */
arc4random_buf(&random, sizeof(random));
- switch (sc->num_rx_queues) {
- case 8:
- case 4:
- reta = 0x00010203;
- break;
- case 2:
- reta = 0x00010001;
- break;
- default:
- reta = 0x00000000;
- }
/* Set up the redirection table */
- for (i = 0; i < 32; i++) {
- IXGBE_WRITE_REG(&sc->hw, IXGBE_RETA(i), reta);
- if (sc->num_rx_queues > 4) {
- ++i;
- IXGBE_WRITE_REG(&sc->hw,
- IXGBE_RETA(i), 0x04050607);
- }
+ for (i = 0, j = 0; i < 128; i++, j++) {
+ if (j == sc->num_queues)
+ j = 0;
+ reta = (reta << 8) | (j * 0x11);
+ if ((i & 3) == 3)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_RETA(i >> 2), reta);
}
/* Now fill our hash function seeds */
for (i = 0; i < 10; i++)
- IXGBE_WRITE_REG_ARRAY(&sc->hw,
- IXGBE_RSSRK(0), i, random[i]);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_RSSRK(i), random[i]);
+ /* Perform hash on these packet types */
mrqc = IXGBE_MRQC_RSSEN
- /* Perform hash on these packet types */
| IXGBE_MRQC_RSS_FIELD_IPV4
| IXGBE_MRQC_RSS_FIELD_IPV4_TCP
| IXGBE_MRQC_RSS_FIELD_IPV4_UDP
@@ -2595,13 +2869,6 @@ ixgbe_initialize_receive_units(struct ix_softc *sc)
IXGBE_WRITE_REG(&sc->hw, IXGBE_RXCSUM, rxcsum);
- /* Enable Receive engine */
- rxctrl = IXGBE_READ_REG(&sc->hw, IXGBE_RXCTRL);
- if (sc->hw.mac.type == ixgbe_mac_82598EB)
- rxctrl |= IXGBE_RXCTRL_DMBYPS;
- rxctrl |= IXGBE_RXCTRL_RXEN;
- sc->hw.mac.ops.enable_rx_dma(&sc->hw, rxctrl);
-
return;
}
@@ -2616,7 +2883,7 @@ ixgbe_free_receive_structures(struct ix_softc *sc)
struct rx_ring *rxr = sc->rx_rings;
int i;
- for (i = 0; i < sc->num_rx_queues; i++, rxr++) {
+ for (i = 0; i < sc->num_queues; i++, rxr++) {
ixgbe_free_receive_buffers(rxr);
}
}
@@ -2629,40 +2896,40 @@ ixgbe_free_receive_structures(struct ix_softc *sc)
void
ixgbe_free_receive_buffers(struct rx_ring *rxr)
{
- struct ix_softc *sc = NULL;
- struct ixgbe_rx_buf *rxbuf = NULL;
+ struct ix_softc *sc;
+ struct ixgbe_rx_buf *rxbuf;
int i;
- INIT_DEBUGOUT("free_receive_buffers: begin");
sc = rxr->sc;
if (rxr->rx_buffers != NULL) {
- rxbuf = rxr->rx_buffers;
- for (i = 0; i < sc->num_rx_desc; i++, rxbuf++) {
+ for (i = 0; i < sc->num_rx_desc; i++) {
+ rxbuf = &rxr->rx_buffers[i];
if (rxbuf->m_head != NULL) {
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->map,
- 0, rxbuf->map->dm_mapsize,
+ bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->hmap,
+ 0, rxbuf->hmap->dm_mapsize,
BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(rxr->rxdma.dma_tag, rxbuf->map);
+ bus_dmamap_unload(rxr->rxdma.dma_tag,
+ rxbuf->hmap);
m_freem(rxbuf->m_head);
rxbuf->m_head = NULL;
}
- bus_dmamap_destroy(rxr->rxdma.dma_tag, rxbuf->map);
- rxbuf->map = NULL;
+ if (rxbuf->m_pack != NULL) {
+ bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->pmap,
+ 0, rxbuf->pmap->dm_mapsize,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rxr->rxdma.dma_tag,
+ rxbuf->pmap);
+ m_freem(rxbuf->m_pack);
+ rxbuf->m_pack = NULL;
+ }
+ bus_dmamap_destroy(rxr->rxdma.dma_tag, rxbuf->hmap);
+ bus_dmamap_destroy(rxr->rxdma.dma_tag, rxbuf->pmap);
+ rxbuf->hmap = NULL;
+ rxbuf->pmap = NULL;
}
- }
- if (rxr->rx_buffers != NULL) {
free(rxr->rx_buffers, M_DEVBUF);
rxr->rx_buffers = NULL;
}
-
- if (rxr->rxtag != NULL)
- rxr->rxtag = NULL;
-
- if (rxr->fmp != NULL) {
- m_freem(rxr->fmp);
- rxr->fmp = NULL;
- rxr->lmp = NULL;
- }
}
/*********************************************************************
@@ -2676,35 +2943,29 @@ ixgbe_free_receive_buffers(struct rx_ring *rxr)
*
*********************************************************************/
int
-ixgbe_rxeof(struct rx_ring *rxr, int count)
+ixgbe_rxeof(struct ix_queue *que, int count)
{
- struct ix_softc *sc = rxr->sc;
+ struct ix_softc *sc = que->sc;
+ struct rx_ring *rxr = que->rxr;
struct ifnet *ifp = &sc->arpcom.ac_if;
- struct mbuf *m;
- uint8_t accept_frame = 0;
+ struct mbuf *mh, *mp, *sendmp;
uint8_t eop = 0;
- uint16_t len, desc_len, prev_len_adj;
- uint32_t staterr;
- struct ixgbe_rx_buf *rxbuf;
+ uint16_t hlen, plen, hdr, vtag;
+ uint32_t staterr, ptype;
+ struct ixgbe_rx_buf *rxbuf, *nxbuf;
union ixgbe_adv_rx_desc *rxdesc;
size_t dsize = sizeof(union ixgbe_adv_rx_desc);
- int i;
+ int i, nextp;
if (!ISSET(ifp->if_flags, IFF_RUNNING))
return FALSE;
i = rxr->next_to_check;
-
while (count != 0 && rxr->rx_ndescs > 0) {
- m = NULL;
-
- rxdesc = &rxr->rx_base[i];
- rxbuf = &rxr->rx_buffers[i];
-
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
- dsize * i, dsize,
- BUS_DMASYNC_POSTREAD);
+ dsize * i, dsize, BUS_DMASYNC_POSTREAD);
+ rxdesc = &rxr->rx_base[i];
staterr = letoh32(rxdesc->wb.upper.status_error);
if (!ISSET(staterr, IXGBE_RXD_STAT_DD)) {
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
@@ -2713,111 +2974,175 @@ ixgbe_rxeof(struct rx_ring *rxr, int count)
break;
}
+ /* Zero out the receive descriptors status */
+ rxdesc->wb.upper.status_error = 0;
+ rxbuf = &rxr->rx_buffers[i];
+
/* pull the mbuf off the ring */
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->map, 0,
- rxbuf->map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(rxr->rxdma.dma_tag, rxbuf->map);
- m = rxbuf->m_head;
- rxbuf->m_head = NULL;
-
- if (m == NULL) {
+ bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->hmap, 0,
+ rxbuf->hmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rxr->rxdma.dma_tag, rxbuf->hmap);
+ bus_dmamap_sync(rxr->rxdma.dma_tag, rxbuf->pmap, 0,
+ rxbuf->pmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rxr->rxdma.dma_tag, rxbuf->pmap);
+
+ mh = rxbuf->m_head;
+ mp = rxbuf->m_pack;
+ plen = letoh16(rxdesc->wb.upper.length);
+ ptype = letoh32(rxdesc->wb.lower.lo_dword.data) &
+ IXGBE_RXDADV_PKTTYPE_MASK;
+ hdr = letoh16(rxdesc->wb.lower.lo_dword.hs_rss.hdr_info);
+ vtag = letoh16(rxdesc->wb.upper.vlan);
+ eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);
+
+ if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) {
+ ifp->if_ierrors++;
+ sc->dropped_pkts++;
+
+ if (rxbuf->fmp) {
+ m_freem(rxbuf->fmp);
+ rxbuf->fmp = NULL;
+ }
+
+ m_freem(mh);
+ m_freem(mp);
+ rxbuf->m_head = NULL;
+ rxbuf->m_pack = NULL;
+ goto next_desc;
+ }
+
+ if (mp == NULL) {
panic("%s: ixgbe_rxeof: NULL mbuf in slot %d "
"(nrx %d, filled %d)", sc->dev.dv_xname,
i, rxr->rx_ndescs,
- rxr->last_rx_desc_filled);
+ rxr->last_desc_filled);
}
- m_cluncount(m, 1);
- rxr->rx_ndescs--;
-
- accept_frame = 1;
- prev_len_adj = 0;
- desc_len = letoh16(rxdesc->wb.upper.length);
-
- if (staterr & IXGBE_RXD_STAT_EOP) {
- count--;
- eop = 1;
- } else {
- eop = 0;
+ /* XXX ixgbe_realign() STRICT_ALIGN */
+ /* Currently no HW RSC support of 82599 */
+ if (!eop) {
+ /*
+ * Figure out the next descriptor of this frame.
+ */
+ nextp = i + 1;
+ if (nextp == sc->num_rx_desc)
+ nextp = 0;
+ nxbuf = &rxr->rx_buffers[nextp];
+ /* prefetch(nxbuf); */
}
- len = desc_len;
-
- if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)
- accept_frame = 0;
-
- if (accept_frame) {
- m->m_len = len;
-
- /* XXX ixgbe_realign() STRICT_ALIGN */
-
- if (rxr->fmp == NULL) {
- m->m_pkthdr.len = m->m_len;
- rxr->fmp = m; /* Store the first mbuf */
- rxr->lmp = m;
+ /*
+ * The header mbuf is ONLY used when header
+ * split is enabled, otherwise we get normal
+ * behavior, ie, both header and payload
+ * are DMA'd into the payload buffer.
+ *
+ * Rather than using the fmp/lmp global pointers
+ * we now keep the head of a packet chain in the
+ * buffer struct and pass this along from one
+ * descriptor to the next, until we get EOP.
+ */
+ if (rxr->hdr_split && (rxbuf->fmp == NULL)) {
+ /* This must be an initial descriptor */
+ hlen = (hdr & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
+ IXGBE_RXDADV_HDRBUFLEN_SHIFT;
+ if (hlen > IXGBE_RX_HDR)
+ hlen = IXGBE_RX_HDR;
+ mh->m_len = hlen;
+ mh->m_pkthdr.len = mh->m_len;
+ rxbuf->m_head = NULL;
+ /*
+ * Check the payload length, this could be zero if
+ * its a small packet.
+ */
+ if (plen > 0) {
+ mp->m_len = plen;
+ mp->m_flags &= ~M_PKTHDR;
+ mh->m_next = mp;
+ mh->m_pkthdr.len += mp->m_len;
+ rxbuf->m_pack = NULL;
+ rxr->rx_split_packets++;
} else {
- /* Chain mbuf's together */
- m->m_flags &= ~M_PKTHDR;
-#if 0
- /*
- * Adjust length of previous mbuf in chain if
- * we received less than 4 bytes in the last
- * descriptor.
- */
- if (prev_len_adj > 0) {
- rxr->lmp->m_len -= prev_len_adj;
- rxr->fmp->m_pkthdr.len -= prev_len_adj;
+ m_freem(mp);
+ rxbuf->m_pack = NULL;
+ }
+ /* Now create the forward chain. */
+ if (eop == 0) {
+ /* stash the chain head */
+ nxbuf->fmp = mh;
+ /* Make forward chain */
+ if (plen)
+ mp->m_next = nxbuf->m_pack;
+ else
+ mh->m_next = nxbuf->m_pack;
+ } else {
+ /* Singlet, prepare to send */
+ sendmp = mh;
+#if NVLAN > 0
+ if ((sc->num_vlans) &&
+ (staterr & IXGBE_RXD_STAT_VP)) {
+ sendmp->m_pkthdr.ether_vtag = vtag;
+ sendmp->m_flags |= M_VLANTAG;
}
#endif
- rxr->lmp->m_next = m;
- rxr->lmp = m;
- rxr->fmp->m_pkthdr.len += m->m_len;
}
-
- if (eop) {
- ifp->if_ipackets++;
-
- m = rxr->fmp;
- m->m_pkthdr.rcvif = ifp;
-
- rxr->packet_count++;
- rxr->byte_count += rxr->fmp->m_pkthdr.len;
-
- ixgbe_rx_checksum(sc, staterr, m);
-
+ } else {
+ /*
+ * Either no header split, or a
+ * secondary piece of a fragmented
+ * split packet.
+ */
+ mp->m_len = plen;
+ /*
+ * See if there is a stored head
+ * that determines what we are
+ */
+ sendmp = rxbuf->fmp;
+ rxbuf->m_pack = rxbuf->fmp = NULL;
+
+ if (sendmp != NULL) /* secondary frag */
+ sendmp->m_pkthdr.len += mp->m_len;
+ else {
+ /* first desc of a non-ps chain */
+ sendmp = mp;
+ sendmp->m_pkthdr.len = mp->m_len;
#if NVLAN > 0
- if (staterr & IXGBE_RXD_STAT_VP) {
- m->m_pkthdr.ether_vtag =
- letoh16(rxdesc->wb.upper.vlan);
- m->m_flags |= M_VLANTAG;
+ if ((sc->num_vlans) &&
+ (staterr & IXGBE_RXD_STAT_VP)) {
+ sendmp->m_pkthdr.ether_vtag = vtag;
+ sendmp->m_flags |= M_VLANTAG;
}
#endif
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap_ether(ifp->if_bpf, m,
- BPF_DIRECTION_IN);
-#endif
-
- ether_input_mbuf(ifp, m);
-
- rxr->fmp = NULL;
- rxr->lmp = NULL;
}
- } else {
- sc->dropped_pkts++;
-
- if (rxr->fmp != NULL) {
- m_freem(rxr->fmp);
- rxr->fmp = NULL;
- rxr->lmp = NULL;
+ /* Pass the head pointer on */
+ if (eop == 0) {
+ nxbuf->fmp = sendmp;
+ sendmp = NULL;
+ mp->m_next = nxbuf->m_pack;
}
-
- m_freem(m);
}
+ rxr->rx_ndescs--;
+ /* Sending this frame? */
+ if (eop) {
+ m_cluncount(sendmp, 1);
- /* Zero out the receive descriptors status */
- rxdesc->wb.upper.status_error = 0;
+ sendmp->m_pkthdr.rcvif = ifp;
+ ifp->if_ipackets++;
+ rxr->rx_packets++;
+ /* capture data for AIM */
+ rxr->bytes += sendmp->m_pkthdr.len;
+ rxr->rx_bytes += sendmp->m_pkthdr.len;
+ ixgbe_rx_checksum(staterr, sendmp, ptype);
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap_ether(ifp->if_bpf, sendmp,
+ BPF_DIRECTION_IN);
+#endif
+
+ ether_input_mbuf(ifp, sendmp);
+ }
+next_desc:
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
dsize * i, dsize,
BUS_DMASYNC_PREREAD);
@@ -2842,8 +3167,7 @@ ixgbe_rxeof(struct rx_ring *rxr, int count)
*
*********************************************************************/
void
-ixgbe_rx_checksum(struct ix_softc *sc,
- uint32_t staterr, struct mbuf * mp)
+ixgbe_rx_checksum(uint32_t staterr, struct mbuf * mp, uint32_t ptype)
{
uint16_t status = (uint16_t) staterr;
uint8_t errors = (uint8_t) (staterr >> 24);
@@ -2867,47 +3191,87 @@ ixgbe_rx_checksum(struct ix_softc *sc,
}
void
-ixgbe_enable_hw_vlans(struct ix_softc *sc)
+ixgbe_setup_vlan_hw_support(struct ix_softc *sc)
{
uint32_t ctrl;
+ int i;
+
+ /*
+ * We get here thru ixgbe_init, meaning
+ * a soft reset, this has already cleared
+ * the VFTA and other state, so if there
+ * have been no vlan's registered do nothing.
+ */
+ if (sc->num_vlans == 0)
+ return;
+
+ /*
+ * A soft reset zero's out the VFTA, so
+ * we need to repopulate it now.
+ */
+ for (i = 0; i < IXGBE_VFTA_SIZE; i++)
+ if (sc->shadow_vfta[i] != 0)
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_VFTA(i),
+ sc->shadow_vfta[i]);
- ixgbe_disable_intr(sc);
ctrl = IXGBE_READ_REG(&sc->hw, IXGBE_VLNCTRL);
+#if 0
+ /* Enable the Filter Table if enabled */
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
+ ctrl &= ~IXGBE_VLNCTRL_CFIEN;
+ ctrl |= IXGBE_VLNCTRL_VFE;
+ }
+#endif
if (sc->hw.mac.type == ixgbe_mac_82598EB)
ctrl |= IXGBE_VLNCTRL_VME;
- ctrl &= ~IXGBE_VLNCTRL_CFIEN;
- ctrl &= ~IXGBE_VLNCTRL_VFE;
IXGBE_WRITE_REG(&sc->hw, IXGBE_VLNCTRL, ctrl);
- ixgbe_enable_intr(sc);
+
+ /* On 82599 the VLAN enable is per/queue in RXDCTL */
+ if (sc->hw.mac.type != ixgbe_mac_82598EB)
+ for (i = 0; i < sc->num_queues; i++) {
+ ctrl = IXGBE_READ_REG(&sc->hw, IXGBE_RXDCTL(i));
+ ctrl |= IXGBE_RXDCTL_VME;
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_RXDCTL(i), ctrl);
+ }
+
}
void
ixgbe_enable_intr(struct ix_softc *sc)
{
struct ixgbe_hw *hw = &sc->hw;
- uint32_t mask = IXGBE_EIMS_ENABLE_MASK;
+ struct ix_queue *que = sc->queues;
+ uint32_t mask = IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE;
+ int i;
/* Enable Fan Failure detection */
- if (hw->phy.media_type == ixgbe_media_type_copper)
+ if (hw->device_id == IXGBE_DEV_ID_82598AT)
mask |= IXGBE_EIMS_GPI_SDP1;
-
- /* 82599 specific interrupts */
- if (sc->hw.mac.type == ixgbe_mac_82599EB) {
+ else {
mask |= IXGBE_EIMS_ECC;
mask |= IXGBE_EIMS_GPI_SDP1;
mask |= IXGBE_EIMS_GPI_SDP2;
}
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
+
/* With RSS we use auto clear */
- if (sc->msix_mem) {
+ if (sc->msix) {
+ mask = IXGBE_EIMS_ENABLE_MASK;
/* Dont autoclear Link */
mask &= ~IXGBE_EIMS_OTHER;
mask &= ~IXGBE_EIMS_LSC;
- IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC,
- sc->eims_mask | mask);
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, mask);
}
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
+ /*
+ * Now enable all queues, this is done separately to
+ * allow for handling the extended (beyond 32) MSIX
+ * vectors that can be used by 82599
+ */
+ for (i = 0; i < sc->num_queues; i++, que++)
+ ixgbe_enable_queue(sc, que->msix);
+
IXGBE_WRITE_FLUSH(hw);
return;
@@ -2916,7 +3280,7 @@ ixgbe_enable_intr(struct ix_softc *sc)
void
ixgbe_disable_intr(struct ix_softc *sc)
{
- if (sc->msix_mem)
+ if (sc->msix)
IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, 0);
if (sc->hw.mac.type == ixgbe_mac_82598EB) {
IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, ~0);
@@ -2933,25 +3297,41 @@ uint16_t
ixgbe_read_pci_cfg(struct ixgbe_hw *hw, uint32_t reg)
{
struct pci_attach_args *pa;
- uint16_t value;
+ uint32_t value;
+ int high = 0;
+ if (reg & 0x2) {
+ high = 1;
+ reg &= ~0x2;
+ }
pa = ((struct ixgbe_osdep *)hw->back)->os_pa;
+ value = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
- /* Should we do read/mask/write...? 16 vs 32 bit!!! */
- value = pci_conf_read(pa->pa_pc, pa->pa_tag, reg) & 0xffff;
+ if (high)
+ value >>= 16;
- return (value);
+ return (value & 0xffff);
}
void
ixgbe_write_pci_cfg(struct ixgbe_hw *hw, uint32_t reg, uint16_t value)
{
struct pci_attach_args *pa;
+ uint32_t rv;
+ int high = 0;
+ /* Need to do read/mask/write... because 16 vs 32 bit!!! */
+ if (reg & 0x2) {
+ high = 1;
+ reg &= ~0x2;
+ }
pa = ((struct ixgbe_osdep *)hw->back)->os_pa;
-
- /* Should we do read/mask/write...? 16 vs 32 bit!!! */
- pci_conf_write(pa->pa_pc, pa->pa_tag, reg, value);
+ rv = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
+ if (!high)
+ rv = (rv & 0xffff0000) | value;
+ else
+ rv = (rv & 0xffff) | ((uint32_t)value << 16);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, reg, rv);
}
/*
@@ -3006,20 +3386,61 @@ ixgbe_set_ivar(struct ix_softc *sc, uint8_t entry, uint8_t vector, int8_t type)
void
ixgbe_configure_ivars(struct ix_softc *sc)
{
- struct tx_ring *txr = sc->tx_rings;
- struct rx_ring *rxr = sc->rx_rings;
+ struct ix_queue *que = sc->queues;
+ uint32_t newitr;
int i;
- for (i = 0; i < sc->num_rx_queues; i++, rxr++)
- ixgbe_set_ivar(sc, i, rxr->msix, 0);
+#if 0
+ if (ixgbe_max_interrupt_rate > 0)
+ newitr = (8000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
+ else
+#endif
+ newitr = 0;
- for (i = 0; i < sc->num_tx_queues; i++, txr++)
- ixgbe_set_ivar(sc, i, txr->msix, 1);
+ for (i = 0; i < sc->num_queues; i++, que++) {
+ /* First the RX queue entry */
+ ixgbe_set_ivar(sc, i, que->msix, 0);
+ /* ... and the TX */
+ ixgbe_set_ivar(sc, i, que->msix, 1);
+ /* Set an Initial EITR value */
+ IXGBE_WRITE_REG(&sc->hw,
+ IXGBE_EITR(que->msix), newitr);
+ }
/* For the Link interrupt */
ixgbe_set_ivar(sc, 1, sc->linkvec, -1);
}
+/*
+ * ixgbe_sfp_probe - called in the local timer to
+ * determine if a port had optics inserted.
+ */
+int
+ixgbe_sfp_probe(struct ix_softc *sc)
+{
+ int result = FALSE;
+
+ if ((sc->hw.phy.type == ixgbe_phy_nl) &&
+ (sc->hw.phy.sfp_type == ixgbe_sfp_type_not_present)) {
+ int32_t ret = sc->hw.phy.ops.identify_sfp(&sc->hw);
+ if (ret)
+ goto out;
+ ret = sc->hw.phy.ops.reset(&sc->hw);
+ if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ printf("%s: Unsupported SFP+ module detected!",
+ sc->dev.dv_xname);
+ goto out;
+ }
+ /* We now have supported optics */
+ sc->sfp_probe = FALSE;
+ /* Set the optics type so system reports correctly */
+ ixgbe_setup_optics(sc);
+ result = TRUE;
+ }
+out:
+ return (result);
+}
+
/**********************************************************************
*
* Update the board statistics counters.
diff --git a/sys/dev/pci/if_ix.h b/sys/dev/pci/if_ix.h
index bca4050468f..0bc365a7311 100644
--- a/sys/dev/pci/if_ix.h
+++ b/sys/dev/pci/if_ix.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ix.h,v 1.11 2010/08/27 08:24:53 deraadt Exp $ */
+/* $OpenBSD: if_ix.h,v 1.12 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -39,10 +39,6 @@
#include <dev/pci/ixgbe.h>
-#if 0
-#include "tcp_lro.h"
-#endif
-
/* Tunables */
/*
@@ -76,12 +72,6 @@
#define DBA_ALIGN 128
/*
- * This parameter controls the maximum no of times the driver will loop in
- * the isr. Minimum Value = 1
- */
-#define MAX_INTR 10
-
-/*
* This parameter controls the duration of transmit watchdog timer.
*/
#define IXGBE_TX_TIMEOUT 5 /* set to 5 seconds */
@@ -96,7 +86,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
@@ -119,47 +109,38 @@
#define IXGBE_82598_SCATTER 100
#define IXGBE_82599_SCATTER 32
#define IXGBE_MSIX_BAR 3
-#if 0
#define IXGBE_TSO_SIZE 65535
-#else
-#define IXGBE_TSO_SIZE IXGBE_MAX_FRAME_SIZE
-#endif
#define IXGBE_TX_BUFFER_SIZE ((uint32_t) 1514)
-#define IXGBE_RX_HDR_SIZE ((uint32_t) 256)
-#define CSUM_OFFLOAD 7 /* Bits in csum flags */
-
-/* The number of MSIX messages the 82598 supports */
-#define IXGBE_MSGS 18
-
-/* For 6.X code compatibility */
-#if __FreeBSD_version < 700000
-#define ETHER_BPF_MTAP BPF_MTAP
-#define CSUM_TSO 0
-#define IFCAP_TSO4 0
-#define FILTER_STRAY
-#define FILTER_HANDLED
-#endif
+#define IXGBE_RX_HDR 128
+#define IXGBE_VFTA_SIZE 128
+#define IXGBE_BR_SIZE 4096
+#define IXGBE_QUEUE_IDLE 0
+#define IXGBE_QUEUE_WORKING 1
+#define IXGBE_QUEUE_HUNG 2
/*
* Interrupt Moderation parameters
- * for now we hardcode, later
- * it would be nice to do dynamic
*/
-#define MAX_IRQ_SEC 8000
-#define DEFAULT_ITR 1000000000/(MAX_IRQ_SEC * 256)
-#define LINK_ITR 1000000000/(1950 * 256)
+#define IXGBE_LOW_LATENCY 128
+#define IXGBE_AVE_LATENCY 400
+#define IXGBE_BULK_LATENCY 1200
+#define IXGBE_LINK_ITR 2000
/* Used for auto RX queue configuration */
extern int mp_ncpus;
struct ixgbe_tx_buf {
+ uint32_t eop_index;
struct mbuf *m_head;
bus_dmamap_t map;
};
struct ixgbe_rx_buf {
struct mbuf *m_head;
- bus_dmamap_t map;
+ struct mbuf *m_pack;
+ struct mbuf *fmp;
+ bus_dmamap_t hmap;
+ bus_dmamap_t pmap;
};
/*
@@ -175,29 +156,42 @@ struct ixgbe_dma_alloc {
};
/*
+ * Driver queue struct: this is the interrupt container
+ * for the associated tx and rx ring.
+ */
+struct ix_queue {
+ struct ix_softc *sc;
+ uint32_t msix; /* This queue's MSIX vector */
+ uint32_t eims; /* This queue's EIMS bit */
+ uint32_t eitr_setting;
+ /* struct resource *res; */
+ void *tag;
+ struct tx_ring *txr;
+ struct rx_ring *rxr;
+ uint64_t irqs;
+};
+
+/*
* The transmit ring, one per tx queue
*/
struct tx_ring {
struct ix_softc *sc;
struct mutex tx_mtx;
uint32_t me;
- uint32_t msix;
- uint32_t eims;
+ int queue_status;
uint32_t watchdog_timer;
union ixgbe_adv_tx_desc *tx_base;
- uint32_t *tx_hwb;
struct ixgbe_dma_alloc txdma;
- struct ixgbe_dma_alloc txwbdma;
- uint32_t next_avail_tx_desc;
- uint32_t next_tx_to_clean;
+ uint32_t next_avail_desc;
+ uint32_t next_to_clean;
struct ixgbe_tx_buf *tx_buffers;
volatile uint16_t tx_avail;
uint32_t txd_cmd;
bus_dma_tag_t txtag;
+ uint32_t bytes; /* Used for AIM calc */
+ uint32_t packets;
/* Soft Stats */
- uint32_t no_tx_desc_avail;
- uint32_t no_tx_desc_late;
- uint64_t tx_irq;
+ uint64_t no_desc_avail;
uint64_t tx_packets;
};
@@ -209,71 +203,91 @@ struct rx_ring {
struct ix_softc *sc;
struct mutex rx_mtx;
uint32_t me;
- uint32_t msix;
- uint32_t eims;
- uint32_t payload;
union ixgbe_adv_rx_desc *rx_base;
struct ixgbe_dma_alloc rxdma;
#if 0
struct lro_ctrl lro;
#endif
- unsigned int last_rx_desc_filled;
+ int lro_enabled;
+ int hdr_split;
+ int hw_rsc;
+ int discard;
+ unsigned int next_to_refresh;
unsigned int next_to_check;
+ unsigned int last_desc_filled;
int rx_ndescs;
struct ixgbe_rx_buf *rx_buffers;
- bus_dma_tag_t rxtag;
- struct mbuf *fmp;
- struct mbuf *lmp;
+
+ uint32_t bytes; /* Used for AIM calc */
+ uint32_t packets;
+
/* Soft stats */
uint64_t rx_irq;
- uint64_t packet_count;
- uint64_t byte_count;
+ uint64_t rx_split_packets;
+ uint64_t rx_packets;
+ uint64_t rx_bytes;
+ uint64_t rx_discarded;
+ uint64_t rsc_num;
};
/* Our adapter structure */
struct ix_softc {
- struct device dev;
- struct arpcom arpcom;
+ struct device dev;
+ struct arpcom arpcom;
struct ixgbe_hw hw;
- struct ixgbe_osdep osdep;
+ struct ixgbe_osdep osdep;
+
+ /* struct resource *pci_mem; */
+ /* struct resource *msix_mem; */
+
+ void *tag;
+ /* struct resource *res; */
+
+ struct ifmedia media;
+ struct timeout timer;
+ int msix;
+ int if_flags;
- struct resource *pci_mem;
- struct resource *msix_mem;
+ struct mutex core_mtx;
+
+ uint16_t num_vlans;
+ uint16_t num_queues;
/*
- * Interrupt resources:
- * Oplin has 20 MSIX messages
- * so allocate that for now.
+ * Shadow VFTA table, this is needed because
+ * the real vlan filter table gets cleared during
+ * a soft reset and the driver needs to be able
+ * to repopulate it.
*/
- void *tag[IXGBE_MSGS];
- struct resource *res[IXGBE_MSGS];
- int rid[IXGBE_MSGS];
- uint32_t eims_mask;
-
- struct ifmedia media;
- struct timeout timer;
- int msix;
- int if_flags;
-
- struct mutex core_mtx;
-
- /* Legacy Fast Intr handling */
- int sfp_probe;
- workq_fn link_task;
-
- /* Info about the board itself */
- uint32_t part_num;
- int link_active;
- uint16_t max_frame_size;
- uint32_t link_speed;
- uint32_t tx_int_delay;
- uint32_t tx_abs_int_delay;
- uint32_t rx_int_delay;
- uint32_t rx_abs_int_delay;
-
- /* Indicates the cluster size to use */
- int bigbufs;
+ uint32_t shadow_vfta[IXGBE_VFTA_SIZE];
+
+ /* Info about the interface */
+ uint optics;
+ int advertise; /* link speeds */
+ int link_active;
+ uint16_t max_frame_size;
+ uint16_t num_segs;
+ uint32_t link_speed;
+ int link_up;
+ uint32_t linkvec;
+
+ /* Mbuf cluster size */
+ uint32_t rx_mbuf_sz;
+
+ /* Support for pluggable optics */
+ int sfp_probe;
+ workq_fn link_task; /* Link tasklet */
+ workq_fn mod_task; /* SFP tasklet */
+ workq_fn msf_task; /* Multispeed Fiber */
+
+ /*
+ * Queues:
+ * This is the irq holder, it has
+ * and RX/TX pair or rings associated
+ * with it.
+ */
+ struct ix_queue *queues;
/*
* Transmit rings:
@@ -281,27 +295,28 @@ struct ix_softc {
*/
struct tx_ring *tx_rings;
int num_tx_desc;
- int num_tx_queues;
/*
* Receive rings:
* Allocated at run time, an array of rings.
*/
struct rx_ring *rx_rings;
+ uint64_t que_mask;
int num_rx_desc;
- int num_rx_queues;
uint32_t rx_process_limit;
- uint optics;
+
+ /* Multicast array memory */
+ uint8_t *mta;
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
- unsigned long mbuf_alloc_failed;
- unsigned long mbuf_cluster_failed;
+ unsigned long mbuf_defrag_failed;
+ unsigned long mbuf_header_failed;
+ unsigned long mbuf_packet_failed;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
unsigned long tso_tx;
- unsigned long linkvec;
unsigned long link_irq;
struct ixgbe_hw_stats stats;
diff --git a/sys/dev/pci/ixgbe.c b/sys/dev/pci/ixgbe.c
index 0acb6d8f7a8..e3227631e69 100644
--- a/sys/dev/pci/ixgbe.c
+++ b/sys/dev/pci/ixgbe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe.c,v 1.5 2010/02/19 18:55:12 jsg Exp $ */
+/* $OpenBSD: ixgbe.c,v 1.6 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -47,11 +47,42 @@ uint16_t ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, uint16_t count);
void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, uint32_t *eec);
void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, uint32_t *eec);
void ixgbe_release_eeprom(struct ixgbe_hw *hw);
-uint16_t ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
int32_t ixgbe_mta_vector(struct ixgbe_hw *hw, uint8_t *mc_addr);
+int32_t ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
+int32_t ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
+int32_t ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
+int32_t ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
+int32_t ixgbe_negotiate_fc(struct ixgbe_hw *hw, uint32_t adv_reg, uint32_t lp_reg,
+ uint32_t adv_sym, uint32_t adv_asm, uint32_t lp_sym, uint32_t lp_asm);
+
+
int32_t ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, uint32_t vlan);
+/* MBX */
+int32_t ixgbe_poll_for_msg(struct ixgbe_hw *hw, uint16_t mbx_id);
+int32_t ixgbe_poll_for_ack(struct ixgbe_hw *hw, uint16_t mbx_id);
+uint32_t ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw);
+int32_t ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, uint32_t mask);
+int32_t ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, uint16_t mbx_id);
+int32_t ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, uint16_t mbx_id);
+int32_t ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, uint16_t mbx_id);
+int32_t ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw);
+int32_t ixgbe_write_mbx_vf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t mbx_id);
+int32_t ixgbe_read_mbx_vf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t mbx_id);
+int32_t ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, uint32_t mask, int32_t index);
+int32_t ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, uint16_t vf_number);
+int32_t ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, uint16_t vf_number);
+int32_t ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, uint16_t vf_number);
+int32_t ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, uint16_t vf_number);
+int32_t ixgbe_write_mbx_pf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t vf_number);
+int32_t ixgbe_read_mbx_pf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t vf_number);
+
+
/**
* ixgbe_init_ops_generic - Inits function ptrs
* @hw: pointer to the hardware structure
@@ -136,7 +167,6 @@ int32_t ixgbe_init_ops_generic(struct ixgbe_hw *hw)
int32_t ixgbe_start_hw_generic(struct ixgbe_hw *hw)
{
uint32_t ctrl_ext;
- int32_t ret_val = IXGBE_SUCCESS;
/* Set the media type */
hw->phy.media_type = hw->mac.ops.get_media_type(hw);
@@ -161,7 +191,46 @@ int32_t ixgbe_start_hw_generic(struct ixgbe_hw *hw)
/* Clear adapter stopped flag */
hw->adapter_stopped = FALSE;
- return ret_val;
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_start_hw_gen2 - Init sequence for common device family
+ * @hw: pointer to hw structure
+ *
+ * Performs the init sequence common to the second generation
+ * of 10 GbE devices.
+ * Devices in the second generation:
+ * 82599
+ * X540
+ **/
+int32_t ixgbe_start_hw_gen2(struct ixgbe_hw *hw)
+{
+ uint32_t i;
+ uint32_t regval;
+
+ /* Clear the rate limiters */
+ 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);
+ }
+
+ return IXGBE_SUCCESS;
}
/**
@@ -271,15 +340,190 @@ int32_t ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
IXGBE_READ_REG(hw, IXGBE_BPTC);
for (i = 0; i < 16; i++) {
IXGBE_READ_REG(hw, IXGBE_QPRC(i));
- IXGBE_READ_REG(hw, IXGBE_QBRC(i));
IXGBE_READ_REG(hw, IXGBE_QPTC(i));
- IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+ if (hw->mac.type >= ixgbe_mac_82599EB) {
+ IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
+ IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
+ IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
+ IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
+ IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+ } else {
+ IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+ IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+ }
}
return IXGBE_SUCCESS;
}
/**
+ * ixgbe_read_pba_string_generic - Reads part number string from EEPROM
+ * @hw: pointer to hardware structure
+ * @pba_num: stores the part number string from the EEPROM
+ * @pba_num_size: part number string buffer length
+ *
+ * Reads the part number string from the EEPROM.
+ **/
+int32_t ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, uint8_t *pba_num,
+ uint32_t pba_num_size)
+{
+ int32_t ret_val;
+ uint16_t data;
+ uint16_t pba_ptr;
+ uint16_t offset;
+ uint16_t length;
+
+ if (pba_num == NULL) {
+ DEBUGOUT("PBA string buffer was null\n");
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
+
+ ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ /*
+ * if data is not ptr guard the PBA must be in legacy format which
+ * means pba_ptr is actually our second data word for the PBA number
+ * and we can decode it into an ascii string
+ */
+ if (data != IXGBE_PBANUM_PTR_GUARD) {
+ DEBUGOUT("NVM PBA number is not stored as string\n");
+
+ /* we will need 11 characters to store the PBA */
+ if (pba_num_size < 11) {
+ DEBUGOUT("PBA string buffer too small\n");
+ return IXGBE_ERR_NO_SPACE;
+ }
+
+ /* extract hex string from data and pba_ptr */
+ pba_num[0] = (data >> 12) & 0xF;
+ pba_num[1] = (data >> 8) & 0xF;
+ pba_num[2] = (data >> 4) & 0xF;
+ pba_num[3] = data & 0xF;
+ pba_num[4] = (pba_ptr >> 12) & 0xF;
+ pba_num[5] = (pba_ptr >> 8) & 0xF;
+ pba_num[6] = '-';
+ pba_num[7] = 0;
+ pba_num[8] = (pba_ptr >> 4) & 0xF;
+ pba_num[9] = pba_ptr & 0xF;
+
+ /* put a null character on the end of our string */
+ pba_num[10] = '\0';
+
+ /* switch all the data but the '-' to hex char */
+ for (offset = 0; offset < 10; offset++) {
+ if (pba_num[offset] < 0xA)
+ pba_num[offset] += '0';
+ else if (pba_num[offset] < 0x10)
+ pba_num[offset] += 'A' - 0xA;
+ }
+
+ return IXGBE_SUCCESS;
+ }
+
+ ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ if (length == 0xFFFF || length == 0) {
+ DEBUGOUT("NVM PBA number section invalid length\n");
+ return IXGBE_ERR_PBA_SECTION;
+ }
+
+ /* check if pba_num buffer is big enough */
+ if (pba_num_size < (((uint32_t)length * 2) - 1)) {
+ DEBUGOUT("PBA string buffer too small\n");
+ return IXGBE_ERR_NO_SPACE;
+ }
+
+ /* trim pba length from start of string */
+ pba_ptr++;
+ length--;
+
+ for (offset = 0; offset < length; offset++) {
+ ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+ pba_num[offset * 2] = (uint8_t)(data >> 8);
+ pba_num[(offset * 2) + 1] = (uint8_t)(data & 0xFF);
+ }
+ pba_num[offset * 2] = '\0';
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_read_pba_length_generic - Reads part number length from EEPROM
+ * @hw: pointer to hardware structure
+ * @pba_num_size: part number string buffer length
+ *
+ * Reads the part number length from the EEPROM.
+ * Returns expected buffer size in pba_num_size
+ **/
+int32_t ixgbe_read_pba_length_generic(struct ixgbe_hw *hw, uint32_t *pba_num_size)
+{
+ int32_t ret_val;
+ uint16_t data;
+ uint16_t pba_ptr;
+ uint16_t length;
+
+ if (pba_num_size == NULL) {
+ DEBUGOUT("PBA buffer size was null\n");
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
+
+ ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ /* if data is not ptr guard the PBA must be in legacy format */
+ if (data != IXGBE_PBANUM_PTR_GUARD) {
+ *pba_num_size = 11;
+ return IXGBE_SUCCESS;
+ }
+
+ ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ if (length == 0xFFFF || length == 0) {
+ DEBUGOUT("NVM PBA number section invalid length\n");
+ return IXGBE_ERR_PBA_SECTION;
+ }
+
+ /*
+ * Convert from length in 16bit values to 8bit chars, add 1 for NULL,
+ * and subtract 2 because length field is included in length.
+ */
+ *pba_num_size = ((uint32_t)length * 2) - 1;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
* ixgbe_read_pba_num_generic - Reads part number from EEPROM
* @hw: pointer to hardware structure
* @pba_num: stores the part number from the EEPROM
@@ -295,6 +539,9 @@ int32_t ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, uint32_t *pba_num)
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
+ } else if (data == IXGBE_PBANUM_PTR_GUARD) {
+ DEBUGOUT("NVM Not supported\n");
+ return IXGBE_NOT_IMPLEMENTED;
}
*pba_num = (uint32_t)(data << 16);
@@ -456,8 +703,7 @@ int32_t ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
* access and verify no pending requests
*/
- if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS)
- DEBUGOUT("PCI-E Master disable polling has failed.\n");
+ ixgbe_disable_pcie_master(hw);
return IXGBE_SUCCESS;
}
@@ -710,6 +956,47 @@ out:
}
/**
+ * ixgbe_write_eewr_generic - Write EEPROM word using EEWR
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to write
+ * @data: word write to the EEPROM
+ *
+ * Write a 16 bit word to the EEPROM using the EEWR register.
+ **/
+int32_t ixgbe_write_eewr_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data)
+{
+ uint32_t eewr;
+ int32_t status;
+
+ hw->eeprom.ops.init_params(hw);
+
+ if (offset >= hw->eeprom.word_size) {
+ status = IXGBE_ERR_EEPROM;
+ goto out;
+ }
+
+ eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) |
+ (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START;
+
+ status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT("Eeprom write EEWR timed out\n");
+ goto out;
+ }
+
+ IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
+
+ status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT("Eeprom write EEWR timed out\n");
+ goto out;
+ }
+
+out:
+ return status;
+}
+
+/**
* ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
* @hw: pointer to hardware structure
* @ee_reg: EEPROM flag for polling
@@ -777,15 +1064,15 @@ int32_t ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
status = IXGBE_ERR_EEPROM;
}
- }
- /* Setup EEPROM for Read/Write */
- if (status == IXGBE_SUCCESS) {
- /* Clear CS and SK */
- eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
- IXGBE_WRITE_FLUSH(hw);
- usec_delay(1);
+ /* Setup EEPROM for Read/Write */
+ if (status == IXGBE_SUCCESS) {
+ /* Clear CS and SK */
+ eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+ usec_delay(1);
+ }
}
return status;
}
@@ -1245,36 +1532,38 @@ int32_t ixgbe_set_rar_generic(struct ixgbe_hw *hw, uint32_t index, uint8_t *addr
uint32_t rar_low, rar_high;
uint32_t rar_entries = hw->mac.num_rar_entries;
+ /* Make sure we are using a valid rar index range */
+ if (index >= rar_entries) {
+ DEBUGOUT1("RAR index %d is out of range.\n", index);
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
+
/* setup VMDq pool selection before this RAR gets enabled */
hw->mac.ops.set_vmdq(hw, index, vmdq);
/* Make sure we are using a valid rar index range */
- if (index < rar_entries) {
- /*
- * HW expects these in little endian so we reverse the byte
- * order from network order (big endian) to little endian
- */
- rar_low = ((uint32_t)addr[0] |
- ((uint32_t)addr[1] << 8) |
- ((uint32_t)addr[2] << 16) |
- ((uint32_t)addr[3] << 24));
- /*
- * Some parts put the VMDq setting in the extra RAH bits,
- * so save everything except the lower 16 bits that hold part
- * of the address and the address valid bit.
- */
- rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
- rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
- rar_high |= ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
+ /*
+ * HW expects these in little endian so we reverse the byte
+ * order from network order (big endian) to little endian
+ */
+ rar_low = ((uint32_t)addr[0] |
+ ((uint32_t)addr[1] << 8) |
+ ((uint32_t)addr[2] << 16) |
+ ((uint32_t)addr[3] << 24));
+ /*
+ * Some parts put the VMDq setting in the extra RAH bits,
+ * so save everything except the lower 16 bits that hold part
+ * of the address and the address valid bit.
+ */
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+ rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+ rar_high |= ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
- if (enable_addr != 0)
- rar_high |= IXGBE_RAH_AV;
+ if (enable_addr != 0)
+ rar_high |= IXGBE_RAH_AV;
- IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
- IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
- } else {
- DEBUGOUT1("RAR index %d is out of range.\n", index);
- }
+ IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
return IXGBE_SUCCESS;
}
@@ -1292,21 +1581,22 @@ int32_t ixgbe_clear_rar_generic(struct ixgbe_hw *hw, uint32_t index)
uint32_t rar_entries = hw->mac.num_rar_entries;
/* Make sure we are using a valid rar index range */
- if (index < rar_entries) {
- /*
- * Some parts put the VMDq setting in the extra RAH bits,
- * so save everything except the lower 16 bits that hold part
- * of the address and the address valid bit.
- */
- rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
- rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
-
- IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
- } else {
+ if (index >= rar_entries) {
DEBUGOUT1("RAR index %d is out of range.\n", index);
+ return IXGBE_ERR_INVALID_ARGUMENT;
}
+ /*
+ * Some parts put the VMDq setting in the extra RAH bits,
+ * so save everything except the lower 16 bits that hold part
+ * of the address and the address valid bit.
+ */
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+ rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+
+ IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+
/* clear VMDq pool/queue selection for this RAR */
hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
@@ -1351,6 +1641,9 @@ int32_t ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
hw->mac.addr[4], hw->mac.addr[5]);
hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
+
+ /* clear VMDq pool/queue selection for RAR 0 */
+ hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
}
hw->addr_ctrl.overflow_promisc = 0;
@@ -1527,7 +1820,6 @@ void ixgbe_set_mta(struct ixgbe_hw *hw, uint8_t *mc_addr)
uint32_t vector;
uint32_t vector_bit;
uint32_t vector_reg;
- uint32_t mta_reg;
hw->addr_ctrl.mta_in_use++;
@@ -1545,9 +1837,7 @@ void ixgbe_set_mta(struct ixgbe_hw *hw, uint8_t *mc_addr)
*/
vector_reg = (vector >> 5) & 0x7F;
vector_bit = vector & 0x1F;
- mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
- mta_reg |= (1 << vector_bit);
- IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
+ hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit);
}
/**
@@ -1575,18 +1865,21 @@ int32_t ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, uint8_t *mc_addr_
hw->addr_ctrl.num_mc_addrs = mc_addr_count;
hw->addr_ctrl.mta_in_use = 0;
- /* Clear the MTA */
+ /* Clear mta_shadow */
DEBUGOUT(" Clearing MTA\n");
- for (i = 0; i < hw->mac.mcft_size; i++)
- IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
+ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
- /* Add the new addresses */
+ /* Update mta_shadow */
for (i = 0; i < mc_addr_count; i++) {
DEBUGOUT(" Adding the multicast addresses:\n");
ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));
}
/* Enable mta */
+ for (i = 0; i < hw->mac.mcft_size; i++)
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i,
+ hw->mac.mta_shadow[i]);
+
if (hw->addr_ctrl.mta_in_use > 0)
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
@@ -1641,10 +1934,11 @@ int32_t ixgbe_fc_enable_generic(struct ixgbe_hw *hw, int32_t packetbuf_num)
uint32_t mflcn_reg, fccfg_reg;
uint32_t reg;
uint32_t rx_pba_size;
+ uint32_t fcrtl, fcrth;
/* Negotiate the fc mode to use */
ret_val = ixgbe_fc_autoneg(hw);
- if (ret_val)
+ if (ret_val == IXGBE_ERR_FLOW_CONTROL)
goto out;
/* Disable any previous flow control settings */
@@ -1666,7 +1960,8 @@ int32_t ixgbe_fc_enable_generic(struct ixgbe_hw *hw, int32_t packetbuf_num)
*/
switch (hw->fc.current_mode) {
case ixgbe_fc_none:
- /* Flow control is disabled by software override or autoneg.
+ /*
+ * Flow control is disabled by software override or autoneg.
* The code below will actually disable it in the HW.
*/
break;
@@ -1705,39 +2000,21 @@ int32_t ixgbe_fc_enable_generic(struct ixgbe_hw *hw, int32_t packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
- reg = IXGBE_READ_REG(hw, IXGBE_MTQC);
- /* Thresholds are different for link flow control when in DCB mode */
- if (reg & IXGBE_MTQC_RT_ENA) {
- rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
+ rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
+ rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
- /* Always disable XON for LFC when in DCB mode */
- reg = (rx_pba_size >> 5) & 0xFFE0;
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg);
+ fcrth = (rx_pba_size - hw->fc.high_water) << 10;
+ fcrtl = (rx_pba_size - hw->fc.low_water) << 10;
- reg = (rx_pba_size >> 2) & 0xFFE0;
- if (hw->fc.current_mode & ixgbe_fc_tx_pause)
- reg |= IXGBE_FCRTH_FCEN;
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg);
- } else {
- /* Set up and enable Rx high/low water mark thresholds,
- * enable XON. */
- if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
- if (hw->fc.send_xon) {
- IXGBE_WRITE_REG(hw,
- IXGBE_FCRTL_82599(packetbuf_num),
- (hw->fc.low_water |
- IXGBE_FCRTL_XONE));
- } else {
- IXGBE_WRITE_REG(hw,
- IXGBE_FCRTL_82599(packetbuf_num),
- hw->fc.low_water);
- }
-
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num),
- (hw->fc.high_water | IXGBE_FCRTH_FCEN));
- }
+ if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
+ fcrth |= IXGBE_FCRTH_FCEN;
+ if (hw->fc.send_xon)
+ fcrtl |= IXGBE_FCRTL_XONE;
}
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl);
+
/* Configure pause time (2 TCs per register) */
reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
if ((packetbuf_num & 1) == 0)
@@ -1763,10 +2040,11 @@ int32_t ixgbe_fc_autoneg(struct ixgbe_hw *hw)
{
int32_t ret_val = IXGBE_SUCCESS;
ixgbe_link_speed speed;
- uint32_t pcs_anadv_reg, pcs_lpab_reg, linkstat;
- uint32_t links2, anlp1_reg, autoc_reg, links;
int link_up;
+ if (hw->fc.disable_fc_autoneg)
+ goto out;
+
/*
* AN should have completed when the cable was plugged in.
* Look for reasons to bail out. Bail out if:
@@ -1777,153 +2055,201 @@ int32_t ixgbe_fc_autoneg(struct ixgbe_hw *hw)
* So use link_up_wait_to_complete=FALSE.
*/
hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
-
- if (hw->fc.disable_fc_autoneg || (!link_up)) {
- hw->fc.fc_was_autonegged = FALSE;
- hw->fc.current_mode = hw->fc.requested_mode;
+ if (!link_up) {
+ ret_val = IXGBE_ERR_FLOW_CONTROL;
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;
- }
+ switch (hw->phy.media_type) {
+ /* Autoneg flow control on fiber adapters */
+ case ixgbe_media_type_fiber:
+ if (speed == IXGBE_LINK_SPEED_1GB_FULL)
+ ret_val = ixgbe_fc_autoneg_fiber(hw);
+ break;
- 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;
- }
- }
+ /* Autoneg flow control on backplane adapters */
+ case ixgbe_media_type_backplane:
+ ret_val = ixgbe_fc_autoneg_backplane(hw);
+ break;
+
+ /* Autoneg flow control on copper adapters */
+ case ixgbe_media_type_copper:
+ if (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)
+ ret_val = ixgbe_fc_autoneg_copper(hw);
+ break;
+
+ default:
+ break;
}
+out:
+ if (ret_val == IXGBE_SUCCESS) {
+ hw->fc.fc_was_autonegged = TRUE;
+ } else {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ }
+ return ret_val;
+}
+
+/**
+ * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
+ * @hw: pointer to hardware structure
+ * @speed:
+ * @link_up
+ *
+ * Enable flow control according on 1 gig fiber.
+ **/
+int32_t ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
+{
+ uint32_t pcs_anadv_reg, pcs_lpab_reg, linkstat;
+ int32_t ret_val;
+
/*
* 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;
- }
+
+ linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+ if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+ ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+ ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ goto out;
}
+ pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+
+ ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg,
+ pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE,
+ IXGBE_PCS1GANA_ASM_PAUSE,
+ IXGBE_PCS1GANA_SYM_PAUSE,
+ IXGBE_PCS1GANA_ASM_PAUSE);
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37
+ * @hw: pointer to hardware structure
+ *
+ * Enable flow control according to IEEE clause 37.
+ **/
+int32_t ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
+{
+ uint32_t links2, anlp1_reg, autoc_reg, links;
+ int32_t ret_val;
+
/*
- * Bail out on
- * - copper or CX4 adapters
- * - fiber adapters running at 10gig
+ * 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_copper) ||
- (hw->phy.media_type == ixgbe_media_type_cx4) ||
- ((hw->phy.media_type == ixgbe_media_type_fiber) &&
- (speed == IXGBE_LINK_SPEED_10GB_FULL))) {
+ 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;
+ ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
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;
+ ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ goto out;
+ }
+ }
/*
- * Read the AN advertisement and LP ability registers and resolve
+ * Read the 10g AN autoc and LP ability registers and resolve
* local flow control settings accordingly
*/
- 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");
- }
- }
+ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
- if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ ret_val = ixgbe_negotiate_fc(hw, autoc_reg,
+ anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
+ IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37
+ * @hw: pointer to hardware structure
+ *
+ * Enable flow control according to IEEE clause 37.
+ **/
+int32_t ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
+{
+ uint16_t technology_ability_reg = 0;
+ uint16_t lp_technology_ability_reg = 0;
+
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &technology_ability_reg);
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+ &lp_technology_ability_reg);
+
+ return ixgbe_negotiate_fc(hw, (uint32_t)technology_ability_reg,
+ (uint32_t)lp_technology_ability_reg,
+ IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE,
+ IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE);
+}
+
+/**
+ * ixgbe_negotiate_fc - Negotiate flow control
+ * @hw: pointer to hardware structure
+ * @adv_reg: flow control advertised settings
+ * @lp_reg: link partner's flow control settings
+ * @adv_sym: symmetric pause bit in advertisement
+ * @adv_asm: asymmetric pause bit in advertisement
+ * @lp_sym: symmetric pause bit in link partner advertisement
+ * @lp_asm: asymmetric pause bit in link partner advertisement
+ *
+ * Find the intersection between advertised settings and link partner's
+ * advertised settings
+ **/
+int32_t ixgbe_negotiate_fc(struct ixgbe_hw *hw, uint32_t adv_reg, uint32_t lp_reg,
+ uint32_t adv_sym, uint32_t adv_asm, uint32_t lp_sym, uint32_t lp_asm)
+{
+ if ((!(adv_reg)) || (!(lp_reg)))
+ return IXGBE_ERR_FC_NOT_NEGOTIATED;
+
+ if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
/*
- * Read the 10g AN autoc and LP ability registers and resolve
- * local flow control settings accordingly
+ * 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.
*/
- 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");
+ 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_none;
- DEBUGOUT("Flow Control = NONE.\n");
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control=RX PAUSE frames only\n");
}
+ } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ hw->fc.current_mode = ixgbe_fc_tx_pause;
+ DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
+ } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ 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;
-
-out:
- return ret_val;
+ return IXGBE_SUCCESS;
}
/**
@@ -1935,7 +2261,8 @@ out:
int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
{
int32_t ret_val = IXGBE_SUCCESS;
- uint32_t reg;
+ uint32_t reg = 0, reg_bp = 0;;
+ uint16_t reg_cu = 0;
/* Validate the packetbuf configuration */
if (packetbuf_num < 0 || packetbuf_num > 7) {
@@ -1973,11 +2300,26 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
hw->fc.requested_mode = ixgbe_fc_full;
/*
- * Set up the 1G flow control advertisement registers so the HW will be
- * able to do fc autoneg once the cable is plugged in. If we end up
- * using 10g instead, this is harmless.
+ * Set up the 1G and 10G flow control advertisement registers so the
+ * HW will be able to do fc autoneg once the cable is plugged in. If
+ * we link at 10G, the 1G advertisement is harmless and vice versa.
*/
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+
+ switch (hw->phy.media_type) {
+ case ixgbe_media_type_fiber:
+ case ixgbe_media_type_backplane:
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ break;
+
+ case ixgbe_media_type_copper:
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg_cu);
+ break;
+
+ default:
+ ;
+ }
/*
* The possible values of fc.requested_mode are:
@@ -1993,6 +2335,11 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
case ixgbe_fc_none:
/* Flow control completely disabled by software override. */
reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE);
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
break;
case ixgbe_fc_rx_pause:
/*
@@ -2004,6 +2351,11 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
* disable the adapter's ability to send PAUSE frames.
*/
reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE);
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
break;
case ixgbe_fc_tx_pause:
/*
@@ -2012,10 +2364,22 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
*/
reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
+ reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
+ } else if (hw->phy.media_type == ixgbe_media_type_copper) {
+ reg_cu |= (IXGBE_TAF_ASM_PAUSE);
+ reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
+ }
break;
case ixgbe_fc_full:
/* Flow control (both Rx and Tx) is enabled by SW override. */
reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE);
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
@@ -2024,6 +2388,10 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
break;
}
+ /*
+ * Enable auto-negotiation between the MAC & PHY;
+ * the MAC will advertise clause 37 flow control.
+ */
IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
@@ -2035,64 +2403,20 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
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.
+ * AUTOC restart handles negotiation of 1G and 10G on backplane
+ * and copper. There is no need to set the PCS1GCTL register.
+ *
*/
- 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;
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ reg_bp |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+ } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
+ (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)) {
+ hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
+ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
}
- /*
- * 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);
+ DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
out:
return ret_val;
}
@@ -2113,6 +2437,10 @@ int32_t ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
uint32_t number_of_queues;
int32_t status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+ /* Just jump out if bus mastering is already disabled */
+ if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+ goto out;
+
/* Disable the receive unit by stopping each queue */
number_of_queues = hw->mac.max_rx_queues;
for (i = 0; i < number_of_queues; i++) {
@@ -2128,13 +2456,42 @@ int32_t ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
- if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) {
- status = IXGBE_SUCCESS;
+ if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+ goto check_device_status;
+ usec_delay(100);
+ }
+
+ DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
+ status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+
+ /*
+ * Before proceeding, make sure that the PCIe block does not have
+ * transactions pending.
+ */
+check_device_status:
+ for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+ if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) &
+ IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
break;
- }
usec_delay(100);
}
+ if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
+ DEBUGOUT("PCIe transaction pending bit also did not clear.\n");
+ else
+ goto out;
+
+ /*
+ * Two consecutive resets are required via CTRL.RST per datasheet
+ * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine
+ * of this need. The first reset prevents new master requests from
+ * being issued by our device. We then must wait 1usec for any
+ * remaining completions from the PCIe bus to trickle in, and then reset
+ * again to clear out any effects they may have had on our device.
+ */
+ hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+
+out:
return status;
}
@@ -2242,7 +2599,6 @@ int32_t ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, uint32_t index)
hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
if (!link_up) {
-
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
autoc_reg |= IXGBE_AUTOC_FLU;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
@@ -2382,37 +2738,38 @@ int32_t ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmd
uint32_t mpsar_lo, mpsar_hi;
uint32_t 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));
+ /* Make sure we are using a valid rar index range */
+ if (rar >= rar_entries) {
+ DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
- if (!mpsar_lo && !mpsar_hi)
- goto done;
+ mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+ mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
- 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);
- }
+ if (!mpsar_lo && !mpsar_hi)
+ goto done;
- /* was that the last pool using this rar? */
- if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
- hw->mac.ops.clear_rar(hw, rar);
+ 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 {
- DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ 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);
done:
return IXGBE_SUCCESS;
}
@@ -2428,18 +2785,20 @@ int32_t ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq)
uint32_t mpsar;
uint32_t 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 {
+ /* Make sure we are using a valid rar index range */
+ if (rar >= rar_entries) {
DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
+
+ 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);
}
return IXGBE_SUCCESS;
}
@@ -2474,6 +2833,10 @@ int32_t ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, uint32_t vlan)
uint32_t first_empty_slot = 0;
int32_t regindex;
+ /* short cut the special case */
+ if (vlan == 0)
+ return 0;
+
/*
* Search for the vlan id in the VLVF entries. Save off the first empty
* slot found along the way
@@ -2496,7 +2859,7 @@ int32_t ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, uint32_t vlan)
regindex = first_empty_slot;
else {
DEBUGOUT("No space in VLVF.\n");
- regindex = -1;
+ regindex = IXGBE_ERR_NO_SPACE;
}
}
@@ -2517,8 +2880,11 @@ int32_t ixgbe_set_vfta_generic(struct ixgbe_hw *hw, uint32_t vlan, uint32_t vind
{
int32_t regindex;
uint32_t bitindex;
+ uint32_t vfta;
uint32_t bits;
uint32_t vt;
+ uint32_t targetbit;
+ int vfta_changed = FALSE;
if (vlan > 4095)
return IXGBE_ERR_PARAM;
@@ -2526,6 +2892,7 @@ int32_t ixgbe_set_vfta_generic(struct ixgbe_hw *hw, uint32_t vlan, uint32_t vind
/*
* this is a 2 part operation - first the VFTA, then the
* VLVF and VLVFB if VT Mode is set
+ * We don't write the VFTA until we know the VLVF part succeeded.
*/
/* Part 1
@@ -2536,13 +2903,20 @@ int32_t ixgbe_set_vfta_generic(struct ixgbe_hw *hw, uint32_t vlan, uint32_t vind
*/
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);
+ targetbit = (1 << bitindex);
+ vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
+ if (vlan_on) {
+ if (!(vfta & targetbit)) {
+ vfta |= targetbit;
+ vfta_changed = TRUE;
+ }
+ } else {
+ if ((vfta & targetbit)) {
+ vfta &= ~targetbit;
+ vfta_changed = TRUE;
+ }
+ }
/* Part 2
* If VT Mode is set
@@ -2554,61 +2928,84 @@ int32_t ixgbe_set_vfta_generic(struct ixgbe_hw *hw, uint32_t vlan, uint32_t 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;
- }
+ int32_t vlvf_index;
+
+ vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
+ if (vlvf_index < 0)
+ return vlvf_index;
if (vlan_on) {
/* set the pool bit */
if (vind < 32) {
bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB(regindex*2));
+ IXGBE_VLVFB(vlvf_index*2));
bits |= (1 << vind);
IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB(regindex*2),
+ IXGBE_VLVFB(vlvf_index*2),
bits);
} else {
bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB((regindex*2)+1));
- bits |= (1 << vind);
+ IXGBE_VLVFB((vlvf_index*2)+1));
+ bits |= (1 << (vind-32));
IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB((regindex*2)+1),
+ IXGBE_VLVFB((vlvf_index*2)+1),
bits);
}
} else {
/* clear the pool bit */
if (vind < 32) {
bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB(regindex*2));
+ IXGBE_VLVFB(vlvf_index*2));
bits &= ~(1 << vind);
IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB(regindex*2),
+ IXGBE_VLVFB(vlvf_index*2),
bits);
bits |= IXGBE_READ_REG(hw,
- IXGBE_VLVFB((regindex*2)+1));
+ IXGBE_VLVFB((vlvf_index*2)+1));
} else {
bits = IXGBE_READ_REG(hw,
- IXGBE_VLVFB((regindex*2)+1));
- bits &= ~(1 << vind);
+ IXGBE_VLVFB((vlvf_index*2)+1));
+ bits &= ~(1 << (vind-32));
IXGBE_WRITE_REG(hw,
- IXGBE_VLVFB((regindex*2)+1),
+ IXGBE_VLVFB((vlvf_index*2)+1),
bits);
bits |= IXGBE_READ_REG(hw,
- IXGBE_VLVFB(regindex*2));
+ IXGBE_VLVFB(vlvf_index*2));
}
}
- if (bits)
- IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex),
+ /*
+ * If there are still bits set in the VLVFB registers
+ * for the VLAN ID indicated we need to see if the
+ * caller is requesting that we clear the VFTA entry bit.
+ * If the caller has requested that we clear the VFTA
+ * entry bit but there are still pools/VFs using this VLAN
+ * ID entry then ignore the request. We're not worried
+ * about the case where we're turning the VFTA VLAN ID
+ * entry bit on, only when requested to turn it off as
+ * there may be multiple pools and/or VFs using the
+ * VLAN ID entry. In that case we cannot clear the
+ * VFTA bit until all pools/VFs using that VLAN ID have also
+ * been cleared. This will be indicated by "bits" being
+ * zero.
+ */
+ if (bits) {
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
(IXGBE_VLVF_VIEN | vlan));
+ if (!vlan_on) {
+ /* someone wants to clear the vfta entry
+ * but some pools/VFs are still using it.
+ * Ignore it. */
+ vfta_changed = FALSE;
+ }
+ }
else
- IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
}
-out:
+
+ if (vfta_changed)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
+
return IXGBE_SUCCESS;
}
@@ -2646,10 +3043,19 @@ int32_t ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
int *link_up, int link_up_wait_to_complete)
{
- uint32_t links_reg;
+ uint32_t links_reg, links_orig;
uint32_t i;
+ /* clear the old state */
+ links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
+
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+
+ if (links_orig != links_reg) {
+ DEBUGOUT2("LINKS changed from %08X to %08X\n",
+ links_orig, links_reg);
+ }
+
if (link_up_wait_to_complete) {
for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
if (links_reg & IXGBE_LINKS_UP) {
@@ -2674,8 +3080,11 @@ int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *spee
else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
IXGBE_LINKS_SPEED_1G_82599)
*speed = IXGBE_LINK_SPEED_1GB_FULL;
- else
+ else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+ IXGBE_LINKS_SPEED_100_82599)
*speed = IXGBE_LINK_SPEED_100_FULL;
+ else
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
/* if link is down, zero out the current_mode */
if (*link_up == FALSE) {
@@ -2685,3 +3094,783 @@ int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *spee
return IXGBE_SUCCESS;
}
+
+/**
+ * ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
+ * control
+ * @hw: pointer to hardware structure
+ *
+ * There are several phys that do not support autoneg flow control. This
+ * function check the device id to see if the associated phy supports
+ * autoneg flow control.
+ **/
+int32_t ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+{
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_82599_T3_LOM:
+ return IXGBE_SUCCESS;
+ default:
+ return IXGBE_ERR_FC_NOT_SUPPORTED;
+ }
+}
+
+/**
+ * ixgbe_get_device_caps_generic - Get additional device capabilities
+ * @hw: pointer to hardware structure
+ * @device_caps: the EEPROM word with the extra device capabilities
+ *
+ * This function will read the EEPROM location for the device capabilities,
+ * and return the word through device_caps.
+ **/
+int32_t ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, uint16_t *device_caps)
+{
+ hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering
+ * @hw: pointer to hardware structure
+ *
+ **/
+void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw)
+{
+ uint32_t regval;
+ uint32_t i;
+
+ DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2");
+
+ /* Enable 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);
+ }
+
+}
+
+/*
+ * MBX: Mailbox handling
+ */
+
+/**
+ * ixgbe_read_mbx - Reads a message from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to read
+ *
+ * returns SUCCESS if it successfuly read message from buffer
+ **/
+int32_t ixgbe_read_mbx(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_read_mbx");
+
+ /* limit read to size of mailbox */
+ if (size > mbx->size)
+ size = mbx->size;
+
+ if (mbx->ops.read)
+ ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_write_mbx - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+int32_t ixgbe_write_mbx(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int32_t ret_val = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_write_mbx");
+
+ if (size > mbx->size)
+ ret_val = IXGBE_ERR_MBX;
+
+ else if (mbx->ops.write)
+ ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_msg - checks to see if someone sent us mail
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_msg(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_check_for_msg");
+
+ if (mbx->ops.check_for_msg)
+ ret_val = mbx->ops.check_for_msg(hw, mbx_id);
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_ack - checks to see if someone sent us ACK
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_ack(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_check_for_ack");
+
+ if (mbx->ops.check_for_ack)
+ ret_val = mbx->ops.check_for_ack(hw, mbx_id);
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_rst - checks to see if other side has reset
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the Status bit was found or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_rst(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_check_for_rst");
+
+ if (mbx->ops.check_for_rst)
+ ret_val = mbx->ops.check_for_rst(hw, mbx_id);
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_poll_for_msg - Wait for message notification
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification
+ **/
+int32_t ixgbe_poll_for_msg(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ DEBUGFUNC("ixgbe_poll_for_msg");
+
+ if (!countdown || !mbx->ops.check_for_msg)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ usec_delay(mbx->usec_delay);
+ }
+
+out:
+ return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
+}
+
+/**
+ * ixgbe_poll_for_ack - Wait for message acknowledgement
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message acknowledgement
+ **/
+int32_t ixgbe_poll_for_ack(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int countdown = mbx->timeout;
+
+ DEBUGFUNC("ixgbe_poll_for_ack");
+
+ if (!countdown || !mbx->ops.check_for_ack)
+ goto out;
+
+ while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+ countdown--;
+ if (!countdown)
+ break;
+ usec_delay(mbx->usec_delay);
+ }
+
+out:
+ return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
+}
+
+/**
+ * ixgbe_read_posted_mbx - Wait for message notification and receive message
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully received a message notification and
+ * copied it into the receive buffer.
+ **/
+int32_t ixgbe_read_posted_mbx(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size, uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_read_posted_mbx");
+
+ if (!mbx->ops.read)
+ goto out;
+
+ ret_val = ixgbe_poll_for_msg(hw, mbx_id);
+
+ /* if ack received read message, otherwise we timed out */
+ if (!ret_val)
+ ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer and
+ * received an ack to that message within delay * timeout period
+ **/
+int32_t ixgbe_write_posted_mbx(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t mbx_id)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_write_posted_mbx");
+
+ /* exit if either we can't write or there isn't a defined timeout */
+ if (!mbx->ops.write || !mbx->timeout)
+ goto out;
+
+ /* send msg */
+ ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+
+ /* if msg sent wait until we receive an ack */
+ if (!ret_val)
+ ret_val = ixgbe_poll_for_ack(hw, mbx_id);
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_init_mbx_ops_generic - Initialize MB function pointers
+ * @hw: pointer to the HW structure
+ *
+ * Setups up the mailbox read and write message function pointers
+ **/
+void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+ mbx->ops.read_posted = ixgbe_read_posted_mbx;
+ mbx->ops.write_posted = ixgbe_write_posted_mbx;
+}
+
+/**
+ * ixgbe_read_v2p_mailbox - read v2p mailbox
+ * @hw: pointer to the HW structure
+ *
+ * This function is used to read the v2p mailbox without losing the read to
+ * clear status bits.
+ **/
+uint32_t ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw)
+{
+ uint32_t v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
+
+ v2p_mailbox |= hw->mbx.v2p_mailbox;
+ hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
+
+ return v2p_mailbox;
+}
+
+/**
+ * ixgbe_check_for_bit_vf - Determine if a status bit was set
+ * @hw: pointer to the HW structure
+ * @mask: bitmask for bits to be tested and cleared
+ *
+ * This function is used to check for the read to clear bits within
+ * the V2P mailbox.
+ **/
+int32_t ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, uint32_t mask)
+{
+ uint32_t v2p_mailbox = ixgbe_read_v2p_mailbox(hw);
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ if (v2p_mailbox & mask)
+ ret_val = IXGBE_SUCCESS;
+
+ hw->mbx.v2p_mailbox &= ~mask;
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_msg_vf - checks to see if the PF has sent mail
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the PF has set the Status bit or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ UNREFERENCED_PARAMETER(mbx_id);
+ DEBUGFUNC("ixgbe_check_for_msg_vf");
+
+ if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) {
+ ret_val = IXGBE_SUCCESS;
+ hw->mbx.stats.reqs++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_ack_vf - checks to see if the PF has ACK'd
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ UNREFERENCED_PARAMETER(mbx_id);
+ DEBUGFUNC("ixgbe_check_for_ack_vf");
+
+ if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) {
+ ret_val = IXGBE_SUCCESS;
+ hw->mbx.stats.acks++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_rst_vf - checks to see if the PF has reset
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to check
+ *
+ * returns TRUE if the PF has set the reset done bit or else FALSE
+ **/
+int32_t ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, uint16_t mbx_id)
+{
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ UNREFERENCED_PARAMETER(mbx_id);
+ DEBUGFUNC("ixgbe_check_for_rst_vf");
+
+ if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD |
+ IXGBE_VFMAILBOX_RSTI))) {
+ ret_val = IXGBE_SUCCESS;
+ hw->mbx.stats.rsts++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_obtain_mbx_lock_vf - obtain mailbox lock
+ * @hw: pointer to the HW structure
+ *
+ * return SUCCESS if we obtained the mailbox lock
+ **/
+int32_t ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw)
+{
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_obtain_mbx_lock_vf");
+
+ /* Take ownership of the buffer */
+ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU);
+
+ /* reserve mailbox for vf use */
+ if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU)
+ ret_val = IXGBE_SUCCESS;
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_write_mbx_vf - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+int32_t ixgbe_write_mbx_vf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t mbx_id)
+{
+ int32_t ret_val;
+ uint16_t i;
+
+ UNREFERENCED_PARAMETER(mbx_id);
+
+ DEBUGFUNC("ixgbe_write_mbx_vf");
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbe_obtain_mbx_lock_vf(hw);
+ if (ret_val)
+ goto out_no_write;
+
+ /* flush msg and acks as we are overwriting the message buffer */
+ ixgbe_check_for_msg_vf(hw, 0);
+ ixgbe_check_for_ack_vf(hw, 0);
+
+ /* copy the caller specified message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]);
+
+ /* update stats */
+ hw->mbx.stats.msgs_tx++;
+
+ /* Drop VFU and interrupt the PF to tell it a message has been sent */
+ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ);
+
+out_no_write:
+ return ret_val;
+}
+
+/**
+ * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to read
+ *
+ * returns SUCCESS if it successfuly read message from buffer
+ **/
+int32_t ixgbe_read_mbx_vf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t mbx_id)
+{
+ int32_t ret_val = IXGBE_SUCCESS;
+ uint16_t i;
+
+ DEBUGFUNC("ixgbe_read_mbx_vf");
+ UNREFERENCED_PARAMETER(mbx_id);
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbe_obtain_mbx_lock_vf(hw);
+ if (ret_val)
+ goto out_no_read;
+
+ /* copy the message from the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i);
+
+ /* Acknowledge receipt and release mailbox, then we're done */
+ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK);
+
+ /* update stats */
+ hw->mbx.stats.msgs_rx++;
+
+out_no_read:
+ return ret_val;
+}
+
+/**
+ * ixgbe_init_mbx_params_vf - set initial values for vf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for vf mailbox
+ */
+void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+ /* start mailbox as timed out and let the reset_hw call set the timeout
+ * value to begin communications */
+ mbx->timeout = 0;
+ mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
+
+ mbx->size = IXGBE_VFMAILBOX_SIZE;
+
+ mbx->ops.read = ixgbe_read_mbx_vf;
+ mbx->ops.write = ixgbe_write_mbx_vf;
+ mbx->ops.read_posted = ixgbe_read_posted_mbx;
+ mbx->ops.write_posted = ixgbe_write_posted_mbx;
+ mbx->ops.check_for_msg = ixgbe_check_for_msg_vf;
+ mbx->ops.check_for_ack = ixgbe_check_for_ack_vf;
+ mbx->ops.check_for_rst = ixgbe_check_for_rst_vf;
+
+ mbx->stats.msgs_tx = 0;
+ mbx->stats.msgs_rx = 0;
+ mbx->stats.reqs = 0;
+ mbx->stats.acks = 0;
+ mbx->stats.rsts = 0;
+}
+
+int32_t ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, uint32_t mask, int32_t index)
+{
+ uint32_t mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ if (mbvficr & mask) {
+ ret_val = IXGBE_SUCCESS;
+ IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
+ }
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, uint16_t vf_number)
+{
+ int32_t ret_val = IXGBE_ERR_MBX;
+ int32_t index = IXGBE_MBVFICR_INDEX(vf_number);
+ uint32_t vf_bit = vf_number % 16;
+
+ DEBUGFUNC("ixgbe_check_for_msg_pf");
+
+ if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
+ index)) {
+ ret_val = IXGBE_SUCCESS;
+ hw->mbx.stats.reqs++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, uint16_t vf_number)
+{
+ int32_t ret_val = IXGBE_ERR_MBX;
+ int32_t index = IXGBE_MBVFICR_INDEX(vf_number);
+ uint32_t vf_bit = vf_number % 16;
+
+ DEBUGFUNC("ixgbe_check_for_ack_pf");
+
+ if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
+ index)) {
+ ret_val = IXGBE_SUCCESS;
+ hw->mbx.stats.acks++;
+ }
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_check_for_rst_pf - checks to see if the VF has reset
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
+ **/
+int32_t ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, uint16_t vf_number)
+{
+ uint32_t reg_offset = (vf_number < 32) ? 0 : 1;
+ uint32_t vf_shift = vf_number % 32;
+ uint32_t vflre = 0;
+ int32_t ret_val = IXGBE_ERR_MBX;
+
+ DEBUGFUNC("ixgbe_check_for_rst_pf");
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
+ break;
+ default:
+ goto out;
+ break;
+ }
+
+ if (vflre & (1 << vf_shift)) {
+ ret_val = IXGBE_SUCCESS;
+ IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
+ hw->mbx.stats.rsts++;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
+ * @hw: pointer to the HW structure
+ * @vf_number: the VF index
+ *
+ * return SUCCESS if we obtained the mailbox lock
+ **/
+int32_t ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, uint16_t vf_number)
+{
+ int32_t ret_val = IXGBE_ERR_MBX;
+ uint32_t p2v_mailbox;
+
+ DEBUGFUNC("ixgbe_obtain_mbx_lock_pf");
+
+ /* Take ownership of the buffer */
+ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
+
+ /* reserve mailbox for vf use */
+ p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
+ if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
+ ret_val = IXGBE_SUCCESS;
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_write_mbx_pf - Places a message in the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_number: the VF index
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+int32_t ixgbe_write_mbx_pf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t vf_number)
+{
+ int32_t ret_val;
+ uint16_t i;
+
+ DEBUGFUNC("ixgbe_write_mbx_pf");
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
+ if (ret_val)
+ goto out_no_write;
+
+ /* flush msg and acks as we are overwriting the message buffer */
+ ixgbe_check_for_msg_pf(hw, vf_number);
+ ixgbe_check_for_ack_pf(hw, vf_number);
+
+ /* copy the caller specified message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
+
+ /* Interrupt VF to tell it a message has been sent and release buffer*/
+ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
+
+ /* update stats */
+ hw->mbx.stats.msgs_tx++;
+
+out_no_write:
+ return ret_val;
+
+}
+
+/**
+ * ixgbe_read_mbx_pf - Read a message from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_number: the VF index
+ *
+ * This function copies a message from the mailbox buffer to the caller's
+ * memory buffer. The presumption is that the caller knows that there was
+ * a message due to a VF request so no polling for message is needed.
+ **/
+int32_t ixgbe_read_mbx_pf(struct ixgbe_hw *hw, uint32_t *msg, uint16_t size,
+ uint16_t vf_number)
+{
+ int32_t ret_val;
+ uint16_t i;
+
+ DEBUGFUNC("ixgbe_read_mbx_pf");
+
+ /* lock the mailbox to prevent pf/vf race condition */
+ ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
+ if (ret_val)
+ goto out_no_read;
+
+ /* copy the message to the mailbox memory buffer */
+ for (i = 0; i < size; i++)
+ msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
+
+ /* Acknowledge the message and release buffer */
+ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
+
+ /* update stats */
+ hw->mbx.stats.msgs_rx++;
+
+out_no_read:
+ return ret_val;
+}
+
+/**
+ * ixgbe_init_mbx_params_pf - set initial values for pf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for pf mailbox
+ */
+void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+ if (hw->mac.type != ixgbe_mac_82599EB)
+ return;
+
+ mbx->timeout = 0;
+ mbx->usec_delay = 0;
+
+ mbx->size = IXGBE_VFMAILBOX_SIZE;
+
+ mbx->ops.read = ixgbe_read_mbx_pf;
+ mbx->ops.write = ixgbe_write_mbx_pf;
+ mbx->ops.read_posted = ixgbe_read_posted_mbx;
+ mbx->ops.write_posted = ixgbe_write_posted_mbx;
+ mbx->ops.check_for_msg = ixgbe_check_for_msg_pf;
+ mbx->ops.check_for_ack = ixgbe_check_for_ack_pf;
+ mbx->ops.check_for_rst = ixgbe_check_for_rst_pf;
+
+ mbx->stats.msgs_tx = 0;
+ mbx->stats.msgs_rx = 0;
+ mbx->stats.reqs = 0;
+ mbx->stats.acks = 0;
+ mbx->stats.rsts = 0;
+}
+
diff --git a/sys/dev/pci/ixgbe.h b/sys/dev/pci/ixgbe.h
index c09791aa0c9..604fa15b3d9 100644
--- a/sys/dev/pci/ixgbe.h
+++ b/sys/dev/pci/ixgbe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe.h,v 1.6 2010/02/23 18:43:15 jsg Exp $ */
+/* $OpenBSD: ixgbe.h,v 1.7 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -110,7 +110,6 @@
#define PCI_COMMAND_REGISTER PCIR_COMMAND
/* Compat glue */
-#define MJUMPAGESIZE MCLBYTES
#define PCIR_BAR(_x) (0x10 + (_x) * 4)
#define roundup2(size, unit) (((size) + (unit) - 1) & ~((unit) - 1))
#define usec_delay(x) delay(x)
@@ -119,12 +118,6 @@
/* This is needed by the shared code */
struct ixgbe_hw;
-extern uint16_t ixgbe_read_pci_cfg(struct ixgbe_hw *, uint32_t);
-#define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg
-
-extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, uint32_t, uint16_t);
-#define IXGBE_WRITE_PCIE_WORD ixgbe_write_pci_cfg
-
struct ixgbe_osdep {
bus_dma_tag_t os_dmat;
bus_space_tag_t os_memt;
@@ -137,6 +130,12 @@ struct ixgbe_osdep {
struct pci_attach_args *os_pa;
};
+extern uint16_t ixgbe_read_pci_cfg(struct ixgbe_hw *, uint32_t);
+#define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg
+
+extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, uint32_t, uint16_t);
+#define IXGBE_WRITE_PCIE_WORD ixgbe_write_pci_cfg
+
#define IXGBE_WRITE_FLUSH(a) \
IXGBE_READ_REG(a, IXGBE_STATUS)
#define IXGBE_READ_REG(a, reg) \
@@ -147,7 +146,7 @@ struct ixgbe_osdep {
((struct ixgbe_osdep *)(a)->back)->os_memh, reg, value)
#define IXGBE_READ_REG_ARRAY(a, reg, offset) \
bus_space_read_4(((struct ixgbe_osdep *)(a)->back)->os_memt, \
- ((struct ixgbe_osdep *)(a)->back)->os_memh, (reg + ((offset) << 2))))
+ ((struct ixgbe_osdep *)(a)->back)->os_memh, (reg + ((offset) << 2)))
#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) \
bus_space_write_4(((struct ixgbe_osdep *)(a)->back)->os_memt, \
((struct ixgbe_osdep *)(a)->back)->os_memh, (reg + ((offset) << 2)), value)
@@ -163,8 +162,12 @@ uint32_t ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw);
int32_t ixgbe_init_ops_generic(struct ixgbe_hw *hw);
int32_t ixgbe_init_hw_generic(struct ixgbe_hw *hw);
int32_t ixgbe_start_hw_generic(struct ixgbe_hw *hw);
+int32_t ixgbe_start_hw_gen2(struct ixgbe_hw *hw);
int32_t ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw);
int32_t ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, uint32_t *pba_num);
+int32_t ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, uint8_t *pba_num,
+ uint32_t pba_num_size);
+int32_t ixgbe_read_pba_length_generic(struct ixgbe_hw *hw, uint32_t *pba_num_size);
int32_t ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, uint8_t *mac_addr);
int32_t ixgbe_get_bus_info_generic(struct ixgbe_hw *hw);
void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw);
@@ -176,6 +179,7 @@ int32_t ixgbe_led_off_generic(struct ixgbe_hw *hw, uint32_t index);
int32_t ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
int32_t ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data);
int32_t ixgbe_read_eerd_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t *data);
+int32_t ixgbe_write_eewr_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data);
int32_t ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, uint16_t offset,
uint16_t *data);
uint16_t ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
@@ -209,6 +213,9 @@ int32_t ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
int32_t ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, uint32_t index);
int32_t ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, uint32_t index);
+int32_t ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, uint8_t *san_mac_addr);
+int32_t ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, uint8_t *san_mac_addr);
+
int32_t ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq);
int32_t ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq);
int32_t ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, uint8_t *addr, uint32_t vmdq);
@@ -221,9 +228,29 @@ int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
int *link_up, int link_up_wait_to_complete);
+int32_t ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, uint16_t *wwnn_prefix,
+ uint16_t *wwpn_prefix);
+
+int32_t ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, uint16_t *bs);
+void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, int enable, int pf);
+void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, int enable, int vf);
+int32_t ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, uint16_t *device_caps);
+void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw);
+
+/* API */
void ixgbe_add_uc_addr(struct ixgbe_hw *hw, uint8_t *addr, uint32_t vmdq);
void ixgbe_set_mta(struct ixgbe_hw *hw, uint8_t *mc_addr);
+int32_t ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
+int32_t ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, uint32_t pballoc);
+int32_t ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, uint32_t pballoc);
+int32_t ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ struct ixgbe_atr_input_masks *masks,
+ uint16_t soft_id,
+ uint8_t queue);
+uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *input, uint32_t key);
+
int32_t ixgbe_init_ops_82598(struct ixgbe_hw *hw);
int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw);
@@ -247,6 +274,7 @@ int32_t ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
int *autoneg);
+/* PHY specific */
int32_t ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
int *link_up);
@@ -261,6 +289,7 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
int32_t ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
uint16_t *list_offset,
uint16_t *data_offset);
+int32_t ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
int32_t ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
uint8_t dev_addr, uint8_t *data);
int32_t ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
@@ -269,4 +298,17 @@ int32_t ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
uint8_t *eeprom_data);
int32_t ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
uint8_t eeprom_data);
+
+/* MBX */
+int32_t ixgbe_read_mbx(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+int32_t ixgbe_write_mbx(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+int32_t ixgbe_read_posted_mbx(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+int32_t ixgbe_write_posted_mbx(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+int32_t ixgbe_check_for_msg(struct ixgbe_hw *, uint16_t);
+int32_t ixgbe_check_for_ack(struct ixgbe_hw *, uint16_t);
+int32_t ixgbe_check_for_rst(struct ixgbe_hw *, uint16_t);
+void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw);
+void ixgbe_init_mbx_params_vf(struct ixgbe_hw *);
+void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
+
#endif /* _IXGBE_H_ */
diff --git a/sys/dev/pci/ixgbe_82598.c b/sys/dev/pci/ixgbe_82598.c
index 1aee2fafc62..2202d54d42a 100644
--- a/sys/dev/pci/ixgbe_82598.c
+++ b/sys/dev/pci/ixgbe_82598.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_82598.c,v 1.5 2010/02/19 18:55:12 jsg Exp $ */
+/* $OpenBSD: ixgbe_82598.c,v 1.6 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -46,6 +46,7 @@ enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw);
int32_t ixgbe_fc_enable_82598(struct ixgbe_hw *hw, int32_t packetbuf_num);
int32_t ixgbe_start_mac_link_82598(struct ixgbe_hw *hw,
int autoneg_wait_to_complete);
+int32_t ixgbe_validate_link_ready(struct ixgbe_hw *hw);
int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
int *link_up, int link_up_wait_to_complete);
@@ -59,6 +60,7 @@ int32_t ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
int autoneg_wait_to_complete);
int32_t ixgbe_reset_hw_82598(struct ixgbe_hw *hw);
int32_t ixgbe_start_hw_82598(struct ixgbe_hw *hw);
+void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw);
int32_t ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq);
int32_t ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq);
int32_t ixgbe_set_vfta_82598(struct ixgbe_hw *hw, uint32_t vlan,
@@ -72,7 +74,6 @@ uint32_t ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
int32_t 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);
-int32_t ixgbe_validate_link_ready(struct ixgbe_hw *hw);
/**
* ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
@@ -160,6 +161,7 @@ int32_t ixgbe_init_ops_82598(struct ixgbe_hw *hw)
/* MAC */
mac->ops.start_hw = &ixgbe_start_hw_82598;
+ mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_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 =
@@ -180,6 +182,7 @@ int32_t ixgbe_init_ops_82598(struct ixgbe_hw *hw)
mac->mcft_size = 128;
mac->vft_size = 128;
mac->num_rar_entries = 16;
+ mac->rx_pb_size = 512;
mac->max_tx_queues = 32;
mac->max_rx_queues = 64;
mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
@@ -190,6 +193,7 @@ int32_t 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.flap_tx_laser = NULL;
mac->ops.get_link_capabilities =
&ixgbe_get_link_capabilities_82598;
@@ -279,17 +283,17 @@ int32_t ixgbe_start_hw_82598(struct ixgbe_hw *hw)
/* Disable relaxed ordering */
for (i = 0; ((i < hw->mac.max_tx_queues) &&
- (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
+ (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++) {
+ (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_DCA_RXCTRL_DESC_HSRO_EN);
IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
}
@@ -370,11 +374,14 @@ enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
enum ixgbe_media_type media_type;
/* Detect if there is a copper PHY attached. */
- if (hw->phy.type == ixgbe_phy_cu_unknown ||
- hw->phy.type == ixgbe_phy_tn ||
- hw->phy.type == ixgbe_phy_aq) {
+ switch (hw->phy.type) {
+ case ixgbe_phy_cu_unknown:
+ case ixgbe_phy_tn:
+ case ixgbe_phy_aq:
media_type = ixgbe_media_type_copper;
goto out;
+ default:
+ break;
}
/* Media type for I82598 is based on device ID */
@@ -421,24 +428,33 @@ int32_t ixgbe_fc_enable_82598(struct ixgbe_hw *hw, int32_t packetbuf_num)
uint32_t fctrl_reg;
uint32_t rmcs_reg;
uint32_t reg;
+ uint32_t rx_pba_size;
uint32_t link_speed = 0;
int link_up;
/*
- * On 82598 backplane having FC on causes resets while doing
- * KX, so turn off here.
+ * On 82598 having Rx FC on causes resets while doing 1G
+ * so if it's on turn it off once we know link_speed. For
+ * more details see 82598 Specification update.
*/
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;
+ if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) {
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_full:
+ hw->fc.requested_mode = ixgbe_fc_tx_pause;
+ break;
+ case ixgbe_fc_rx_pause:
+ hw->fc.requested_mode = ixgbe_fc_none;
+ break;
+ default:
+ /* no change */
+ break;
+ }
}
/* Negotiate the fc mode to use */
ret_val = ixgbe_fc_autoneg(hw);
- if (ret_val)
+ if (ret_val == IXGBE_ERR_FLOW_CONTROL)
goto out;
/* Disable any previous flow control settings */
@@ -460,7 +476,8 @@ int32_t ixgbe_fc_enable_82598(struct ixgbe_hw *hw, int32_t packetbuf_num)
*/
switch (hw->fc.current_mode) {
case ixgbe_fc_none:
- /* Flow control is disabled by software override or autoneg.
+ /*
+ * Flow control is disabled by software override or autoneg.
* The code below will actually disable it in the HW.
*/
break;
@@ -501,16 +518,19 @@ int32_t ixgbe_fc_enable_82598(struct ixgbe_hw *hw, int32_t packetbuf_num)
/* Set up and enable Rx high/low water mark thresholds, enable XON. */
if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
- if (hw->fc.send_xon) {
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
- (hw->fc.low_water | IXGBE_FCRTL_XONE));
- } else {
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
- hw->fc.low_water);
- }
+ rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
+ rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
+
+ reg = (rx_pba_size - hw->fc.low_water) << 6;
+ if (hw->fc.send_xon)
+ reg |= IXGBE_FCRTL_XONE;
+
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
+
+ reg = (rx_pba_size - hw->fc.high_water) << 6;
+ reg |= IXGBE_FCRTH_FCEN;
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num),
- (hw->fc.high_water | IXGBE_FCRTH_FCEN));
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
}
/* Configure pause time (2 TCs per register) */
@@ -574,6 +594,41 @@ int32_t ixgbe_start_mac_link_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.
+ **/
+int32_t ixgbe_validate_link_ready(struct ixgbe_hw *hw)
+{
+ uint32_t timeout;
+ uint16_t 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;
+}
+
+/**
* ixgbe_check_mac_link_82598 - Get link/speed status
* @hw: pointer to hardware structure
* @speed: pointer to link speed
@@ -618,8 +673,7 @@ int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
&adapt_comp_reg);
}
} else {
- if ((link_reg & 1) &&
- ((adapt_comp_reg & 1) == 0))
+ if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0))
*link_up = TRUE;
else
*link_up = FALSE;
@@ -654,7 +708,7 @@ int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
*speed = IXGBE_LINK_SPEED_1GB_FULL;
if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == TRUE) &&
- (ixgbe_validate_link_ready(hw) != IXGBE_SUCCESS))
+ (ixgbe_validate_link_ready(hw) != IXGBE_SUCCESS))
*link_up = FALSE;
/* if link is down, zero out the current_mode */
@@ -662,7 +716,6 @@ int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
hw->fc.current_mode = ixgbe_fc_none;
hw->fc.fc_was_autonegged = FALSE;
}
-
out:
return IXGBE_SUCCESS;
}
@@ -718,6 +771,7 @@ int32_t ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
return status;
}
+
/**
* ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field
* @hw: pointer to hardware structure
@@ -816,12 +870,9 @@ no_phy_reset:
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
* access and verify no pending requests before reset
*/
- status = ixgbe_disable_pcie_master(hw);
- if (status != IXGBE_SUCCESS) {
- status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
- DEBUGOUT("PCI-E Master disable polling has failed.\n");
- }
+ ixgbe_disable_pcie_master(hw);
+mac_reset_top:
/*
* Issue global reset to the MAC. This needs to be a SW reset.
* If link reset is used, it might reset the MAC when mng is using it
@@ -842,6 +893,19 @@ no_phy_reset:
DEBUGOUT("Reset polling failed to complete.\n");
}
+ /*
+ * Double resets are required for recovery from certain error
+ * conditions. Between resets, it is necessary to stall to allow time
+ * for any pending HW events to complete. We use 1usec since that is
+ * what is needed for ixgbe_disable_pcie_master(). The second reset
+ * then clears out any effects of those events.
+ */
+ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+ hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ usec_delay(1);
+ goto mac_reset_top;
+ }
+
msec_delay(50);
gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
@@ -857,8 +921,9 @@ no_phy_reset:
if (hw->mac.orig_link_settings_stored == FALSE) {
hw->mac.orig_autoc = autoc;
hw->mac.orig_link_settings_stored = TRUE;
- } else if (autoc != hw->mac.orig_autoc)
+ } else if (autoc != hw->mac.orig_autoc) {
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
+ }
/* Store the permanent mac address */
hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
@@ -869,11 +934,10 @@ no_phy_reset:
*/
hw->mac.ops.init_rx_addrs(hw);
-
-
reset_hw_out:
if (phy_status != IXGBE_SUCCESS)
status = phy_status;
+
return status;
}
@@ -886,6 +950,13 @@ reset_hw_out:
int32_t ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq)
{
uint32_t rar_high;
+ uint32_t rar_entries = hw->mac.num_rar_entries;
+
+ /* Make sure we are using a valid rar index range */
+ if (rar >= rar_entries) {
+ DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
rar_high &= ~IXGBE_RAH_VIND_MASK;
@@ -907,14 +978,16 @@ int32_t ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq)
UNREFERENCED_PARAMETER(vmdq);
- if (rar < rar_entries) {
- rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
- if (rar_high & IXGBE_RAH_VIND_MASK) {
- rar_high &= ~IXGBE_RAH_VIND_MASK;
- IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
- }
- } else {
+ /* Make sure we are using a valid rar index range */
+ if (rar >= rar_entries) {
DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
+
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+ if (rar_high & IXGBE_RAH_VIND_MASK) {
+ rar_high &= ~IXGBE_RAH_VIND_MASK;
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
}
return IXGBE_SUCCESS;
@@ -1112,8 +1185,10 @@ uint32_t ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
/* Copper PHY must be checked before AUTOC LMS to determine correct
* physical layer because 10GBase-T PHYs use LMS = KX4/KX */
- if (hw->phy.type == ixgbe_phy_tn ||
- hw->phy.type == ixgbe_phy_cu_unknown) {
+ switch (hw->phy.type) {
+ case ixgbe_phy_tn:
+ case ixgbe_phy_aq:
+ case ixgbe_phy_cu_unknown:
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
@@ -1123,6 +1198,8 @@ uint32_t ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
goto out;
+ default:
+ break;
}
switch (autoc & IXGBE_AUTOC_LMS_MASK) {
@@ -1223,36 +1300,31 @@ void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw)
}
/**
- * ixgbe_validate_link_ready - Function looks for phy link
+ * ixgbe_enable_relaxed_ordering_82598 - enable relaxed ordering
* @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.
**/
-int32_t ixgbe_validate_link_ready(struct ixgbe_hw *hw)
+void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw)
{
- uint32_t timeout;
- uint16_t an_reg;
-
- if (hw->device_id != IXGBE_DEV_ID_82598AT2)
- return IXGBE_SUCCESS;
+ uint32_t regval;
+ uint32_t i;
- 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);
+ DEBUGFUNC("ixgbe_enable_relaxed_ordering_82598");
- if ((an_reg & IXGBE_MII_AUTONEG_COMPLETE) &&
- (an_reg & IXGBE_MII_AUTONEG_LINK_UP))
- break;
-
- msec_delay(100);
+ /* Enable 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);
}
- if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) {
- DEBUGOUT("Link was indicated but link is down\n");
- return IXGBE_ERR_LINK_SETUP;
+ 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);
}
- return IXGBE_SUCCESS;
}
diff --git a/sys/dev/pci/ixgbe_82599.c b/sys/dev/pci/ixgbe_82599.c
index 56dc114be3a..f6c90d87a04 100644
--- a/sys/dev/pci/ixgbe_82599.c
+++ b/sys/dev/pci/ixgbe_82599.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_82599.c,v 1.2 2010/02/25 10:56:07 jsg Exp $ */
+/* $OpenBSD: ixgbe_82599.c,v 1.3 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -42,6 +42,9 @@ int32_t ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
int *autoneg);
enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw);
+void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
ixgbe_link_speed speed, int autoneg,
int autoneg_wait_to_complete);
@@ -68,50 +71,16 @@ int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
int32_t ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw);
uint32_t ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
int32_t ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, uint32_t regval);
-int32_t ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, uint16_t *device_caps);
int32_t ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
+int ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
-int32_t ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
-int32_t ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, uint32_t pballoc);
-int32_t ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, uint32_t pballoc);
+uint32_t ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
+ union ixgbe_atr_hash_dword common);
int32_t ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
- struct ixgbe_atr_input *input,
+ union ixgbe_atr_hash_dword input,
+ union ixgbe_atr_hash_dword common,
uint8_t queue);
-int32_t ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- struct ixgbe_atr_input *input,
- uint16_t soft_id,
- uint8_t queue);
-uint16_t ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *input, uint32_t key);
-int32_t ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, uint16_t vlan_id);
-int32_t ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, uint32_t src_addr);
-int32_t ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, uint32_t dst_addr);
-int32_t ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, uint32_t src_addr_1,
- uint32_t src_addr_2, uint32_t src_addr_3,
- uint32_t src_addr_4);
-int32_t ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, uint32_t dst_addr_1,
- uint32_t dst_addr_2, uint32_t dst_addr_3,
- uint32_t dst_addr_4);
-int32_t ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, uint16_t src_port);
-int32_t ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, uint16_t dst_port);
-int32_t ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, uint16_t flex_byte);
-int32_t ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, uint8_t vm_pool);
-int32_t ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, uint8_t l4type);
-int32_t ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, uint16_t *vlan_id);
-int32_t ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, uint32_t *src_addr);
-int32_t ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, uint32_t *dst_addr);
-int32_t ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input, uint32_t *src_addr_1,
- uint32_t *src_addr_2, uint32_t *src_addr_3,
- uint32_t *src_addr_4);
-int32_t ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, uint32_t *dst_addr_1,
- uint32_t *dst_addr_2, uint32_t *dst_addr_3,
- uint32_t *dst_addr_4);
-int32_t ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, uint16_t *src_port);
-int32_t ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, uint16_t *dst_port);
-int32_t ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input,
- uint16_t *flex_byte);
-int32_t ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, uint8_t *vm_pool);
-int32_t ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, uint8_t *l4type);
-
+uint32_t ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks);
void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
{
@@ -119,16 +88,32 @@ void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
DEBUGFUNC("ixgbe_init_mac_link_ops_82599");
+ /* enable the laser control functions for SFP+ fiber */
+ if (mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) {
+ mac->ops.disable_tx_laser =
+ &ixgbe_disable_tx_laser_multispeed_fiber;
+ mac->ops.enable_tx_laser =
+ &ixgbe_enable_tx_laser_multispeed_fiber;
+ mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;
+
+ } else {
+ mac->ops.disable_tx_laser = NULL;
+ mac->ops.enable_tx_laser = NULL;
+ mac->ops.flap_tx_laser = NULL;
+ }
+
if (hw->phy.multispeed_fiber) {
/* Set up dual speed SFP+ support */
mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
} else {
- if ((ixgbe_get_media_type_82599(hw) == ixgbe_media_type_backplane) &&
+ if ((ixgbe_hw0(hw, get_media_type) == ixgbe_media_type_backplane) &&
(hw->phy.smart_speed == ixgbe_smart_speed_auto ||
- hw->phy.smart_speed == ixgbe_smart_speed_on))
+ hw->phy.smart_speed == ixgbe_smart_speed_on) &&
+ !ixgbe_verify_lesm_fw_enabled_82599(hw)) {
mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed;
- else
+ } else {
mac->ops.setup_link = &ixgbe_setup_mac_link_82599;
+ }
}
}
@@ -188,6 +173,8 @@ init_phy_ops_out:
int32_t ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
{
int32_t ret_val = IXGBE_SUCCESS;
+ uint32_t reg_anlp1 = 0;
+ uint32_t i = 0;
uint16_t list_offset, data_offset, data_value;
DEBUGFUNC("ixgbe_setup_sfp_modules_82599");
@@ -215,14 +202,34 @@ int32_t ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
IXGBE_WRITE_FLUSH(hw);
hw->eeprom.ops.read(hw, ++data_offset, &data_value);
}
- /* Now restart DSP by setting Restart_AN */
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
- (IXGBE_READ_REG(hw, IXGBE_AUTOC) | IXGBE_AUTOC_AN_RESTART));
/* Release the semaphore */
ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
/* Delay obtaining semaphore again to allow FW access */
msec_delay(hw->eeprom.semaphore_delay);
+
+ /* Now restart DSP by setting Restart_AN and clearing LMS */
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw,
+ IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) |
+ IXGBE_AUTOC_AN_RESTART));
+
+ /* Wait for AN to leave state 0 */
+ for (i = 0; i < 10; i++) {
+ msec_delay(4);
+ reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+ if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)
+ break;
+ }
+ if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) {
+ DEBUGOUT("sfp module setup not complete\n");
+ ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
+ goto setup_sfp_out;
+ }
+
+ /* Restart DSP by setting Restart_AN and return to SFI mode */
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
+ IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL |
+ IXGBE_AUTOC_AN_RESTART));
}
setup_sfp_out:
@@ -254,6 +261,7 @@ int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw)
/* MAC */
mac->ops.reset_hw = &ixgbe_reset_hw_82599;
+ mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_gen2;
mac->ops.get_media_type = &ixgbe_get_media_type_82599;
mac->ops.get_supported_physical_layer =
&ixgbe_get_supported_physical_layer_82599;
@@ -261,7 +269,14 @@ int32_t 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_device_caps = &ixgbe_get_device_caps_82599;
+
+ mac->ops.get_device_caps = &ixgbe_get_device_caps_generic;
+#if 0
+ 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_wwn_prefix = &ixgbe_get_wwn_prefix_generic;
+ mac->ops.get_fcoe_boot_status = &ixgbe_get_fcoe_boot_status_generic;
+#endif
/* RAR, Multicast, VLAN */
mac->ops.set_vmdq = &ixgbe_set_vmdq_generic;
@@ -272,6 +287,10 @@ int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw)
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;
+#if 0
+ mac->ops.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing;
+ mac->ops.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing;
+#endif
/* Link */
mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599;
@@ -281,10 +300,12 @@ int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw)
mac->mcft_size = 128;
mac->vft_size = 128;
mac->num_rar_entries = 128;
+ mac->rx_pb_size = 512;
mac->max_tx_queues = 128;
mac->max_rx_queues = 128;
mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
+ hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
return ret_val;
}
@@ -306,6 +327,14 @@ int32_t ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
DEBUGFUNC("ixgbe_get_link_capabilities_82599");
+ /* Check if 1G SFP module. */
+ if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1) {
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ *negotiation = TRUE;
+ goto out;
+ }
+
/*
* Determine link capabilities based on the stored value of AUTOC,
* which represents EEPROM defaults. If AUTOC value has not
@@ -394,28 +423,35 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
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 ||
- hw->phy.type == ixgbe_phy_aq) {
+ switch (hw->phy.type) {
+ case ixgbe_phy_cu_unknown:
+ case ixgbe_phy_tn:
+ case ixgbe_phy_aq:
media_type = ixgbe_media_type_copper;
goto out;
+ default:
+ break;
}
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_BACKPLANE_FCOE:
case IXGBE_DEV_ID_82599_XAUI_LOM:
/* Default device ID is mezzanine card KX/KX4 */
media_type = ixgbe_media_type_backplane;
break;
case IXGBE_DEV_ID_82599_SFP:
- case IXGBE_DEV_ID_82599_SFP_EM:
+ case IXGBE_DEV_ID_82599_SFP_FCOE:
media_type = ixgbe_media_type_fiber;
break;
case IXGBE_DEV_ID_82599_CX4:
media_type = ixgbe_media_type_cx4;
break;
+ case IXGBE_DEV_ID_82599_T3_LOM:
+ media_type = ixgbe_media_type_copper;
+ break;
default:
media_type = ixgbe_media_type_unknown;
break;
@@ -452,8 +488,8 @@ int32_t ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
IXGBE_AUTOC_LMS_KX4_KX_KR ||
(autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
- IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN
- || (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
+ IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
+ (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
links_reg = 0; /* Just in case Autoneg time = 0 */
for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
@@ -476,6 +512,67 @@ int32_t ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
}
/**
+ * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
+ * @hw: pointer to hardware structure
+ *
+ * The base drivers may require better control over SFP+ module
+ * PHY states. This includes selectively shutting down the Tx
+ * laser on the PHY, effectively halting physical link.
+ **/
+void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+{
+ uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+ /* Disable tx laser; allow 100us to go dark per spec */
+ esdp_reg |= IXGBE_ESDP_SDP3;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+ IXGBE_WRITE_FLUSH(hw);
+ usec_delay(100);
+}
+
+/**
+ * ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
+ * @hw: pointer to hardware structure
+ *
+ * The base drivers may require better control over SFP+ module
+ * PHY states. This includes selectively turning on the Tx
+ * laser on the PHY, effectively starting physical link.
+ **/
+void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+{
+ uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+ /* Enable tx laser; allow 100ms to light up */
+ esdp_reg &= ~IXGBE_ESDP_SDP3;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+ IXGBE_WRITE_FLUSH(hw);
+ msec_delay(100);
+}
+
+/**
+ * ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
+ * @hw: pointer to hardware structure
+ *
+ * When the driver changes the link speeds that it can support,
+ * it sets autotry_restart to TRUE to indicate that we need to
+ * initiate a new autotry session with the link partner. To do
+ * so, we set the speed then disable and re-enable the tx laser, to
+ * alert the link partner that it also needs to restart autotry on its
+ * end. This is consistent with TRUE clause 37 autoneg, which also
+ * involves a loss of signal.
+ **/
+void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+{
+ DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber");
+
+ if (hw->mac.autotry_restart) {
+ ixgbe_disable_tx_laser_multispeed_fiber(hw);
+ ixgbe_enable_tx_laser_multispeed_fiber(hw);
+ hw->mac.autotry_restart = FALSE;
+ }
+}
+
+/**
* ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
* @hw: pointer to hardware structure
* @speed: new link speed
@@ -500,23 +597,13 @@ int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
/* Mask off requested but non-supported speeds */
- status = ixgbe_get_link_capabilities_82599(hw, &link_speed, &negotiation);
+ status = ixgbe_hw(hw, get_link_capabilities, &link_speed, &negotiation);
if (status != IXGBE_SUCCESS)
return status;
speed &= link_speed;
/*
- * When the driver changes the link speeds that it can support,
- * it sets autotry_restart to TRUE to indicate that we need to
- * initiate a new autotry session with the link partner. To do
- * so, we set the speed then disable and re-enable the tx laser, to
- * alert the link partner that it also needs to restart autotry on its
- * end. This is consistent with TRUE clause 37 autoneg, which also
- * involves a loss of signal.
- */
-
- /*
* Try each speed one by one, highest priority first. We do this in
* software because 10gb fiber doesn't support speed autonegotiation.
*/
@@ -525,7 +612,7 @@ int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
/* If we already have link at this speed, just jump out */
- status = ixgbe_check_mac_link_generic(hw, &link_speed, &link_up, FALSE);
+ status = ixgbe_hw(hw, check_link, &link_speed, &link_up, FALSE);
if (status != IXGBE_SUCCESS)
return status;
@@ -535,30 +622,20 @@ int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
/* Set the module link speed */
esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+ IXGBE_WRITE_FLUSH(hw);
/* Allow module to change analog characteristics (1G->10G) */
msec_delay(40);
- status = ixgbe_setup_mac_link_82599(
- hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg,
- autoneg_wait_to_complete);
+ status = ixgbe_setup_mac_link_82599(hw,
+ IXGBE_LINK_SPEED_10GB_FULL,
+ autoneg,
+ autoneg_wait_to_complete);
if (status != IXGBE_SUCCESS)
return status;
/* Flap the tx laser if it has not already been done */
- if (hw->mac.autotry_restart) {
- /* Disable tx laser; allow 100us to go dark per spec */
- esdp_reg |= IXGBE_ESDP_SDP3;
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- usec_delay(100);
-
- /* Enable tx laser; allow 2ms to light up per spec */
- esdp_reg &= ~IXGBE_ESDP_SDP3;
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- msec_delay(2);
-
- hw->mac.autotry_restart = FALSE;
- }
+ ixgbe_hw(hw, flap_tx_laser);
/*
* Wait for the controller to acquire link. Per IEEE 802.3ap,
@@ -570,7 +647,7 @@ int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
msec_delay(100);
/* If we have link, just jump out */
- status = ixgbe_check_mac_link_generic(hw, &link_speed,
+ status = ixgbe_hw(hw, check_link, &link_speed,
&link_up, FALSE);
if (status != IXGBE_SUCCESS)
return status;
@@ -586,7 +663,7 @@ int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
/* If we already have link at this speed, just jump out */
- status = ixgbe_check_mac_link_generic(hw, &link_speed, &link_up, FALSE);
+ status = ixgbe_hw(hw, check_link, &link_speed, &link_up, FALSE);
if (status != IXGBE_SUCCESS)
return status;
@@ -597,36 +674,26 @@ int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
esdp_reg &= ~IXGBE_ESDP_SDP5;
esdp_reg |= IXGBE_ESDP_SDP5_DIR;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+ IXGBE_WRITE_FLUSH(hw);
/* Allow module to change analog characteristics (10G->1G) */
msec_delay(40);
- status = ixgbe_setup_mac_link_82599(
- hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg,
- autoneg_wait_to_complete);
+ status = ixgbe_setup_mac_link_82599(hw,
+ IXGBE_LINK_SPEED_1GB_FULL,
+ autoneg,
+ autoneg_wait_to_complete);
if (status != IXGBE_SUCCESS)
return status;
/* Flap the tx laser if it has not already been done */
- if (hw->mac.autotry_restart) {
- /* Disable tx laser; allow 100us to go dark per spec */
- esdp_reg |= IXGBE_ESDP_SDP3;
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- usec_delay(100);
-
- /* Enable tx laser; allow 2ms to light up per spec */
- esdp_reg &= ~IXGBE_ESDP_SDP3;
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
- msec_delay(2);
-
- hw->mac.autotry_restart = FALSE;
- }
+ ixgbe_hw(hw, flap_tx_laser);
/* Wait for the link partner to also set speed */
msec_delay(100);
/* If we have link, just jump out */
- status = ixgbe_check_mac_link_generic(hw, &link_speed, &link_up, FALSE);
+ status = ixgbe_hw(hw, check_link, &link_speed, &link_up, FALSE);
if (status != IXGBE_SUCCESS)
return status;
@@ -714,7 +781,7 @@ int32_t ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
msec_delay(100);
/* If we have link, just jump out */
- status = ixgbe_check_mac_link_generic(hw, &link_speed, &link_up,
+ status = ixgbe_hw(hw, check_link, &link_speed, &link_up,
FALSE);
if (status != IXGBE_SUCCESS)
goto out;
@@ -749,7 +816,7 @@ int32_t ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
msec_delay(100);
/* If we have link, just jump out */
- status = ixgbe_check_mac_link_generic(hw, &link_speed, &link_up, FALSE);
+ status = ixgbe_hw(hw, check_link, &link_speed, &link_up, FALSE);
if (status != IXGBE_SUCCESS)
goto out;
@@ -763,6 +830,9 @@ int32_t ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
autoneg_wait_to_complete);
out:
+ if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
+ DEBUGOUT("Smartspeed has downgraded the link speed "
+ "from the maximum advertised\n");
return status;
}
@@ -794,7 +864,7 @@ int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
DEBUGFUNC("ixgbe_setup_mac_link_82599");
/* Check to see if speed passed in is supported. */
- status = ixgbe_get_link_capabilities_82599(hw, &link_capabilities, &autoneg);
+ status = ixgbe_hw(hw, get_link_capabilities, &link_capabilities, &autoneg);
if (status != IXGBE_SUCCESS)
goto out;
@@ -812,8 +882,8 @@ int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
orig_autoc = autoc;
if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
- link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
- link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
+ link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
+ link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
/* Set KX4/KX/KR support according to speed requested */
autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
if (speed & IXGBE_LINK_SPEED_10GB_FULL)
@@ -834,7 +904,7 @@ int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
autoc |= IXGBE_AUTOC_LMS_10G_SERIAL;
}
} else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) &&
- (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
+ (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
/* Switch from 10G SFI to 1G SFI if requested */
if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
(pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
@@ -847,7 +917,6 @@ int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
}
if (autoc != start_autoc) {
-
/* Restart link */
autoc |= IXGBE_AUTOC_AN_RESTART;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
@@ -918,7 +987,7 @@ int32_t ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
{
int32_t status = IXGBE_SUCCESS;
- uint32_t ctrl, ctrl_ext;
+ uint32_t ctrl;
uint32_t i;
uint32_t autoc;
uint32_t autoc2;
@@ -953,12 +1022,9 @@ int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
* access and verify no pending requests before reset
*/
- status = ixgbe_disable_pcie_master(hw);
- if (status != IXGBE_SUCCESS) {
- status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
- DEBUGOUT("PCI-E Master disable polling has failed.\n");
- }
+ ixgbe_disable_pcie_master(hw);
+mac_reset_top:
/*
* Issue global reset to the MAC. This needs to be a SW reset.
* If link reset is used, it might reset the MAC when mng is using it
@@ -978,10 +1044,19 @@ int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
status = IXGBE_ERR_RESET_FAILED;
DEBUGOUT("Reset polling failed to complete.\n");
}
- /* Clear PF Reset Done bit so PF/VF Mail Ops can work */
- ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
- ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
- IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
+
+ /*
+ * Double resets are required for recovery from certain error
+ * conditions. Between resets, it is necessary to stall to allow time
+ * for any pending HW events to complete. We use 1usec since that is
+ * what is needed for ixgbe_disable_pcie_master(). The second reset
+ * then clears out any effects of those events.
+ */
+ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+ hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ usec_delay(1);
+ goto mac_reset_top;
+ }
msec_delay(50);
@@ -1010,7 +1085,7 @@ int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
}
}
- /* Store the permanent mac address */
+ /* Store the permanent mac address */
hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
/*
@@ -1021,6 +1096,23 @@ int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
hw->mac.num_rar_entries = 128;
hw->mac.ops.init_rx_addrs(hw);
+#if 0
+ /* Store the permanent SAN mac address */
+ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
+
+ /* Add the SAN MAC address to the RAR only if it's a valid address */
+ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+ hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
+ hw->mac.san_addr, 0, IXGBE_RAH_AV);
+
+ /* Reserve the last RAR for the SAN MAC address */
+ 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);
+#endif
reset_hw_out:
return status;
}
@@ -1162,10 +1254,8 @@ int32_t ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, uint32_t pballoc)
/* Prime the keys for hashing */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
- htonl(IXGBE_ATR_BUCKET_HASH_KEY));
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
- htonl(IXGBE_ATR_SIGNATURE_HASH_KEY));
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
/*
* Poll init-done after we write the register. Estimated times:
@@ -1212,7 +1302,6 @@ int32_t ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, uint32_t pballoc)
* must be reduced. The new value is the current size minus
* flow director memory usage size.
*/
-
pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
(IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
@@ -1229,6 +1318,9 @@ int32_t ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, uint32_t pballoc)
/* Send interrupt when 64 filters are left */
fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
+ /* Initialize the drop queue to Rx queue 127 */
+ fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
+
switch (pballoc) {
case IXGBE_FDIR_PBALLOC_64K:
/* 2k - 1 perfect filters */
@@ -1255,10 +1347,8 @@ int32_t ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, uint32_t pballoc)
fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
/* Prime the keys for hashing */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
- htonl(IXGBE_ATR_BUCKET_HASH_KEY));
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
- htonl(IXGBE_ATR_SIGNATURE_HASH_KEY));
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
/*
* Poll init-done after we write the register. Estimated times:
@@ -1291,13 +1381,13 @@ int32_t ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, uint32_t pballoc)
return IXGBE_SUCCESS;
}
-
/**
* ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
* @stream: input bitstream to compute the hash on
* @key: 32-bit hash key
**/
-uint16_t ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, uint32_t key)
+uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
+ uint32_t key)
{
/*
* The algorithm is as follows:
@@ -1317,524 +1407,158 @@ uint16_t ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, uint32_
* To simplify for programming, the algorithm is implemented
* in software this way:
*
- * Key[31:0], Stream[335:0]
+ * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
+ *
+ * for (i = 0; i < 352; i+=32)
+ * hi_hash_dword[31:0] ^= Stream[(i+31):i];
+ *
+ * lo_hash_dword[15:0] ^= Stream[15:0];
+ * lo_hash_dword[15:0] ^= hi_hash_dword[31:16];
+ * lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
*
- * tmp_key[11 * 32 - 1:0] = 11{Key[31:0] = key concatenated 11 times
- * int_key[350:0] = tmp_key[351:1]
- * int_stream[365:0] = Stream[14:0] | Stream[335:0] | Stream[335:321]
+ * hi_hash_dword[31:0] ^= Stream[351:320];
*
- * hash[15:0] = 0;
- * for (i = 0; i < 351; i++) {
- * if (int_key[i])
- * hash ^= int_stream[(i + 15):i];
+ * if(key[0])
+ * hash[15:0] ^= Stream[15:0];
+ *
+ * for (i = 0; i < 16; i++) {
+ * if (key[i])
+ * hash[15:0] ^= lo_hash_dword[(i+15):i];
+ * if (key[i + 16])
+ * hash[15:0] ^= hi_hash_dword[(i+15):i];
* }
+ *
*/
+ __be32 common_hash_dword = 0;
+ uint32_t hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+ uint32_t hash_result = 0;
+ uint8_t i;
- union {
- uint64_t fill[6];
- uint32_t key[11];
- uint8_t key_stream[44];
- } tmp_key;
+ /* record the flow_vm_vlan bits as they are a key part to the hash */
+ flow_vm_vlan = ntohl(atr_input->dword_stream[0]);
- uint8_t *stream = (uint8_t *)atr_input;
- uint8_t int_key[44]; /* upper-most bit unused */
- uint8_t hash_str[46]; /* upper-most 2 bits unused */
- uint16_t hash_result = 0;
- int i, j, k, h;
+ /* generate common hash dword */
+ for (i = 10; i; i -= 2)
+ common_hash_dword ^= atr_input->dword_stream[i] ^
+ atr_input->dword_stream[i - 1];
- DEBUGFUNC("ixgbe_atr_compute_hash_82599");
+ hi_hash_dword = ntohl(common_hash_dword);
- /*
- * Initialize the fill member to prevent warnings
- * on some compilers
- */
- tmp_key.fill[0] = 0;
+ /* low dword is word swapped version of common */
+ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
- /* First load the temporary key stream */
- for (i = 0; i < 6; i++) {
- uint64_t fillkey = ((uint64_t)key << 32) | key;
- tmp_key.fill[i] = fillkey;
- }
+ /* apply flow ID/VM pool/VLAN ID bits to hash words */
+ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
- /*
- * Set the interim key for the hashing. Bit 352 is unused, so we must
- * shift and compensate when building the key.
- */
-
- int_key[0] = tmp_key.key_stream[0] >> 1;
- for (i = 1, j = 0; i < 44; i++) {
- unsigned int this_key = tmp_key.key_stream[j] << 7;
- j++;
- int_key[i] = (uint8_t)(this_key | (tmp_key.key_stream[j] >> 1));
- }
+ /* Process bits 0 and 16 */
+ if (key & 0x0001) hash_result ^= lo_hash_dword;
+ if (key & 0x00010000) hash_result ^= hi_hash_dword;
/*
- * Set the interim bit string for the hashing. Bits 368 and 367 are
- * unused, so shift and compensate when building the string.
+ * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+ * delay this because bit 0 of the stream should not be processed
+ * so we do not add the vlan until after bit 0 was processed
*/
- hash_str[0] = (stream[40] & 0x7f) >> 1;
- for (i = 1, j = 40; i < 46; i++) {
- unsigned int this_str = stream[j] << 7;
- j++;
- if (j > 41)
- j = 0;
- hash_str[i] = (uint8_t)(this_str | (stream[j] >> 1));
- }
-
- /*
- * Now compute the hash. i is the index into hash_str, j is into our
- * key stream, k is counting the number of bits, and h interates within
- * each byte.
- */
- for (i = 45, j = 43, k = 0; k < 351 && i >= 2 && j >= 0; i--, j--) {
- for (h = 0; h < 8 && k < 351; h++, k++) {
- if (int_key[j] & (1 << h)) {
- /*
- * Key bit is set, XOR in the current 16-bit
- * string. Example of processing:
- * h = 0,
- * tmp = (hash_str[i - 2] & 0 << 16) |
- * (hash_str[i - 1] & 0xff << 8) |
- * (hash_str[i] & 0xff >> 0)
- * So tmp = hash_str[15 + k:k], since the
- * i + 2 clause rolls off the 16-bit value
- * h = 7,
- * tmp = (hash_str[i - 2] & 0x7f << 9) |
- * (hash_str[i - 1] & 0xff << 1) |
- * (hash_str[i] & 0x80 >> 7)
- */
- int tmp = (hash_str[i] >> h);
- tmp |= (hash_str[i - 1] << (8 - h));
- tmp |= (int)(hash_str[i - 2] & ((1 << h) - 1))
- << (16 - h);
- hash_result ^= (uint16_t)tmp;
- }
- }
- }
-
- return hash_result;
-}
-
-/**
- * ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream
- * @input: input stream to modify
- * @vlan: the VLAN id to load
- **/
-int32_t ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, uint16_t 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;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address
- * @input: input stream to modify
- * @src_addr: the IP address to load
- **/
-int32_t ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, uint32_t 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;
- input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] =
- (src_addr >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET] = src_addr & 0xff;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address
- * @input: input stream to modify
- * @dst_addr: the IP address to load
- **/
-int32_t ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, uint32_t 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;
- input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] =
- (dst_addr >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET] = dst_addr & 0xff;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address
- * @input: input stream to modify
- * @src_addr_1: the first 4 bytes of the IP address to load
- * @src_addr_2: the second 4 bytes of the IP address to load
- * @src_addr_3: the third 4 bytes of the IP address to load
- * @src_addr_4: the fourth 4 bytes of the IP address to load
- **/
-int32_t ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
- uint32_t src_addr_1, uint32_t src_addr_2,
- uint32_t src_addr_3, uint32_t 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;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] =
- (src_addr_4 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24;
-
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] =
- (src_addr_3 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] =
- (src_addr_3 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24;
-
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] =
- (src_addr_2 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] =
- (src_addr_2 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24;
-
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] =
- (src_addr_1 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] =
- (src_addr_1 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address
- * @input: input stream to modify
- * @dst_addr_1: the first 4 bytes of the IP address to load
- * @dst_addr_2: the second 4 bytes of the IP address to load
- * @dst_addr_3: the third 4 bytes of the IP address to load
- * @dst_addr_4: the fourth 4 bytes of the IP address to load
- **/
-int32_t ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
- uint32_t dst_addr_1, uint32_t dst_addr_2,
- uint32_t dst_addr_3, uint32_t 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;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] =
- (dst_addr_4 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24;
-
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] =
- (dst_addr_3 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] =
- (dst_addr_3 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24;
-
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] =
- (dst_addr_2 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] =
- (dst_addr_2 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24;
-
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] =
- (dst_addr_1 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] =
- (dst_addr_1 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_src_port_82599 - Sets the source port
- * @input: input stream to modify
- * @src_port: the source port to load
- **/
-int32_t ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, uint16_t 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;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_dst_port_82599 - Sets the destination port
- * @input: input stream to modify
- * @dst_port: the destination port to load
- **/
-int32_t ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, uint16_t 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;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_flex_byte_82599 - Sets the flexible bytes
- * @input: input stream to modify
- * @flex_bytes: the flexible bytes to load
- **/
-int32_t ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, uint16_t 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;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool
- * @input: input stream to modify
- * @vm_pool: the Virtual Machine pool to load
- **/
-int32_t ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, uint8_t vm_pool)
-{
- DEBUGFUNC("ixgbe_atr_set_vm_pool_82599");
-
- input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type
- * @input: input stream to modify
- * @l4type: the layer 4 type value to load
- **/
-int32_t ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, uint8_t l4type)
-{
- DEBUGFUNC("ixgbe_atr_set_l4type_82599");
-
- input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_get_vlan_id_82599 - Gets the VLAN id from the ATR input stream
- * @input: input stream to search
- * @vlan: the VLAN id to load
- **/
-int32_t ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, uint16_t *vlan)
-{
- DEBUGFUNC("ixgbe_atr_get_vlan_id_82599");
+ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
- *vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET];
- *vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8;
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_get_src_ipv4_82599 - Gets the source IPv4 address
- * @input: input stream to search
- * @src_addr: the IP address to load
- **/
-int32_t ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, uint32_t *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;
- *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] << 24;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_get_dst_ipv4_82599 - Gets the destination IPv4 address
- * @input: input stream to search
- * @dst_addr: the IP address to load
- **/
-int32_t ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, uint32_t *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;
- *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] << 24;
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_get_src_ipv6_82599 - Gets the source IPv6 address
- * @input: input stream to search
- * @src_addr_1: the first 4 bytes of the IP address to load
- * @src_addr_2: the second 4 bytes of the IP address to load
- * @src_addr_3: the third 4 bytes of the IP address to load
- * @src_addr_4: the fourth 4 bytes of the IP address to load
- **/
-int32_t ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
- uint32_t *src_addr_1, uint32_t *src_addr_2,
- uint32_t *src_addr_3, uint32_t *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;
- *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] << 24;
-
- *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8];
- *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] << 8;
- *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] << 16;
- *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] << 24;
-
- *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4];
- *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] << 8;
- *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] << 16;
- *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] << 24;
-
- *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET];
- *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] << 8;
- *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] << 16;
- *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] << 24;
+ /* process the remaining 30 bits in the key 2 bits at a time */
+ for (i = 15; i; i-- ) {
+ if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
+ if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
+ }
- return IXGBE_SUCCESS;
+ return hash_result & IXGBE_ATR_HASH_MASK;
}
-/**
- * ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address
- * @input: input stream to search
- * @dst_addr_1: the first 4 bytes of the IP address to load
- * @dst_addr_2: the second 4 bytes of the IP address to load
- * @dst_addr_3: the third 4 bytes of the IP address to load
- * @dst_addr_4: the fourth 4 bytes of the IP address to load
- **/
-int32_t ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
- uint32_t *dst_addr_1, uint32_t *dst_addr_2,
- uint32_t *dst_addr_3, uint32_t *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;
- *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24;
-
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8];
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8;
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16;
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24;
-
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4];
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8;
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16;
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24;
-
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET];
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8;
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16;
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24;
-
- return IXGBE_SUCCESS;
-}
+/*
+ * These defines allow us to quickly generate all of the necessary instructions
+ * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
+ * for values 0 through 15
+ */
+#define IXGBE_ATR_COMMON_HASH_KEY \
+ (IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY)
+#define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \
+do { \
+ uint32_t n = (_n); \
+ if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \
+ common_hash ^= lo_hash_dword >> n; \
+ else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
+ bucket_hash ^= lo_hash_dword >> n; \
+ else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \
+ sig_hash ^= lo_hash_dword << (16 - n); \
+ if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \
+ common_hash ^= hi_hash_dword >> n; \
+ else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
+ bucket_hash ^= hi_hash_dword >> n; \
+ else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \
+ sig_hash ^= hi_hash_dword << (16 - n); \
+} while (0);
/**
- * ixgbe_atr_get_src_port_82599 - Gets the source port
- * @input: input stream to modify
- * @src_port: the source port to load
- *
- * Even though the input is given in big-endian, the FDIRPORT registers
- * expect the ports to be programmed in little-endian. Hence the need to swap
- * endianness when retrieving the data. This can be confusing since the
- * internal hash engine expects it to be big-endian.
- **/
-int32_t ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, uint16_t *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];
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_get_dst_port_82599 - Gets the destination port
- * @input: input stream to modify
- * @dst_port: the destination port to load
+ * ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash
+ * @stream: input bitstream to compute the hash on
*
- * Even though the input is given in big-endian, the FDIRPORT registers
- * expect the ports to be programmed in little-endian. Hence the need to swap
- * endianness when retrieving the data. This can be confusing since the
- * internal hash engine expects it to be big-endian.
+ * This function is almost identical to the function above but contains
+ * several optomizations such as unwinding all of the loops, letting the
+ * compiler work out all of the conditional ifs since the keys are static
+ * defines, and computing two keys at once since the hashed dword stream
+ * will be the same for both keys.
**/
-int32_t ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, uint16_t *dst_port)
+uint32_t ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
+ union ixgbe_atr_hash_dword common)
{
- DEBUGFUNC("ixgbe_atr_get_dst_port_82599");
+ uint32_t hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+ uint32_t sig_hash = 0, bucket_hash = 0, common_hash = 0;
- *dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8;
- *dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1];
+ /* record the flow_vm_vlan bits as they are a key part to the hash */
+ flow_vm_vlan = ntohl(input.dword);
- return IXGBE_SUCCESS;
-}
+ /* generate common hash dword */
+ hi_hash_dword = ntohl(common.dword);
-/**
- * ixgbe_atr_get_flex_byte_82599 - Gets the flexible bytes
- * @input: input stream to modify
- * @flex_bytes: the flexible bytes to load
- **/
-int32_t ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, uint16_t *flex_byte)
-{
- DEBUGFUNC("ixgbe_atr_get_flex_byte_82599");
+ /* low dword is word swapped version of common */
+ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
- *flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET];
- *flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8;
+ /* apply flow ID/VM pool/VLAN ID bits to hash words */
+ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
- return IXGBE_SUCCESS;
-}
+ /* Process bits 0 and 16 */
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(0);
-/**
- * ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool
- * @input: input stream to modify
- * @vm_pool: the Virtual Machine pool to load
- **/
-int32_t ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, uint8_t *vm_pool)
-{
- DEBUGFUNC("ixgbe_atr_get_vm_pool_82599");
+ /*
+ * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+ * delay this because bit 0 of the stream should not be processed
+ * so we do not add the vlan until after bit 0 was processed
+ */
+ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
+
+ /* Process remaining 30 bit of the key */
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(1);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(2);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(3);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(4);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(5);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(6);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(7);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(8);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(9);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(10);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(11);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(12);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(13);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(14);
+ IXGBE_COMPUTE_SIG_HASH_ITERATION(15);
+
+ /* combine common_hash result with signature and bucket hashes */
+ bucket_hash ^= common_hash;
+ bucket_hash &= IXGBE_ATR_HASH_MASK;
- *vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET];
+ sig_hash ^= common_hash << 16;
+ sig_hash &= IXGBE_ATR_HASH_MASK << 16;
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type
- * @input: input stream to modify
- * @l4type: the layer 4 type value to load
- **/
-int32_t ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, uint8_t *l4type)
-{
- DEBUGFUNC("ixgbe_atr_get_l4type__82599");
-
- *l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET];
-
- return IXGBE_SUCCESS;
+ /* return completed signature hash */
+ return sig_hash ^ bucket_hash;
}
/**
@@ -1844,159 +1568,228 @@ int32_t ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, uint8_t *l4typ
* @queue: queue index to direct traffic to
**/
int32_t ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
- struct ixgbe_atr_input *input,
+ union ixgbe_atr_hash_dword input,
+ union ixgbe_atr_hash_dword common,
uint8_t queue)
{
uint64_t fdirhashcmd;
uint64_t fdircmd;
- uint32_t fdirhash;
- uint16_t bucket_hash, sig_hash;
- uint8_t l4type;
DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
- bucket_hash = ixgbe_atr_compute_hash_82599(input,
- IXGBE_ATR_BUCKET_HASH_KEY);
-
- /* bucket_hash is only 15 bits */
- bucket_hash &= IXGBE_ATR_HASH_MASK;
-
- sig_hash = ixgbe_atr_compute_hash_82599(input,
- IXGBE_ATR_SIGNATURE_HASH_KEY);
-
- /* Get the l4type in order to program FDIRCMD properly */
- /* lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 */
- ixgbe_atr_get_l4type_82599(input, &l4type);
-
/*
- * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
- * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH.
+ * Get the flow_type in order to program FDIRCMD properly
+ * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
*/
- fdirhash = sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
-
- fdircmd = (IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
- IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN);
-
- switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
- case IXGBE_ATR_L4TYPE_TCP:
- fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
- break;
- case IXGBE_ATR_L4TYPE_UDP:
- fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
- break;
- case IXGBE_ATR_L4TYPE_SCTP:
- fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+ switch (input.formatted.flow_type) {
+ case IXGBE_ATR_FLOW_TYPE_TCPV4:
+ case IXGBE_ATR_FLOW_TYPE_UDPV4:
+ case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+ case IXGBE_ATR_FLOW_TYPE_TCPV6:
+ case IXGBE_ATR_FLOW_TYPE_UDPV6:
+ case IXGBE_ATR_FLOW_TYPE_SCTPV6:
break;
default:
- DEBUGOUT(" Error on l4type input\n");
+ DEBUGOUT(" Error on flow type input\n");
return IXGBE_ERR_CONFIG;
}
- if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK)
- fdircmd |= IXGBE_FDIRCMD_IPV6;
-
- fdircmd |= ((uint64_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT);
- fdirhashcmd = ((fdircmd << 32) | fdirhash);
+ /* configure FDIRCMD register */
+ fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
+ IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+ fdircmd |= input.formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
+ fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
- DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, fdirhash & 0x7FFF7FFF);
+ /*
+ * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
+ * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH.
+ */
+ fdirhashcmd = (uint64_t)fdircmd << 32;
+ fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
+ DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (uint32_t)fdirhashcmd);
+
return IXGBE_SUCCESS;
}
/**
+ * ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
+ * @input_mask: mask to be bit swapped
+ *
+ * The source and destination port masks for flow director are bit swapped
+ * in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc. In order to
+ * generate a correctly swapped value we need to bit swap the mask and that
+ * is what is accomplished by this function.
+ **/
+uint32_t ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
+{
+ uint32_t mask = ntohs(input_masks->dst_port_mask);
+ mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
+ mask |= ntohs(input_masks->src_port_mask);
+ mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
+ mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
+ mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
+ return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8);
+}
+
+/*
+ * These two macros are meant to address the fact that we have registers
+ * that are either all or in part big-endian. As a result on big-endian
+ * systems we will end up byte swapping the value to little-endian before
+ * it is byte swapped again and written to the hardware in the original
+ * big-endian format.
+ */
+#define IXGBE_STORE_AS_BE32(_value) \
+ (((uint32_t)(_value) >> 24) | (((uint32_t)(_value) & 0x00FF0000) >> 8) | \
+ (((uint32_t)(_value) & 0x0000FF00) << 8) | ((uint32_t)(_value) << 24))
+
+#define IXGBE_WRITE_REG_BE32(a, reg, value) \
+ IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
+
+#define IXGBE_STORE_AS_BE16(_value) \
+ (((uint16_t)(_value) >> 8) | ((uint16_t)(_value) << 8))
+
+
+/**
* ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
* @hw: pointer to hardware structure
- * @input: input bitstream
+ * @input_masks: masks for the input bitstream
+ * @soft_id: software index for the filters
* @queue: queue index to direct traffic to
*
* Note that the caller to this function must lock before calling, since the
* hardware writes must be protected from one another.
**/
int32_t ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- struct ixgbe_atr_input *input,
- uint16_t soft_id,
- uint8_t queue)
+ union ixgbe_atr_input *input,
+ struct ixgbe_atr_input_masks *input_masks,
+ uint16_t soft_id, uint8_t queue)
{
- uint32_t fdircmd = 0;
uint32_t fdirhash;
- uint32_t src_ipv4, dst_ipv4;
- uint32_t src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4;
- uint16_t src_port, dst_port, vlan_id, flex_bytes;
- uint16_t bucket_hash;
- uint8_t l4type;
+ uint32_t fdircmd;
+ uint32_t fdirport, fdirtcpm;
+ uint32_t fdirvlan;
+ /* start with VLAN, flex bytes, VM pool, and IPv6 destination masked */
+ uint32_t fdirm = IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP | IXGBE_FDIRM_FLEX |
+ IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599");
- /* Get our input values */
- ixgbe_atr_get_l4type_82599(input, &l4type);
-
/*
- * Check l4type formatting, and bail out before we touch the hardware
+ * Check flow_type formatting, and bail out before we touch the hardware
* if there's a configuration issue
*/
- switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
- case IXGBE_ATR_L4TYPE_TCP:
- fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
- break;
- case IXGBE_ATR_L4TYPE_UDP:
- fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
- break;
- case IXGBE_ATR_L4TYPE_SCTP:
- fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+ switch (input->formatted.flow_type) {
+ case IXGBE_ATR_FLOW_TYPE_IPV4:
+ /* use the L4 protocol mask for raw IPv4/IPv6 traffic */
+ fdirm |= IXGBE_FDIRM_L4P;
+ case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+ if (input_masks->dst_port_mask || input_masks->src_port_mask) {
+ DEBUGOUT(" Error on src/dst port mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+ case IXGBE_ATR_FLOW_TYPE_TCPV4:
+ case IXGBE_ATR_FLOW_TYPE_UDPV4:
break;
default:
- DEBUGOUT(" Error on l4type input\n");
+ DEBUGOUT(" Error on flow type input\n");
return IXGBE_ERR_CONFIG;
}
- bucket_hash = ixgbe_atr_compute_hash_82599(input,
- IXGBE_ATR_BUCKET_HASH_KEY);
-
- /* bucket_hash is only 15 bits */
- bucket_hash &= IXGBE_ATR_HASH_MASK;
-
- ixgbe_atr_get_vlan_id_82599(input, &vlan_id);
- ixgbe_atr_get_src_port_82599(input, &src_port);
- ixgbe_atr_get_dst_port_82599(input, &dst_port);
- ixgbe_atr_get_flex_byte_82599(input, &flex_bytes);
-
- fdirhash = soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
-
- /* Now figure out if we're IPv4 or IPv6 */
- if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK) {
- /* IPv6 */
- ixgbe_atr_get_src_ipv6_82599(input, &src_ipv6_1, &src_ipv6_2,
- &src_ipv6_3, &src_ipv6_4);
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), src_ipv6_1);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), src_ipv6_2);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), src_ipv6_3);
- /* The last 4 bytes is the same register as IPv4 */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv6_4);
-
- fdircmd |= IXGBE_FDIRCMD_IPV6;
- fdircmd |= IXGBE_FDIRCMD_IPv6DMATCH;
- } else {
- /* IPv4 */
- ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4);
+ /*
+ * Program the relevant mask registers. If src/dst_port or src/dst_addr
+ * are zero, then assume a full mask for that field. Also assume that
+ * a VLAN of 0 is unspecified, so mask that out as well. L4type
+ * cannot be masked out in this implementation.
+ *
+ * This also assumes IPv4 only. IPv6 masking isn't supported at this
+ * point in time.
+ */
+ /* Program FDIRM */
+ switch (ntohs(input_masks->vlan_id_mask) & 0xEFFF) {
+ case 0xEFFF:
+ /* Unmask VLAN ID - bit 0 and fall through to unmask prio */
+ fdirm &= ~IXGBE_FDIRM_VLANID;
+ case 0xE000:
+ /* Unmask VLAN prio - bit 1 */
+ fdirm &= ~IXGBE_FDIRM_VLANP;
+ break;
+ case 0x0FFF:
+ /* Unmask VLAN ID - bit 0 */
+ fdirm &= ~IXGBE_FDIRM_VLANID;
+ break;
+ case 0x0000:
+ /* do nothing, vlans already masked */
+ break;
+ default:
+ DEBUGOUT(" Error on VLAN mask\n");
+ return IXGBE_ERR_CONFIG;
}
- ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, dst_ipv4);
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id |
- (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT)));
- IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port |
- (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
+ if (input_masks->flex_mask & 0xFFFF) {
+ if ((input_masks->flex_mask & 0xFFFF) != 0xFFFF) {
+ DEBUGOUT(" Error on flexible byte mask\n");
+ return IXGBE_ERR_CONFIG;
+ }
+ /* Unmask Flex Bytes - bit 4 */
+ fdirm &= ~IXGBE_FDIRM_FLEX;
+ }
- fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW;
- fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE;
- fdircmd |= IXGBE_FDIRCMD_LAST;
- fdircmd |= IXGBE_FDIRCMD_QUEUE_EN;
- fdircmd |= queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+ /* Now mask VM pool and destination IPv6 - bits 5 and 2 */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
+
+ /* store the TCP/UDP port masks, bit reversed from port layout */
+ fdirtcpm = ixgbe_get_fdirtcpm_82599(input_masks);
+
+ /* write both the same so that UDP and TCP use the same mask */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
+
+ /* store source and destination IP masks (big-enian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
+ ~input_masks->src_ip_mask[0]);
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
+ ~input_masks->dst_ip_mask[0]);
+
+ /* Apply masks to input data */
+ input->formatted.vlan_id &= input_masks->vlan_id_mask;
+ input->formatted.flex_bytes &= input_masks->flex_mask;
+ input->formatted.src_port &= input_masks->src_port_mask;
+ input->formatted.dst_port &= input_masks->dst_port_mask;
+ input->formatted.src_ip[0] &= input_masks->src_ip_mask[0];
+ input->formatted.dst_ip[0] &= input_masks->dst_ip_mask[0];
+
+ /* record vlan (little-endian) and flex_bytes(big-endian) */
+ fdirvlan =
+ IXGBE_STORE_AS_BE16(ntohs(input->formatted.flex_bytes));
+ fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
+ fdirvlan |= ntohs(input->formatted.vlan_id);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
+
+ /* record source and destination port (little-endian)*/
+ fdirport = ntohs(input->formatted.dst_port);
+ fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
+ fdirport |= ntohs(input->formatted.src_port);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
+
+ /* record the first 32 bits of the destination address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
+
+ /* record the source address (big-endian) */
+ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+
+ /* configure FDIRCMD register */
+ fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
+ IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+ fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
+ fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+
+ /* we only want the bucket hash so drop the upper 16 bits */
+ fdirhash = ixgbe_atr_compute_hash_82599(input,
+ IXGBE_ATR_BUCKET_HASH_KEY);
+ fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
@@ -2054,46 +1847,45 @@ int32_t ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, uint32_t reg, uint8_t
* ixgbe_start_hw_rev_1_82599 - Prepare hardware for Tx/Rx
* @hw: pointer to hardware structure
*
- * Starts the hardware using the generic start_hw function.
- * Then performs revision-specific operations:
- * Clears the rate limiter registers.
+ * Starts the hardware using the generic start_hw function
+ * and the generation start_hw function.
+ * Then performs revision-specific operations, if any.
**/
int32_t ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw)
{
- uint32_t i;
- uint32_t regval;
int32_t ret_val = IXGBE_SUCCESS;
+ uint32_t gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
DEBUGFUNC("ixgbe_start_hw_rev_1__82599");
ret_val = ixgbe_start_hw_generic(hw);
+ if (ret_val != IXGBE_SUCCESS)
+ goto out;
- /* Clear the rate limiters */
- 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);
- }
+ ret_val = ixgbe_start_hw_gen2(hw);
+ if (ret_val != IXGBE_SUCCESS)
+ goto out;
/* We need to run link autotry after the driver loads */
hw->mac.autotry_restart = TRUE;
+ /*
+ * From the 82599 specification update:
+ * set the completion timeout value for 16ms to 55ms if needed
+ */
+ if (gcr & IXGBE_GCR_CAP_VER2) {
+ uint16_t reg;
+ reg = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2);
+ if ((reg & 0x0f) == 0) {
+ reg |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
+ IXGBE_WRITE_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2,
+ reg);
+ }
+ }
+
if (ret_val == IXGBE_SUCCESS)
ret_val = ixgbe_verify_fw_version_82599(hw);
+out:
return ret_val;
}
@@ -2113,8 +1905,14 @@ int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
/* Detect PHY if not unknown - returns success if already detected. */
status = ixgbe_identify_phy_generic(hw);
- if (status != IXGBE_SUCCESS)
- status = ixgbe_identify_sfp_module_generic(hw);
+ if (status != IXGBE_SUCCESS) {
+ /* 82599 10GBASE-T requires an external PHY */
+ if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
+ goto out;
+ else
+ status = ixgbe_identify_sfp_module_generic(hw);
+ }
+
/* Set PHY type none if no PHY detected */
if (hw->phy.type == ixgbe_phy_unknown) {
hw->phy.type = ixgbe_phy_none;
@@ -2125,6 +1923,7 @@ int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
if (hw->phy.type == ixgbe_phy_sfp_unsupported)
status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+out:
return status;
}
@@ -2144,14 +1943,16 @@ uint32_t ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
uint32_t pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
uint16_t ext_ability = 0;
uint8_t comp_codes_10g = 0;
+ uint8_t comp_codes_1g = 0;
DEBUGFUNC("ixgbe_get_support_physical_layer_82599");
hw->phy.ops.identify(hw);
- if (hw->phy.type == ixgbe_phy_tn ||
- hw->phy.type == ixgbe_phy_aq ||
- hw->phy.type == ixgbe_phy_cu_unknown) {
+ switch (hw->phy.type) {
+ case ixgbe_phy_tn:
+ case ixgbe_phy_aq:
+ case ixgbe_phy_cu_unknown:
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
@@ -2161,6 +1962,8 @@ uint32_t ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
goto out;
+ default:
+ break;
}
switch (autoc & IXGBE_AUTOC_LMS_MASK) {
@@ -2214,20 +2017,28 @@ sfp_check:
goto out;
switch (hw->phy.type) {
- case ixgbe_phy_tw_tyco:
- case ixgbe_phy_tw_unknown:
+ case ixgbe_phy_sfp_passive_tyco:
+ case ixgbe_phy_sfp_passive_unknown:
physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
break;
+ case ixgbe_phy_sfp_ftl_active:
+ case ixgbe_phy_sfp_active_unknown:
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
+ break;
case ixgbe_phy_sfp_avago:
case ixgbe_phy_sfp_ftl:
case ixgbe_phy_sfp_intel:
case ixgbe_phy_sfp_unknown:
hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g);
+ hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+ else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
+ physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
break;
default:
break;
@@ -2285,23 +2096,6 @@ int32_t ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, uint32_t regval)
}
/**
- * ixgbe_get_device_caps_82599 - Get additional device capabilities
- * @hw: pointer to hardware structure
- * @device_caps: the EEPROM word with the extra device capabilities
- *
- * This function will read the EEPROM location for the device capabilities,
- * and return the word through device_caps.
- **/
-int32_t ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, uint16_t *device_caps)
-{
- DEBUGFUNC("ixgbe_get_device_caps_82599");
-
- hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
-
- return IXGBE_SUCCESS;
-}
-
-/**
* ixgbe_verify_fw_version_82599 - verify fw version for 82599
* @hw: pointer to hardware structure
*
@@ -2350,3 +2144,49 @@ int32_t ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
fw_version_out:
return status;
}
+
+/**
+ * ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state.
+ * @hw: pointer to hardware structure
+ *
+ * Returns TRUE if the LESM FW module is present and enabled. Otherwise
+ * returns FALSE. Smart Speed must be disabled if LESM FW module is enabled.
+ **/
+int ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
+{
+ int lesm_enabled = FALSE;
+ uint16_t fw_offset, fw_lesm_param_offset, fw_lesm_state;
+ int32_t status;
+
+ DEBUGFUNC("ixgbe_verify_lesm_fw_enabled_82599");
+
+ /* get the offset to the Firmware Module block */
+ status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
+
+ if ((status != IXGBE_SUCCESS) ||
+ (fw_offset == 0) || (fw_offset == 0xFFFF))
+ goto out;
+
+ /* get the offset to the LESM Parameters block */
+ status = hw->eeprom.ops.read(hw, (fw_offset +
+ IXGBE_FW_LESM_PARAMETERS_PTR),
+ &fw_lesm_param_offset);
+
+ if ((status != IXGBE_SUCCESS) ||
+ (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF))
+ goto out;
+
+ /* get the lesm state word */
+ status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
+ IXGBE_FW_LESM_STATE_1),
+ &fw_lesm_state);
+
+ if ((status == IXGBE_SUCCESS) &&
+ (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
+ lesm_enabled = TRUE;
+
+out:
+ return lesm_enabled;
+}
+
+
diff --git a/sys/dev/pci/ixgbe_phy.c b/sys/dev/pci/ixgbe_phy.c
index c859aef86f1..7bfcd7ff9b7 100644
--- a/sys/dev/pci/ixgbe_phy.c
+++ b/sys/dev/pci/ixgbe_phy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_phy.c,v 1.5 2010/09/21 00:29:29 claudio Exp $ */
+/* $OpenBSD: ixgbe_phy.c,v 1.6 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -75,7 +75,7 @@ int32_t ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw)
phy->ops.i2c_bus_clear = &ixgbe_i2c_bus_clear;
phy->ops.identify_sfp = &ixgbe_identify_sfp_module_generic;
phy->sfp_type = ixgbe_sfp_type_unknown;
-
+ phy->ops.check_overtemp = &ixgbe_tn_check_overtemp;
return IXGBE_SUCCESS;
}
@@ -105,9 +105,8 @@ int32_t ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&ext_ability);
if (ext_ability &
- IXGBE_MDIO_PHY_10GBASET_ABILITY ||
- ext_ability &
- IXGBE_MDIO_PHY_1000BASET_ABILITY)
+ (IXGBE_MDIO_PHY_10GBASET_ABILITY |
+ IXGBE_MDIO_PHY_1000BASET_ABILITY))
hw->phy.type =
ixgbe_phy_cu_unknown;
else
@@ -119,6 +118,7 @@ int32_t ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
break;
}
}
+ /* clear value if nothing found */
if (status != IXGBE_SUCCESS)
hw->phy.addr = 0;
} else {
@@ -221,6 +221,11 @@ int32_t ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
if (status != IXGBE_SUCCESS || hw->phy.type == ixgbe_phy_none)
goto out;
+ /* Don't reset PHY if it's shut down due to overtemp. */
+ if (!hw->phy.reset_if_overtemp &&
+ (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
+ goto out;
+
/*
* Perform soft PHY reset to the PHY_XS.
* This will cause a soft reset to the PHY
@@ -229,13 +234,19 @@ int32_t ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
IXGBE_MDIO_PHY_XS_DEV_TYPE,
IXGBE_MDIO_PHY_XS_RESET);
- /* Poll for reset bit to self-clear indicating reset is complete */
- for (i = 0; i < 500; i++) {
- msec_delay(1);
+ /*
+ * Poll for reset bit to self-clear indicating reset is complete.
+ * Some PHYs could take up to 3 seconds to complete and need about
+ * 1.7 usec delay after the reset is complete.
+ */
+ for (i = 0; i < 30; i++) {
+ msec_delay(100);
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
IXGBE_MDIO_PHY_XS_DEV_TYPE, &ctrl);
- if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET))
+ if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET)) {
+ usec_delay(2);
break;
+ }
}
if (ctrl & IXGBE_MDIO_PHY_XS_RESET) {
@@ -289,9 +300,8 @@ int32_t ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, uint32_t reg_addr,
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
- if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
+ if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
break;
- }
}
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
@@ -438,10 +448,10 @@ int32_t ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, uint32_t 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.
**/
int32_t ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
{
@@ -520,12 +530,15 @@ int32_t ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
&autoneg_reg);
autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
- if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE)
+ if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) {
break;
+ }
}
- 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;
}
@@ -727,8 +740,9 @@ int32_t ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
&autoneg_reg);
autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
- if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE)
+ if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) {
break;
+ }
}
if (time_out == max_time_out) {
@@ -739,7 +753,6 @@ int32_t ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
return status;
}
-
/**
* ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
* @hw: pointer to hardware structure
@@ -757,7 +770,6 @@ int32_t ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
return status;
}
-
/**
* ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version
* @hw: pointer to hardware structure
@@ -888,6 +900,7 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
uint8_t comp_codes_10g = 0;
uint8_t oui_bytes[3] = {0, 0, 0};
uint8_t cable_tech = 0;
+ uint8_t cable_spec = 0;
uint16_t enforce_sfp = 0;
if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
@@ -900,15 +913,10 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
&identifier);
- if (status == IXGBE_ERR_SFP_NOT_PRESENT || status == IXGBE_ERR_I2C) {
- status = IXGBE_ERR_SFP_NOT_PRESENT;
- hw->phy.sfp_type = ixgbe_sfp_type_not_present;
- if (hw->phy.type != ixgbe_phy_nl) {
- hw->phy.id = 0;
- hw->phy.type = ixgbe_phy_unknown;
- }
- goto out;
- }
+ if (status == IXGBE_ERR_SWFW_SYNC ||
+ status == IXGBE_ERR_I2C ||
+ status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto err_read_i2c_eeprom;
/* LAN ID is needed for sfp_type determination */
hw->mac.ops.set_lan_id(hw);
@@ -917,15 +925,31 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
hw->phy.type = ixgbe_phy_sfp_unsupported;
status = IXGBE_ERR_SFP_NOT_SUPPORTED;
} else {
- hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
- &comp_codes_1g);
- hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES,
- &comp_codes_10g);
- hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_CABLE_TECHNOLOGY,
- &cable_tech);
-
- DEBUGOUT3("SFP+ capa codes 1G %x 10G %x cable %x\n",
- comp_codes_1g, comp_codes_10g, cable_tech);
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_1GBE_COMP_CODES,
+ &comp_codes_1g);
+
+ if (status == IXGBE_ERR_SWFW_SYNC ||
+ status == IXGBE_ERR_I2C ||
+ status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto err_read_i2c_eeprom;
+
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_10GBE_COMP_CODES,
+ &comp_codes_10g);
+
+ if (status == IXGBE_ERR_SWFW_SYNC ||
+ status == IXGBE_ERR_I2C ||
+ status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto err_read_i2c_eeprom;
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_CABLE_TECHNOLOGY,
+ &cable_tech);
+
+ if (status == IXGBE_ERR_SWFW_SYNC ||
+ status == IXGBE_ERR_I2C ||
+ status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto err_read_i2c_eeprom;
/* ID Module
* =========
@@ -936,6 +960,10 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
* 4 SFP_DA_CORE1 - 82599-specific
* 5 SFP_SR/LR_CORE0 - 82599-specific
* 6 SFP_SR/LR_CORE1 - 82599-specific
+ * 7 SFP_act_lmt_DA_CORE0 - 82599-specific
+ * 8 SFP_act_lmt_DA_CORE1 - 82599-specific
+ * 9 SFP_1g_cu_CORE0 - 82599-specific
+ * 10 SFP_1g_cu_CORE1 - 82599-specific
*/
if (hw->mac.type == ixgbe_mac_82598EB) {
if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
@@ -949,29 +977,48 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
else
hw->phy.sfp_type = ixgbe_sfp_type_unknown;
} else if (hw->mac.type == ixgbe_mac_82599EB) {
- if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
+ if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
if (hw->bus.lan_id == 0)
hw->phy.sfp_type =
ixgbe_sfp_type_da_cu_core0;
else
hw->phy.sfp_type =
ixgbe_sfp_type_da_cu_core1;
- else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+ } else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) {
+ hw->phy.ops.read_i2c_eeprom(
+ hw, IXGBE_SFF_CABLE_SPEC_COMP,
+ &cable_spec);
+ if (cable_spec &
+ IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) {
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_da_act_lmt_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_da_act_lmt_core1;
+ } else {
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_unknown;
+ }
+ } else if (comp_codes_10g &
+ (IXGBE_SFF_10GBASESR_CAPABLE |
+ IXGBE_SFF_10GBASELR_CAPABLE)) {
if (hw->bus.lan_id == 0)
hw->phy.sfp_type =
ixgbe_sfp_type_srlr_core0;
else
hw->phy.sfp_type =
ixgbe_sfp_type_srlr_core1;
- else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+ } else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
if (hw->bus.lan_id == 0)
hw->phy.sfp_type =
- ixgbe_sfp_type_srlr_core0;
+ ixgbe_sfp_type_1g_cu_core0;
else
hw->phy.sfp_type =
- ixgbe_sfp_type_srlr_core1;
- else
+ ixgbe_sfp_type_1g_cu_core1;
+ } else {
hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ }
}
if (hw->phy.sfp_type != stored_sfp_type)
@@ -988,28 +1035,49 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
/* Determine PHY vendor */
if (hw->phy.type != ixgbe_phy_nl) {
hw->phy.id = identifier;
- hw->phy.ops.read_i2c_eeprom(hw,
+ status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_VENDOR_OUI_BYTE0,
&oui_bytes[0]);
- hw->phy.ops.read_i2c_eeprom(hw,
+
+ if (status == IXGBE_ERR_SWFW_SYNC ||
+ status == IXGBE_ERR_I2C ||
+ status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto err_read_i2c_eeprom;
+
+ status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_VENDOR_OUI_BYTE1,
&oui_bytes[1]);
- hw->phy.ops.read_i2c_eeprom(hw,
+
+ if (status == IXGBE_ERR_SWFW_SYNC ||
+ status == IXGBE_ERR_I2C ||
+ status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto err_read_i2c_eeprom;
+
+ status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_VENDOR_OUI_BYTE2,
&oui_bytes[2]);
+ if (status == IXGBE_ERR_SWFW_SYNC ||
+ status == IXGBE_ERR_I2C ||
+ status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto err_read_i2c_eeprom;
+
vendor_oui =
- ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
- (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
- (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
+ ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
+ (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
+ (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
switch (vendor_oui) {
case IXGBE_SFF_VENDOR_OUI_TYCO:
if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
- hw->phy.type = ixgbe_phy_tw_tyco;
+ hw->phy.type =
+ ixgbe_phy_sfp_passive_tyco;
break;
case IXGBE_SFF_VENDOR_OUI_FTL:
- hw->phy.type = ixgbe_phy_sfp_ftl;
+ if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
+ hw->phy.type = ixgbe_phy_sfp_ftl_active;
+ else
+ hw->phy.type = ixgbe_phy_sfp_ftl;
break;
case IXGBE_SFF_VENDOR_OUI_AVAGO:
hw->phy.type = ixgbe_phy_sfp_avago;
@@ -1019,21 +1087,28 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
break;
default:
if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
- hw->phy.type = ixgbe_phy_tw_unknown;
+ hw->phy.type =
+ ixgbe_phy_sfp_passive_unknown;
+ else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
+ hw->phy.type =
+ ixgbe_phy_sfp_active_unknown;
else
hw->phy.type = ixgbe_phy_sfp_unknown;
break;
}
}
- /* All passive DA cables are supported */
- if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
+ /* Allow any DA cable vendor */
+ if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
+ IXGBE_SFF_DA_ACTIVE_CABLE)) {
status = IXGBE_SUCCESS;
goto out;
}
- /* 1G SFP modules are not supported */
- if (comp_codes_10g == 0) {
+ /* Verify supported 1G SFP modules */
+ if (comp_codes_10g == 0 &&
+ !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0)) {
hw->phy.type = ixgbe_phy_sfp_unsupported;
status = IXGBE_ERR_SFP_NOT_SUPPORTED;
goto out;
@@ -1048,7 +1123,9 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
/* unimplemented even in the intel driver */
/* ixgbe_get_device_caps(hw, &enforce_sfp); */
enforce_sfp = IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP;
- if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
+ if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
+ !((hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0) ||
+ (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1))) {
/* Make sure we're a supported PHY type */
if (hw->phy.type == ixgbe_phy_sfp_intel) {
status = IXGBE_SUCCESS;
@@ -1065,6 +1142,14 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
out:
return status;
+
+err_read_i2c_eeprom:
+ hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+ if (hw->phy.type != ixgbe_phy_nl) {
+ hw->phy.id = 0;
+ hw->phy.type = ixgbe_phy_unknown;
+ }
+ return IXGBE_ERR_SFP_NOT_PRESENT;
}
/**
@@ -1081,6 +1166,7 @@ int32_t ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
uint16_t *data_offset)
{
uint16_t sfp_id;
+ uint16_t sfp_type = hw->phy.sfp_type;
if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
return IXGBE_ERR_SFP_NOT_SUPPORTED;
@@ -1092,6 +1178,17 @@ int32_t ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
(hw->phy.sfp_type == ixgbe_sfp_type_da_cu))
return IXGBE_ERR_SFP_NOT_SUPPORTED;
+ /*
+ * Limiting active cables and 1G Phys must be initialized as
+ * SR modules
+ */
+ if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 ||
+ sfp_type == ixgbe_sfp_type_1g_cu_core0)
+ sfp_type = ixgbe_sfp_type_srlr_core0;
+ else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 ||
+ sfp_type == ixgbe_sfp_type_1g_cu_core1)
+ sfp_type = ixgbe_sfp_type_srlr_core1;
+
/* Read offset to PHY init contents */
hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
@@ -1108,7 +1205,7 @@ int32_t ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
hw->eeprom.ops.read(hw, *list_offset, &sfp_id);
while (sfp_id != IXGBE_PHY_INIT_END_NL) {
- if (sfp_id == hw->phy.sfp_type) {
+ if (sfp_id == sfp_type) {
(*list_offset)++;
hw->eeprom.ops.read(hw, *list_offset, data_offset);
if ((!*data_offset) || (*data_offset == 0xFFFF)) {
@@ -1135,9 +1232,10 @@ int32_t ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
(*list_offset) += 2;
hw->eeprom.ops.read(hw, *list_offset, data_offset);
- } else if (sfp_id == IXGBE_PHY_INIT_END_NL)
+ } else if (sfp_id == IXGBE_PHY_INIT_END_NL) {
+ DEBUGOUT("No matching SFP+ module found\n");
return IXGBE_ERR_SFP_NOT_SUPPORTED;
-
+ }
return IXGBE_SUCCESS;
}
@@ -1196,7 +1294,6 @@ int32_t ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
else
swfw_mask = IXGBE_GSSR_PHY0_SM;
-
do {
if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) {
status = IXGBE_ERR_SWFW_SYNC;
@@ -1401,7 +1498,7 @@ int32_t ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, uint8_t *data)
for (i = 7; i >= 0; i--) {
status = ixgbe_clock_in_i2c_bit(hw, &bit);
- *data |= bit<<i;
+ *data |= bit << i;
if (status != IXGBE_SUCCESS)
break;
@@ -1670,3 +1767,29 @@ void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
/* Put the i2c bus back to default state */
ixgbe_i2c_stop(hw);
}
+
+/**
+ * ixgbe_tn_check_overtemp - Checks if an overtemp occured.
+ * @hw: pointer to hardware structure
+ *
+ * Checks if the LASI temp alarm status was triggered due to overtemp
+ **/
+int32_t ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
+{
+ int32_t status = IXGBE_SUCCESS;
+ uint16_t phy_data = 0;
+
+ if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM)
+ goto out;
+
+ /* Check that the LASI temp alarm status was triggered */
+ hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_data);
+
+ if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM))
+ goto out;
+
+ status = IXGBE_ERR_OVERTEMP;
+out:
+ return status;
+}
diff --git a/sys/dev/pci/ixgbe_type.h b/sys/dev/pci/ixgbe_type.h
index 3fa9b69c48f..239a4f19db7 100644
--- a/sys/dev/pci/ixgbe_type.h
+++ b/sys/dev/pci/ixgbe_type.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_type.h,v 1.7 2010/11/10 15:23:25 claudio Exp $ */
+/* $OpenBSD: ixgbe_type.h,v 1.8 2011/06/10 12:46:35 claudio Exp $ */
/******************************************************************************
@@ -56,11 +56,17 @@
#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_COMBO_BACKPLANE 0x10F8
+#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C
#define IXGBE_DEV_ID_82599_CX4 0x10F9
#define IXGBE_DEV_ID_82599_SFP 0x10FB
#define IXGBE_DEV_ID_82599_SFP_EM 0x1507
+#define IXGBE_SUBDEV_ID_82599_SFP 0x11A9
+#define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A
+#define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529
#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC
+#define IXGBE_DEV_ID_82599_T3_LOM 0x151C
+#define IXGBE_DEV_ID_82599_VF 0x10ED
/* General Registers */
#define IXGBE_CTRL 0x00000
@@ -89,17 +95,17 @@
#define IXGBE_GRC 0x10200
/* General Receive Control */
-#define IXGBE_GRC_MNG 0x00000001 /* Manageability Enable */
-#define IXGBE_GRC_APME 0x00000002 /* Advanced Power Management Enable */
+#define IXGBE_GRC_MNG 0x00000001 /* Manageability Enable */
+#define IXGBE_GRC_APME 0x00000002 /* APM enabled in EEPROM */
#define IXGBE_VPDDIAG0 0x10204
#define IXGBE_VPDDIAG1 0x10208
/* I2CCTL Bit Masks */
-#define IXGBE_I2C_CLK_IN 0x00000001
-#define IXGBE_I2C_CLK_OUT 0x00000002
-#define IXGBE_I2C_DATA_IN 0x00000004
-#define IXGBE_I2C_DATA_OUT 0x00000008
+#define IXGBE_I2C_CLK_IN 0x00000001
+#define IXGBE_I2C_CLK_OUT 0x00000002
+#define IXGBE_I2C_DATA_IN 0x00000004
+#define IXGBE_I2C_DATA_OUT 0x00000008
/* Interrupt Registers */
#define IXGBE_EICR 0x00800
@@ -108,19 +114,19 @@
#define IXGBE_EIMC 0x00888
#define IXGBE_EIAC 0x00810
#define IXGBE_EIAM 0x00890
-#define IXGBE_EICS_EX(_i) (0x00A90 + (_i) * 4)
-#define IXGBE_EIMS_EX(_i) (0x00AA0 + (_i) * 4)
-#define IXGBE_EIMC_EX(_i) (0x00AB0 + (_i) * 4)
-#define IXGBE_EIAM_EX(_i) (0x00AD0 + (_i) * 4)
+#define IXGBE_EICS_EX(_i) (0x00A90 + (_i) * 4)
+#define IXGBE_EIMS_EX(_i) (0x00AA0 + (_i) * 4)
+#define IXGBE_EIMC_EX(_i) (0x00AB0 + (_i) * 4)
+#define IXGBE_EIAM_EX(_i) (0x00AD0 + (_i) * 4)
/* 82599 EITR is only 12 bits, with the lower 3 always zero */
/*
* 82598 EITR is 16 bits but set the limits based on the max
* supported by all ixgbe hardware
*/
-#define IXGBE_MAX_INT_RATE 488281
-#define IXGBE_MIN_INT_RATE 956
-#define IXGBE_MAX_EITR 0x00000FF8
-#define IXGBE_MIN_EITR 8
+#define IXGBE_MAX_INT_RATE 488281
+#define IXGBE_MIN_INT_RATE 956
+#define IXGBE_MAX_EITR 0x00000FF8
+#define IXGBE_MIN_EITR 8
#define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : \
(0x012300 + (((_i) - 24) * 4)))
#define IXGBE_EITR_ITR_INT_MASK 0x00000FF8
@@ -199,6 +205,7 @@
#define IXGBE_RFCTL 0x05008
#define IXGBE_DRECCCTL 0x02F08
#define IXGBE_DRECCCTL_DISABLE 0
+
/* Multicast Table Array - 128 entries */
#define IXGBE_MTA(_i) (0x05200 + ((_i) * 4))
#define IXGBE_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
@@ -229,9 +236,11 @@
#define IXGBE_MTQC 0x08120
#define IXGBE_VLVF(_i) (0x0F100 + ((_i) * 4)) /* 64 of these (0-63) */
#define IXGBE_VLVFB(_i) (0x0F200 + ((_i) * 4)) /* 128 of these (0-127) */
+#define IXGBE_VMVIR(_i) (0x08000 + ((_i) * 4)) /* 64 of these (0-63) */
#define IXGBE_VT_CTL 0x051B0
#define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4))
#define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4))
+#define IXGBE_VMECM(_i) (0x08790 + ((_i) * 4))
#define IXGBE_QDE 0x2F04
#define IXGBE_VMOLR(_i) (0x0F000 + ((_i) * 4)) /* 64 total */
#define IXGBE_UTA(_i) (0x0F400 + ((_i) * 4))
@@ -286,13 +295,14 @@
#define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40))
#define IXGBE_DTXCTL 0x07E00
-#define IXGBE_DMATXCTL 0x04A80
-#define IXGBE_PFDTXGSWC 0x08220
-#define IXGBE_DTXMXSZRQ 0x08100
-#define IXGBE_DTXTCPFLGL 0x04A88
-#define IXGBE_DTXTCPFLGH 0x04A8C
-#define IXGBE_LBDRPEN 0x0CA00
-#define IXGBE_TXPBTHRESH(_i) (0x04950 + ((_i) * 4)) /* 8 of these 0 - 7 */
+#define IXGBE_DMATXCTL 0x04A80
+#define IXGBE_PFVFSPOOF(_i) (0x08200 + ((_i) * 4)) /* 8 of these 0 - 7 */
+#define IXGBE_PFDTXGSWC 0x08220
+#define IXGBE_DTXMXSZRQ 0x08100
+#define IXGBE_DTXTCPFLGL 0x04A88
+#define IXGBE_DTXTCPFLGH 0x04A8C
+#define IXGBE_LBDRPEN 0x0CA00
+#define IXGBE_TXPBTHRESH(_i) (0x04950 + ((_i) * 4)) /* 8 of these 0 - 7 */
#define IXGBE_DMATXCTL_TE 0x1 /* Transmit Enable */
#define IXGBE_DMATXCTL_NS 0x2 /* No Snoop LSO hdr buffer */
@@ -300,6 +310,12 @@
#define IXGBE_DMATXCTL_VT_SHIFT 16 /* VLAN EtherType */
#define IXGBE_PFDTXGSWC_VT_LBEN 0x1 /* Local L2 VT switch enable */
+
+/* Anti-spoofing defines */
+#define IXGBE_SPOOF_MACAS_MASK 0xFF
+#define IXGBE_SPOOF_VLANAS_MASK 0xFF00
+#define IXGBE_SPOOF_VLANAS_SHIFT 8
+#define IXGBE_PFVFSPOOF_REG_COUNT 8
#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */
/* Tx DCA Control register : 128 of these (0-127) */
#define IXGBE_DCA_TXCTRL_82599(_i) (0x0600C + ((_i) * 0x40))
@@ -335,7 +351,7 @@
/* Wake Up Control */
#define IXGBE_WUC_PME_EN 0x00000002 /* PME Enable */
#define IXGBE_WUC_PME_STATUS 0x00000004 /* PME Status */
-#define IXGBE_WUC_ADVD3WUC 0x00000010 /* D3Cold wake up cap. enable*/
+#define IXGBE_WUC_WKEN 0x00000010 /* Enable PE_WAKE_N pin assertion */
/* Wake Up Filter Control */
#define IXGBE_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
@@ -512,6 +528,11 @@
#define IXGBE_RTTDTECC_NO_BCN 0x00000100
#define IXGBE_RTTBCNRC 0x04984
+#define IXGBE_RTTBCNRC_RS_ENA 0x80000000
+#define IXGBE_RTTBCNRC_RF_DEC_MASK 0x00003FFF
+#define IXGBE_RTTBCNRC_RF_INT_SHIFT 14
+#define IXGBE_RTTBCNRC_RF_INT_MASK \
+ (IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT)
/* BCN (for DCB) Registers */
#define IXGBE_RTTBCNRM 0x04980
@@ -650,6 +671,8 @@
#define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QBRC(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QBTC(_i) (0x06034 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QBRC_L(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QBRC_H(_i) (0x01038 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */
#define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */
@@ -737,6 +760,12 @@
#define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000
#define IXGBE_GCR_CAP_VER2 0x00040000
+#define IXGBE_GCR_EXT_MSIX_EN 0x80000000
+#define IXGBE_GCR_EXT_VT_MODE_16 0x00000001
+#define IXGBE_GCR_EXT_VT_MODE_32 0x00000002
+#define IXGBE_GCR_EXT_VT_MODE_64 0x00000003
+#define IXGBE_GCR_EXT_SRIOV (IXGBE_GCR_EXT_MSIX_EN | \
+ IXGBE_GCR_EXT_VT_MODE_64)
/* Time Sync Registers */
#define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */
#define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */
@@ -890,6 +919,8 @@
#define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */
#define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 /* RSC First packet size */
#define IXGBE_RDRXCTL_RSCLLIDIS 0x00800000 /* Disable RSC compl on LLI */
+#define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC enabled */
+#define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC enabled */
/* RQTC Bit Masks and Shifts */
#define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4)
@@ -959,8 +990,8 @@
#define IXGBE_MSCA_OP_CODE_SHIFT 26 /* OP CODE shift */
#define IXGBE_MSCA_ADDR_CYCLE 0x00000000 /* OP CODE 00 (addr cycle) */
#define IXGBE_MSCA_WRITE 0x04000000 /* OP CODE 01 (write) */
-#define IXGBE_MSCA_READ 0x08000000 /* OP CODE 10 (read) */
-#define IXGBE_MSCA_READ_AUTOINC 0x0C000000 /* OP CODE 11 (read, auto inc)*/
+#define IXGBE_MSCA_READ 0x0C000000 /* OP CODE 11 (read) */
+#define IXGBE_MSCA_READ_AUTOINC 0x08000000 /* OP CODE 10 (read, auto inc)*/
#define IXGBE_MSCA_ST_CODE_MASK 0x30000000 /* ST Code mask */
#define IXGBE_MSCA_ST_CODE_SHIFT 28 /* ST Code shift */
#define IXGBE_MSCA_NEW_PROTOCOL 0x00000000 /* ST CODE 00 (new protocol) */
@@ -1009,6 +1040,8 @@
#define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */
#define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */
+#define IXGBE_MDIO_AUTO_NEG_ADVT 0x10 /* AUTO_NEG Advt Reg */
+#define IXGBE_MDIO_AUTO_NEG_LP 0x13 /* AUTO_NEG LP Status Reg */
#define IXGBE_MDIO_PHY_XS_CONTROL 0x0 /* PHY_XS Control Reg */
#define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */
#define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/
@@ -1021,7 +1054,9 @@
#define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */
#define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */
#define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */
+#define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE 0x0800 /* Set low power mode */
+#define IXGBE_MDIO_PMA_PMD_CONTROL_ADDR 0x0000 /* PMA/PMD Control Reg */
#define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */
#define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */
#define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */
@@ -1077,7 +1112,6 @@
#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */
#define IXGBE_GPIE_EIAME 0x40000000
#define IXGBE_GPIE_PBA_SUPPORT 0x80000000
-#define IXGBE_GPIE_LLI_DELAY_SHIFT 7
#define IXGBE_GPIE_RSC_DELAY_SHIFT 11
#define IXGBE_GPIE_VTMODE_MASK 0x0000C000 /* VT Mode Mask */
#define IXGBE_GPIE_VTMODE_16 0x00004000 /* 16 VFs 8 queues per VF */
@@ -1371,10 +1405,12 @@
* EAPOL 802.1x (0x888e): Filter 0
* FCoE (0x8906): Filter 2
* 1588 (0x88f7): Filter 3
+ * FIP (0x8914): Filter 4
*/
#define IXGBE_ETQF_FILTER_EAPOL 0
#define IXGBE_ETQF_FILTER_FCOE 2
#define IXGBE_ETQF_FILTER_1588 3
+#define IXGBE_ETQF_FILTER_FIP 4
/* VLAN Control Bit Masks */
#define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */
#define IXGBE_VLNCTRL_CFI 0x10000000 /* bit 28 */
@@ -1386,6 +1422,9 @@
#define IXGBE_VLVF_VIEN 0x80000000 /* filter is valid */
#define IXGBE_VLVF_ENTRIES 64
#define IXGBE_VLVF_VLANID_MASK 0x00000FFF
+/* Per VF Port VLAN insertion rules */
+#define IXGBE_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
+#define IXGBE_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
#define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */
@@ -1478,6 +1517,7 @@
#define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT)
#define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT)
+
/* LINKS Bit Masks */
#define IXGBE_LINKS_KX_AN_COMP 0x80000000
#define IXGBE_LINKS_UP 0x40000000
@@ -1529,6 +1569,7 @@
#define IXGBE_ANLP1_PAUSE 0x0C00
#define IXGBE_ANLP1_SYM_PAUSE 0x0400
#define IXGBE_ANLP1_ASM_PAUSE 0x0800
+#define IXGBE_ANLP1_AN_STATE_MASK 0x000f0000
/* SW Semaphore Register bitmasks */
#define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
@@ -1557,6 +1598,7 @@
#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_SEC1VAL 0x02000000 /* Sector 1 Valid */
#define IXGBE_EEC_FLUDONE 0x04000000 /* Flash update done */
/* EEPROM Addressing bits based on type (0-small, 1-large) */
#define IXGBE_EEC_ADDR_SIZE 0x00000400
@@ -1566,7 +1608,11 @@
#define IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT 6
#define IXGBE_EEPROM_OPCODE_BITS 8
+/* Part Number String Length */
+#define IXGBE_PBANUM_LENGTH 11
+
/* Checksum and EEPROM pointers */
+#define IXGBE_PBANUM_PTR_GUARD 0xFAFA
#define IXGBE_EEPROM_CHECKSUM 0x3F
#define IXGBE_EEPROM_SUM 0xBABA
#define IXGBE_PCIE_ANALOG_PTR 0x03
@@ -1645,18 +1691,28 @@
#define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3
#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1
#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2
+#define IXGBE_FW_LESM_PARAMETERS_PTR 0x2
+#define IXGBE_FW_LESM_STATE_1 0x1
+#define IXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */
#define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4
-#define IXGBE_FW_PATCH_VERSION_4 0x7
+#define IXGBE_FW_PATCH_VERSION_4 0x7
+#define IXGBE_FCOE_IBA_CAPS_BLK_PTR 0x33 /* iSCSI/FCOE block */
+#define IXGBE_FCOE_IBA_CAPS_FCOE 0x20 /* FCOE flags */
+#define IXGBE_ISCSI_FCOE_BLK_PTR 0x17 /* iSCSI/FCOE block */
+#define IXGBE_ISCSI_FCOE_FLAGS_OFFSET 0x0 /* FCOE flags */
+#define IXGBE_ISCSI_FCOE_FLAGS_ENABLE 0x1 /* FCOE flags enable bit */
#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 */
+#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_DEVICE_STATUS 0xAA
+#define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING 0x0020
#define IXGBE_PCI_LINK_STATUS 0xB2
#define IXGBE_PCI_DEVICE_CONTROL2 0xC8
#define IXGBE_PCI_LINK_WIDTH 0x3F0
@@ -1789,6 +1845,7 @@
#define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */
#define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */
#define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */
+#define IXGBE_MTQC_4TC_4TQ 0x8 /* 4 TC if RT_ENA and VT_ENA */
#define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */
/* Receive Descriptor bit definitions */
@@ -2002,10 +2059,9 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIRM_VLANID 0x00000001
#define IXGBE_FDIRM_VLANP 0x00000002
#define IXGBE_FDIRM_POOL 0x00000004
-#define IXGBE_FDIRM_L3P 0x00000008
-#define IXGBE_FDIRM_L4P 0x00000010
-#define IXGBE_FDIRM_FLEX 0x00000020
-#define IXGBE_FDIRM_DIPv6 0x00000040
+#define IXGBE_FDIRM_L4P 0x00000008
+#define IXGBE_FDIRM_FLEX 0x00000010
+#define IXGBE_FDIRM_DIPv6 0x00000020
#define IXGBE_FDIRFREE_FREE_MASK 0xFFFF
#define IXGBE_FDIRFREE_FREE_SHIFT 0
@@ -2045,6 +2101,7 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIRCMD_LAST 0x00000800
#define IXGBE_FDIRCMD_COLLISION 0x00001000
#define IXGBE_FDIRCMD_QUEUE_EN 0x00008000
+#define IXGBE_FDIRCMD_FLOW_TYPE_SHIFT 5
#define IXGBE_FDIRCMD_RX_QUEUE_SHIFT 16
#define IXGBE_FDIRCMD_VT_POOL_SHIFT 24
#define IXGBE_FDIR_INIT_DONE_POLL 10
@@ -2052,7 +2109,7 @@ enum ixgbe_fdir_pballoc_type {
/* Transmit Descriptor - Legacy */
struct ixgbe_legacy_tx_desc {
- uint64_t buffer_addr; /* Address of the descriptor's data buffer */
+ uint64_t buffer_addr; /* Address of the descriptor's data buffer */
union {
__le32 data;
struct {
@@ -2220,44 +2277,103 @@ typedef uint32_t ixgbe_physical_layer;
#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400
#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800
#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000
+#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000
+
+/* Flow Control Macros */
+#define PAUSE_RTT 8
+#define PAUSE_MTU(MTU) ((MTU + 1024 - 1) / 1024)
+
+#define FC_HIGH_WATER(MTU) ((((PAUSE_RTT + PAUSE_MTU(MTU)) * 144) + 99) / 100 +\
+ PAUSE_MTU(MTU))
+#define FC_LOW_WATER(MTU) (2 * (2 * PAUSE_MTU(MTU) + PAUSE_RTT))
/* Software ATR hash keys */
-#define IXGBE_ATR_BUCKET_HASH_KEY 0xE214AD3D
-#define IXGBE_ATR_SIGNATURE_HASH_KEY 0x14364D17
-
-/* Software ATR input stream offsets and masks */
-#define IXGBE_ATR_VLAN_OFFSET 0
-#define IXGBE_ATR_SRC_IPV6_OFFSET 2
-#define IXGBE_ATR_SRC_IPV4_OFFSET 14
-#define IXGBE_ATR_DST_IPV6_OFFSET 18
-#define IXGBE_ATR_DST_IPV4_OFFSET 30
-#define IXGBE_ATR_SRC_PORT_OFFSET 34
-#define IXGBE_ATR_DST_PORT_OFFSET 36
-#define IXGBE_ATR_FLEX_BYTE_OFFSET 38
-#define IXGBE_ATR_VM_POOL_OFFSET 40
-#define IXGBE_ATR_L4TYPE_OFFSET 41
+#define IXGBE_ATR_BUCKET_HASH_KEY 0x3DAD14E2
+#define IXGBE_ATR_SIGNATURE_HASH_KEY 0x174D3614
+/* Software ATR input stream values and masks */
+#define IXGBE_ATR_HASH_MASK 0x7fff
#define IXGBE_ATR_L4TYPE_MASK 0x3
-#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4
#define IXGBE_ATR_L4TYPE_UDP 0x1
#define IXGBE_ATR_L4TYPE_TCP 0x2
#define IXGBE_ATR_L4TYPE_SCTP 0x3
-#define IXGBE_ATR_HASH_MASK 0x7fff
+#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4
+enum ixgbe_atr_flow_type {
+ IXGBE_ATR_FLOW_TYPE_IPV4 = 0x0,
+ IXGBE_ATR_FLOW_TYPE_UDPV4 = 0x1,
+ IXGBE_ATR_FLOW_TYPE_TCPV4 = 0x2,
+ IXGBE_ATR_FLOW_TYPE_SCTPV4 = 0x3,
+ IXGBE_ATR_FLOW_TYPE_IPV6 = 0x4,
+ IXGBE_ATR_FLOW_TYPE_UDPV6 = 0x5,
+ IXGBE_ATR_FLOW_TYPE_TCPV6 = 0x6,
+ IXGBE_ATR_FLOW_TYPE_SCTPV6 = 0x7,
+};
/* Flow Director ATR input struct. */
-struct ixgbe_atr_input {
- /* Byte layout in order, all values with MSB first:
+union ixgbe_atr_input {
+ /*
+ * Byte layout in order, all values with MSB first:
*
+ * vm_pool - 1 byte
+ * flow_type - 1 byte
* vlan_id - 2 bytes
* src_ip - 16 bytes
* dst_ip - 16 bytes
* src_port - 2 bytes
* dst_port - 2 bytes
* flex_bytes - 2 bytes
- * vm_pool - 1 byte
- * l4type - 1 byte
+ * rsvd0 - 2 bytes - space reserved must be 0.
*/
- uint8_t byte_stream[42];
+ struct {
+ uint8_t vm_pool;
+ uint8_t flow_type;
+ __be16 vlan_id;
+ __be32 dst_ip[4];
+ __be32 src_ip[4];
+ __be16 src_port;
+ __be16 dst_port;
+ __be16 flex_bytes;
+ __be16 rsvd0;
+ } formatted;
+ __be32 dword_stream[11];
+};
+
+/* Flow Director compressed ATR hash input struct */
+union ixgbe_atr_hash_dword {
+ struct {
+ uint8_t vm_pool;
+ uint8_t flow_type;
+ __be16 vlan_id;
+ } formatted;
+ __be32 ip;
+ struct {
+ __be16 src;
+ __be16 dst;
+ } port;
+ __be16 flex_bytes;
+ __be32 dword;
+};
+
+
+struct ixgbe_atr_input_masks {
+ __be16 rsvd0;
+ __be16 vlan_id_mask;
+ __be32 dst_ip_mask[4];
+ __be32 src_ip_mask[4];
+ __be16 src_port_mask;
+ __be16 dst_port_mask;
+ __be16 flex_mask;
+};
+
+/*
+ * Unavailable: The FCoE Boot Option ROM is not present in the flash.
+ * Disabled: Present; boot order is not set for any targets on the port.
+ * Enabled: Present; boot order is set for at least one target on the port.
+ */
+enum ixgbe_fcoe_boot_status {
+ ixgbe_fcoe_bootstatus_disabled = 0,
+ ixgbe_fcoe_bootstatus_enabled = 1,
+ ixgbe_fcoe_bootstatus_unavailable = 0xFFFF
};
enum ixgbe_eeprom_type {
@@ -2271,6 +2387,7 @@ enum ixgbe_mac_type {
ixgbe_mac_unknown = 0,
ixgbe_mac_82598EB,
ixgbe_mac_82599EB,
+ ixgbe_mac_82599_vf,
ixgbe_num_macs
};
@@ -2283,10 +2400,12 @@ enum ixgbe_phy_type {
ixgbe_phy_qt,
ixgbe_phy_xaui,
ixgbe_phy_nl,
- ixgbe_phy_tw_tyco,
- ixgbe_phy_tw_unknown,
+ ixgbe_phy_sfp_passive_tyco,
+ ixgbe_phy_sfp_passive_unknown,
+ ixgbe_phy_sfp_active_unknown,
ixgbe_phy_sfp_avago,
ixgbe_phy_sfp_ftl,
+ ixgbe_phy_sfp_ftl_active,
ixgbe_phy_sfp_unknown,
ixgbe_phy_sfp_intel,
ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/
@@ -2314,6 +2433,10 @@ enum ixgbe_sfp_type {
ixgbe_sfp_type_da_cu_core1 = 4,
ixgbe_sfp_type_srlr_core0 = 5,
ixgbe_sfp_type_srlr_core1 = 6,
+ ixgbe_sfp_type_da_act_lmt_core0 = 7,
+ ixgbe_sfp_type_da_act_lmt_core1 = 8,
+ ixgbe_sfp_type_1g_cu_core0 = 9,
+ ixgbe_sfp_type_1g_cu_core1 = 10,
ixgbe_sfp_type_not_present = 0xFFFE,
ixgbe_sfp_type_unknown = 0xFFFF
};
@@ -2356,25 +2479,25 @@ enum ixgbe_bus_type {
/* PCI bus speeds */
enum ixgbe_bus_speed {
ixgbe_bus_speed_unknown = 0,
- ixgbe_bus_speed_33,
- ixgbe_bus_speed_66,
- ixgbe_bus_speed_100,
- ixgbe_bus_speed_120,
- ixgbe_bus_speed_133,
- ixgbe_bus_speed_2500,
- ixgbe_bus_speed_5000,
+ ixgbe_bus_speed_33 = 33,
+ ixgbe_bus_speed_66 = 66,
+ ixgbe_bus_speed_100 = 100,
+ ixgbe_bus_speed_120 = 120,
+ ixgbe_bus_speed_133 = 133,
+ ixgbe_bus_speed_2500 = 2500,
+ ixgbe_bus_speed_5000 = 5000,
ixgbe_bus_speed_reserved
};
/* PCI bus widths */
enum ixgbe_bus_width {
ixgbe_bus_width_unknown = 0,
- ixgbe_bus_width_pcie_x1,
- ixgbe_bus_width_pcie_x2,
+ ixgbe_bus_width_pcie_x1 = 1,
+ ixgbe_bus_width_pcie_x2 = 2,
ixgbe_bus_width_pcie_x4 = 4,
ixgbe_bus_width_pcie_x8 = 8,
- ixgbe_bus_width_32,
- ixgbe_bus_width_64,
+ ixgbe_bus_width_32 = 32,
+ ixgbe_bus_width_64 = 64,
ixgbe_bus_width_reserved
};
@@ -2460,8 +2583,6 @@ struct ixgbe_hw_stats {
uint64_t mptc;
uint64_t bptc;
uint64_t xec;
- uint64_t rqsmr[16];
- uint64_t tqsmr[8];
uint64_t qprc[16];
uint64_t qptc[16];
uint64_t qbrc[16];
@@ -2487,8 +2608,8 @@ struct ixgbe_hw_stats {
struct ixgbe_hw;
/* iterator type for walking multicast address lists */
-typedef uint8_t* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, uint8_t **mc_addr_ptr,
- uint32_t *vmdq);
+typedef uint8_t* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw,
+ uint8_t **mc_addr_ptr, uint32_t *vmdq);
/* Function pointer table */
struct ixgbe_eeprom_operations {
@@ -2505,6 +2626,7 @@ struct ixgbe_mac_operations {
int32_t (*reset_hw)(struct ixgbe_hw *);
int32_t (*start_hw)(struct ixgbe_hw *);
int32_t (*clear_hw_cntrs)(struct ixgbe_hw *);
+ void (*enable_relaxed_ordering)(struct ixgbe_hw *);
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
uint32_t (*get_supported_physical_layer)(struct ixgbe_hw *);
int32_t (*get_mac_addr)(struct ixgbe_hw *, uint8_t *);
@@ -2512,6 +2634,7 @@ struct ixgbe_mac_operations {
int32_t (*set_san_mac_addr)(struct ixgbe_hw *, uint8_t *);
int32_t (*get_device_caps)(struct ixgbe_hw *, uint16_t *);
int32_t (*get_wwn_prefix)(struct ixgbe_hw *, uint16_t *, uint16_t *);
+ int32_t (*get_fcoe_boot_status)(struct ixgbe_hw *, uint16_t *);
int32_t (*stop_adapter)(struct ixgbe_hw *);
int32_t (*get_bus_info)(struct ixgbe_hw *);
void (*set_lan_id)(struct ixgbe_hw *);
@@ -2523,6 +2646,9 @@ struct ixgbe_mac_operations {
void (*release_swfw_sync)(struct ixgbe_hw *, uint16_t);
/* Link */
+ void (*disable_tx_laser)(struct ixgbe_hw *);
+ void (*enable_tx_laser)(struct ixgbe_hw *);
+ void (*flap_tx_laser)(struct ixgbe_hw *);
int32_t (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, int, int);
int32_t (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, int *, int);
int32_t (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
@@ -2550,6 +2676,8 @@ struct ixgbe_mac_operations {
int32_t (*clear_vfta)(struct ixgbe_hw *);
int32_t (*set_vfta)(struct ixgbe_hw *, uint32_t, uint32_t, int);
int32_t (*init_uta_tables)(struct ixgbe_hw *);
+ void (*set_mac_anti_spoofing)(struct ixgbe_hw *, int, int);
+ void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, int, int);
/* Flow Control */
int32_t (*fc_enable)(struct ixgbe_hw *, int32_t);
@@ -2572,6 +2700,7 @@ struct ixgbe_phy_operations {
int32_t (*read_i2c_eeprom)(struct ixgbe_hw *, uint8_t , uint8_t *);
int32_t (*write_i2c_eeprom)(struct ixgbe_hw *, uint8_t, uint8_t);
void (*i2c_bus_clear)(struct ixgbe_hw *);
+ int32_t (*check_overtemp)(struct ixgbe_hw *);
};
struct ixgbe_eeprom_info {
@@ -2582,6 +2711,7 @@ struct ixgbe_eeprom_info {
uint16_t address_bits;
};
+#define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01
struct ixgbe_mac_info {
struct ixgbe_mac_operations ops;
enum ixgbe_mac_type type;
@@ -2592,11 +2722,14 @@ struct ixgbe_mac_info {
uint16_t wwnn_prefix;
/* prefix for World Wide Port Name (WWPN) */
uint16_t wwpn_prefix;
+#define IXGBE_MAX_MTA 128
+ uint32_t mta_shadow[IXGBE_MAX_MTA];
int32_t mc_filter_type;
uint32_t mcft_size;
uint32_t vft_size;
uint32_t num_rar_entries;
uint32_t rar_highwater;
+ uint32_t rx_pb_size;
uint32_t max_tx_queues;
uint32_t max_rx_queues;
uint32_t max_msix_vectors;
@@ -2605,6 +2738,7 @@ struct ixgbe_mac_info {
uint32_t orig_autoc2;
int orig_link_settings_stored;
int autotry_restart;
+ uint8_t flags;
};
struct ixgbe_phy_info {
@@ -2621,6 +2755,101 @@ struct ixgbe_phy_info {
enum ixgbe_smart_speed smart_speed;
int smart_speed_active;
int multispeed_fiber;
+ int reset_if_overtemp;
+};
+
+/* MBX */
+#define IXGBE_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
+#define IXGBE_ERR_MBX -100
+
+#define IXGBE_VFMAILBOX 0x002FC
+#define IXGBE_VFMBMEM 0x00200
+
+/* Define mailbox register bits */
+#define IXGBE_VFMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
+#define IXGBE_VFMAILBOX_ACK 0x00000002 /* Ack PF message received */
+#define IXGBE_VFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
+#define IXGBE_VFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
+#define IXGBE_VFMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
+#define IXGBE_VFMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
+#define IXGBE_VFMAILBOX_RSTI 0x00000040 /* PF has reset indication */
+#define IXGBE_VFMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
+#define IXGBE_VFMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
+
+#define IXGBE_PFMAILBOX(x) (0x04B00 + (4 * x))
+#define IXGBE_PFMBMEM(vfn) (0x13000 + (64 * vfn))
+
+#define IXGBE_PFMAILBOX_STS 0x00000001 /* Initiate message send to VF */
+#define IXGBE_PFMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */
+#define IXGBE_PFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
+#define IXGBE_PFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
+#define IXGBE_PFMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */
+
+#define IXGBE_MBVFICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */
+#define IXGBE_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */
+#define IXGBE_MBVFICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */
+#define IXGBE_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */
+
+
+/* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the
+ * PF. The reverse is TRUE if it is IXGBE_PF_*.
+ * Message ACK's are the value or'd with 0xF0000000
+ */
+#define IXGBE_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
+ * this are the ACK */
+#define IXGBE_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
+ * this are the NACK */
+#define IXGBE_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
+ clear to send requests */
+#define IXGBE_VT_MSGINFO_SHIFT 16
+/* bits 23:16 are used for exra info for certain messages */
+#define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT)
+
+#define IXGBE_VF_RESET 0x01 /* VF requests reset */
+#define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */
+#define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */
+#define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */
+#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */
+
+/* length of permanent address message returned from PF */
+#define IXGBE_VF_PERMADDR_MSG_LEN 4
+/* word in permanent address message with the current multicast type */
+#define IXGBE_VF_MC_TYPE_WORD 3
+
+#define IXGBE_PF_CONTROL_MSG 0x0100 /* PF control message */
+
+#define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
+#define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */
+
+/* end MBX */
+
+struct ixgbe_mbx_operations {
+ void (*init_params)(struct ixgbe_hw *hw);
+ int32_t (*read)(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+ int32_t (*write)(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+ int32_t (*read_posted)(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+ int32_t (*write_posted)(struct ixgbe_hw *, uint32_t *, uint16_t, uint16_t);
+ int32_t (*check_for_msg)(struct ixgbe_hw *, uint16_t);
+ int32_t (*check_for_ack)(struct ixgbe_hw *, uint16_t);
+ int32_t (*check_for_rst)(struct ixgbe_hw *, uint16_t);
+};
+
+struct ixgbe_mbx_stats {
+ uint32_t msgs_tx;
+ uint32_t msgs_rx;
+
+ uint32_t acks;
+ uint32_t reqs;
+ uint32_t rsts;
+};
+
+struct ixgbe_mbx_info {
+ struct ixgbe_mbx_operations ops;
+ struct ixgbe_mbx_stats stats;
+ uint32_t timeout;
+ uint32_t usec_delay;
+ uint32_t v2p_mailbox;
+ uint16_t size;
};
struct ixgbe_hw {
@@ -2632,6 +2861,7 @@ struct ixgbe_hw {
struct ixgbe_phy_info phy;
struct ixgbe_eeprom_info eeprom;
struct ixgbe_bus_info bus;
+ struct ixgbe_mbx_info mbx;
uint16_t device_id;
uint16_t vendor_id;
uint16_t subsystem_device_id;
@@ -2676,6 +2906,14 @@ struct ixgbe_hw {
#define IXGBE_ERR_NO_SAN_ADDR_PTR -22
#define IXGBE_ERR_FDIR_REINIT_FAILED -23
#define IXGBE_ERR_EEPROM_VERSION -24
+#define IXGBE_ERR_NO_SPACE -25
+#define IXGBE_ERR_OVERTEMP -26
+#define IXGBE_ERR_FC_NOT_NEGOTIATED -27
+#define IXGBE_ERR_FC_NOT_SUPPORTED -28
+#define IXGBE_ERR_FLOW_CONTROL -29
+#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30
+#define IXGBE_ERR_PBA_SECTION -31
+#define IXGBE_ERR_INVALID_ARGUMENT -32
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#define UNREFERENCED_PARAMETER(_p)
@@ -2692,11 +2930,15 @@ struct ixgbe_hw {
#define IXGBE_SFF_1GBE_COMP_CODES 0x6
#define IXGBE_SFF_10GBE_COMP_CODES 0x3
#define IXGBE_SFF_CABLE_TECHNOLOGY 0x8
+#define IXGBE_SFF_CABLE_SPEC_COMP 0x3C
/* Bitmasks */
#define IXGBE_SFF_DA_PASSIVE_CABLE 0x4
+#define IXGBE_SFF_DA_ACTIVE_CABLE 0x8
+#define IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4
#define IXGBE_SFF_1GBASESX_CAPABLE 0x1
#define IXGBE_SFF_1GBASELX_CAPABLE 0x2
+#define IXGBE_SFF_1GBASET_CAPABLE 0x8
#define IXGBE_SFF_10GBASESR_CAPABLE 0x10
#define IXGBE_SFF_10GBASELR_CAPABLE 0x20
#define IXGBE_SFF_DA_BAD_HP_CABLE 0x80
@@ -2707,6 +2949,10 @@ struct ixgbe_hw {
#define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2
#define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3
+/* Flow control defines */
+#define IXGBE_TAF_SYM_PAUSE 0x400
+#define IXGBE_TAF_ASM_PAUSE 0x800
+
/* Bit-shift macros */
#define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 24
#define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 16
@@ -2730,6 +2976,9 @@ struct ixgbe_hw {
#define IXGBE_I2C_T_SU_STO 4
#define IXGBE_I2C_T_BUF 5
+#define IXGBE_TN_LASI_STATUS_REG 0x9005
+#define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008
+
/* end PHY */
#endif /* _IXGBE_TYPE_H_ */