summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2007-09-04 02:31:35 +0000
committerjfv <jfv@FreeBSD.org>2007-09-04 02:31:35 +0000
commit4130a5f18eed16cb9f94a0fcd51f1a647e05d482 (patch)
treed3cbef1453420f4aa11a6c8aa57bc03d94bc4120
parent2128419ce0e7d289fdf900cb1903e62bfd962d38 (diff)
downloadFreeBSD-src-4130a5f18eed16cb9f94a0fcd51f1a647e05d482.zip
FreeBSD-src-4130a5f18eed16cb9f94a0fcd51f1a647e05d482.tar.gz
This is an update to the new Intel 10G 82598 driver.
The first drop was Beta, this code is expected to be the release version. Note that this driver code will build in either 6.2 or 7. If you use the code in 6.2 you will not get TSO or MSI/X support but it will function in a legacy mode. Approved by: re
-rw-r--r--sys/dev/ixgbe/ixgbe.c607
-rw-r--r--sys/dev/ixgbe/ixgbe.h78
-rw-r--r--sys/dev/ixgbe/ixgbe_82598.c342
-rw-r--r--sys/dev/ixgbe/ixgbe_api.c76
-rw-r--r--sys/dev/ixgbe/ixgbe_api.h3
-rw-r--r--sys/dev/ixgbe/ixgbe_common.c4
-rw-r--r--sys/dev/ixgbe/ixgbe_osdep.h2
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.c191
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.h10
-rw-r--r--sys/dev/ixgbe/ixgbe_type.h106
-rw-r--r--sys/modules/ixgbe/Makefile15
11 files changed, 958 insertions, 476 deletions
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index 6e1707d..fbb24d7 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -46,7 +46,7 @@ int ixgbe_display_debug_stats = 0;
/*********************************************************************
* Driver version
*********************************************************************/
-char ixgbe_driver_version[] = "1.1.3";
+char ixgbe_driver_version[] = "1.2.6";
/*********************************************************************
* PCI Device ID Table
@@ -60,10 +60,9 @@ char ixgbe_driver_version[] = "1.1.3";
static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
{
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
- {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT_DUAL_PORT, 0, 0, 0},
+ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
/* required last entry */
{0, 0, 0, 0, 0}
};
@@ -100,8 +99,9 @@ static int ixgbe_hardware_init(struct adapter *);
static void ixgbe_setup_interface(device_t, struct adapter *);
static int ixgbe_allocate_queues(struct adapter *);
static int ixgbe_allocate_msix_resources(struct adapter *);
+#if __FreeBSD_version >= 700000
static int ixgbe_setup_msix(struct adapter *);
-
+#endif
static int ixgbe_allocate_transmit_buffers(struct tx_ring *);
static int ixgbe_setup_transmit_structures(struct adapter *);
static void ixgbe_setup_transmit_ring(struct tx_ring *);
@@ -119,7 +119,7 @@ static void ixgbe_free_receive_buffers(struct rx_ring *);
static void ixgbe_enable_intr(struct adapter *);
static void ixgbe_disable_intr(struct adapter *);
static void ixgbe_update_stats_counters(struct adapter *);
-static boolean_t ixgbe_txeof(struct tx_ring *);
+static bool ixgbe_txeof(struct tx_ring *);
static int ixgbe_rxeof(struct rx_ring *, int);
static void ixgbe_rx_checksum(struct adapter *, uint32_t, struct mbuf *);
static void ixgbe_set_promisc(struct adapter *);
@@ -133,6 +133,7 @@ static void ixgbe_enable_vlans(struct adapter * adapter);
static int ixgbe_encap(struct adapter *, struct mbuf **);
static int ixgbe_sysctl_stats(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS);
+static int ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS);
static int ixgbe_dma_malloc(struct adapter *, bus_size_t,
struct ixgbe_dma_alloc *, int);
static void ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *);
@@ -143,14 +144,23 @@ static boolean_t ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
static void ixgbe_set_ivar(struct adapter *, u16, u8);
static void ixgbe_configure_ivars(struct adapter *);
-/* Legacy Interrupt handler */
-static void ixgbe_intr(void *);
-
+/* Legacy Fast Interrupt routine and handlers */
+#if __FreeBSD_version >= 700000
+static int ixgbe_fast_irq(void *);
/* The MSI/X Interrupt handlers */
-static void ixgbe_txint(void *);
-static void ixgbe_rxint(void *);
-static void ixgbe_linkint(void *);
+static void ixgbe_msix_tx(void *);
+static void ixgbe_msix_rx(void *);
+static void ixgbe_msix_link(void *);
+#else
+static void ixgbe_fast_irq(void *);
+#endif
+
+static void ixgbe_rxtx(void *context, int pending);
+static void ixgbe_link(void *context, int pending);
+#ifndef NO_82598_A0_SUPPORT
+static void desc_flip(void *);
+#endif
/*********************************************************************
* FreeBSD Device Interface Entry Points
@@ -175,27 +185,41 @@ DRIVER_MODULE(ixgbe, pci, ixgbe_driver, ixgbe_devclass, 0, 0);
MODULE_DEPEND(ixgbe, pci, 1, 1, 1);
MODULE_DEPEND(ixgbe, ether, 1, 1, 1);
+/*
+** TUNEABLE PARAMETERS:
+*/
+
/* How many packets rxeof tries to clean at a time */
static int ixgbe_rx_process_limit = 100;
TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
-/*
- * Should the driver do MSI/X and RSS/MQ?
- * - default to MSI/X and RSS enabled
- */
-static int ixgbe_disable_msix = 0;
-TUNABLE_INT("hw.ixgbe.disable_msix", &ixgbe_disable_msix);
-
-/*
-** Flow control tuneable:
-** 0 - off
-** 1 - rx pause
-** 2 - tx pause
-** 3 - full
-*/
-static int ixgbe_flow_control = 0;
+/* Flow control setting, default to full */
+static int ixgbe_flow_control = 3;
TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
+/* Number of TX Queues, note multi tx is not working */
+static int ixgbe_tx_queues = 1;
+TUNABLE_INT("hw.ixgbe.tx_queues", &ixgbe_tx_queues);
+
+/* Number of RX Queues */
+static int ixgbe_rx_queues = 8;
+TUNABLE_INT("hw.ixgbe.rx_queues", &ixgbe_rx_queues);
+
+/* Number of Other Queues, this is used for link interrupts */
+static int ixgbe_other_queues = 1;
+TUNABLE_INT("hw.ixgbe.other_queues", &ixgbe_other_queues);
+
+/* Number of TX descriptors per ring */
+static int ixgbe_txd = DEFAULT_TXD;
+TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd);
+
+/* Number of RX descriptors per ring */
+static int ixgbe_rxd = DEFAULT_RXD;
+TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
+
+/* Total number of Interfaces - need for config sanity check */
+static int ixgbe_total_ports;
+
/*********************************************************************
* Device identification routine
*
@@ -239,6 +263,15 @@ ixgbe_probe(device_t dev)
sprintf(adapter_name, "%s, Version - %s",
ixgbe_strings[ent->index],
ixgbe_driver_version);
+ switch (pci_device_id) {
+ case IXGBE_DEV_ID_82598AF_DUAL_PORT :
+ ixgbe_total_ports += 2;
+ break;
+ case IXGBE_DEV_ID_82598AF_SINGLE_PORT :
+ ixgbe_total_ports += 1;
+ default:
+ break;
+ }
device_set_desc_copy(dev, adapter_name);
return (0);
}
@@ -264,13 +297,17 @@ ixgbe_attach(device_t dev)
struct adapter *adapter;
int error = 0;
uint32_t ctrl_ext;
+ char name_string[16];
INIT_DEBUGOUT("ixgbe_attach: begin");
/* Allocate, clear, and link in our adapter structure */
adapter = device_get_softc(dev);
adapter->dev = adapter->osdep.dev = dev;
- IXGBE_LOCK_INIT(adapter, device_get_nameunit(dev));
+ /* General Lock Init*/
+ snprintf(name_string, sizeof(name_string), "%s:core",
+ device_get_nameunit(dev));
+ mtx_init(&adapter->core_mtx, name_string, NULL, MTX_DEF);
/* SYSCTL APIs */
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
@@ -283,25 +320,17 @@ ixgbe_attach(device_t dev)
OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW,
adapter, 0, ixgbe_sysctl_debug, "I", "Debug Info");
- SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "flow control", CTLFLAG_RW,
- &ixgbe_flow_control, 0, "Flow Control");
+ OID_AUTO, "flow_control", CTLTYPE_INT | CTLFLAG_RW,
+ adapter, 0, ixgbe_set_flowcntl, "I", "Flow Control");
/* Set up the timer callout */
- callout_init_mtx(&adapter->timer, &adapter->mtx, 0);
+ callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
/* Determine hardware revision */
ixgbe_identify_hardware(adapter);
- /*
- ** Descriptors: (configurable by user), note these are
- ** constant for all rings, I saw no reason to vary
- ** them, but perhaps someone later would.
- */
- adapter->num_tx_desc = DEFAULT_TXD;
- adapter->num_rx_desc = DEFAULT_RXD;
-
/* Indicate to RX setup to use Jumbo Clusters */
adapter->bigbufs = TRUE;
@@ -312,17 +341,50 @@ ixgbe_attach(device_t dev)
goto err_out;
}
+ /* Do descriptor calc and sanity checks */
+ if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
+ ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) {
+ device_printf(dev, "TXD config issue, using default!\n");
+ adapter->num_tx_desc = DEFAULT_TXD;
+ } else
+ adapter->num_tx_desc = ixgbe_txd;
+
+ /*
+ ** With many RX rings it is easy to exceed the
+ ** system mbuf allocation. Tuning nmbclusters
+ ** can alleviate this.
+ */
+ if ((adapter->num_rx_queues > 1) && (nmbclusters > 0 )){
+ int s;
+ /* Calculate the total RX mbuf needs */
+ s = (ixgbe_rxd * adapter->num_rx_queues) * ixgbe_total_ports;
+ if (s > nmbclusters) {
+ device_printf(dev, "RX Descriptors exceed "
+ "system mbuf max, using default instead!\n");
+ ixgbe_rxd = DEFAULT_RXD;
+ }
+ }
+
+ if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
+ ixgbe_rxd < MIN_TXD || ixgbe_rxd > MAX_TXD) {
+ device_printf(dev, "RXD config issue, using default!\n");
+ adapter->num_rx_desc = DEFAULT_RXD;
+ } else
+ adapter->num_rx_desc = ixgbe_rxd;
+
/* Allocate our TX/RX Queues */
if (ixgbe_allocate_queues(adapter)) {
error = ENOMEM;
goto err_out;
}
+#if __FreeBSD_version >= 700000
if (adapter->msix) {
error = ixgbe_setup_msix(adapter);
if (error)
goto err_out;
}
+#endif
/* Initialize the shared code */
if (ixgbe_init_shared_code(&adapter->hw)) {
@@ -382,14 +444,25 @@ ixgbe_detach(device_t dev)
INIT_DEBUGOUT("ixgbe_detach: begin");
/* Make sure VLANS are not using driver */
+#if __FreeBSD_version >= 700000
if (adapter->ifp->if_vlantrunk != NULL) {
+#else
+ if (adapter->ifp->if_nvlans != 0) {
+#endif
device_printf(dev,"Vlan in use, detach first\n");
return (EBUSY);
}
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
ixgbe_stop(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
+
+ if (adapter->tq != NULL) {
+ taskqueue_drain(adapter->tq, &adapter->rxtx_task);
+ taskqueue_drain(taskqueue_fast, &adapter->link_task);
+ taskqueue_free(adapter->tq);
+ adapter->tq = NULL;
+ }
/* let hardware know driver is unloading */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
@@ -405,7 +478,7 @@ ixgbe_detach(device_t dev)
ixgbe_free_transmit_structures(adapter);
ixgbe_free_receive_structures(adapter);
- IXGBE_LOCK_DESTROY(adapter);
+ mtx_destroy(&adapter->core_mtx);
return (0);
}
@@ -419,9 +492,9 @@ static int
ixgbe_shutdown(device_t dev)
{
struct adapter *adapter = device_get_softc(dev);
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
ixgbe_stop(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
return (0);
}
@@ -442,7 +515,7 @@ ixgbe_start_locked(struct ifnet * ifp)
struct mbuf *m_head;
struct adapter *adapter = ifp->if_softc;
- IXGBE_LOCK_ASSERT(adapter);
+ mtx_assert(&adapter->tx_mtx, MA_OWNED);
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING)
@@ -464,7 +537,7 @@ ixgbe_start_locked(struct ifnet * ifp)
break;
}
/* Send a copy of the frame to the BPF listener */
- BPF_MTAP(ifp, m_head);
+ ETHER_BPF_MTAP(ifp, m_head);
/* Set timeout in case hardware has problems transmitting */
adapter->watchdog_timer = IXGBE_TX_TIMEOUT;
@@ -478,10 +551,10 @@ ixgbe_start(struct ifnet *ifp)
{
struct adapter *adapter = ifp->if_softc;
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->tx_mtx);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ixgbe_start_locked(ifp);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->tx_mtx);
return;
}
@@ -508,9 +581,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
if (ifa->ifa_addr->sa_family == AF_INET) {
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
ixgbe_init_locked(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
}
arp_ifinit(ifp, ifa);
} else
@@ -521,17 +594,17 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
error = EINVAL;
} else {
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
ifp->if_mtu = ifr->ifr_mtu;
adapter->max_frame_size =
ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
ixgbe_init_locked(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
}
break;
case SIOCSIFFLAGS:
IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if ((ifp->if_flags ^ adapter->if_flags) &
@@ -545,17 +618,17 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ixgbe_stop(adapter);
adapter->if_flags = ifp->if_flags;
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
ixgbe_disable_intr(adapter);
ixgbe_set_multi(adapter);
ixgbe_enable_intr(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
}
break;
case SIOCSIFMEDIA:
@@ -575,7 +648,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ixgbe_init(adapter);
+#if __FreeBSD_version >= 700000
VLAN_CAPABILITIES(ifp);
+#endif
break;
}
default:
@@ -598,7 +673,7 @@ static void
ixgbe_watchdog(struct adapter *adapter)
{
- IXGBE_LOCK_ASSERT(adapter);
+ mtx_assert(&adapter->core_mtx, MA_OWNED);
/*
* The timer is set to 5 every time ixgbe_start() queues a packet.
@@ -651,13 +726,15 @@ ixgbe_init_locked(struct adapter *adapter)
INIT_DEBUGOUT("ixgbe_init: begin");
- IXGBE_LOCK_ASSERT(adapter);
+ mtx_assert(&adapter->core_mtx, MA_OWNED);
ixgbe_stop(adapter);
/* Get the latest mac address, User can use a LAA */
bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr,
IXGBE_ETH_LENGTH_OF_ADDRESS);
+ ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, 1);
+ adapter->hw.addr_ctrl.rar_used_count = 1;
/* Initialize the hardware */
if (ixgbe_hardware_init(adapter)) {
@@ -756,60 +833,91 @@ ixgbe_init(void *arg)
{
struct adapter *adapter = arg;
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
ixgbe_init_locked(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
return;
}
+static void
+ixgbe_link(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ifnet *ifp = adapter->ifp;
+
+ mtx_lock(&adapter->core_mtx);
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ mtx_unlock(&adapter->core_mtx);
+ return;
+ }
+
+ callout_stop(&adapter->timer);
+ ixgbe_update_link_status(adapter);
+ callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
+ mtx_unlock(&adapter->core_mtx);
+}
+
+/*
+** MSI and Legacy Deferred Handler
+** - note this runs without the general lock
+*/
+static void
+ixgbe_rxtx(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ifnet *ifp = adapter->ifp;
+ /* For legacy there is only one of each */
+ struct rx_ring *rxr = adapter->rx_rings;
+ struct tx_ring *txr = adapter->tx_rings;
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (ixgbe_rxeof(rxr, adapter->rx_process_limit) != 0)
+ taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
+ mtx_lock(&adapter->tx_mtx);
+ ixgbe_txeof(txr);
+
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ ixgbe_start_locked(ifp);
+ mtx_unlock(&adapter->tx_mtx);
+ }
+
+ ixgbe_enable_intr(adapter);
+}
+
+
/*********************************************************************
*
* Legacy Interrupt Service routine
*
**********************************************************************/
+#if __FreeBSD_version >= 700000
+static int
+#else
static void
-ixgbe_intr(void *arg)
+#endif
+ixgbe_fast_irq(void *arg)
{
- u32 loop_cnt = MAX_INTR;
u32 reg_eicr;
struct adapter *adapter = arg;
- struct ifnet *ifp = adapter->ifp;
- struct rx_ring *rxr = adapter->rx_rings;
- struct tx_ring *txr = adapter->tx_rings;
-
- IXGBE_LOCK(adapter);
reg_eicr = IXGBE_READ_REG(&adapter->hw, IXGBE_EICR);
- if (reg_eicr == 0) {
- IXGBE_UNLOCK(adapter);
- return;
- }
+ if (reg_eicr == 0)
+ return FILTER_STRAY;
- /* Link status change */
- if (reg_eicr & IXGBE_EICR_LSC) {
- callout_stop(&adapter->timer);
- ixgbe_update_link_status(adapter);
- callout_reset(&adapter->timer, hz,
- ixgbe_local_timer, adapter);
- }
+ ixgbe_disable_intr(adapter);
+ taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
- while ((--loop_cnt > 0) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- ixgbe_rxeof(rxr, adapter->rx_process_limit);
- ixgbe_txeof(txr);
- }
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- ifp->if_snd.ifq_head != NULL)
- ixgbe_start_locked(ifp);
+ /* Link status change */
+ if (reg_eicr & IXGBE_EICR_LSC)
+ taskqueue_enqueue(taskqueue_fast, &adapter->link_task);
- IXGBE_UNLOCK(adapter);
- return;
+ return FILTER_HANDLED;
}
+#if __FreeBSD_version >= 700000
/*********************************************************************
*
* MSI TX Interrupt Service routine
@@ -817,14 +925,14 @@ ixgbe_intr(void *arg)
**********************************************************************/
void
-ixgbe_txint(void *arg)
+ixgbe_msix_tx(void *arg)
{
struct tx_ring *txr = arg;
struct adapter *adapter = txr->adapter;
struct ifnet *ifp = adapter->ifp;
uint32_t loop_cnt = MAX_INTR;
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->tx_mtx);
while (loop_cnt > 0) {
if (__predict_false(!ixgbe_txeof(txr)))
@@ -836,7 +944,7 @@ ixgbe_txint(void *arg)
ifp->if_snd.ifq_head != NULL)
ixgbe_start_locked(ifp);
ixgbe_enable_intr(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->tx_mtx);
return;
}
@@ -847,31 +955,27 @@ ixgbe_txint(void *arg)
**********************************************************************/
static void
-ixgbe_rxint(void *arg)
+ixgbe_msix_rx(void *arg)
{
struct rx_ring *rxr = arg;
struct adapter *adapter = rxr->adapter;
struct ifnet *ifp = adapter->ifp;
- //uint32_t reg_eicr, loop = MAX_INTR;
uint32_t loop = MAX_INTR;
- IXGBE_LOCK(adapter);
-
while ((loop-- > 0) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
ixgbe_rxeof(rxr, adapter->rx_process_limit);
ixgbe_enable_intr(adapter);
- IXGBE_UNLOCK(adapter);
}
static void
-ixgbe_linkint(void *arg)
+ixgbe_msix_link(void *arg)
{
struct adapter *adapter = arg;
uint32_t reg_eicr;
- IXGBE_LOCK(adapter);
+ mtx_lock(&adapter->core_mtx);
reg_eicr = IXGBE_READ_REG(&adapter->hw, IXGBE_EICR);
@@ -884,8 +988,9 @@ ixgbe_linkint(void *arg)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
ixgbe_enable_intr(adapter);
- IXGBE_UNLOCK(adapter);
+ mtx_unlock(&adapter->core_mtx);
}
+#endif /* __FreeBSD_version >= 700000 */
/*********************************************************************
*
@@ -966,6 +1071,7 @@ ixgbe_encap(struct adapter *adapter, struct mbuf **m_headp)
/* Basic descriptor defines */
cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA;
cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT;
+
if (m_head->m_flags & M_VLANTAG)
cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
@@ -1086,6 +1192,10 @@ ixgbe_encap(struct adapter *adapter, struct mbuf **m_headp)
if (j == (nsegs -1)) /* Last descriptor gets EOP and RS */
txd->read.cmd_type_len |=
htole32(IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS);
+#ifndef NO_82598_A0_SUPPORT
+ if (adapter->hw.revision_id == 0)
+ desc_flip(txd);
+#endif
}
txr->tx_avail -= nsegs;
@@ -1211,7 +1321,7 @@ ixgbe_local_timer(void *arg)
struct adapter *adapter = arg;
struct ifnet *ifp = adapter->ifp;
- IXGBE_LOCK_ASSERT(adapter);
+ mtx_assert(&adapter->core_mtx, MA_OWNED);
ixgbe_update_link_status(adapter);
ixgbe_update_stats_counters(adapter);
@@ -1273,7 +1383,7 @@ ixgbe_stop(void *arg)
struct adapter *adapter = arg;
ifp = adapter->ifp;
- IXGBE_LOCK_ASSERT(adapter);
+ mtx_assert(&adapter->core_mtx, MA_OWNED);
INIT_DEBUGOUT("ixgbe_stop: begin\n");
ixgbe_disable_intr(adapter);
@@ -1286,7 +1396,8 @@ ixgbe_stop(void *arg)
ixgbe_stop_adapter(&adapter->hw);
callout_stop(&adapter->timer);
- ixgbe_reset_hw(&adapter->hw);
+ /* reprogram the RAR[0] in case user changed it. */
+ ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
return;
}
@@ -1314,6 +1425,7 @@ ixgbe_identify_hardware(struct adapter *adapter)
return;
}
+#if __FreeBSD_version >= 700000
/*********************************************************************
*
* Setup MSIX: this is a prereq for doing Multiqueue/RSS.
@@ -1341,7 +1453,7 @@ ixgbe_setup_msix(struct adapter *adapter)
/* Set the handler function */
error = bus_setup_intr(dev, adapter->res[vector],
INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixgbe_txint, txr, &adapter->tag[vector]);
+ ixgbe_msix_tx, txr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
device_printf(dev, "Failed to register TX handler");
@@ -1363,7 +1475,7 @@ ixgbe_setup_msix(struct adapter *adapter)
}
/* Set the handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_rxint,
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_rx,
rxr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
@@ -1383,7 +1495,7 @@ ixgbe_setup_msix(struct adapter *adapter)
}
/* Set the link handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_linkint,
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_link,
adapter, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
@@ -1394,6 +1506,7 @@ ixgbe_setup_msix(struct adapter *adapter)
return (0);
}
+#endif
static int
ixgbe_allocate_pci_resources(struct adapter *adapter)
@@ -1421,10 +1534,24 @@ ixgbe_allocate_pci_resources(struct adapter *adapter)
* if that fails fall back to Legacy.
*/
if (ixgbe_allocate_msix_resources(adapter)) {
+ int val;
+
adapter->num_tx_queues = 1;
adapter->num_rx_queues = 1;
- adapter->msix = 0;
- rid = 0;
+ val = 0;
+
+#if __FreeBSD_version >= 700000
+ /* Attempt to use MSI */
+ val = pci_msi_count(dev);
+ if ((val) && pci_alloc_msi(dev, &val) == 0) {
+ adapter->rid[0] = 1;
+ device_printf(dev, "MSI Interrupts enabled\n");
+ } else
+#endif
+ {
+ adapter->rid[0] = 0;
+ device_printf(dev, "Legacy Interrupts enabled\n");
+ }
adapter->res[0] = bus_alloc_resource_any(dev,
SYS_RES_IRQ, &adapter->rid[0], RF_SHAREABLE | RF_ACTIVE);
if (adapter->res[0] == NULL) {
@@ -1432,13 +1559,25 @@ ixgbe_allocate_pci_resources(struct adapter *adapter)
"resource: interrupt\n");
return (ENXIO);
}
- /* Set the handler function */
+ /* Set the handler contexts */
+ TASK_INIT(&adapter->rxtx_task, 0, ixgbe_rxtx, adapter);
+ TASK_INIT(&adapter->link_task, 0, ixgbe_link, adapter);
+ adapter->tq = taskqueue_create_fast("ix_taskq", M_NOWAIT,
+ taskqueue_thread_enqueue, &adapter->tq);
+ taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
+ device_get_nameunit(adapter->dev));
+#if __FreeBSD_version < 700000
error = bus_setup_intr(dev, adapter->res[0],
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
- ixgbe_intr, adapter, &adapter->tag[0]);
+ INTR_TYPE_NET | INTR_FAST, ixgbe_fast_irq,
+#else
+ error = bus_setup_intr(dev, adapter->res[0],
+ INTR_TYPE_NET, ixgbe_fast_irq, NULL,
+#endif
+ adapter, &adapter->tag[0]);
if (error) {
adapter->res[0] = NULL;
- device_printf(dev, "Failed to register Legacy handler");
+ device_printf(dev, "Failed to register"
+ " Fast Legacy handler");
return (error);
}
}
@@ -1447,6 +1586,7 @@ ixgbe_allocate_pci_resources(struct adapter *adapter)
return (0);
}
+#if __FreeBSD_version >= 700000
/*
* Attempt to configure MSI/X, the prefered
* interrupt option.
@@ -1458,9 +1598,6 @@ ixgbe_allocate_msix_resources(struct adapter *adapter)
device_t dev = adapter->dev;
int vector = 1;
- /* An artificial means to force it off */
- if (ixgbe_disable_msix)
- return (-1);
/* First map the MSIX table */
rid = PCIR_BAR(3);
@@ -1475,20 +1612,15 @@ ixgbe_allocate_msix_resources(struct adapter *adapter)
val = pci_msix_count(dev);
/* check configured values */
- want = IXGBE_TX_QUEUES + IXGBE_RX_QUEUES + IXGBE_OTHER;
+ want = ixgbe_tx_queues + ixgbe_rx_queues + ixgbe_other_queues;
/*
* We arent going to do anything fancy for now,
* we either can meet desired config or we fail.
*/
if (val >= want)
val = want;
- else {
- device_printf(dev, "FAIL MSI/X setup:\n"
- "\tqueues wanted = %d\n"
- "\tqueues available = %d\n"
- "\tPlease reconfigure settings\n", want, val);
+ else
return (ENXIO);
- }
/* Initialize the resource arrays */
for (int i = 0; i < IXGBE_MSGS; i++, vector++) {
@@ -1497,8 +1629,8 @@ ixgbe_allocate_msix_resources(struct adapter *adapter)
adapter->res[i] = NULL;
}
- adapter->num_tx_queues = IXGBE_TX_QUEUES;
- adapter->num_rx_queues = IXGBE_RX_QUEUES;
+ adapter->num_tx_queues = ixgbe_tx_queues;
+ adapter->num_rx_queues = ixgbe_rx_queues;
/* Now allocate the vectors */
if ((error = pci_alloc_msix(dev, &val)) == 0) {
@@ -1512,6 +1644,13 @@ ixgbe_allocate_msix_resources(struct adapter *adapter)
}
return (0);
}
+#else /* FreeBSD 6.2 */
+static int
+ixgbe_allocate_msix_resources(struct adapter *adapter)
+{
+ return (1); /* Force Legacy behavior for 6.2 */
+}
+#endif
static void
ixgbe_free_pci_resources(struct adapter * adapter)
@@ -1545,9 +1684,9 @@ ixgbe_free_pci_resources(struct adapter * adapter)
}
}
- if (adapter->msix)
- pci_release_msi(dev);
-
+#if __FreeBSD_version >= 700000
+ pci_release_msi(dev);
+#endif
if (adapter->res_memory != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
IXGBE_MMBA, adapter->res_memory);
@@ -1581,7 +1720,11 @@ ixgbe_hardware_init(struct adapter *adapter)
}
/* Get Hardware Flow Control setting */
- adapter->hw.fc.original_type = ixgbe_flow_control;
+ adapter->hw.fc.original_type = ixgbe_fc_full;
+ adapter->hw.fc.pause_time = IXGBE_FC_PAUSE;
+ adapter->hw.fc.low_water = IXGBE_FC_LO;
+ adapter->hw.fc.high_water = IXGBE_FC_HI;
+ adapter->hw.fc.send_xon = TRUE;
if (ixgbe_init_hw(&adapter->hw)) {
device_printf(dev,"Hardware Initialization Failed");
@@ -1619,9 +1762,6 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
ether_ifattach(ifp, adapter->hw.mac.addr);
- /* Override ether_ifattach */
- ifp->if_mtu = PERFORMANCE_MTU; /* set to 9K by default */
-
adapter->max_frame_size =
ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
@@ -1630,7 +1770,7 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
- if (adapter->msix) /* Don't use CSUM with RSS */
+ if (adapter->msix) /* RSS and HWCSUM not compatible */
ifp->if_capabilities |= IFCAP_TSO4;
else
ifp->if_capabilities |= (IFCAP_HWCSUM | IFCAP_TSO4);
@@ -1721,6 +1861,8 @@ fail_0:
static void
ixgbe_dma_free(struct adapter *adapter, struct ixgbe_dma_alloc *dma)
{
+ bus_dmamap_sync(dma->dma_tag, dma->dma_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(dma->dma_tag, dma->dma_map);
bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
bus_dma_tag_destroy(dma->dma_tag);
@@ -1739,7 +1881,7 @@ ixgbe_allocate_queues(struct adapter *adapter)
device_t dev = adapter->dev;
struct tx_ring *txr;
struct rx_ring *rxr;
- int rsize, error = IXGBE_SUCCESS;
+ int rsize, tsize, error = IXGBE_SUCCESS;
int txconf = 0, rxconf = 0;
/* First allocate the TX ring struct memory */
@@ -1762,8 +1904,7 @@ ixgbe_allocate_queues(struct adapter *adapter)
}
rxr = adapter->rx_rings;
- /* Only do this once, RX and TX desc are the same size */
- rsize = roundup2(adapter->num_tx_desc *
+ tsize = roundup2(adapter->num_tx_desc *
sizeof(union ixgbe_adv_tx_desc), 4096);
/*
* Now set up the TX queues, txconf is needed to handle the
@@ -1771,12 +1912,20 @@ ixgbe_allocate_queues(struct adapter *adapter)
* undo memory gracefully
*/
for (int i = 0; i < adapter->num_tx_queues; i++, txconf++) {
+ char name_string[16];
/* Set up some basics */
txr = &adapter->tx_rings[i];
txr->adapter = adapter;
txr->me = i;
-
- if (ixgbe_dma_malloc(adapter, rsize,
+ /*
+ * Initialize the TX side lock
+ * -this has to change for multi tx
+ */
+ snprintf(name_string, sizeof(name_string), "%s:tx",
+ device_get_nameunit(dev));
+ mtx_init(&adapter->tx_mtx, name_string, NULL, MTX_DEF);
+
+ if (ixgbe_dma_malloc(adapter, tsize,
&txr->txdma, BUS_DMA_NOWAIT)) {
device_printf(dev,
"Unable to allocate TX Descriptor memory\n");
@@ -1784,7 +1933,7 @@ ixgbe_allocate_queues(struct adapter *adapter)
goto err_tx_desc;
}
txr->tx_base = (union ixgbe_adv_tx_desc *)txr->txdma.dma_vaddr;
- bzero((void *)txr->tx_base, rsize);
+ bzero((void *)txr->tx_base, tsize);
/* Now allocate transmit buffers for the ring */
if (ixgbe_allocate_transmit_buffers(txr)) {
@@ -1799,6 +1948,8 @@ ixgbe_allocate_queues(struct adapter *adapter)
/*
* Next the RX queues...
*/
+ rsize = roundup2(adapter->num_rx_desc *
+ sizeof(union ixgbe_adv_rx_desc), 4096);
for (int i = 0; i < adapter->num_rx_queues; i++, rxconf++) {
rxr = &adapter->rx_rings[i];
/* Set up some basics */
@@ -1997,11 +2148,13 @@ static void
ixgbe_free_transmit_structures(struct adapter *adapter)
{
struct tx_ring *txr = adapter->tx_rings;
+ mtx_lock(&adapter->tx_mtx);
for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
ixgbe_free_transmit_buffers(txr);
ixgbe_dma_free(adapter, &txr->txdma);
}
-
+ mtx_unlock(&adapter->tx_mtx);
+ mtx_destroy(&adapter->tx_mtx);
free(adapter->tx_rings, M_DEVBUF);
}
@@ -2076,7 +2229,12 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp)
u16 etype;
u8 ipproto;
int ctxd = txr->next_avail_tx_desc;
+#if __FreeBSD_version < 700000
+ struct m_tag *mtag;
+#else
u16 vtag = 0;
+#endif
+
tx_buffer = &txr->tx_buffers[ctxd];
TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];
@@ -2085,11 +2243,17 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp)
** In advanced descriptors the vlan tag must
** be placed into the descriptor itself.
*/
+#if __FreeBSD_version < 700000
+ mtag = VLAN_OUTPUT_TAG(ifp, mp);
+ if (mtag != NULL)
+ vlan_macip_lens |=
+ htole16(VLAN_TAG_VALUE(mtag)) << IXGBE_ADVTXD_VLAN_SHIFT;
+#else
if (mp->m_flags & M_VLANTAG) {
vtag = htole16(mp->m_pkthdr.ether_vtag);
vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT);
}
-
+#endif
/*
* Determine where frame payload starts.
* Jump over vlan headers if already present,
@@ -2148,6 +2312,11 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp)
TXD->seqnum_seed = htole32(0);
TXD->mss_l4len_idx = htole32(0);
+#ifndef NO_82598_A0_SUPPORT
+ if (adapter->hw.revision_id == 0)
+ desc_flip(TXD);
+#endif
+
tx_buffer->m_head = NULL;
tx_buffer->next_eop = -1;
@@ -2160,6 +2329,7 @@ ixgbe_tx_csum_setup(struct tx_ring *txr, struct mbuf *mp)
return TRUE;
}
+#if __FreeBSD_version >= 700000
/**********************************************************************
*
* Setup work for hardware segmentation offload (TSO) on
@@ -2242,6 +2412,11 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
tx_buffer->m_head = NULL;
tx_buffer->next_eop = -1;
+#ifndef NO_82598_A0_SUPPORT
+ if (adapter->hw.revision_id == 0)
+ desc_flip(TXD);
+#endif
+
if (++ctxd == adapter->num_tx_desc)
ctxd = 0;
@@ -2250,6 +2425,14 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
return TRUE;
}
+#else /* For 6.2 RELEASE */
+/* This makes it easy to keep the code common */
+static boolean_t
+ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
+{
+ return (FALSE);
+}
+#endif
/**********************************************************************
*
@@ -2267,7 +2450,7 @@ ixgbe_txeof(struct tx_ring *txr)
struct ixgbe_tx_buf *tx_buffer;
struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc;
- IXGBE_LOCK_ASSERT(adapter);
+ mtx_assert(&adapter->tx_mtx, MA_OWNED);
if (txr->tx_avail == adapter->num_tx_desc)
return FALSE;
@@ -2419,9 +2602,22 @@ ixgbe_get_buf(struct rx_ring *rxr, int i)
rxr->spare_map[old] = map;
bus_dmamap_sync(rxr->rxtag[s], rxbuf->map[s], BUS_DMASYNC_PREREAD);
rxbuf->m_head = mp;
+ rxbuf->bigbuf = s;
rxr->rx_base[i].read.pkt_addr = htole64(segs[0].ds_addr);
+#ifndef NO_82598_A0_SUPPORT
+ /* A0 needs to One's Compliment descriptors */
+ if (adapter->hw.revision_id == 0) {
+ struct dhack {u32 a1; u32 a2; u32 b1; u32 b2;};
+ struct dhack *d;
+
+ d = (struct dhack *)&rxr->rx_base[i];
+ d->a1 = ~(d->a1);
+ d->a2 = ~(d->a2);
+ }
+#endif
+
return (0);
}
@@ -2578,7 +2774,7 @@ fail:
* 'j' is the failing index, decrement it to get the
* last success.
*/
- for (--j; j > 0; j--) {
+ for (--j; j < 0; j--) {
rxbuf = &rxr->rx_buffers[j];
if (rxbuf->m_head != NULL) {
bus_dmamap_sync(rxr->rxtag[s], rxbuf->map[s],
@@ -2904,9 +3100,15 @@ ixgbe_rxeof(struct rx_ring *rxr, int count)
staterr, rxr->fmp);
if (staterr & IXGBE_RXD_STAT_VP) {
+#if __FreeBSD_version < 700000
+ VLAN_INPUT_TAG_NEW(ifp, rxr->fmp,
+ (le16toh(cur->wb.upper.vlan) &
+ IXGBE_RX_DESC_SPECIAL_VLAN_MASK));
+#else
rxr->fmp->m_pkthdr.ether_vtag =
le16toh(cur->wb.upper.vlan);
rxr->fmp->m_flags |= M_VLANTAG;
+#endif
}
m = rxr->fmp;
rxr->fmp = NULL;
@@ -2944,9 +3146,7 @@ discard:
/* Now send up to the stack */
if (m != NULL) {
rxr->next_to_check = i;
- IXGBE_UNLOCK(adapter);
(*ifp->if_input)(ifp, m);
- IXGBE_LOCK(adapter);
i = rxr->next_to_check;
}
/* Get next descriptor */
@@ -3013,7 +3213,7 @@ ixgbe_enable_vlans(struct adapter *adapter)
ixgbe_disable_intr(adapter);
ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL);
- ctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
+ ctrl |= IXGBE_VLNCTRL_VME;
ctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
ixgbe_enable_intr(adapter);
@@ -3027,7 +3227,7 @@ ixgbe_enable_intr(struct adapter *adapter)
{
u32 mask;
- /* Set up what to auto clear */
+ /* With RSS set up what to auto clear */
if (adapter->msix) {
mask = IXGBE_EIMS_ENABLE_MASK;
mask &= ~IXGBE_EIMS_OTHER;
@@ -3165,7 +3365,7 @@ ixgbe_update_stats_counters(struct adapter *adapter)
/* Rx Errors */
ifp->if_ierrors =
- adapter->dropped_pkts +
+ adapter->stats.mpc[0] +
adapter->stats.crcerrs +
adapter->stats.rlec;
@@ -3185,40 +3385,41 @@ ixgbe_print_hw_stats(struct adapter * adapter)
device_t dev = adapter->dev;
- device_printf(dev,"Tx Descriptors not Avail1 = %ld\n",
+ device_printf(dev,"Tx Descriptors not Avail1 = %lu\n",
adapter->no_tx_desc_avail1);
- device_printf(dev,"Tx Descriptors not Avail2 = %ld\n",
+ device_printf(dev,"Tx Descriptors not Avail2 = %lu\n",
adapter->no_tx_desc_avail2);
- device_printf(dev,"Std Mbuf Failed = %ld\n",
+ device_printf(dev,"Std Mbuf Failed = %lu\n",
adapter->mbuf_alloc_failed);
- device_printf(dev,"Std Cluster Failed = %ld\n",
+ device_printf(dev,"Std Cluster Failed = %lu\n",
adapter->mbuf_cluster_failed);
- device_printf(dev,"Missed Packets = %lld\n",
- (long long)adapter->stats.mprc);
- device_printf(dev,"Receive length errors = %lld\n",
- (long long)adapter->stats.rlec);
- device_printf(dev,"Crc errors = %lld\n",
+ device_printf(dev,"Missed Packets = %llu\n",
+ (long long)adapter->stats.mpc[0]);
+ device_printf(dev,"Receive length errors = %llu\n",
+ ((long long)adapter->stats.roc +
+ (long long)adapter->stats.ruc));
+ device_printf(dev,"Crc errors = %llu\n",
(long long)adapter->stats.crcerrs);
- device_printf(dev,"Driver dropped packets = %ld\n",
+ device_printf(dev,"Driver dropped packets = %lu\n",
adapter->dropped_pkts);
- device_printf(dev,"XON Rcvd = %lld\n",
+ device_printf(dev,"XON Rcvd = %llu\n",
(long long)adapter->stats.lxonrxc);
- device_printf(dev,"XON Xmtd = %lld\n",
+ device_printf(dev,"XON Xmtd = %llu\n",
(long long)adapter->stats.lxontxc);
- device_printf(dev,"XOFF Rcvd = %lld\n",
+ device_printf(dev,"XOFF Rcvd = %llu\n",
(long long)adapter->stats.lxoffrxc);
- device_printf(dev,"XOFF Xmtd = %lld\n",
+ device_printf(dev,"XOFF Xmtd = %llu\n",
(long long)adapter->stats.lxofftxc);
- device_printf(dev,"Total Packets Rcvd = %lld\n",
+ device_printf(dev,"Total Packets Rcvd = %llu\n",
(long long)adapter->stats.tpr);
- device_printf(dev,"Good Packets Rcvd = %lld\n",
+ device_printf(dev,"Good Packets Rcvd = %llu\n",
(long long)adapter->stats.gprc);
- device_printf(dev,"Good Packets Xmtd = %lld\n",
+ device_printf(dev,"Good Packets Xmtd = %llu\n",
(long long)adapter->stats.gptc);
- device_printf(dev,"TSO Transmissions = %ld\n",
+ device_printf(dev,"TSO Transmissions = %lu\n",
adapter->tso_tx);
return;
@@ -3259,23 +3460,17 @@ ixgbe_print_debug_info(struct adapter *adapter)
device_printf(dev,"Queue(0) tdh = %d, hw tdt = %d\n",
IXGBE_READ_REG(hw, IXGBE_TDH(0)),
IXGBE_READ_REG(hw, IXGBE_TDT(0)));
- device_printf(dev,"Total Packets Received = %d \n",
- IXGBE_READ_REG(hw, IXGBE_TPR));
- device_printf(dev,"Error Byte Count = %d \n",
+ device_printf(dev,"Error Byte Count = %u \n",
IXGBE_READ_REG(hw, IXGBE_ERRBC));
- device_printf(dev,"Rx Length Errors = %d \n",
- IXGBE_READ_REG(hw, IXGBE_RLEC));
- device_printf(dev,"Rx CRC Errors = %d \n",
- IXGBE_READ_REG(hw, IXGBE_CRCERRS));
for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
- device_printf(dev,"Queue %d Packets Received: %lx\n",
+ device_printf(dev,"Queue %d Packets Received: %lu\n",
rxr->me, (long)rxr->packet_count);
}
rxr = adapter->rx_rings; // Reset
for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
- device_printf(dev,"Queue %d Bytes Received: %lx\n",
+ device_printf(dev,"Queue %d Bytes Received: %lu\n",
rxr->me, (long)rxr->byte_count);
}
@@ -3284,12 +3479,6 @@ ixgbe_print_debug_info(struct adapter *adapter)
i, IXGBE_READ_REG(hw, IXGBE_RDH(i)),
IXGBE_READ_REG(hw, IXGBE_RDT(i)));
}
- device_printf(dev,"Std mbuf failed = %ld\n",
- adapter->mbuf_alloc_failed);
- device_printf(dev,"Std mbuf cluster failed = %ld\n",
- adapter->mbuf_cluster_failed);
- device_printf(dev,"Driver dropped packets = %ld\n",
- adapter->dropped_pkts);
return;
}
@@ -3333,6 +3522,41 @@ ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS)
return error;
}
+/*
+** Set flow control using sysctl:
+** Flow control values:
+** 0 - off
+** 1 - rx pause
+** 2 - tx pause
+** 3 - full
+*/
+static int
+ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct adapter *adapter;
+
+ error = sysctl_handle_int(oidp, &ixgbe_flow_control, 0, req);
+
+ if (error)
+ return (error);
+
+ adapter = (struct adapter *) arg1;
+ switch (ixgbe_flow_control) {
+ case ixgbe_fc_rx_pause:
+ case ixgbe_fc_tx_pause:
+ case ixgbe_fc_full:
+ adapter->hw.fc.original_type = ixgbe_flow_control;
+ break;
+ case ixgbe_fc_none:
+ default:
+ adapter->hw.fc.original_type = ixgbe_fc_none;
+ }
+
+ ixgbe_setup_fc(&adapter->hw, 0);
+ return error;
+}
+
static void
ixgbe_add_rx_process_limit(struct adapter *adapter, const char *name,
const char *description, int *limit, int value)
@@ -3342,3 +3566,26 @@ ixgbe_add_rx_process_limit(struct adapter *adapter, const char *name,
SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
}
+
+#ifndef NO_82598_A0_SUPPORT
+/*
+ * A0 Workaround: invert descriptor for hardware
+ */
+void
+desc_flip(void *desc)
+{
+ struct dhack {u32 a1; u32 a2; u32 b1; u32 b2;};
+ struct dhack *d;
+
+ d = (struct dhack *)desc;
+ d->a1 = ~(d->a1);
+ d->a2 = ~(d->a2);
+ d->b1 = ~(d->b1);
+ d->b2 = ~(d->b2);
+ d->b2 &= 0xFFFFFFF0;
+ d->b1 &= ~IXGBE_ADVTXD_DCMD_RS;
+}
+#endif
+
+
+
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index c75c167..c496244 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -86,39 +86,35 @@ POSSIBILITY OF SUCH DAMAGE.
/* Tunables */
/*
-** The number of queues: right now significant performance
-** seems to be gained by using muliple RX queues. The
-** infrastructure for multiple TX is there but its not
-** completely working, dont set greater than 1 for now.
-** OTHER is the vector used for link changes, it also
-** should only be set to 1.
-*/
-#define IXGBE_TX_QUEUES 1
-#define IXGBE_RX_QUEUES 8
-#define IXGBE_OTHER 1
-
-/*
- * TxDescriptors Valid Range: 64-4096 Default Value: 2048 This value is the
+ * TxDescriptors Valid Range: 64-4096 Default Value: 256 This value is the
* number of transmit descriptors allocated by the driver. Increasing this
* value allows the driver to queue more transmits. Each descriptor is 16
- * bytes.
+ * bytes. Performance tests have show the 2K value to be optimal for top
+ * performance.
*/
-#define DEFAULT_TXD 2048
+#define DEFAULT_TXD 256
+#define PERFORM_TXD 2048
#define MAX_TXD 4096
#define MIN_TXD 64
/*
- * RxDescriptors Valid Range: 64-4096 Default Value: 2048 This value is the
- * number of receive descriptors allocated by the driver. Increasing this
+ * RxDescriptors Valid Range: 64-4096 Default Value: 256 This value is the
+ * number of receive descriptors allocated for each RX queue. Increasing this
* value allows the driver to buffer more incoming packets. Each descriptor
- * is 16 bytes. A receive buffer is also allocated for each descriptor. The
- * maximum MTU size is 16110.
+ * is 16 bytes. A receive buffer is also allocated for each descriptor.
*
+ * Note: with 8 rings and a dual port card, it is possible to bump up
+ * against the system mbuf pool limit, you can tune nmbclusters
+ * to adjust for this.
*/
-#define DEFAULT_RXD 2048
+#define DEFAULT_RXD 256
+#define PERFORM_RXD 2048
#define MAX_RXD 4096
#define MIN_RXD 64
+/* Alignment for rings */
+#define DBA_ALIGN 128
+
/*
* This parameter controls the maximum no of times the driver will loop in
* the isr. Minimum Value = 1
@@ -138,15 +134,11 @@ POSSIBILITY OF SUCH DAMAGE.
#define IXGBE_TX_OP_THRESHOLD (adapter->num_tx_desc / 32)
#define IXGBE_MAX_FRAME_SIZE 0x3F00
-#define PERFORMANCE_MTU 9000 /* Best thruput results */
-/*
-** This controls the size mbuf pool used, it
-** may ultimately be automatic, but for now its
-** a compile time option.
-** - use MCLBYTES for legacy size
-*/
-#define IXGBE_RXBUF MJUMPAGESIZE
+/* Flow control constants */
+#define IXGBE_FC_PAUSE 0x680
+#define IXGBE_FC_HI 0x20000
+#define IXGBE_FC_LO 0x10000
/* Defines for printing debug information */
#define DEBUG_INIT 0
@@ -174,13 +166,23 @@ POSSIBILITY OF SUCH DAMAGE.
/* 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
+
/*
* Interrupt Moderation parameters
* for now we hardcode, later
* it would be nice to do dynamic
*/
-#define DEFAULT_ITR 8000
-#define LINK_ITR 1950
+#define MAX_IRQ_SEC 8000
+#define DEFAULT_ITR 1000000000/(MAX_IRQ_SEC * 256)
+#define LINK_ITR 1000000000/(1950 * 256)
/*
* ******************************************************************************
@@ -232,7 +234,6 @@ struct ixgbe_dma_alloc {
struct tx_ring {
struct adapter *adapter;
u32 me;
- struct mtx mtx;
union ixgbe_adv_tx_desc *tx_base;
struct ixgbe_dma_alloc txdma;
uint32_t next_avail_tx_desc;
@@ -250,7 +251,6 @@ struct tx_ring {
struct rx_ring {
struct adapter *adapter;
u32 me;
- struct mtx mtx;
u32 payload;
union ixgbe_adv_rx_desc *rx_base;
struct ixgbe_dma_alloc rxdma;
@@ -292,7 +292,12 @@ struct adapter {
int watchdog_timer;
int msix;
int if_flags;
- struct mtx mtx;
+ struct mtx core_mtx;
+ struct mtx tx_mtx;
+ /* Legacy Fast Intr handling */
+ struct task link_task;
+ struct task rxtx_task;
+ struct taskqueue *tq;
/* Info about the board itself */
uint32_t part_num;
@@ -338,11 +343,4 @@ struct adapter {
struct ixgbe_hw_stats stats;
};
-#define IXGBE_LOCK_INIT(_sc, _name) \
- mtx_init(&(_sc)->mtx, _name, MTX_NETWORK_LOCK, MTX_DEF)
-#define IXGBE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx)
-#define IXGBE_LOCK(_sc) mtx_lock(&(_sc)->mtx)
-#define IXGBE_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
-#define IXGBE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED)
-
#endif /* _IXGBE_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c
index f7e5b21..35d7e5e 100644
--- a/sys/dev/ixgbe/ixgbe_82598.c
+++ b/sys/dev/ixgbe/ixgbe_82598.c
@@ -32,6 +32,7 @@
*******************************************************************************/
/* $FreeBSD$ */
+
#include "ixgbe_type.h"
#include "ixgbe_api.h"
#include "ixgbe_common.h"
@@ -73,6 +74,10 @@ s32 ixgbe_reset_hw_rev_0_82598(struct ixgbe_hw *hw);
#endif
s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw);
u32 ixgbe_get_num_rx_addrs_82598(struct ixgbe_hw *hw);
+s32 ixgbe_configure_fiber_serdes_fc_82598(struct ixgbe_hw *hw);
+s32 ixgbe_setup_fiber_serdes_link_82598(struct ixgbe_hw *hw);
+s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
+s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
/**
@@ -84,9 +89,6 @@ u32 ixgbe_get_num_rx_addrs_82598(struct ixgbe_hw *hw);
**/
s32 ixgbe_init_shared_code_82598(struct ixgbe_hw *hw)
{
- /* Set MAC type */
- hw->mac.type = ixgbe_mac_82598EB;
-
/* Assign function pointers */
ixgbe_assign_func_pointers_82598(hw);
@@ -109,6 +111,10 @@ s32 ixgbe_assign_func_pointers_82598(struct ixgbe_hw *hw)
&ixgbe_get_num_of_tx_queues_82598;
hw->func.ixgbe_func_get_num_of_rx_queues =
&ixgbe_get_num_of_rx_queues_82598;
+ hw->func.ixgbe_func_read_analog_reg8 =
+ &ixgbe_read_analog_reg8_82598;
+ hw->func.ixgbe_func_write_analog_reg8 =
+ &ixgbe_write_analog_reg8_82598;
#ifndef NO_82598_A0_SUPPORT
if (hw->revision_id == 0) {
hw->func.ixgbe_func_reset_hw =
@@ -250,18 +256,11 @@ enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
/* Media type for I82598 is based on device ID */
switch (hw->device_id) {
- case IXGBE_DEV_ID_82598:
- /* Default device ID is mezzanine card KX/KX4 */
- media_type = ixgbe_media_type_backplane;
- break;
- case IXGBE_DEV_ID_82598_FPGA:
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
+ case IXGBE_DEV_ID_82598EB_CX4:
media_type = ixgbe_media_type_fiber;
break;
- case IXGBE_DEV_ID_82598AT_DUAL_PORT:
- media_type = ixgbe_media_type_copper;
- break;
default:
media_type = ixgbe_media_type_unknown;
break;
@@ -278,9 +277,6 @@ enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
**/
u32 ixgbe_get_num_of_tx_queues_82598(struct ixgbe_hw *hw)
{
- if (hw->device_id == IXGBE_DEV_ID_82598_FPGA)
- return 8;
-
return IXGBE_82598_MAX_TX_QUEUES;
}
@@ -292,9 +288,6 @@ u32 ixgbe_get_num_of_tx_queues_82598(struct ixgbe_hw *hw)
**/
u32 ixgbe_get_num_of_rx_queues_82598(struct ixgbe_hw *hw)
{
- if (hw->device_id == IXGBE_DEV_ID_82598_FPGA)
- return 8;
-
return IXGBE_82598_MAX_RX_QUEUES;
}
@@ -307,6 +300,8 @@ u32 ixgbe_get_num_of_rx_queues_82598(struct ixgbe_hw *hw)
**/
s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
{
+ ixgbe_link_speed speed;
+ bool link_up;
u32 autoc_reg;
u32 links_reg;
u32 i;
@@ -346,6 +341,22 @@ s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
}
}
+ /*
+ * We want to save off the original Flow Control configuration just in
+ * case we get disconnected and then reconnected into a different hub
+ * or switch with different Flow Control capabilities.
+ */
+ hw->fc.type = hw->fc.original_type;
+ /*
+ * Set up the SerDes link if in 1Gb mode, otherwise just set up
+ * 10Gb flow control.
+ */
+ ixgbe_check_link(hw, &speed, &link_up);
+ if (speed == IXGBE_LINK_SPEED_1GB_FULL)
+ status = ixgbe_setup_fiber_serdes_link_82598(hw);
+ else
+ ixgbe_setup_fc_generic(hw, 0);
+
/* Add delay to filter out noises during initial link setup */
msec_delay(50);
@@ -381,6 +392,236 @@ s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
}
/**
+ * ixgbe_configure_fiber_serdes_fc_82598 - Configure fiber flow control
+ * @hw: pointer to hardware structure
+ *
+ * Reads PCS registers and sets flow control settings, based on
+ * link-partner's abilities.
+ **/
+s32 ixgbe_configure_fiber_serdes_fc_82598(struct ixgbe_hw *hw)
+{
+ s32 ret_val = IXGBE_SUCCESS;
+ u32 delay = 300, pcs_anadv_reg, pcs_lpab_reg, pcs_lstat_reg, i;
+
+ DEBUGFUNC("ixgbe_configure_fiber_serdes_fc_82598");
+
+ /* Check that autonegotiation has completed */
+ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
+ /*
+ * Delay 300msec before reading PCS1GLSTA. Reading PCS1GLSTA
+ * before then will sometimes result in AN_COMPLETE not being
+ * set.
+ */
+ msec_delay(delay);
+ pcs_lstat_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+ if (pcs_lstat_reg & IXGBE_PCS1GLSTA_AN_COMPLETE) {
+ if (pcs_lstat_reg & (IXGBE_PCS1GLSTA_LINK_OK)) {
+ if (!(pcs_lstat_reg &
+ (IXGBE_PCS1GLSTA_AN_TIMED_OUT)))
+ hw->mac.autoneg_failed = 0;
+ else
+ hw->mac.autoneg_failed = 1;
+ break;
+ } else {
+ hw->mac.autoneg_failed = 1;
+ break;
+ }
+ }
+
+ /*
+ * Increment the delay time by 50ms to wait before reading
+ * PCS1GLSTA again.
+ */
+ delay += 50;
+ }
+
+ if (i == FIBER_LINK_UP_LIMIT)
+ hw->mac.autoneg_failed = 1;
+
+ if (hw->mac.autoneg_failed) {
+ /*
+ * AutoNeg failed to achieve a link, so we will turn
+ * flow control off.
+ */
+ hw->fc.type = ixgbe_fc_none;
+ DEBUGOUT("Flow Control = NONE.\n");
+ ret_val = ixgbe_setup_fc_generic(hw, 0);
+ goto out;
+ }
+
+ /*
+ * Read the AN advertisement and LP ability registers and resolve
+ * local flow control settings accordingly
+ */
+ pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+ if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+ (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+ /*
+ * 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.original_type == ixgbe_fc_full) {
+ hw->fc.type = ixgbe_fc_full;
+ DEBUGOUT("Flow Control = FULL.\n");
+ } else {
+ hw->fc.type = 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.type = 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.type = ixgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
+ } else if ((hw->fc.original_type == ixgbe_fc_none ||
+ hw->fc.original_type == ixgbe_fc_tx_pause) ||
+ hw->fc.strict_ieee) {
+ hw->fc.type = ixgbe_fc_none;
+ DEBUGOUT("Flow Control = NONE.\n");
+ } else {
+ hw->fc.type = ixgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
+ }
+
+ ret_val = ixgbe_setup_fc_generic(hw, 0);
+ if (ret_val) {
+ DEBUGOUT("Error forcing flow control settings\n");
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_setup_fiber_serdes_link_82598 - Configure fiber serdes link
+ * @hw: pointer to hardware structure
+ *
+ * Sets up PCS registers and sets flow control settings, based on
+ * link-partner's abilities.
+ **/
+s32 ixgbe_setup_fiber_serdes_link_82598(struct ixgbe_hw *hw)
+{
+ u32 reg;
+ s32 ret_val;
+
+ DEBUGFUNC("ixgbe_setup_fiber_serdes_link_82598");
+
+ /*
+ * 82598 fiber/serdes devices require that flow control be resolved in
+ * software. Set up flow control advertisement if autoneg is enabled.
+ */
+ if (hw->mac.autoneg) {
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+
+ /*
+ * Check for a software override of the flow control settings,
+ * and setup the device accordingly. If auto-negotiation is
+ * enabled, then software will have to set the "PAUSE" bits to
+ * the correct value and re-start auto- negotiation. However,
+ * if auto-negotiation is disabled, then software will have to
+ * manually configure flow control.
+ *
+ * The possible values of the "fc" parameter 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.
+ */
+
+ switch (hw->fc.type) {
+ case ixgbe_fc_none:
+ /*
+ * Flow control completely disabled by a software
+ * over-ride.
+ */
+ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE |
+ IXGBE_PCS1GANA_ASM_PAUSE);
+ break;
+ case ixgbe_fc_rx_pause:
+ /*
+ * RX Flow control is enabled and TX Flow control is
+ * disabled by a software over-ride. 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_PCS1GANA_SYM_PAUSE |
+ IXGBE_PCS1GANA_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /*
+ * TX Flow control is enabled, and RX Flow control is
+ * disabled, by a software over-ride.
+ */
+ reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
+ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+ break;
+ case ixgbe_fc_full:
+ /*
+ * Flow control (both RX and TX) is enabled by a
+ * software over-ride.
+ */
+ reg |= (IXGBE_PCS1GANA_SYM_PAUSE |
+ IXGBE_PCS1GANA_ASM_PAUSE);
+ break;
+ default:
+ DEBUGOUT("Flow control param set incorrectly\n");
+ ret_val = -IXGBE_ERR_CONFIG;
+ goto out;
+ break;
+ }
+
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+ }
+
+ /*
+ * New SerDes mode allows for forcing speed or autonegotiating speed
+ * at 1gb. Autoneg should be default set by most drivers. This is the
+ * mode that will be compatible with older link partners and switches.
+ * However, both are supported by the hardware and some drivers/tools.
+ */
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+ reg &= ~(IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN);
+
+ if (hw->mac.autoneg) {
+ /* Set PCS register for autoneg */
+ reg |= IXGBE_PCS1GLCTL_AN_ENABLE | /* Enable Autoneg */
+ IXGBE_PCS1GLCTL_AN_RESTART; /* Restart autoneg */
+ DEBUGOUT1("Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg);
+ } else {
+ /* Set PCS register for forced speed */
+ reg |= IXGBE_PCS1GLCTL_FLV_LINK_UP | /* Force link up */
+ IXGBE_PCS1GLCTL_FORCE_LINK; /* Force Link */
+ DEBUGOUT1("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg);
+ }
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+
+ /*
+ * Configure flow control. If we aren't auto-negotiating,
+ * just setup the flow control and do not worry about PCS autoneg.
+ */
+ if (hw->mac.autoneg)
+ ixgbe_configure_fiber_serdes_fc_82598(hw);
+
+out:
+ return IXGBE_SUCCESS;
+}
+
+/**
* ixgbe_setup_mac_link_speed_82598 - Set MAC link speed
* @hw: pointer to hardware structure
* @speed: new link speed
@@ -644,10 +885,36 @@ s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
u32 gheccr;
u32 i;
u32 autoc;
+ u8 analog_val;
/* Call adapter stop to disable tx/rx and clear interrupts */
ixgbe_stop_adapter(hw);
+ /*
+ * Power up the Atlas TX lanes if they are currently powered down.
+ * Atlas TX lanes are powered down for MAC loopback tests, but
+ * they are not automatically restored on reset.
+ */
+ ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val);
+ if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) {
+ /* Enable TX Atlas so packets can be transmitted again */
+ ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val);
+ analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN;
+ ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val);
+
+ ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val);
+ analog_val &= ~ IXGBE_ATLAS_PDN_TX_10G_QL_ALL;
+ ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val);
+
+ ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val);
+ analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL;
+ ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val);
+
+ ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val);
+ analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL;
+ ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val);
+ }
+
/* Reset PHY */
ixgbe_reset_phy(hw);
@@ -714,6 +981,47 @@ s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
}
/**
+ * ixgbe_read_analog_reg8_82598 - Reads 8 bit 82598 Atlas analog register
+ * @hw: pointer to hardware structure
+ * @reg: analog register to read
+ * @val: read value
+ *
+ * Performs write operation to analog register specified.
+ **/
+s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val)
+{
+ u32 atlas_ctl;
+
+ IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8));
+ IXGBE_WRITE_FLUSH(hw);
+ usec_delay(10);
+ atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL);
+ *val = (u8)atlas_ctl;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_write_analog_reg8_82598 - Writes 8 bit 82598 Atlas analog register
+ * @hw: pointer to hardware structure
+ * @reg: atlas register to write
+ * @val: value to write
+ *
+ * Performs write operation to Atlas analog register specified.
+ **/
+s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
+{
+ u32 atlas_ctl;
+
+ atlas_ctl = (reg << 8) | val;
+ IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl);
+ IXGBE_WRITE_FLUSH(hw);
+ usec_delay(10);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
* ixgbe_get_num_rx_addrs_82598 - Get RX address registers
* @hw: pointer to hardware structure
*
diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c
index d881c3d..57b5678 100644
--- a/sys/dev/ixgbe/ixgbe_api.c
+++ b/sys/dev/ixgbe/ixgbe_api.c
@@ -32,6 +32,7 @@
*******************************************************************************/
/* $FreeBSD$ */
+
#include "ixgbe_api.h"
#include "ixgbe_common.h"
@@ -52,7 +53,7 @@ extern s32 ixgbe_init_shared_code_phy(struct ixgbe_hw *hw);
**/
s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
{
- s32 status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
+ s32 status;
/*
* Assign generic function pointers before entering adapter-specific
@@ -60,23 +61,53 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
*/
ixgbe_assign_func_pointers_generic(hw);
+ /*
+ * Set the mac type
+ */
+ ixgbe_set_mac_type(hw);
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ status = ixgbe_init_shared_code_82598(hw);
+ status = ixgbe_init_shared_code_phy(hw);
+ break;
+ default:
+ status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * ixgbe_set_mac_type - Sets MAC type
+ * @hw: pointer to the HW structure
+ *
+ * This function sets the mac type of the adapter based on the
+ * vendor ID and device ID stored in the hw structure.
+ **/
+s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
+{
+ s32 ret_val = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_set_mac_type");
+
if (hw->vendor_id == IXGBE_INTEL_VENDOR_ID) {
switch (hw->device_id) {
- case IXGBE_DEV_ID_82598:
- case IXGBE_DEV_ID_82598_FPGA:
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
- case IXGBE_DEV_ID_82598AT_DUAL_PORT:
- status = ixgbe_init_shared_code_82598(hw);
- status = ixgbe_init_shared_code_phy(hw);
+ case IXGBE_DEV_ID_82598EB_CX4:
+ hw->mac.type = ixgbe_mac_82598EB;
break;
default:
- status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
+ ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
break;
}
+ } else {
+ ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
}
- return status;
+ return ret_val;
}
/**
@@ -643,3 +674,32 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_NOT_IMPLEMENTED);
}
+
+/**
+ * ixgbe_read_analog_reg8 - Reads 8 bit analog register
+ * @hw: pointer to hardware structure
+ * @reg: analog register to read
+ * @val: read value
+ *
+ * Performs write operation to analog register specified.
+ **/
+s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val)
+{
+ return ixgbe_call_func(hw, ixgbe_func_read_analog_reg8, (hw, reg, val),
+ IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_write_analog_reg8 - Writes 8 bit analog register
+ * @hw: pointer to hardware structure
+ * @reg: analog register to write
+ * @val: value to write
+ *
+ * Performs write operation to Atlas analog register specified.
+ **/
+s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val)
+{
+ return ixgbe_call_func(hw, ixgbe_func_write_analog_reg8, (hw, reg, val),
+ IXGBE_NOT_IMPLEMENTED);
+}
+
diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h
index 691957f..5154cf7 100644
--- a/sys/dev/ixgbe/ixgbe_api.h
+++ b/sys/dev/ixgbe/ixgbe_api.h
@@ -39,6 +39,7 @@
s32 ixgbe_init_shared_code(struct ixgbe_hw *hw);
+s32 ixgbe_set_mac_type(struct ixgbe_hw *hw);
s32 ixgbe_init_hw(struct ixgbe_hw *hw);
s32 ixgbe_reset_hw(struct ixgbe_hw *hw);
s32 ixgbe_start_hw(struct ixgbe_hw *hw);
@@ -90,5 +91,7 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr);
+s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val);
+s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val);
#endif /* _IXGBE_API_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c
index 30a2625..f9cc69c 100644
--- a/sys/dev/ixgbe/ixgbe_common.c
+++ b/sys/dev/ixgbe/ixgbe_common.c
@@ -32,6 +32,7 @@
*******************************************************************************/
/* $FreeBSD$ */
+
#include "ixgbe_common.h"
#include "ixgbe_api.h"
@@ -133,9 +134,6 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
/* Clear statistics registers */
ixgbe_clear_hw_cntrs(hw);
- /* Set up flow control */
- ixgbe_setup_fc(hw, 0);
-
/* Set No Snoop Disable */
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h
index a150908..d995c7c 100644
--- a/sys/dev/ixgbe/ixgbe_osdep.h
+++ b/sys/dev/ixgbe/ixgbe_osdep.h
@@ -87,7 +87,7 @@ typedef uint16_t u16;
typedef uint32_t u32;
typedef int32_t s32;
typedef uint64_t u64;
-typedef booleant bool;
+typedef boolean_t bool;
#define le16_to_cpu
diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c
index 5043109..e19d303 100644
--- a/sys/dev/ixgbe/ixgbe_phy.c
+++ b/sys/dev/ixgbe/ixgbe_phy.c
@@ -32,6 +32,7 @@
*******************************************************************************/
/* $FreeBSD$ */
+
#include "ixgbe_api.h"
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
@@ -66,24 +67,6 @@ s32 ixgbe_assign_func_pointers_phy(struct ixgbe_hw *hw)
hw->func.ixgbe_func_identify_phy =
&ixgbe_identify_phy_generic;
- if (ixgbe_get_media_type(hw) == ixgbe_media_type_copper) {
- /* Call PHY identify routine to get the phy type */
- ixgbe_identify_phy(hw);
-
- switch (hw->phy.type) {
- case ixgbe_phy_tn:
- hw->func.ixgbe_func_setup_phy_link =
- &ixgbe_setup_tnx_phy_link;
- hw->func.ixgbe_func_check_phy_link =
- &ixgbe_check_tnx_phy_link;
- hw->func.ixgbe_func_setup_phy_link_speed =
- &ixgbe_setup_tnx_phy_link_speed;
- break;
- default:
- break;
- }
- }
-
return IXGBE_SUCCESS;
}
@@ -171,14 +154,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
enum ixgbe_phy_type phy_type;
switch (phy_id) {
- case TN1010_PHY_ID:
- phy_type = ixgbe_phy_tn;
- break;
-
case QT2022_PHY_ID:
phy_type = ixgbe_phy_qt;
break;
-
default:
phy_type = ixgbe_phy_unknown;
break;
@@ -213,7 +191,6 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
{
u32 command;
u32 i;
- u32 timeout = 10;
u32 data;
s32 status = IXGBE_SUCCESS;
u16 gssr;
@@ -240,7 +217,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
* The MDI Command bit will clear when the operation is
* complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
@@ -251,7 +228,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
}
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
- DEBUGFUNC("PHY address command did not complete.\n");
+ DEBUGOUT("PHY address command did not complete.\n");
status = IXGBE_ERR_PHY;
}
@@ -272,7 +249,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
* completed. The MDI Command bit will clear when the
* operation is complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
@@ -282,7 +259,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
}
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
- DEBUGFUNC("PHY read command didn't complete\n");
+ DEBUGOUT("PHY read command didn't complete\n");
status = IXGBE_ERR_PHY;
} else {
/*
@@ -312,7 +289,6 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
{
u32 command;
u32 i;
- u32 timeout = 10;
s32 status = IXGBE_SUCCESS;
u16 gssr;
@@ -341,7 +317,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
* The MDI Command bit will clear when the operation is
* complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
@@ -372,7 +348,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
* completed. The MDI Command bit will clear when the
* operation is complete
*/
- for (i = 0; i < timeout; i++) {
+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
@@ -437,156 +413,3 @@ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
IXGBE_NOT_IMPLEMENTED);
}
-/**
- * ixgbe_setup_tnx_phy_link - Set and restart autoneg
- * @hw: pointer to hardware structure
- *
- * Restart autonegotiation and PHY and waits for completion.
- **/
-s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw)
-{
- s32 status = IXGBE_NOT_IMPLEMENTED;
- u32 time_out;
- u32 max_time_out = 10;
- u16 autoneg_speed_selection_register = 0x10;
- u16 autoneg_restart_mask = 0x0200;
- u16 autoneg_complete_mask = 0x0020;
- u16 autoneg_reg = 0;
-
- /*
- * Set advertisement settings in PHY based on autoneg_advertised
- * settings. If autoneg_advertised = 0, then advertise default values
- * txn devices cannot be "forced" to a autoneg 10G and fail. But can
- * for a 1G.
- */
- ixgbe_read_phy_reg(hw,
- autoneg_speed_selection_register,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
-
- if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL)
- autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */
- else
- autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */
-
- ixgbe_write_phy_reg(hw,
- autoneg_speed_selection_register,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
-
-
- /* Restart PHY autonegotiation and wait for completion */
- ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_AUTO_NEG_CONTROL,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
-
- autoneg_reg |= autoneg_restart_mask;
-
- ixgbe_write_phy_reg(hw,
- IXGBE_MDIO_AUTO_NEG_CONTROL,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- autoneg_reg);
-
- /* Wait for autonegotiation to finish */
- for (time_out = 0; time_out < max_time_out; time_out++) {
- usec_delay(10);
- /* Restart PHY autonegotiation and wait for completion */
- status = ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_AUTO_NEG_STATUS,
- IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
- &autoneg_reg);
-
- autoneg_reg &= autoneg_complete_mask;
- if (autoneg_reg == autoneg_complete_mask) {
- status = IXGBE_SUCCESS;
- break;
- }
- }
-
- if (time_out == max_time_out)
- status = IXGBE_ERR_LINK_SETUP;
-
- return status;
-}
-
-/**
- * ixgbe_check_tnx_phy_link - Determine link and speed status
- * @hw: pointer to hardware structure
- *
- * Reads the VS1 register to determine if link is up and the current speed for
- * the PHY.
- **/
-s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
- bool *link_up)
-{
- s32 status = IXGBE_SUCCESS;
- u32 time_out;
- u32 max_time_out = 10;
- u16 phy_link = 0;
- u16 phy_speed = 0;
- u16 phy_data = 0;
-
- /* Initialize speed and link to default case */
- *link_up = FALSE;
- *speed = IXGBE_LINK_SPEED_10GB_FULL;
-
- /*
- * Check current speed and link status of the PHY register.
- * This is a vendor specific register and may have to
- * be changed for other copper PHYs.
- */
- for (time_out = 0; time_out < max_time_out; time_out++) {
- usec_delay(10);
- if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
- *link_up = TRUE;
- if (phy_speed ==
- IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
- *speed = IXGBE_LINK_SPEED_1GB_FULL;
- break;
- } else {
- status = ixgbe_read_phy_reg(hw,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
- &phy_data);
- phy_link = phy_data &
- IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
- phy_speed = phy_data &
- IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
- }
- }
-
- return status;
-}
-
-/**
- * ixgbe_setup_tnx_phy_link_speed - Sets the auto advertised capabilities
- * @hw: pointer to hardware structure
- * @speed: new link speed
- * @autoneg: TRUE if autonegotiation enabled
- **/
-s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
- bool autoneg,
- bool autoneg_wait_to_complete)
-{
- UNREFERENCED_PARAMETER(autoneg);
- UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
-
- /*
- * Clear autoneg_advertised and set new values based on input link
- * speed.
- */
- hw->phy.autoneg_advertised = 0;
-
- if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
- hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
- }
- if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
- hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
- }
-
- /* Setup link based on the new speed settings */
- ixgbe_setup_tnx_phy_link(hw);
-
- return IXGBE_SUCCESS;
-}
diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h
index 9f04732..4313de1 100644
--- a/sys/dev/ixgbe/ixgbe_phy.h
+++ b/sys/dev/ixgbe/ixgbe_phy.h
@@ -57,14 +57,4 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 phy_data);
-/* PHY specific */
-s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw);
-s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw,
- ixgbe_link_speed *speed,
- bool *link_up);
-s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw,
- ixgbe_link_speed speed,
- bool autoneg,
- bool autoneg_wait_to_complete);
-
#endif /* _IXGBE_PHY_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h
index 3168c3e..bfbd701 100644
--- a/sys/dev/ixgbe/ixgbe_type.h
+++ b/sys/dev/ixgbe/ixgbe_type.h
@@ -41,11 +41,9 @@
#define IXGBE_INTEL_VENDOR_ID 0x8086
/* Device IDs */
-#define IXGBE_DEV_ID_82598 0x10B6
-#define IXGBE_DEV_ID_82598_FPGA 0xF0C0
#define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
-#define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8
+#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
/* General Registers */
#define IXGBE_CTRL 0x00000
@@ -280,23 +278,17 @@
#define IXGBE_DCA_CTRL 0x11074
/* Diagnostic Registers */
-#define IXGBE_RDSTATCTL 0x02C20
-#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */
-#define IXGBE_RDHMPN 0x02F08
-#define IXGBE_RIC_DW0 0x02F10
-#define IXGBE_RIC_DW1 0x02F14
-#define IXGBE_RIC_DW2 0x02F18
-#define IXGBE_RIC_DW3 0x02F1C
-#define IXGBE_RDPROBE 0x02F20
-#define IXGBE_TDSTATCTL 0x07C20
-#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */
-#define IXGBE_TDHMPN 0x07F08
-#define IXGBE_TIC_DW0 0x07F10
-#define IXGBE_TIC_DW1 0x07F14
-#define IXGBE_TIC_DW2 0x07F18
-#define IXGBE_TIC_DW3 0x07F1C
-#define IXGBE_TDPROBE 0x07F20
-#define IXGBE_TXBUFCTRL 0x0C600
+#define IXGBE_RDSTATCTL 0x02C20
+#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */
+#define IXGBE_RDHMPN 0x02F08
+#define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4))
+#define IXGBE_RDPROBE 0x02F20
+#define IXGBE_TDSTATCTL 0x07C20
+#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */
+#define IXGBE_TDHMPN 0x07F08
+#define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4))
+#define IXGBE_TDPROBE 0x07F20
+#define IXGBE_TXBUFCTRL 0x0C600
#define IXGBE_TXBUFDATA0 0x0C610
#define IXGBE_TXBUFDATA1 0x0C614
#define IXGBE_TXBUFDATA2 0x0C618
@@ -393,6 +385,8 @@
#define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
+#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* TX Desc writeback RO bit */
+#define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */
/* MSCA Bit Masks */
#define IXGBE_MSCA_NP_ADDR_MASK 0x0000FFFF /* MDI Address (new protocol) */
@@ -415,10 +409,23 @@
#define IXGBE_MSCA_MDI_IN_PROG_EN 0x80000000 /* MDI in progress enable */
/* MSRWD bit masks */
-#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF
-#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0
-#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000
-#define IXGBE_MSRWD_READ_DATA_SHIFT 16
+#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF
+#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0
+#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000
+#define IXGBE_MSRWD_READ_DATA_SHIFT 16
+
+/* Atlas registers */
+#define IXGBE_ATLAS_PDN_LPBK 0x24
+#define IXGBE_ATLAS_PDN_10G 0xB
+#define IXGBE_ATLAS_PDN_1G 0xC
+#define IXGBE_ATLAS_PDN_AN 0xD
+
+/* Atlas bit masks */
+#define IXGBE_ATLASCTL_WRITE_CMD 0x00010000
+#define IXGBE_ATLAS_PDN_TX_REG_EN 0x10
+#define IXGBE_ATLAS_PDN_TX_10G_QL_ALL 0xF0
+#define IXGBE_ATLAS_PDN_TX_1G_QL_ALL 0xF0
+#define IXGBE_ATLAS_PDN_TX_AN_QL_ALL 0xF0
/* Device Type definitions for new protocol MDIO commands */
#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1
@@ -427,6 +434,8 @@
#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */
+#define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */
+
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Control Reg */
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */
@@ -448,7 +457,6 @@
#define IXGBE_MAX_PHY_ADDR 32
/* PHY IDs*/
-#define TN1010_PHY_ID 0x00A19410
#define QT2022_PHY_ID 0x0043A400
/* General purpose Interrupt Enable */
@@ -689,7 +697,29 @@
#define IXGBE_LINKS_TL_FAULT 0x00001000
#define IXGBE_LINKS_SIGNAL 0x00000F00
-#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
+#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
+
+#define FIBER_LINK_UP_LIMIT 50
+
+/* PCS1GLSTA Bit Masks */
+#define IXGBE_PCS1GLSTA_LINK_OK 1
+#define IXGBE_PCS1GLSTA_SYNK_OK 0x10
+#define IXGBE_PCS1GLSTA_AN_COMPLETE 0x10000
+#define IXGBE_PCS1GLSTA_AN_PAGE_RX 0x20000
+#define IXGBE_PCS1GLSTA_AN_TIMED_OUT 0x40000
+#define IXGBE_PCS1GLSTA_AN_REMOTE_FAULT 0x80000
+#define IXGBE_PCS1GLSTA_AN_ERROR_RWS 0x100000
+
+#define IXGBE_PCS1GANA_SYM_PAUSE 0x80
+#define IXGBE_PCS1GANA_ASM_PAUSE 0x100
+
+/* PCS1GLCTL Bit Masks */
+#define IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN 0x00040000 /* PCS 1G autoneg timeout enable (bit 18) */
+#define IXGBE_PCS1GLCTL_FLV_LINK_UP 1
+#define IXGBE_PCS1GLCTL_FORCE_LINK 0x20
+#define IXGBE_PCS1GLCTL_LOW_LINK_LATCH 0x40
+#define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000
+#define IXGBE_PCS1GLCTL_AN_RESTART 0x20000
/* SW Semaphore Register bitmasks */
#define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
@@ -741,6 +771,11 @@
#define IXGBE_CSR1_CONFIG_PTR 0x0E
#define IXGBE_FW_PTR 0x0F
+/* Legacy EEPROM word offsets */
+#define IXGBE_ISCSI_BOOT_CAPS 0x0033
+#define IXGBE_ISCSI_SETUP_PORT_0 0x0030
+#define IXGBE_ISCSI_SETUP_PORT_1 0x0034
+
/* EEPROM Commands - SPI */
#define IXGBE_EEPROM_MAX_RETRY_SPI 5000 /* Max wait 5ms for RDY signal */
#define IXGBE_EEPROM_STATUS_RDY_SPI 0x01
@@ -783,6 +818,8 @@
#define IXGBE_PCI_LINK_SPEED 0xF
#define IXGBE_PCI_LINK_SPEED_2500 0x1
#define IXGBE_PCI_LINK_SPEED_5000 0x2
+#define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E
+#define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80
/* Number of 100 microseconds we wait for PCI Express master disable */
#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
@@ -911,14 +948,15 @@
#define IXGBE_RXD_CFI_SHIFT 12
/* SRRCTL bit definitions */
-#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */
-#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F
-#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00
-#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000
+#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */
+#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F
+#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00
+#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000
#define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
#define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
+#define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000
#define IXGBE_RXDPS_HDRSTAT_HDRSP 0x00008000
#define IXGBE_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF
@@ -1107,6 +1145,7 @@ typedef u32 ixgbe_autoneg_advertised;
/* Link speed */
typedef u32 ixgbe_link_speed;
#define IXGBE_LINK_SPEED_UNKNOWN 0
+#define IXGBE_LINK_SPEED_100_FULL 0x0008
#define IXGBE_LINK_SPEED_1GB_FULL 0x0020
#define IXGBE_LINK_SPEED_10GB_FULL 0x0080
@@ -1125,7 +1164,6 @@ enum ixgbe_mac_type {
enum ixgbe_phy_type {
ixgbe_phy_unknown = 0,
- ixgbe_phy_tn,
ixgbe_phy_qt,
ixgbe_phy_xaui
};
@@ -1287,8 +1325,8 @@ struct ixgbe_functions
u32 (*ixgbe_func_get_num_of_rx_queues)(struct ixgbe_hw *);
s32 (*ixgbe_func_stop_adapter)(struct ixgbe_hw *);
s32 (*ixgbe_func_get_bus_info)(struct ixgbe_hw *);
-
-
+ s32 (*ixgbe_func_read_analog_reg8)(struct ixgbe_hw*, u32, u8*);
+ s32 (*ixgbe_func_write_analog_reg8)(struct ixgbe_hw*, u32, u8);
/* PHY */
s32 (*ixgbe_func_identify_phy)(struct ixgbe_hw *);
s32 (*ixgbe_func_reset_phy)(struct ixgbe_hw *);
@@ -1347,6 +1385,8 @@ struct ixgbe_mac_info {
u32 link_attach_type;
u32 link_mode_select;
bool link_settings_loaded;
+ bool autoneg;
+ bool autoneg_failed;
};
struct ixgbe_phy_info {
diff --git a/sys/modules/ixgbe/Makefile b/sys/modules/ixgbe/Makefile
new file mode 100644
index 0000000..ae31c15
--- /dev/null
+++ b/sys/modules/ixgbe/Makefile
@@ -0,0 +1,15 @@
+#$FreeBSD$
+.PATH: ${.CURDIR}/../../dev/ixgbe
+KMOD = ixgbe
+SRCS = device_if.h bus_if.h pci_if.h opt_bdg.h
+SRCS += ixgbe.c
+# Shared source
+SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_82598.c
+CFLAGS+= -I${.CURDIR}/../../dev/ixgbe
+
+clean:
+ rm -f opt_bdg.h device_if.h bus_if.h pci_if.h setdef* *_StripErr
+ rm -f *.o *.kld *.ko
+ rm -f @ machine
+
+.include <bsd.kmod.mk>
OpenPOWER on IntegriCloud