summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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