PERFORCE change 108892 for review
John Birrell
jb at FreeBSD.org
Wed Nov 1 07:20:25 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=108892
Change 108892 by jb at jb_freebsd8 on 2006/11/01 07:19:53
Reset these files to match current. I had been keeping a
version of the never-ending-updated-by-everyone driver
that actually worked on sun4v. It changes faster than I
can test it.
In my new sun4v branch I've got a driver called 'me' that
I can use every time the 'em' from current goes off into
no-worky-land.
Affected files ...
.. //depot/projects/dtrace/src/sys/dev/em/if_em.c#10 integrate
.. //depot/projects/dtrace/src/sys/dev/em/if_em.h#6 integrate
.. //depot/projects/dtrace/src/sys/dev/em/if_em_hw.c#7 integrate
.. //depot/projects/dtrace/src/sys/dev/em/if_em_hw.h#5 integrate
.. //depot/projects/dtrace/src/sys/dev/em/if_em_osdep.h#6 integrate
Differences ...
==== //depot/projects/dtrace/src/sys/dev/em/if_em.c#10 (text+ko) ====
@@ -1,7 +1,6 @@
-//depot/projects/dtrace/src/sys/dev/em/if_em.c#7 - edit change 102692 (text+ko)
/**************************************************************************
-Copyright (c) 2001-2005, Intel Corporation
+Copyright (c) 2001-2006, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -32,7 +31,7 @@
***************************************************************************/
-/*$FreeBSD: src/sys/dev/em/if_em.c,v 1.119 2006/07/20 04:18:45 yongari Exp $*/
+/*$FreeBSD: src/sys/dev/em/if_em.c,v 1.160 2006/10/31 17:21:14 jhb Exp $*/
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_device_polling.h"
@@ -70,9 +69,11 @@
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
+#include <machine/in_cksum.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/em/if_em_hw.h>
@@ -87,7 +88,7 @@
* Driver version
*********************************************************************/
-char em_driver_version[] = "Version - 5.1.5";
+char em_driver_version[] = "Version - 6.2.9";
/*********************************************************************
@@ -151,6 +152,10 @@
{ 0x8086, E1000_DEV_ID_82571EB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82571EB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82571EB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82572EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82572EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
@@ -160,10 +165,21 @@
{ 0x8086, E1000_DEV_ID_82573E, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82573E_IAMT, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82573L, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_80003ES2LAN_COPPER_SPT,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_80003ES2LAN_SERDES_SPT,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_80003ES2LAN_COPPER_DPT,
PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_80003ES2LAN_SERDES_DPT,
PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_ICH8_IGP_M_AMT, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_ICH8_IGP_AMT, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_ICH8_IGP_C, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_ICH8_IFE, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_ICH8_IFE_GT, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_ICH8_IFE_G, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_ICH8_IGP_M, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
@@ -191,64 +207,65 @@
static int em_ioctl(struct ifnet *, u_long, caddr_t);
static void em_watchdog(struct ifnet *);
static void em_init(void *);
-static void em_init_locked(struct em_softc *);
+static void em_init_locked(struct adapter *);
static void em_stop(void *);
static void em_media_status(struct ifnet *, struct ifmediareq *);
static int em_media_change(struct ifnet *);
-static void em_identify_hardware(struct em_softc *);
-static int em_allocate_pci_resources(struct em_softc *);
-static int em_allocate_intr(struct em_softc *);
-static void em_free_intr(struct em_softc *);
-static void em_free_pci_resources(struct em_softc *);
+static void em_identify_hardware(struct adapter *);
+static int em_allocate_pci_resources(struct adapter *);
+static int em_allocate_intr(struct adapter *);
+static void em_free_intr(struct adapter *);
+static void em_free_pci_resources(struct adapter *);
static void em_local_timer(void *);
-static int em_hardware_init(struct em_softc *);
-static void em_setup_interface(device_t, struct em_softc *);
-static int em_setup_transmit_structures(struct em_softc *);
-static void em_initialize_transmit_unit(struct em_softc *);
-static int em_setup_receive_structures(struct em_softc *);
-static void em_initialize_receive_unit(struct em_softc *);
-static void em_enable_intr(struct em_softc *);
-static void em_disable_intr(struct em_softc *);
-static void em_free_transmit_structures(struct em_softc *);
-static void em_free_receive_structures(struct em_softc *);
-static void em_update_stats_counters(struct em_softc *);
-static void em_txeof(struct em_softc *);
-static int em_allocate_receive_structures(struct em_softc *);
-static int em_allocate_transmit_structures(struct em_softc *);
-static int em_rxeof(struct em_softc *, int);
+static int em_hardware_init(struct adapter *);
+static void em_setup_interface(device_t, struct adapter *);
+static void em_setup_transmit_structures(struct adapter *);
+static void em_initialize_transmit_unit(struct adapter *);
+static int em_setup_receive_structures(struct adapter *);
+static void em_initialize_receive_unit(struct adapter *);
+static void em_enable_intr(struct adapter *);
+static void em_disable_intr(struct adapter *);
+static void em_free_transmit_structures(struct adapter *);
+static void em_free_receive_structures(struct adapter *);
+static void em_update_stats_counters(struct adapter *);
+static void em_txeof(struct adapter *);
+static int em_allocate_receive_structures(struct adapter *);
+static int em_allocate_transmit_structures(struct adapter *);
+static int em_rxeof(struct adapter *, int);
#ifndef __NO_STRICT_ALIGNMENT
-static int em_fixup_rx(struct em_softc *);
+static int em_fixup_rx(struct adapter *);
#endif
-static void em_receive_checksum(struct em_softc *, struct em_rx_desc *,
+static void em_receive_checksum(struct adapter *, struct em_rx_desc *,
struct mbuf *);
-static void em_transmit_checksum_setup(struct em_softc *, struct mbuf *,
+static void em_transmit_checksum_setup(struct adapter *, struct mbuf *,
+ uint32_t *, uint32_t *);
+static boolean_t em_tso_setup(struct adapter *, struct mbuf *,
uint32_t *, uint32_t *);
-static void em_set_promisc(struct em_softc *);
-static void em_disable_promisc(struct em_softc *);
-static void em_set_multi(struct em_softc *);
-static void em_print_hw_stats(struct em_softc *);
-static void em_update_link_status(struct em_softc *);
-static int em_get_buf(int i, struct em_softc *, struct mbuf *);
-static void em_enable_vlans(struct em_softc *);
-static void em_disable_vlans(struct em_softc *);
-static int em_encap(struct em_softc *, struct mbuf **);
-static void em_smartspeed(struct em_softc *);
-static int em_82547_fifo_workaround(struct em_softc *, int);
-static void em_82547_update_fifo_head(struct em_softc *, int);
-static int em_82547_tx_fifo_reset(struct em_softc *);
+static void em_set_promisc(struct adapter *);
+static void em_disable_promisc(struct adapter *);
+static void em_set_multi(struct adapter *);
+static void em_print_hw_stats(struct adapter *);
+static void em_update_link_status(struct adapter *);
+static int em_get_buf(struct adapter *, int);
+static void em_enable_vlans(struct adapter *);
+static void em_disable_vlans(struct adapter *);
+static int em_encap(struct adapter *, struct mbuf **);
+static void em_smartspeed(struct adapter *);
+static int em_82547_fifo_workaround(struct adapter *, int);
+static void em_82547_update_fifo_head(struct adapter *, int);
+static int em_82547_tx_fifo_reset(struct adapter *);
static void em_82547_move_tail(void *arg);
-static void em_82547_move_tail_locked(struct em_softc *);
-static int em_dma_malloc(struct em_softc *, bus_size_t,
+static int em_dma_malloc(struct adapter *, bus_size_t,
struct em_dma_alloc *, int);
-static void em_dma_free(struct em_softc *, struct em_dma_alloc *);
-static void em_print_debug_info(struct em_softc *);
+static void em_dma_free(struct adapter *, struct em_dma_alloc *);
+static void em_print_debug_info(struct adapter *);
static int em_is_valid_ether_addr(uint8_t *);
static int em_sysctl_stats(SYSCTL_HANDLER_ARGS);
static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
static uint32_t em_fill_descriptors (bus_addr_t address, uint32_t length,
PDESC_ARRAY desc_array);
static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
-static void em_add_int_delay_sysctl(struct em_softc *, const char *,
+static void em_add_int_delay_sysctl(struct adapter *, const char *,
const char *, struct em_int_delay_info *, int, int);
/*
@@ -260,7 +277,7 @@
static void em_intr(void *);
#else
static void em_intr_fast(void *);
-static void em_add_int_process_limit(struct em_softc *, const char *,
+static void em_add_int_process_limit(struct adapter *, const char *,
const char *, int *, int);
static void em_handle_rxtx(void *context, int pending);
static void em_handle_link(void *context, int pending);
@@ -282,7 +299,7 @@
};
static driver_t em_driver = {
- "em", em_methods, sizeof(struct em_softc),
+ "em", em_methods, sizeof(struct adapter),
};
static devclass_t em_devclass;
@@ -296,6 +313,7 @@
#define E1000_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000)
#define E1000_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024)
+#define M_TSO_LEN 66
static int em_tx_int_delay_dflt = E1000_TICKS_TO_USECS(EM_TIDV);
static int em_rx_int_delay_dflt = E1000_TICKS_TO_USECS(EM_RDTR);
@@ -303,6 +321,7 @@
static int em_rx_abs_int_delay_dflt = E1000_TICKS_TO_USECS(EM_RADV);
static int em_rxd = EM_DEFAULT_RXD;
static int em_txd = EM_DEFAULT_TXD;
+static int em_smart_pwr_down = FALSE;
TUNABLE_INT("hw.em.tx_int_delay", &em_tx_int_delay_dflt);
TUNABLE_INT("hw.em.rx_int_delay", &em_rx_int_delay_dflt);
@@ -310,6 +329,7 @@
TUNABLE_INT("hw.em.rx_abs_int_delay", &em_rx_abs_int_delay_dflt);
TUNABLE_INT("hw.em.rxd", &em_rxd);
TUNABLE_INT("hw.em.txd", &em_txd);
+TUNABLE_INT("hw.em.smart_pwr_down", &em_smart_pwr_down);
#ifndef DEVICE_POLLING
static int em_rx_process_limit = 100;
TUNABLE_INT("hw.em.rx_process_limit", &em_rx_process_limit);
@@ -379,199 +399,216 @@
static int
em_attach(device_t dev)
{
- struct em_softc *sc;
+ struct adapter *adapter;
int tsize, rsize;
int error = 0;
INIT_DEBUGOUT("em_attach: begin");
- sc = device_get_softc(dev);
- sc->dev = sc->osdep.dev = dev;
- EM_LOCK_INIT(sc, device_get_nameunit(dev));
+ adapter = device_get_softc(dev);
+ adapter->dev = adapter->osdep.dev = dev;
+ EM_LOCK_INIT(adapter, device_get_nameunit(dev));
/* SYSCTL stuff */
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "debug_info", CTLTYPE_INT|CTLFLAG_RW, sc, 0,
+ OID_AUTO, "debug_info", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
em_sysctl_debug_info, "I", "Debug Information");
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, sc, 0,
+ OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
em_sysctl_stats, "I", "Statistics");
- callout_init(&sc->timer, CALLOUT_MPSAFE);
- callout_init(&sc->tx_fifo_timer, CALLOUT_MPSAFE);
+ callout_init_mtx(&adapter->timer, &adapter->mtx, 0);
+ callout_init_mtx(&adapter->tx_fifo_timer, &adapter->mtx, 0);
/* Determine hardware revision */
- em_identify_hardware(sc);
+ em_identify_hardware(adapter);
/* Set up some sysctls for the tunable interrupt delays */
- em_add_int_delay_sysctl(sc, "rx_int_delay",
- "receive interrupt delay in usecs", &sc->rx_int_delay,
- E1000_REG_OFFSET(&sc->hw, RDTR), em_rx_int_delay_dflt);
- em_add_int_delay_sysctl(sc, "tx_int_delay",
- "transmit interrupt delay in usecs", &sc->tx_int_delay,
- E1000_REG_OFFSET(&sc->hw, TIDV), em_tx_int_delay_dflt);
- if (sc->hw.mac_type >= em_82540) {
- em_add_int_delay_sysctl(sc, "rx_abs_int_delay",
+ em_add_int_delay_sysctl(adapter, "rx_int_delay",
+ "receive interrupt delay in usecs", &adapter->rx_int_delay,
+ E1000_REG_OFFSET(&adapter->hw, RDTR), em_rx_int_delay_dflt);
+ em_add_int_delay_sysctl(adapter, "tx_int_delay",
+ "transmit interrupt delay in usecs", &adapter->tx_int_delay,
+ E1000_REG_OFFSET(&adapter->hw, TIDV), em_tx_int_delay_dflt);
+ if (adapter->hw.mac_type >= em_82540) {
+ em_add_int_delay_sysctl(adapter, "rx_abs_int_delay",
"receive interrupt delay limit in usecs",
- &sc->rx_abs_int_delay,
- E1000_REG_OFFSET(&sc->hw, RADV),
+ &adapter->rx_abs_int_delay,
+ E1000_REG_OFFSET(&adapter->hw, RADV),
em_rx_abs_int_delay_dflt);
- em_add_int_delay_sysctl(sc, "tx_abs_int_delay",
+ em_add_int_delay_sysctl(adapter, "tx_abs_int_delay",
"transmit interrupt delay limit in usecs",
- &sc->tx_abs_int_delay,
- E1000_REG_OFFSET(&sc->hw, TADV),
+ &adapter->tx_abs_int_delay,
+ E1000_REG_OFFSET(&adapter->hw, TADV),
em_tx_abs_int_delay_dflt);
}
#ifndef DEVICE_POLLING
/* Sysctls for limiting the amount of work done in the taskqueue */
- em_add_int_process_limit(sc, "rx_processing_limit",
- "max number of rx packets to process", &sc->rx_process_limit,
+ em_add_int_process_limit(adapter, "rx_processing_limit",
+ "max number of rx packets to process", &adapter->rx_process_limit,
em_rx_process_limit);
#endif
/*
* Validate number of transmit and receive descriptors. It
* must not exceed hardware maximum, and must be multiple
- * of E1000_DBA_ALIGN.
+ * of EM_DBA_ALIGN.
*/
- if (((em_txd * sizeof(struct em_tx_desc)) % E1000_DBA_ALIGN) != 0 ||
- (sc->hw.mac_type >= em_82544 && em_txd > EM_MAX_TXD) ||
- (sc->hw.mac_type < em_82544 && em_txd > EM_MAX_TXD_82543) ||
+ if (((em_txd * sizeof(struct em_tx_desc)) % EM_DBA_ALIGN) != 0 ||
+ (adapter->hw.mac_type >= em_82544 && em_txd > EM_MAX_TXD) ||
+ (adapter->hw.mac_type < em_82544 && em_txd > EM_MAX_TXD_82543) ||
(em_txd < EM_MIN_TXD)) {
device_printf(dev, "Using %d TX descriptors instead of %d!\n",
EM_DEFAULT_TXD, em_txd);
- sc->num_tx_desc = EM_DEFAULT_TXD;
+ adapter->num_tx_desc = EM_DEFAULT_TXD;
} else
- sc->num_tx_desc = em_txd;
- if (((em_rxd * sizeof(struct em_rx_desc)) % E1000_DBA_ALIGN) != 0 ||
- (sc->hw.mac_type >= em_82544 && em_rxd > EM_MAX_RXD) ||
- (sc->hw.mac_type < em_82544 && em_rxd > EM_MAX_RXD_82543) ||
+ adapter->num_tx_desc = em_txd;
+ if (((em_rxd * sizeof(struct em_rx_desc)) % EM_DBA_ALIGN) != 0 ||
+ (adapter->hw.mac_type >= em_82544 && em_rxd > EM_MAX_RXD) ||
+ (adapter->hw.mac_type < em_82544 && em_rxd > EM_MAX_RXD_82543) ||
(em_rxd < EM_MIN_RXD)) {
device_printf(dev, "Using %d RX descriptors instead of %d!\n",
EM_DEFAULT_RXD, em_rxd);
- sc->num_rx_desc = EM_DEFAULT_RXD;
+ adapter->num_rx_desc = EM_DEFAULT_RXD;
} else
- sc->num_rx_desc = em_rxd;
+ adapter->num_rx_desc = em_rxd;
- sc->hw.autoneg = DO_AUTO_NEG;
- sc->hw.wait_autoneg_complete = WAIT_FOR_AUTO_NEG_DEFAULT;
- sc->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
- sc->hw.tbi_compatibility_en = TRUE;
- sc->rx_buffer_len = EM_RXBUFFER_2048;
+ adapter->hw.autoneg = DO_AUTO_NEG;
+ adapter->hw.wait_autoneg_complete = WAIT_FOR_AUTO_NEG_DEFAULT;
+ adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
+ adapter->hw.tbi_compatibility_en = TRUE;
+ adapter->rx_buffer_len = EM_RXBUFFER_2048;
- sc->hw.phy_init_script = 1;
- sc->hw.phy_reset_disable = FALSE;
+ adapter->hw.phy_init_script = 1;
+ adapter->hw.phy_reset_disable = FALSE;
#ifndef EM_MASTER_SLAVE
- sc->hw.master_slave = em_ms_hw_default;
+ adapter->hw.master_slave = em_ms_hw_default;
#else
- sc->hw.master_slave = EM_MASTER_SLAVE;
+ adapter->hw.master_slave = EM_MASTER_SLAVE;
#endif
/*
* Set the max frame size assuming standard ethernet
* sized frames.
*/
- sc->hw.max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ adapter->hw.max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
- sc->hw.min_frame_size = MINIMUM_ETHERNET_PACKET_SIZE + ETHER_CRC_LEN;
+ adapter->hw.min_frame_size = MINIMUM_ETHERNET_PACKET_SIZE + ETHER_CRC_LEN;
/*
* This controls when hardware reports transmit completion
* status.
*/
- sc->hw.report_tx_early = 1;
- if (em_allocate_pci_resources(sc)) {
+ adapter->hw.report_tx_early = 1;
+ if (em_allocate_pci_resources(adapter)) {
device_printf(dev, "Allocation of PCI resources failed\n");
error = ENXIO;
goto err_pci;
}
/* Initialize eeprom parameters */
- em_init_eeprom_params(&sc->hw);
+ em_init_eeprom_params(&adapter->hw);
- tsize = roundup2(sc->num_tx_desc * sizeof(struct em_tx_desc),
- E1000_DBA_ALIGN);
+ tsize = roundup2(adapter->num_tx_desc * sizeof(struct em_tx_desc),
+ EM_DBA_ALIGN);
/* Allocate Transmit Descriptor ring */
- if (em_dma_malloc(sc, tsize, &sc->txdma, BUS_DMA_NOWAIT)) {
+ if (em_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) {
device_printf(dev, "Unable to allocate tx_desc memory\n");
error = ENOMEM;
goto err_tx_desc;
}
- sc->tx_desc_base = (struct em_tx_desc *)sc->txdma.dma_vaddr;
+ adapter->tx_desc_base = (struct em_tx_desc *)adapter->txdma.dma_vaddr;
- rsize = roundup2(sc->num_rx_desc * sizeof(struct em_rx_desc),
- E1000_DBA_ALIGN);
+ rsize = roundup2(adapter->num_rx_desc * sizeof(struct em_rx_desc),
+ EM_DBA_ALIGN);
/* Allocate Receive Descriptor ring */
- if (em_dma_malloc(sc, rsize, &sc->rxdma, BUS_DMA_NOWAIT)) {
+ if (em_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) {
device_printf(dev, "Unable to allocate rx_desc memory\n");
error = ENOMEM;
goto err_rx_desc;
}
- sc->rx_desc_base = (struct em_rx_desc *)sc->rxdma.dma_vaddr;
+ adapter->rx_desc_base = (struct em_rx_desc *)adapter->rxdma.dma_vaddr;
/* Initialize the hardware */
- if (em_hardware_init(sc)) {
+ if (em_hardware_init(adapter)) {
device_printf(dev, "Unable to initialize the hardware\n");
error = EIO;
goto err_hw_init;
}
/* Copy the permanent MAC address out of the EEPROM */
- if (em_read_mac_addr(&sc->hw) < 0) {
+ if (em_read_mac_addr(&adapter->hw) < 0) {
device_printf(dev, "EEPROM read error while reading MAC"
" address\n");
error = EIO;
goto err_hw_init;
}
- if (!em_is_valid_ether_addr(sc->hw.mac_addr)) {
+ if (!em_is_valid_ether_addr(adapter->hw.mac_addr)) {
device_printf(dev, "Invalid MAC address\n");
error = EIO;
goto err_hw_init;
}
+ /* Allocate transmit descriptors and buffers */
+ if (em_allocate_transmit_structures(adapter)) {
+ device_printf(dev, "Could not setup transmit structures\n");
+ error = ENOMEM;
+ goto err_tx_struct;
+ }
+
+ /* Allocate receive descriptors and buffers */
+ if (em_allocate_receive_structures(adapter)) {
+ device_printf(dev, "Could not setup receive structures\n");
+ error = ENOMEM;
+ goto err_rx_struct;
+ }
+
/* Setup OS specific network interface */
- em_setup_interface(dev, sc);
+ em_setup_interface(dev, adapter);
- em_allocate_intr(sc);
+ em_allocate_intr(adapter);
/* Initialize statistics */
- em_clear_hw_cntrs(&sc->hw);
- em_update_stats_counters(sc);
- sc->hw.get_link_status = 1;
- em_update_link_status(sc);
+ em_clear_hw_cntrs(&adapter->hw);
+ em_update_stats_counters(adapter);
+ adapter->hw.get_link_status = 1;
+ em_update_link_status(adapter);
/* Indicate SOL/IDER usage */
- if (em_check_phy_reset_block(&sc->hw))
+ if (em_check_phy_reset_block(&adapter->hw))
device_printf(dev,
"PHY reset is blocked due to SOL/IDER session.\n");
/* Identify 82544 on PCIX */
- em_get_bus_info(&sc->hw);
- if(sc->hw.bus_type == em_bus_type_pcix && sc->hw.mac_type == em_82544)
- sc->pcix_82544 = TRUE;
+ em_get_bus_info(&adapter->hw);
+ if(adapter->hw.bus_type == em_bus_type_pcix && adapter->hw.mac_type == em_82544)
+ adapter->pcix_82544 = TRUE;
else
- sc->pcix_82544 = FALSE;
+ adapter->pcix_82544 = FALSE;
INIT_DEBUGOUT("em_attach: end");
return (0);
+err_rx_struct:
+ em_free_transmit_structures(adapter);
+err_tx_struct:
err_hw_init:
- em_dma_free(sc, &sc->rxdma);
+ em_dma_free(adapter, &adapter->rxdma);
err_rx_desc:
- em_dma_free(sc, &sc->txdma);
+ em_dma_free(adapter, &adapter->txdma);
err_tx_desc:
err_pci:
- em_free_intr(sc);
- em_free_pci_resources(sc);
- EM_LOCK_DESTROY(sc);
+ em_free_intr(adapter);
+ em_free_pci_resources(adapter);
+ EM_LOCK_DESTROY(adapter);
return (error);
}
@@ -589,8 +626,8 @@
static int
em_detach(device_t dev)
{
- struct em_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->ifp;
+ struct adapter *adapter = device_get_softc(dev);
+ struct ifnet *ifp = adapter->ifp;
INIT_DEBUGOUT("em_detach: begin");
@@ -599,31 +636,37 @@
ether_poll_deregister(ifp);
#endif
- em_free_intr(sc);
- EM_LOCK(sc);
- sc->in_detach = 1;
- em_stop(sc);
- em_phy_hw_reset(&sc->hw);
- EM_UNLOCK(sc);
- ether_ifdetach(sc->ifp);
+ em_free_intr(adapter);
+ EM_LOCK(adapter);
+ adapter->in_detach = 1;
+ em_stop(adapter);
+ em_phy_hw_reset(&adapter->hw);
+ EM_UNLOCK(adapter);
+ ether_ifdetach(adapter->ifp);
+
+ callout_drain(&adapter->timer);
+ callout_drain(&adapter->tx_fifo_timer);
- em_free_pci_resources(sc);
+ em_free_pci_resources(adapter);
bus_generic_detach(dev);
if_free(ifp);
+ em_free_transmit_structures(adapter);
+ em_free_receive_structures(adapter);
+
/* Free Transmit Descriptor ring */
- if (sc->tx_desc_base) {
- em_dma_free(sc, &sc->txdma);
- sc->tx_desc_base = NULL;
+ if (adapter->tx_desc_base) {
+ em_dma_free(adapter, &adapter->txdma);
+ adapter->tx_desc_base = NULL;
}
/* Free Receive Descriptor ring */
- if (sc->rx_desc_base) {
- em_dma_free(sc, &sc->rxdma);
- sc->rx_desc_base = NULL;
+ if (adapter->rx_desc_base) {
+ em_dma_free(adapter, &adapter->rxdma);
+ adapter->rx_desc_base = NULL;
}
- EM_LOCK_DESTROY(sc);
+ EM_LOCK_DESTROY(adapter);
return (0);
}
@@ -637,10 +680,10 @@
static int
em_shutdown(device_t dev)
{
- struct em_softc *sc = device_get_softc(dev);
- EM_LOCK(sc);
- em_stop(sc);
- EM_UNLOCK(sc);
+ struct adapter *adapter = device_get_softc(dev);
+ EM_LOCK(adapter);
+ em_stop(adapter);
+ EM_UNLOCK(adapter);
return (0);
}
@@ -650,11 +693,11 @@
static int
em_suspend(device_t dev)
{
- struct em_softc *sc = device_get_softc(dev);
+ struct adapter *adapter = device_get_softc(dev);
- EM_LOCK(sc);
- em_stop(sc);
- EM_UNLOCK(sc);
+ EM_LOCK(adapter);
+ em_stop(adapter);
+ EM_UNLOCK(adapter);
return bus_generic_suspend(dev);
}
@@ -662,15 +705,15 @@
static int
em_resume(device_t dev)
{
- struct em_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->ifp;
+ struct adapter *adapter = device_get_softc(dev);
+ struct ifnet *ifp = adapter->ifp;
- EM_LOCK(sc);
- em_init_locked(sc);
+ EM_LOCK(adapter);
+ em_init_locked(adapter);
if ((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING))
em_start_locked(ifp);
- EM_UNLOCK(sc);
+ EM_UNLOCK(adapter);
return bus_generic_resume(dev);
}
@@ -689,15 +732,15 @@
static void
em_start_locked(struct ifnet *ifp)
{
- struct em_softc *sc = ifp->if_softc;
+ struct adapter *adapter = ifp->if_softc;
struct mbuf *m_head;
- EM_LOCK_ASSERT(sc);
+ EM_LOCK_ASSERT(adapter);
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING)
return;
- if (!sc->link_active)
+ if (!adapter->link_active)
return;
while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
@@ -709,7 +752,7 @@
* em_encap() can modify our pointer, and or make it NULL on
* failure. In that event, we can't requeue.
*/
- if (em_encap(sc, &m_head)) {
+ if (em_encap(adapter, &m_head)) {
if (m_head == NULL)
break;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -728,12 +771,12 @@
static void
em_start(struct ifnet *ifp)
{
- struct em_softc *sc = ifp->if_softc;
+ struct adapter *adapter = ifp->if_softc;
- EM_LOCK(sc);
+ EM_LOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
em_start_locked(ifp);
- EM_UNLOCK(sc);
+ EM_UNLOCK(adapter);
}
/*********************************************************************
@@ -748,12 +791,12 @@
static int
em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
- struct em_softc *sc = ifp->if_softc;
+ struct adapter *adapter = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct ifaddr *ifa = (struct ifaddr *)data;
int error = 0;
- if (sc->in_detach)
+ if (adapter->in_detach)
return (error);
switch (command) {
@@ -769,9 +812,9 @@
*/
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- EM_LOCK(sc);
- em_init_locked(sc);
- EM_UNLOCK(sc);
+ EM_LOCK(adapter);
+ em_init_locked(adapter);
+ EM_UNLOCK(adapter);
}
arp_ifinit(ifp, ifa);
} else
@@ -784,14 +827,14 @@
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
- EM_LOCK(sc);
- switch (sc->hw.mac_type) {
+ EM_LOCK(adapter);
+ switch (adapter->hw.mac_type) {
case em_82573:
/*
* 82573 only supports jumbo frames
* if ASPM is disabled.
*/
- em_read_eeprom(&sc->hw, EEPROM_INIT_3GIO_3, 1,
+ em_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1,
&eeprom_data);
if (eeprom_data & EEPROM_WORD1A_ASPM_MASK) {
max_frame_size = ETHER_MAX_LEN;
@@ -803,64 +846,77 @@
case em_80003es2lan: /* Limit Jumbo Frame size */
max_frame_size = 9234;
break;
+ case em_ich8lan:
+ /* ICH8 does not support jumbo frames */
+ max_frame_size = ETHER_MAX_LEN;
+ break;
default:
max_frame_size = MAX_JUMBO_FRAME_SIZE;
}
if (ifr->ifr_mtu > max_frame_size - ETHER_HDR_LEN -
ETHER_CRC_LEN) {
- EM_UNLOCK(sc);
+ EM_UNLOCK(adapter);
error = EINVAL;
break;
}
ifp->if_mtu = ifr->ifr_mtu;
- sc->hw.max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
- em_init_locked(sc);
- EM_UNLOCK(sc);
+ adapter->hw.max_frame_size =
+ ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ em_init_locked(adapter);
+ EM_UNLOCK(adapter);
break;
}
case SIOCSIFFLAGS:
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
- EM_LOCK(sc);
+ EM_LOCK(adapter);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- if ((ifp->if_flags ^ sc->if_flags) &
+ if ((ifp->if_flags ^ adapter->if_flags) &
IFF_PROMISC) {
- em_disable_promisc(sc);
- em_set_promisc(sc);
+ em_disable_promisc(adapter);
+ em_set_promisc(adapter);
}
} else
- em_init_locked(sc);
+ em_init_locked(adapter);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- em_stop(sc);
+ em_stop(adapter);
}
}
- sc->if_flags = ifp->if_flags;
- EM_UNLOCK(sc);
+ adapter->if_flags = ifp->if_flags;
+ EM_UNLOCK(adapter);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- EM_LOCK(sc);
- em_disable_intr(sc);
- em_set_multi(sc);
- if (sc->hw.mac_type == em_82542_rev2_0) {
- em_initialize_receive_unit(sc);
+ EM_LOCK(adapter);
+ em_disable_intr(adapter);
+ em_set_multi(adapter);
+ if (adapter->hw.mac_type == em_82542_rev2_0) {
+ em_initialize_receive_unit(adapter);
}
#ifdef DEVICE_POLLING
if (!(ifp->if_capenable & IFCAP_POLLING))
#endif
- em_enable_intr(sc);
- EM_UNLOCK(sc);
+ em_enable_intr(adapter);
+ EM_UNLOCK(adapter);
}
break;
case SIOCSIFMEDIA:
+ /* Check SOL/IDER usage */
+ EM_LOCK(adapter);
+ if (em_check_phy_reset_block(&adapter->hw)) {
+ EM_UNLOCK(adapter);
+ device_printf(adapter->dev, "Media change is"
+ "blocked due to SOL/IDER session.\n");
+ break;
+ }
+ EM_UNLOCK(adapter);
case SIOCGIFMEDIA:
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)");
- error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
+ error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
break;
case SIOCSIFCAP:
{
@@ -875,17 +931,17 @@
error = ether_poll_register(em_poll, ifp);
if (error)
return (error);
- EM_LOCK(sc);
- em_disable_intr(sc);
+ EM_LOCK(adapter);
+ em_disable_intr(adapter);
ifp->if_capenable |= IFCAP_POLLING;
- EM_UNLOCK(sc);
+ EM_UNLOCK(adapter);
} else {
error = ether_poll_deregister(ifp);
/* Enable interrupt even in error case */
- EM_LOCK(sc);
- em_enable_intr(sc);
+ EM_LOCK(adapter);
+ em_enable_intr(adapter);
ifp->if_capenable &= ~IFCAP_POLLING;
- EM_UNLOCK(sc);
+ EM_UNLOCK(adapter);
}
}
#endif
@@ -893,12 +949,16 @@
ifp->if_capenable ^= IFCAP_HWCSUM;
reinit = 1;
}
+ if (mask & IFCAP_TSO4) {
+ ifp->if_capenable ^= IFCAP_TSO4;
+ reinit = 1;
+ }
if (mask & IFCAP_VLAN_HWTAGGING) {
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
reinit = 1;
}
if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- em_init(sc);
+ em_init(adapter);
VLAN_CAPABILITIES(ifp);
break;
}
@@ -920,26 +980,38 @@
static void
em_watchdog(struct ifnet *ifp)
{
- struct em_softc *sc = ifp->if_softc;
+ struct adapter *adapter = ifp->if_softc;
- EM_LOCK(sc);
+ EM_LOCK(adapter);
/* If we are in this routine because of pause frames, then
* don't reset the hardware.
*/
- if (E1000_READ_REG(&sc->hw, STATUS) & E1000_STATUS_TXOFF) {
+ if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF) {
ifp->if_timer = EM_TX_TIMEOUT;
- EM_UNLOCK(sc);
+ EM_UNLOCK(adapter);
+ return;
+ }
+
+ /*
+ * Reclaim first as there is a possibility of losing Tx completion
+ * interrupts. Possible cause of missing Tx completion interrupts
+ * comes from Tx interrupt moderation mechanism(delayed interrupts)
+ * or chipset bug.
+ */
+ em_txeof(adapter);
+ if (adapter->num_tx_desc_avail == adapter->num_tx_desc) {
+ EM_UNLOCK(adapter);
return;
}
- if (em_check_for_link(&sc->hw) == 0)
- device_printf(sc->dev, "watchdog timeout -- resetting\n");
+ if (em_check_for_link(&adapter->hw) == 0)
+ device_printf(adapter->dev, "watchdog timeout -- resetting\n");
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- sc->watchdog_events++;
+ adapter->watchdog_events++;
- em_init_locked(sc);
- EM_UNLOCK(sc);
+ em_init_locked(adapter);
+ EM_UNLOCK(adapter);
}
/*********************************************************************
@@ -954,33 +1026,39 @@
**********************************************************************/
static void
-em_init_locked(struct em_softc *sc)
+em_init_locked(struct adapter *adapter)
{
- struct ifnet *ifp = sc->ifp;
- device_t dev = sc->dev;
+ struct ifnet *ifp = adapter->ifp;
+ device_t dev = adapter->dev;
uint32_t pba;
INIT_DEBUGOUT("em_init: begin");
- EM_LOCK_ASSERT(sc);
+ EM_LOCK_ASSERT(adapter);
- em_stop(sc);
+ em_stop(adapter);
/*
* Packet Buffer Allocation (PBA)
* Writing PBA sets the receive portion of the buffer
* the remainder is used for the transmit buffer.
+ *
+ * Devices before the 82547 had a Packet Buffer of 64K.
+ * Default allocation: PBA=48K for Rx, leaving 16K for Tx.
+ * After the 82547 the buffer was reduced to 40K.
+ * Default allocation: PBA=30K for Rx, leaving 10K for Tx.
+ * Note: default does not leave enough room for Jumbo Frame >10k.
*/
- switch (sc->hw.mac_type) {
+ switch (adapter->hw.mac_type) {
case em_82547:
case em_82547_rev_2: /* 82547: Total Packet Buffer is 40K */
- if (sc->hw.max_frame_size > EM_RXBUFFER_8192)
+ if (adapter->hw.max_frame_size > EM_RXBUFFER_8192)
pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */
else
pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */
- sc->tx_fifo_head = 0;
- sc->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT;
- sc->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT;
+ adapter->tx_fifo_head = 0;
+ adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT;
+ adapter->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT;
break;
case em_80003es2lan: /* 80003es2lan: Total Packet Buffer is 48K */
case em_82571: /* 82571: Total Packet Buffer is 48K */
@@ -991,150 +1069,154 @@
/* Jumbo frames not supported */
pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */
break;
+ case em_ich8lan:
+ pba = E1000_PBA_8K;
+ break;
default:
/* Devices before 82547 had a Packet Buffer of 64K. */
- if(sc->hw.max_frame_size > EM_RXBUFFER_8192)
+ if(adapter->hw.max_frame_size > EM_RXBUFFER_8192)
pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
else
pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */
}
INIT_DEBUGOUT1("em_init: pba=%dK",pba);
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list