svn commit: r191030 - stable/7/sys/dev/ixgbe
Jack F Vogel
jfv at FreeBSD.org
Mon Apr 13 17:23:14 PDT 2009
Author: jfv
Date: Tue Apr 14 00:23:13 2009
New Revision: 191030
URL: http://svn.freebsd.org/changeset/base/191030
Log:
MFC ixgbe version 1.7.4 for FreeBSD 7.2, this is earlier
than planned but coordinated with and approved by RE.
Most important reason for this was so that FreeBSD 7.2
will have native support for the 82599 controller which
is part of the Nehalem launch.
The driver now does pluggable optics, multispeed fiber,
and header split. I am adding this to the GENERIC kernel
only in the amd64 architecture since its where I expect
most use and others were untested.
Enjoy!
Approved by: re
Added:
stable/7/sys/dev/ixgbe/ixgbe_82599.c (contents, props changed)
Modified:
stable/7/sys/dev/ixgbe/LICENSE
stable/7/sys/dev/ixgbe/ixgbe.c
stable/7/sys/dev/ixgbe/ixgbe.h
stable/7/sys/dev/ixgbe/ixgbe_82598.c
stable/7/sys/dev/ixgbe/ixgbe_api.c
stable/7/sys/dev/ixgbe/ixgbe_api.h
stable/7/sys/dev/ixgbe/ixgbe_common.c
stable/7/sys/dev/ixgbe/ixgbe_common.h
stable/7/sys/dev/ixgbe/ixgbe_osdep.h
stable/7/sys/dev/ixgbe/ixgbe_phy.c
stable/7/sys/dev/ixgbe/ixgbe_phy.h
stable/7/sys/dev/ixgbe/ixgbe_type.h
Modified: stable/7/sys/dev/ixgbe/LICENSE
==============================================================================
--- stable/7/sys/dev/ixgbe/LICENSE Mon Apr 13 23:50:44 2009 (r191029)
+++ stable/7/sys/dev/ixgbe/LICENSE Tue Apr 14 00:23:13 2009 (r191030)
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
Modified: stable/7/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- stable/7/sys/dev/ixgbe/ixgbe.c Mon Apr 13 23:50:44 2009 (r191029)
+++ stable/7/sys/dev/ixgbe/ixgbe.c Tue Apr 14 00:23:13 2009 (r191030)
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,7 @@ int ixgbe_display_debug_stat
/*********************************************************************
* Driver version
*********************************************************************/
-char ixgbe_driver_version[] = "1.6.2";
+char ixgbe_driver_version[] = "1.7.4";
/*********************************************************************
* PCI Device ID Table
@@ -71,6 +71,8 @@ static ixgbe_vendor_info_t ixgbe_vendor_
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
+ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
+ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
/* required last entry */
{0, 0, 0, 0, 0}
};
@@ -104,7 +106,9 @@ static int ixgbe_allocate_pci_resou
static int ixgbe_allocate_msix(struct adapter *);
static int ixgbe_allocate_legacy(struct adapter *);
static int ixgbe_allocate_queues(struct adapter *);
+#if __FreeBSD_version >= 602105
static int ixgbe_setup_msix(struct adapter *);
+#endif
static void ixgbe_free_pci_resources(struct adapter *);
static void ixgbe_local_timer(void *);
static int ixgbe_hardware_init(struct adapter *);
@@ -124,6 +128,7 @@ static void ixgbe_initialize_receive
static void ixgbe_free_receive_structures(struct adapter *);
static void ixgbe_free_receive_buffers(struct rx_ring *);
+static void ixgbe_init_moderation(struct adapter *);
static void ixgbe_enable_intr(struct adapter *);
static void ixgbe_disable_intr(struct adapter *);
static void ixgbe_update_stats_counters(struct adapter *);
@@ -146,7 +151,7 @@ static int ixgbe_dma_malloc(struct adapt
static void ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *);
static void ixgbe_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
-static boolean_t ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
+static int ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
static boolean_t ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
static void ixgbe_set_ivar(struct adapter *, u16, u8, s8);
static void ixgbe_configure_ivars(struct adapter *);
@@ -157,6 +162,12 @@ static void ixgbe_register_vlan(void *,
static void ixgbe_unregister_vlan(void *, struct ifnet *, u16);
#endif
+#ifdef IXGBE_TIMESYNC
+/* Precision Time sync support */
+static int ixgbe_tsync_init(struct adapter *);
+static void ixgbe_tsync_disable(struct adapter *);
+#endif
+
static void ixgbe_update_aim(struct rx_ring *);
/* Support for pluggable optic modules */
@@ -165,14 +176,19 @@ static bool ixgbe_sfp_probe(struct adapt
/* Legacy (single vector interrupt handler */
static void ixgbe_legacy_irq(void *);
+#if __FreeBSD_version >= 602105
/* The MSI/X Interrupt handlers */
static void ixgbe_msix_tx(void *);
static void ixgbe_msix_rx(void *);
static void ixgbe_msix_link(void *);
+#endif
-/* Legacy interrupts use deferred handlers */
-static void ixgbe_handle_tx(void *context, int pending);
-static void ixgbe_handle_rx(void *context, int pending);
+/* Deferred interrupt tasklets */
+static void ixgbe_handle_tx(void *, int);
+static void ixgbe_handle_rx(void *, int);
+static void ixgbe_handle_link(void *, int);
+static void ixgbe_handle_msf(void *, int);
+static void ixgbe_handle_mod(void *, int);
/*********************************************************************
@@ -213,8 +229,8 @@ static int ixgbe_enable_aim = TRUE;
TUNABLE_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim);
static int ixgbe_low_latency = IXGBE_LOW_LATENCY;
TUNABLE_INT("hw.ixgbe.low_latency", &ixgbe_low_latency);
-static int ixgbe_ave_latency = IXGBE_LOW_LATENCY;
-TUNABLE_INT("hw.ixgbe.ave_latency", &ixgbe_low_latency);
+static int ixgbe_ave_latency = IXGBE_AVE_LATENCY;
+TUNABLE_INT("hw.ixgbe.ave_latency", &ixgbe_ave_latency);
static int ixgbe_bulk_latency = IXGBE_BULK_LATENCY;
TUNABLE_INT("hw.ixgbe.bulk_latency", &ixgbe_bulk_latency);
@@ -222,8 +238,8 @@ TUNABLE_INT("hw.ixgbe.bulk_latency", &ix
static int ixgbe_rx_process_limit = 100;
TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
-/* Flow control setting, default to full */
-static int ixgbe_flow_control = ixgbe_fc_none;
+/* Flow control setting, default to off */
+static int ixgbe_flow_control = ixgbe_fc_full;
TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
/*
@@ -239,11 +255,16 @@ TUNABLE_INT("hw.ixgbe.enable_lro", &ixgb
* MSIX should be the default for best performance,
* but this allows it to be forced off for testing.
*/
+#if __FreeBSD_version >= 602105
static int ixgbe_enable_msix = 1;
+#else
+static int ixgbe_enable_msix = 0;
+#endif
TUNABLE_INT("hw.ixgbe.enable_msix", &ixgbe_enable_msix);
/*
* Enable RX Header Split
+ * WARNING: disable this if bridging or forwarding!!
*/
static int ixgbe_rx_hdr_split = 1;
TUNABLE_INT("hw.ixgbe.rx_hdr_split", &ixgbe_rx_hdr_split);
@@ -268,6 +289,13 @@ TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
/* Total number of Interfaces - need for config sanity check */
static int ixgbe_total_ports;
+/*
+** The number of scatter-gather segments
+** differs for 82598 and 82599, default to
+** the former.
+*/
+static int ixgbe_num_segs = IXGBE_82598_SCATTER;
+
/*********************************************************************
* Device identification routine
*
@@ -312,6 +340,7 @@ ixgbe_probe(device_t dev)
ixgbe_strings[ent->index],
ixgbe_driver_version);
device_set_desc_copy(dev, adapter_name);
+ ++ixgbe_total_ports;
return (0);
}
ent++;
@@ -333,6 +362,7 @@ static int
ixgbe_attach(device_t dev)
{
struct adapter *adapter;
+ struct ixgbe_hw *hw;
int error = 0;
u16 pci_device_id;
u32 ctrl_ext;
@@ -342,37 +372,34 @@ ixgbe_attach(device_t dev)
/* Allocate, clear, and link in our adapter structure */
adapter = device_get_softc(dev);
adapter->dev = adapter->osdep.dev = dev;
+ hw = &adapter->hw;
/* Core Lock Init*/
IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
- /* Keep track of number of ports and optics */
+ /* Keep track of optics */
pci_device_id = pci_get_device(dev);
switch (pci_device_id) {
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT :
+ case IXGBE_DEV_ID_82598EB_CX4 :
adapter->optics = IFM_10G_CX4;
- ixgbe_total_ports += 2;
break;
case IXGBE_DEV_ID_82598AF_DUAL_PORT :
- adapter->optics = IFM_10G_SR;
- ixgbe_total_ports += 2;
- break;
+ case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
case IXGBE_DEV_ID_82598AF_SINGLE_PORT :
+ case IXGBE_DEV_ID_82598AT :
adapter->optics = IFM_10G_SR;
- ixgbe_total_ports += 1;
break;
case IXGBE_DEV_ID_82598EB_XF_LR :
adapter->optics = IFM_10G_LR;
- ixgbe_total_ports += 1;
break;
- case IXGBE_DEV_ID_82598EB_CX4 :
- adapter->optics = IFM_10G_CX4;
- ixgbe_total_ports += 1;
+ case IXGBE_DEV_ID_82599_SFP :
+ adapter->optics = IFM_10G_SR;
+ ixgbe_num_segs = IXGBE_82599_SCATTER;
break;
- case IXGBE_DEV_ID_82598AT :
- ixgbe_total_ports += 1;
- case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
- ixgbe_total_ports += 2;
+ case IXGBE_DEV_ID_82599_KX4 :
+ adapter->optics = IFM_10G_CX4;
+ ixgbe_num_segs = IXGBE_82599_SCATTER;
default:
break;
}
@@ -474,7 +501,7 @@ ixgbe_attach(device_t dev)
}
/* Initialize the shared code */
- error = ixgbe_init_shared_code(&adapter->hw);
+ error = ixgbe_init_shared_code(hw);
if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
/*
** No optics in this port, set up
@@ -525,11 +552,11 @@ ixgbe_attach(device_t dev)
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
ixgbe_unregister_vlan, 0, EVENTHANDLER_PRI_FIRST);
#endif
-
+
/* let hardware know driver is loaded */
- ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
+ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
INIT_DEBUGOUT("ixgbe_attach: end");
return (0);
@@ -590,6 +617,14 @@ ixgbe_detach(device_t dev)
}
}
+ /* Drain the Link queue */
+ if (adapter->tq) {
+ taskqueue_drain(adapter->tq, &adapter->link_task);
+ taskqueue_drain(adapter->tq, &adapter->mod_task);
+ taskqueue_drain(adapter->tq, &adapter->msf_task);
+ taskqueue_free(adapter->tq);
+ }
+
/* let hardware know driver is unloading */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
@@ -662,6 +697,19 @@ ixgbe_start_locked(struct tx_ring *txr,
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL)
break;
+ /*
+ * Force a cleanup if number of TX descriptors
+ * available is below the threshold. If it fails
+ * to get above, then abort transmit.
+ */
+ if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) {
+ ixgbe_txeof(txr);
+ /* Make sure things have improved */
+ if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
+ txr->no_tx_desc_avail++;
+ break;
+ }
+ }
if (ixgbe_xmit(txr, &m_head)) {
if (m_head == NULL)
@@ -701,7 +749,8 @@ ixgbe_start(struct ifnet *ifp)
txr = &adapter->tx_rings[queue];
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_TX_LOCK(txr);
+ if (IXGBE_TX_TRYLOCK(txr) == 0)
+ return;
ixgbe_start_locked(txr, ifp);
IXGBE_TX_UNLOCK(txr);
}
@@ -803,6 +852,67 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
#endif
break;
}
+#ifdef IXGBE_TIMESYNC
+ /*
+ ** IOCTL support for Precision Time (IEEE 1588) Support
+ */
+ case IXGBE_TIMESYNC_READTS:
+ {
+ u32 rx_ctl, tx_ctl;
+ struct ixgbe_tsync_read *tdata;
+
+ tdata = (struct ixgbe_tsync_read *) ifr->ifr_data;
+
+ if (tdata->read_current_time) {
+ getnanotime(&tdata->system_time);
+ tdata->network_time = IXGBE_READ_REG(&adapter->hw,
+ IXGBE_SYSTIML);
+ tdata->network_time |=
+ (u64)IXGBE_READ_REG(&adapter->hw,
+ IXGBE_SYSTIMH ) << 32;
+ }
+
+ rx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCRXCTL);
+ tx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCTXCTL);
+
+ if (rx_ctl & 0x1) {
+ u32 tmp;
+ unsigned char *tmp_cp;
+
+ tdata->rx_valid = 1;
+ tdata->rx_stamp = IXGBE_READ_REG(&adapter->hw,
+ IXGBE_RXSTMPL);
+ tdata->rx_stamp |= (u64)IXGBE_READ_REG(&adapter->hw,
+ IXGBE_RXSTMPH) << 32;
+
+ tmp = IXGBE_READ_REG(&adapter->hw, IXGBE_RXSATRL);
+ tmp_cp = (unsigned char *) &tmp;
+ tdata->srcid[0] = tmp_cp[0];
+ tdata->srcid[1] = tmp_cp[1];
+ tdata->srcid[2] = tmp_cp[2];
+ tdata->srcid[3] = tmp_cp[3];
+ tmp = IXGBE_READ_REG(&adapter->hw, IXGBE_RXSATRH);
+ tmp_cp = (unsigned char *) &tmp;
+ tdata->srcid[4] = tmp_cp[0];
+ tdata->srcid[5] = tmp_cp[1];
+ tdata->seqid = tmp >> 16;
+ tdata->seqid = htons(tdata->seqid);
+ } else
+ tdata->rx_valid = 0;
+
+ if (tx_ctl & 0x1) {
+ tdata->tx_valid = 1;
+ tdata->tx_stamp = IXGBE_READ_REG(&adapter->hw,
+ IXGBE_TXSTMPL);
+ tdata->tx_stamp |= (u64) IXGBE_READ_REG(&adapter->hw,
+ IXGBE_TXSTMPH) << 32;
+ } else
+ tdata->tx_valid = 0;
+
+ return (0);
+ }
+#endif /* IXGBE_TIMESYNC */
+
default:
IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
error = ether_ioctl(ifp, command, data);
@@ -905,13 +1015,12 @@ ixgbe_watchdog(struct adapter *adapter)
static void
ixgbe_init_locked(struct adapter *adapter)
{
- struct rx_ring *rxr = adapter->rx_rings;
- struct tx_ring *txr = adapter->tx_rings;
struct ifnet *ifp = adapter->ifp;
device_t dev = adapter->dev;
struct ixgbe_hw *hw;
u32 k, txdctl, mhadd, gpie;
u32 rxdctl, rxctrl;
+ int err;
INIT_DEBUGOUT("ixgbe_init: begin");
@@ -951,13 +1060,6 @@ ixgbe_init_locked(struct adapter *adapte
ixgbe_initialize_transmit_units(adapter);
- /* TX irq moderation rate is fixed */
- for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(txr->msix), ixgbe_ave_latency);
- txr->watchdog_timer = FALSE;
- }
-
/* Setup Multicast table */
ixgbe_set_multi(adapter);
@@ -980,23 +1082,21 @@ ixgbe_init_locked(struct adapter *adapte
/* Configure RX settings */
ixgbe_initialize_receive_units(adapter);
- /* RX moderation will be adapted over time, set default */
- for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(rxr->msix), ixgbe_low_latency);
- }
-
- /* Set Link moderation */
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(adapter->linkvec), IXGBE_LINK_ITR);
+ /* Configure Interrupt Moderation */
+ ixgbe_init_moderation(adapter);
gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ gpie |= IXGBE_SDP1_GPIEN;
+ gpie |= IXGBE_SDP2_GPIEN;
+ }
+
/* Enable Fan Failure Interrupt */
- if (adapter->hw.phy.media_type == ixgbe_media_type_copper)
+ if (hw->device_id == IXGBE_DEV_ID_82598AT)
gpie |= IXGBE_SDP1_GPIEN;
- if (adapter->msix) {
+ if (adapter->msix > 2) {
/* Enable Enhanced MSIX mode */
gpie |= IXGBE_GPIE_MSIX_MODE;
gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
@@ -1058,9 +1158,40 @@ ixgbe_init_locked(struct adapter *adapte
/* Set up MSI/X routing */
if (ixgbe_enable_msix)
ixgbe_configure_ivars(adapter);
+ else { /* Simple settings for Legacy/MSI */
+ ixgbe_set_ivar(adapter, 0, 0, 0);
+ ixgbe_set_ivar(adapter, 0, 0, 1);
+ }
ixgbe_enable_intr(adapter);
+ /*
+ ** Check on any SFP devices that
+ ** need to be kick-started
+ */
+ err = hw->phy.ops.identify(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev,
+ "Unsupported SFP+ module type was detected.\n");
+ ixgbe_detach(dev);
+ return;
+ }
+ if (ixgbe_is_sfp(hw)) {
+ if (hw->phy.multispeed_fiber) {
+ hw->mac.ops.setup_sfp(hw);
+ taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+ } else
+ taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+ } else
+ taskqueue_enqueue(adapter->tq, &adapter->link_task);
+
+
+#ifdef IXGBE_TIMESYNC
+ /* Initialize IEEE 1588 support */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ ixgbe_tsync_init(adapter);
+#endif
+
/* Now inform the stack we're ready */
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -1081,7 +1212,7 @@ ixgbe_init(void *arg)
/*
-** MSIX Interrupt Handlers
+** MSIX Interrupt Tasklets
*/
static void
@@ -1136,7 +1267,8 @@ ixgbe_legacy_irq(void *arg)
struct ixgbe_hw *hw = &adapter->hw;
struct tx_ring *txr = adapter->tx_rings;
struct rx_ring *rxr = adapter->rx_rings;
- u32 reg_eicr;
+ bool more;
+ u32 reg_eicr, loop = MAX_LOOP;
reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
@@ -1148,7 +1280,15 @@ ixgbe_legacy_irq(void *arg)
if (ixgbe_rxeof(rxr, adapter->rx_process_limit))
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
- if (ixgbe_txeof(txr))
+
+ IXGBE_TX_LOCK(txr);
+ ++txr->tx_irq;
+ do {
+ more = ixgbe_txeof(txr);
+ } while (loop-- && more);
+ IXGBE_TX_UNLOCK(txr);
+
+ if (more)
taskqueue_enqueue(txr->tq, &txr->tx_task);
/* Check for fan failure */
@@ -1160,20 +1300,27 @@ ixgbe_legacy_irq(void *arg)
}
/* Link status change */
- if (reg_eicr & IXGBE_EICR_LSC)
+ if (reg_eicr & IXGBE_EICR_LSC) {
+ ixgbe_check_link(&adapter->hw,
+ &adapter->link_speed, &adapter->link_up, 0);
ixgbe_update_link_status(adapter);
+ }
+
+ /* Update interrupt rate */
+ if (ixgbe_enable_aim == TRUE)
+ ixgbe_update_aim(rxr);
ixgbe_enable_intr(adapter);
return;
}
+#if __FreeBSD_version >= 602105
/*********************************************************************
*
* MSI TX Interrupt Service routine
*
**********************************************************************/
-
void
ixgbe_msix_tx(void *arg)
{
@@ -1181,6 +1328,8 @@ ixgbe_msix_tx(void *arg)
struct adapter *adapter = txr->adapter;
bool more;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, txr->eims);
+
IXGBE_TX_LOCK(txr);
++txr->tx_irq;
more = ixgbe_txeof(txr);
@@ -1198,7 +1347,6 @@ ixgbe_msix_tx(void *arg)
* MSIX RX Interrupt Service routine
*
**********************************************************************/
-
static void
ixgbe_msix_rx(void *arg)
{
@@ -1206,18 +1354,72 @@ ixgbe_msix_rx(void *arg)
struct adapter *adapter = rxr->adapter;
bool more;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims);
+
++rxr->rx_irq;
- more = ixgbe_rxeof(rxr, -1);
+ more = ixgbe_rxeof(rxr, adapter->rx_process_limit);
+
+ /* Update interrupt rate */
+ if (ixgbe_enable_aim == TRUE)
+ ixgbe_update_aim(rxr);
+
if (more)
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
else
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rxr->eims);
- /* Update interrupt rate */
- if (ixgbe_enable_aim == TRUE)
- ixgbe_update_aim(rxr);
return;
}
+
+static void
+ixgbe_msix_link(void *arg)
+{
+ struct adapter *adapter = arg;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reg_eicr;
+
+ ++adapter->link_irq;
+
+ /* First get the cause */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, IXGBE_EIMS_OTHER);
+ reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
+ /* Clear with write */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
+
+ /* Link status change */
+ if (reg_eicr & IXGBE_EICR_LSC)
+ taskqueue_enqueue(adapter->tq, &adapter->link_task);
+
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ if (reg_eicr & IXGBE_EICR_ECC) {
+ device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! "
+ "Please Reboot!!\n");
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
+ }
+ if (reg_eicr & IXGBE_EICR_GPI_SDP1) {
+ /* Clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+ taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+ } else if (reg_eicr & IXGBE_EICR_GPI_SDP2) {
+ /* Clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
+ taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+ }
+ }
+
+ /* Check for fan failure */
+ if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
+ (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
+ device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
+ "REPLACE IMMEDIATELY!!\n");
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+ }
+
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
+ return;
+}
+#endif /* FreeBSD_version >= 602105 */
+
/*
** Routine to do adjust the RX EITR value based on traffic,
** its a simple three state model, but seems to help.
@@ -1267,33 +1469,36 @@ ixgbe_update_aim(struct rx_ring *rxr)
return;
}
-
static void
-ixgbe_msix_link(void *arg)
+ixgbe_init_moderation(struct adapter *adapter)
{
- struct adapter *adapter = arg;
- struct ixgbe_hw *hw = &adapter->hw;
- u32 reg_eicr;
-
- ++adapter->link_irq;
+ struct rx_ring *rxr = adapter->rx_rings;
+ struct tx_ring *txr = adapter->tx_rings;
- reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+ /* Single interrupt - MSI or Legacy? */
+ if (adapter->msix < 2) {
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(0), 100);
+ return;
+ }
- if (reg_eicr & IXGBE_EICR_LSC)
- ixgbe_update_link_status(adapter);
+ /* TX irq moderation rate is fixed */
+ for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_EITR(txr->msix), ixgbe_ave_latency);
+ txr->watchdog_timer = FALSE;
+ }
- /* Check for fan failure */
- if ((hw->phy.media_type == ixgbe_media_type_copper) &&
- (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
- device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
- "REPLACE IMMEDIATELY!!\n");
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1);
+ /* RX moderation will be adapted over time, set default */
+ for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_EITR(rxr->msix), ixgbe_low_latency);
}
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
- return;
-}
+ /* Set Link moderation */
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_EITR(adapter->linkvec), IXGBE_LINK_ITR);
+}
/*********************************************************************
*
@@ -1382,12 +1587,12 @@ static int
ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
{
struct adapter *adapter = txr->adapter;
- u32 olinfo_status = 0, cmd_type_len = 0;
+ u32 olinfo_status = 0, cmd_type_len;
u32 paylen = 0;
int i, j, error, nsegs;
- int first, last = 0;
+ int first, last = 0, offload = 0;
struct mbuf *m_head;
- bus_dma_segment_t segs[IXGBE_MAX_SCATTER];
+ bus_dma_segment_t segs[ixgbe_num_segs];
bus_dmamap_t map;
struct ixgbe_tx_buf *txbuf, *txbuf_mapped;
union ixgbe_adv_tx_desc *txd = NULL;
@@ -1395,26 +1600,12 @@ ixgbe_xmit(struct tx_ring *txr, struct m
m_head = *m_headp;
/* Basic descriptor defines */
- cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA;
- cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT;
+ cmd_type_len = (IXGBE_ADVTXD_DTYP_DATA |
+ IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);
if (m_head->m_flags & M_VLANTAG)
cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
- /*
- * Force a cleanup if number of TX descriptors
- * available is below the threshold. If it fails
- * to get above, then abort transmit.
- */
- if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) {
- ixgbe_txeof(txr);
- /* Make sure things have improved */
- if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
- txr->no_tx_desc_avail++;
- return (ENOBUFS);
- }
- }
-
/*
* Important to capture the first descriptor
* used because it will contain the index of
@@ -1475,19 +1666,27 @@ ixgbe_xmit(struct tx_ring *txr, struct m
m_head = *m_headp;
/*
- ** Set the appropriate offload context
+ ** Set up the appropriate offload context
** this becomes the first descriptor of
** a packet.
*/
- if (ixgbe_tso_setup(txr, m_head, &paylen)) {
- cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
- olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
- olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
- olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
- ++adapter->tso_tx;
- } else if (ixgbe_tx_ctx_setup(txr, m_head))
+ if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
+ if (ixgbe_tso_setup(txr, m_head, &paylen)) {
+ cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
+ olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-
+ olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
+ ++adapter->tso_tx;
+ } else
+ return (ENXIO);
+ } else /* Offloads other than TSO */
+ offload = ixgbe_tx_ctx_setup(txr, m_head);
+ if (offload == TRUE)
+ olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
+#ifdef IXGBE_TIMESYNC
+ if (offload == IXGBE_TIMESTAMP)
+ cmd_type_len |= IXGBE_ADVTXD_TSTAMP;
+#endif
/* Record payload length */
if (paylen == 0)
olinfo_status |= m_head->m_pkthdr.len <<
@@ -1513,6 +1712,7 @@ ixgbe_xmit(struct tx_ring *txr, struct m
i = 0;
txbuf->m_head = NULL;
+ txbuf->eop_index = -1;
}
txd->read.cmd_type_len |=
@@ -1526,6 +1726,7 @@ ixgbe_xmit(struct tx_ring *txr, struct m
/* Set the index of the descriptor that will be marked done */
txbuf = &txr->tx_buffers[first];
+ txbuf->eop_index = last;
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1685,17 +1886,20 @@ out:
callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
}
+/*
+** Note: this routine updates the OS on the link state
+** the real check of the hardware only happens with
+** a link interrupt.
+*/
static void
ixgbe_update_link_status(struct adapter *adapter)
{
- boolean_t link_up = FALSE;
struct ifnet *ifp = adapter->ifp;
struct tx_ring *txr = adapter->tx_rings;
device_t dev = adapter->dev;
- ixgbe_check_link(&adapter->hw, &adapter->link_speed, &link_up, 0);
- if (link_up){
+ if (adapter->link_up){
if (adapter->link_active == FALSE) {
if (bootverbose)
device_printf(dev,"Link is up %d Gbps %s \n",
@@ -1720,7 +1924,6 @@ ixgbe_update_link_status(struct adapter
}
-
/*********************************************************************
*
* This routine disables all traffic on the adapter by issuing a
@@ -1743,6 +1946,11 @@ ixgbe_stop(void *arg)
/* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+#ifdef IXGBE_TIMESYNC
+ /* Disable IEEE 1588 support */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ ixgbe_tsync_disable(adapter);
+#endif
ixgbe_reset_hw(&adapter->hw);
adapter->hw.adapter_stopped = FALSE;
ixgbe_stop_adapter(&adapter->hw);
@@ -1817,8 +2025,13 @@ ixgbe_allocate_legacy(struct adapter *ad
device_get_nameunit(adapter->dev));
taskqueue_start_threads(&rxr->tq, 1, PI_NET, "%s rxq",
device_get_nameunit(adapter->dev));
+
if ((error = bus_setup_intr(dev, adapter->res[0],
+#if __FreeBSD_version >= 700000
INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq,
+#else
+ INTR_TYPE_NET | INTR_MPSAFE, ixgbe_legacy_irq,
+#endif
adapter, &adapter->tag[0])) != 0) {
device_printf(dev, "Failed to register fast interrupt "
"handler: %d\n", error);
@@ -1833,6 +2046,7 @@ ixgbe_allocate_legacy(struct adapter *ad
}
+#if __FreeBSD_version >= 602105
/*********************************************************************
*
* Setup MSIX Interrupt resources and handlers
@@ -1859,7 +2073,10 @@ ixgbe_allocate_msix(struct adapter *adap
}
/* Set the handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+ NULL,
+#endif
ixgbe_msix_tx, txr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
@@ -1867,7 +2084,7 @@ ixgbe_allocate_msix(struct adapter *adap
return (error);
}
txr->msix = vector;
- txr->eims = IXGBE_IVAR_TX_QUEUE(vector);
+ txr->eims = 1 << vector;
TASK_INIT(&txr->tx_task, 0, ixgbe_handle_tx, txr);
txr->tq = taskqueue_create_fast("ixgbe_txq", M_NOWAIT,
taskqueue_thread_enqueue, &txr->tq);
@@ -1888,15 +2105,18 @@ ixgbe_allocate_msix(struct adapter *adap
}
/* Set the handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_rx,
- rxr, &adapter->tag[vector]);
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+ NULL,
+#endif
+ ixgbe_msix_rx, rxr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
device_printf(dev, "Failed to register RX handler");
return (error);
}
rxr->msix = vector;
- rxr->eims = IXGBE_IVAR_RX_QUEUE(vector);
+ rxr->eims = 1 << vector;
/* used in local timer */
adapter->rx_mask |= rxr->eims;
TASK_INIT(&rxr->rx_task, 0, ixgbe_handle_rx, rxr);
@@ -1916,19 +2136,37 @@ ixgbe_allocate_msix(struct adapter *adap
}
/* Set the link handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_link,
- adapter, &adapter->tag[vector]);
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+ NULL,
+#endif
+ ixgbe_msix_link, adapter, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
device_printf(dev, "Failed to register LINK handler");
return (error);
}
adapter->linkvec = vector;
+ /* Tasklets for Link, SFP and Multispeed Fiber */
+ TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
+ TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
+ TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
+ adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
+ taskqueue_thread_enqueue, &adapter->tq);
+ taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
+ device_get_nameunit(adapter->dev));
return (0);
}
+#else /* Freebsd 6.1/2 */
+static int
+ixgbe_allocate_msix(struct adapter *adapter)
+{
+ return (1);
+}
+#endif
-
+#if __FreeBSD_version >= 602105
/*
* Setup Either MSI/X or MSI
*/
@@ -1996,6 +2234,7 @@ msi:
device_printf(adapter->dev,"Using MSI interrupt\n");
return (msgs);
}
+#endif /* FreeBSD_version >= 602105 */
static int
ixgbe_allocate_pci_resources(struct adapter *adapter)
@@ -2031,9 +2270,10 @@ ixgbe_allocate_pci_resources(struct adap
adapter->num_tx_queues = 1;
adapter->num_rx_queues = 1;
+#if __FreeBSD_version >= 602105
/* Now setup MSI or MSI/X */
adapter->msix = ixgbe_setup_msix(adapter);
-
+#endif
adapter->hw.back = &adapter->osdep;
return (0);
}
@@ -2051,7 +2291,10 @@ ixgbe_free_pci_resources(struct adapter
if (adapter->msix == 0)
adapter->msix = 1;
- rid = PCIR_BAR(MSIX_82598_BAR);
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ rid = PCIR_BAR(MSIX_82598_BAR);
+ else
+ rid = PCIR_BAR(MSIX_82599_BAR);
/*
* First release all the interrupt resources:
@@ -2071,12 +2314,14 @@ ixgbe_free_pci_resources(struct adapter
}
}
+#if __FreeBSD_version >= 602105
if (adapter->msix)
pci_release_msi(dev);
if (adapter->msix_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
rid, adapter->msix_mem);
+#endif
if (adapter->pci_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
@@ -2215,7 +2460,7 @@ ixgbe_dma_malloc(struct adapter *adapter
int r;
r = bus_dma_tag_create(NULL, /* parent */
- PAGE_SIZE, 0, /* alignment, bounds */
+ 1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
@@ -2415,12 +2660,12 @@ ixgbe_allocate_transmit_buffers(struct t
* Setup DMA descriptor areas.
*/
if ((error = bus_dma_tag_create(NULL, /* parent */
- PAGE_SIZE, 0, /* alignment, bounds */
+ 1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
IXGBE_TSO_SIZE, /* maxsize */
- IXGBE_MAX_SCATTER, /* nsegments */
+ ixgbe_num_segs, /* nsegments */
PAGE_SIZE, /* maxsegsize */
0, /* flags */
NULL, /* lockfunc */
@@ -2484,6 +2729,8 @@ ixgbe_setup_transmit_ring(struct tx_ring
m_freem(txbuf->m_head);
txbuf->m_head = NULL;
}
+ /* Clear the EOP index */
+ txbuf->eop_index = -1;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-7
mailing list