Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Feb 2011 23:00:24 +0000 (UTC)
From:      David Christensen <davidch@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r218423 - head/sys/dev/bce
Message-ID:  <201102072300.p17N0OUh025540@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidch
Date: Mon Feb  7 23:00:24 2011
New Revision: 218423
URL: http://svn.freebsd.org/changeset/base/218423

Log:
  - Added systcls for header splitting, RX/TX buffer count, interrupt
    coalescing, strict RX MTU, verbose output, and shared memory debug.
  - Added additional debug counters (VLAN tags and split header frames).
  - Updated debug counters to 64 bit definitions.
  - Updated l2fhdr bit definitions.
  - Combined RX buffer sizing into a single function.
  - Added buffer size and interrupt coalescing settings to adapter info
    printout.
  
  Submitted by:	davidch
  MFC after:	2 weeks

Modified:
  head/sys/dev/bce/if_bce.c
  head/sys/dev/bce/if_bcereg.h

Modified: head/sys/dev/bce/if_bce.c
==============================================================================
--- head/sys/dev/bce/if_bce.c	Mon Feb  7 22:37:27 2011	(r218422)
+++ head/sys/dev/bce/if_bce.c	Mon Feb  7 23:00:24 2011	(r218423)
@@ -287,48 +287,43 @@ static int  bce_shutdown		(device_t);
 /* BCE Debug Data Structure Dump Routines                                   */
 /****************************************************************************/
 #ifdef BCE_DEBUG
-static u32  bce_reg_rd			(struct bce_softc *, u32);
-static void bce_reg_wr			(struct bce_softc *, u32, u32);
-static void bce_reg_wr16		(struct bce_softc *, u32, u16);
-static u32  bce_ctx_rd			(struct bce_softc *, u32, u32);
-static void bce_dump_enet		(struct bce_softc *, struct mbuf *);
-static void bce_dump_mbuf		(struct bce_softc *, struct mbuf *);
+static u32  bce_reg_rd				(struct bce_softc *, u32);
+static void bce_reg_wr				(struct bce_softc *, u32, u32);
+static void bce_reg_wr16			(struct bce_softc *, u32, u16);
+static u32  bce_ctx_rd				(struct bce_softc *, u32, u32);
+static void bce_dump_enet			(struct bce_softc *, struct mbuf *);
+static void bce_dump_mbuf			(struct bce_softc *, struct mbuf *);
 static void bce_dump_tx_mbuf_chain	(struct bce_softc *, u16, int);
 static void bce_dump_rx_mbuf_chain	(struct bce_softc *, u16, int);
-#ifdef BCE_JUMBO_HDRSPLIT
 static void bce_dump_pg_mbuf_chain	(struct bce_softc *, u16, int);
-#endif
-static void bce_dump_txbd		(struct bce_softc *,
+static void bce_dump_txbd			(struct bce_softc *,
     int, struct tx_bd *);
-static void bce_dump_rxbd		(struct bce_softc *,
+static void bce_dump_rxbd			(struct bce_softc *,
     int, struct rx_bd *);
-#ifdef BCE_JUMBO_HDRSPLIT
-static void bce_dump_pgbd		(struct bce_softc *,
+static void bce_dump_pgbd			(struct bce_softc *,
     int, struct rx_bd *);
-#endif
 static void bce_dump_l2fhdr		(struct bce_softc *,
     int, struct l2_fhdr *);
-static void bce_dump_ctx		(struct bce_softc *, u16);
-static void bce_dump_ftqs		(struct bce_softc *);
+static void bce_dump_ctx			(struct bce_softc *, u16);
+static void bce_dump_ftqs			(struct bce_softc *);
 static void bce_dump_tx_chain		(struct bce_softc *, u16, int);
 static void bce_dump_rx_bd_chain	(struct bce_softc *, u16, int);
-#ifdef BCE_JUMBO_HDRSPLIT
 static void bce_dump_pg_chain		(struct bce_softc *, u16, int);
-#endif
 static void bce_dump_status_block	(struct bce_softc *);
 static void bce_dump_stats_block	(struct bce_softc *);
 static void bce_dump_driver_state	(struct bce_softc *);
 static void bce_dump_hw_state		(struct bce_softc *);
+static void bce_dump_shmem_state	(struct bce_softc *);
 static void bce_dump_mq_regs		(struct bce_softc *);
 static void bce_dump_bc_state		(struct bce_softc *);
 static void bce_dump_txp_state		(struct bce_softc *, int);
 static void bce_dump_rxp_state		(struct bce_softc *, int);
-static void bce_dump_tpat_state		(struct bce_softc *, int);
+static void bce_dump_tpat_state	(struct bce_softc *, int);
 static void bce_dump_cp_state		(struct bce_softc *, int);
 static void bce_dump_com_state		(struct bce_softc *, int);
-static void bce_dump_rv2p_state		(struct bce_softc *);
-static void bce_breakpoint		(struct bce_softc *);
-#endif
+static void bce_dump_rv2p_state	(struct bce_softc *);
+static void bce_breakpoint			(struct bce_softc *);
+#endif /*BCE_DEBUG */
 
 
 /****************************************************************************/
@@ -355,15 +350,15 @@ static int sysctl_nvram_write(SYSCTL_HAN
 /****************************************************************************/
 static int  bce_acquire_nvram_lock	(struct bce_softc *);
 static int  bce_release_nvram_lock	(struct bce_softc *);
-static void bce_enable_nvram_access	(struct bce_softc *);
-static void bce_disable_nvram_access	(struct bce_softc *);
+static void bce_enable_nvram_access(struct bce_softc *);
+static void bce_disable_nvram_access(struct bce_softc *);
 static int  bce_nvram_read_dword	(struct bce_softc *, u32, u8 *, u32);
-static int  bce_init_nvram		(struct bce_softc *);
-static int  bce_nvram_read		(struct bce_softc *, u32, u8 *, int);
-static int  bce_nvram_test		(struct bce_softc *);
+static int  bce_init_nvram			(struct bce_softc *);
+static int  bce_nvram_read			(struct bce_softc *, u32, u8 *, int);
+static int  bce_nvram_test			(struct bce_softc *);
 #ifdef BCE_NVRAM_WRITE_SUPPORT
 static int  bce_enable_nvram_write	(struct bce_softc *);
-static void bce_disable_nvram_write	(struct bce_softc *);
+static void bce_disable_nvram_write(struct bce_softc *);
 static int  bce_nvram_erase_page	(struct bce_softc *, u32);
 static int  bce_nvram_write_dword	(struct bce_softc *, u32, u8 *, u32);
 static int  bce_nvram_write		(struct bce_softc *, u32, u8 *, int);
@@ -372,12 +367,12 @@ static int  bce_nvram_write		(struct bce
 /****************************************************************************/
 /*                                                                          */
 /****************************************************************************/
-static void bce_get_media		(struct bce_softc *);
-static void bce_init_media		(struct bce_softc *);
-static void bce_dma_map_addr		(void *,
-    bus_dma_segment_t *, int, int);
-static int  bce_dma_alloc		(device_t);
-static void bce_dma_free		(struct bce_softc *);
+static void bce_get_rx_buffer_sizes(struct bce_softc *, int);
+static void bce_get_media			(struct bce_softc *);
+static void bce_init_media			(struct bce_softc *);
+static void bce_dma_map_addr		(void *, bus_dma_segment_t *, int, int);
+static int  bce_dma_alloc			(device_t);
+static void bce_dma_free			(struct bce_softc *);
 static void bce_release_resources	(struct bce_softc *);
 
 /****************************************************************************/
@@ -387,69 +382,67 @@ static int  bce_fw_sync			(struct bce_so
 static void bce_load_rv2p_fw		(struct bce_softc *, u32 *, u32, u32);
 static void bce_load_cpu_fw		(struct bce_softc *,
     struct cpu_reg *, struct fw_info *);
-static void bce_start_cpu		(struct bce_softc *, struct cpu_reg *);
-static void bce_halt_cpu		(struct bce_softc *, struct cpu_reg *);
+static void bce_start_cpu			(struct bce_softc *, struct cpu_reg *);
+static void bce_halt_cpu			(struct bce_softc *, struct cpu_reg *);
 static void bce_start_rxp_cpu		(struct bce_softc *);
 static void bce_init_rxp_cpu		(struct bce_softc *);
 static void bce_init_txp_cpu 		(struct bce_softc *);
 static void bce_init_tpat_cpu		(struct bce_softc *);
 static void bce_init_cp_cpu	  	(struct bce_softc *);
 static void bce_init_com_cpu	  	(struct bce_softc *);
-static void bce_init_cpus		(struct bce_softc *);
+static void bce_init_cpus			(struct bce_softc *);
 
-static void	bce_print_adapter_info	(struct bce_softc *);
+static void bce_print_adapter_info	(struct bce_softc *);
 static void bce_probe_pci_caps		(device_t, struct bce_softc *);
-static void bce_stop			(struct bce_softc *);
-static int  bce_reset			(struct bce_softc *, u32);
-static int  bce_chipinit 		(struct bce_softc *);
-static int  bce_blockinit 		(struct bce_softc *);
+static void bce_stop				(struct bce_softc *);
+static int  bce_reset				(struct bce_softc *, u32);
+static int  bce_chipinit 			(struct bce_softc *);
+static int  bce_blockinit 			(struct bce_softc *);
 
 static int  bce_init_tx_chain		(struct bce_softc *);
 static void bce_free_tx_chain		(struct bce_softc *);
 
-static int  bce_get_rx_buf		(struct bce_softc *,
+static int  bce_get_rx_buf			(struct bce_softc *,
     struct mbuf *, u16 *, u16 *, u32 *);
 static int  bce_init_rx_chain		(struct bce_softc *);
 static void bce_fill_rx_chain		(struct bce_softc *);
 static void bce_free_rx_chain		(struct bce_softc *);
 
-#ifdef BCE_JUMBO_HDRSPLIT
-static int  bce_get_pg_buf		(struct bce_softc *,
+static int  bce_get_pg_buf			(struct bce_softc *,
     struct mbuf *, u16 *, u16 *);
 static int  bce_init_pg_chain		(struct bce_softc *);
 static void bce_fill_pg_chain		(struct bce_softc *);
 static void bce_free_pg_chain		(struct bce_softc *);
-#endif
 
 static struct mbuf *bce_tso_setup	(struct bce_softc *,
     struct mbuf **, u16 *);
-static int  bce_tx_encap		(struct bce_softc *, struct mbuf **);
+static int  bce_tx_encap			(struct bce_softc *, struct mbuf **);
 static void bce_start_locked		(struct ifnet *);
-static void bce_start			(struct ifnet *);
-static int  bce_ioctl			(struct ifnet *, u_long, caddr_t);
-static void bce_watchdog		(struct bce_softc *);
+static void bce_start				(struct ifnet *);
+static int  bce_ioctl				(struct ifnet *, u_long, caddr_t);
+static void bce_watchdog			(struct bce_softc *);
 static int  bce_ifmedia_upd		(struct ifnet *);
 static int  bce_ifmedia_upd_locked	(struct ifnet *);
 static void bce_ifmedia_sts		(struct ifnet *, struct ifmediareq *);
 static void bce_init_locked		(struct bce_softc *);
-static void bce_init			(void *);
+static void bce_init				(void *);
 static void bce_mgmt_init_locked	(struct bce_softc *sc);
 
-static int  bce_init_ctx		(struct bce_softc *);
+static int  bce_init_ctx			(struct bce_softc *);
 static void bce_get_mac_addr		(struct bce_softc *);
 static void bce_set_mac_addr		(struct bce_softc *);
-static void bce_phy_intr		(struct bce_softc *);
+static void bce_phy_intr			(struct bce_softc *);
 static inline u16 bce_get_hw_rx_cons	(struct bce_softc *);
 static void bce_rx_intr			(struct bce_softc *);
 static void bce_tx_intr			(struct bce_softc *);
 static void bce_disable_intr		(struct bce_softc *);
 static void bce_enable_intr		(struct bce_softc *, int);
 
-static void bce_intr			(void *);
+static void bce_intr				(void *);
 static void bce_set_rx_mode		(struct bce_softc *);
 static void bce_stats_update		(struct bce_softc *);
-static void bce_tick			(void *);
-static void bce_pulse			(void *);
+static void bce_tick				(void *);
+static void bce_pulse				(void *);
 static void bce_add_sysctls		(struct bce_softc *);
 
 
@@ -505,23 +498,148 @@ DRIVER_MODULE(miibus, bce, miibus_driver
 SYSCTL_NODE(_hw, OID_AUTO, bce, CTLFLAG_RD, 0, "bce driver parameters");
 
 /* Allowable values are TRUE or FALSE */
+static int bce_verbose = TRUE;
+TUNABLE_INT("hw.bce.verbose", &bce_verbose);
+SYSCTL_INT(_hw_bce, OID_AUTO, verbose, CTLFLAG_RDTUN, &bce_verbose, 0,
+    "Verbose output enable/disable");
+
+/* Allowable values are TRUE or FALSE */
 static int bce_tso_enable = TRUE;
 TUNABLE_INT("hw.bce.tso_enable", &bce_tso_enable);
 SYSCTL_INT(_hw_bce, OID_AUTO, tso_enable, CTLFLAG_RDTUN, &bce_tso_enable, 0,
-"TSO Enable/Disable");
+    "TSO Enable/Disable");
 
 /* Allowable values are 0 (IRQ), 1 (MSI/IRQ), and 2 (MSI-X/MSI/IRQ) */
 /* ToDo: Add MSI-X support. */
 static int bce_msi_enable = 1;
 TUNABLE_INT("hw.bce.msi_enable", &bce_msi_enable);
 SYSCTL_INT(_hw_bce, OID_AUTO, msi_enable, CTLFLAG_RDTUN, &bce_msi_enable, 0,
-"MSI-X|MSI|INTx selector");
+    "MSI-X|MSI|INTx selector");
+
+/* Allowable values are 1, 2, 4, 8. */
+static int bce_rx_pages = DEFAULT_RX_PAGES;
+TUNABLE_INT("hw.bce.rx_pages", &bce_rx_pages);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_pages, CTLFLAG_RDTUN, &bce_rx_pages, 0,
+    "Receive buffer descriptor pages (1 page = 255 buffer descriptors)");
+
+/* Allowable values are 1, 2, 4, 8. */
+static int bce_tx_pages = DEFAULT_TX_PAGES;
+TUNABLE_INT("hw.bce.tx_pages", &bce_tx_pages);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_pages, CTLFLAG_RDTUN, &bce_tx_pages, 0,
+    "Transmit buffer descriptor pages (1 page = 255 buffer descriptors)");
+
+/* Allowable values are TRUE or FALSE. */
+static int bce_hdr_split = TRUE;
+TUNABLE_INT("hw.bce.hdr_split", &bce_hdr_split);
+SYSCTL_UINT(_hw_bce, OID_AUTO, hdr_split, CTLFLAG_RDTUN, &bce_hdr_split, 0,
+    "Frame header/payload splitting Enable/Disable");
+
+/* Allowable values are TRUE or FALSE. */
+static int bce_strict_rx_mtu = FALSE;
+TUNABLE_INT("hw.bce.strict_rx_mtu", &bce_strict_rx_mtu);
+SYSCTL_UINT(_hw_bce, OID_AUTO, loose_rx_mtu, CTLFLAG_RDTUN,
+    &bce_strict_rx_mtu, 0,
+    "Enable/Disable strict RX frame size checking");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate 1 interrupt for every transmit completion. */
+static int bce_tx_quick_cons_trip_int = 1;
+#else
+/* Generate 1 interrupt for every 20 transmit completions. */
+static int bce_tx_quick_cons_trip_int = DEFAULT_TX_QUICK_CONS_TRIP_INT;
+#endif
+TUNABLE_INT("hw.bce.tx_quick_cons_trip_int", &bce_tx_quick_cons_trip_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_quick_cons_trip_int, CTLFLAG_RDTUN,
+    &bce_tx_quick_cons_trip_int, 0,
+    "Transmit BD trip point during interrupts");
+
+/* Allowable values are 0 ... 100 */
+/* Generate 1 interrupt for every transmit completion. */
+#ifdef BCE_DEBUG
+static int bce_tx_quick_cons_trip = 1;
+#else
+/* Generate 1 interrupt for every 20 transmit completions. */
+static int bce_tx_quick_cons_trip = DEFAULT_TX_QUICK_CONS_TRIP;
+#endif
+TUNABLE_INT("hw.bce.tx_quick_cons_trip", &bce_tx_quick_cons_trip);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_quick_cons_trip, CTLFLAG_RDTUN,
+    &bce_tx_quick_cons_trip, 0,
+    "Transmit BD trip point");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an interrupt if 0us have elapsed since the last TX completion. */
+static int bce_tx_ticks_int = 0;
+#else
+/* Generate an interrupt if 80us have elapsed since the last TX completion. */
+static int bce_tx_ticks_int = DEFAULT_TX_TICKS_INT;
+#endif
+TUNABLE_INT("hw.bce.tx_ticks_int", &bce_tx_ticks_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_ticks_int, CTLFLAG_RDTUN,
+    &bce_tx_ticks_int, 0, "Transmit ticks count during interrupt");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an interrupt if 0us have elapsed since the last TX completion. */
+static int bce_tx_ticks = 0;
+#else
+/* Generate an interrupt if 80us have elapsed since the last TX completion. */
+static int bce_tx_ticks = DEFAULT_TX_TICKS;
+#endif
+TUNABLE_INT("hw.bce.tx_ticks", &bce_tx_ticks);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_ticks, CTLFLAG_RDTUN,
+    &bce_tx_ticks, 0, "Transmit ticks count");
 
-/* ToDo: Add tunable to enable/disable strict MTU handling. */
-/* Currently allows "loose" RX MTU checking (i.e. sets the  */
-/* H/W RX MTU to the size of the largest receive buffer, or */
-/* 2048 bytes). This will cause a UNH failure but is more   */
-/* desireable from a functional perspective.                */
+/* Allowable values are 1 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate 1 interrupt for every received frame. */
+static int bce_rx_quick_cons_trip_int = 1;
+#else
+/* Generate 1 interrupt for every 6 received frames. */
+static int bce_rx_quick_cons_trip_int = DEFAULT_RX_QUICK_CONS_TRIP_INT;
+#endif
+TUNABLE_INT("hw.bce.rx_quick_cons_trip_int", &bce_rx_quick_cons_trip_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_quick_cons_trip_int, CTLFLAG_RDTUN,
+    &bce_rx_quick_cons_trip_int, 0,
+    "Receive BD trip point duirng interrupts");
+
+/* Allowable values are 1 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate 1 interrupt for every received frame. */
+static int bce_rx_quick_cons_trip = 1;
+#else
+/* Generate 1 interrupt for every 6 received frames. */
+static int bce_rx_quick_cons_trip = DEFAULT_RX_QUICK_CONS_TRIP;
+#endif
+TUNABLE_INT("hw.bce.rx_quick_cons_trip", &bce_rx_quick_cons_trip);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_quick_cons_trip, CTLFLAG_RDTUN,
+    &bce_rx_quick_cons_trip, 0,
+    "Receive BD trip point");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an int. if 0us have elapsed since the last received frame. */
+static int bce_rx_ticks_int = 0;
+#else
+/* Generate an int. if 18us have elapsed since the last received frame. */
+static int bce_rx_ticks_int = DEFAULT_RX_TICKS_INT;
+#endif
+TUNABLE_INT("hw.bce.rx_ticks_int", &bce_rx_ticks_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_ticks_int, CTLFLAG_RDTUN,
+    &bce_rx_ticks_int, 0, "Receive ticks count during interrupt");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an int. if 0us have elapsed since the last received frame. */
+static int bce_rx_ticks = 0;
+#else
+/* Generate an int. if 18us have elapsed since the last received frame. */
+static int bce_rx_ticks = DEFAULT_RX_TICKS;
+#endif
+TUNABLE_INT("hw.bce.rx_ticks", &bce_rx_ticks);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_ticks, CTLFLAG_RDTUN,
+    &bce_rx_ticks, 0, "Receive ticks count");
 
 
 /****************************************************************************/
@@ -603,7 +721,7 @@ bce_print_adapter_info(struct bce_softc 
 
 	DBENTER(BCE_VERBOSE_LOAD);
 
-	if (bootverbose) {
+	if (bce_verbose || bootverbose) {
 		BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid);
 		printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >>
 		    12) + 'A', ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
@@ -625,12 +743,14 @@ bce_print_adapter_info(struct bce_softc 
 		}
 
 		/* Firmware version and device features. */
-		printf("B/C (%s); Flags (", sc->bce_bc_ver);
+		printf("B/C (%s); Bufs (RX:%d;TX:%d;PG:%d); Flags (",
+		    sc->bce_bc_ver,	sc->rx_pages, sc->tx_pages,
+		    (bce_hdr_split == TRUE ? sc->pg_pages: 0));
 
-	#ifdef BCE_JUMBO_HDRSPLIT
-		printf("SPLT");
-		i++;
-	#endif
+		if (bce_hdr_split == TRUE) {
+			printf("SPLT");
+			i++;
+		}
 
 		if (sc->bce_flags & BCE_USING_MSI_FLAG) {
 			if (i > 0) printf("|");
@@ -653,6 +773,17 @@ bce_print_adapter_info(struct bce_softc 
 		} else {
 			printf(")\n");
 		}
+
+		printf("Coal (RX:%d,%d,%d,%d; TX:%d,%d,%d,%d)\n",
+		    sc->bce_rx_quick_cons_trip_int,
+		    sc->bce_rx_quick_cons_trip,
+		    sc->bce_rx_ticks_int,
+		    sc->bce_rx_ticks,
+		    sc->bce_tx_quick_cons_trip_int,
+		    sc->bce_tx_quick_cons_trip,
+		    sc->bce_tx_ticks_int,
+		    sc->bce_tx_ticks);
+
 	}
 
 	DBEXIT(BCE_VERBOSE_LOAD);
@@ -711,6 +842,189 @@ bce_probe_pci_caps(device_t dev, struct 
 
 
 /****************************************************************************/
+/* Load and validate user tunable settings.                                 */
+/*                                                                          */
+/* Returns:                                                                 */
+/*   Nothing.                                                               */
+/****************************************************************************/
+static void
+bce_set_tunables(struct bce_softc *sc)
+{
+	/* Set sysctl values for RX page count. */
+	switch (bce_rx_pages) {
+	case 1:
+		/* fall-through */
+	case 2:
+		/* fall-through */
+	case 4:
+		/* fall-through */
+	case 8:
+		sc->rx_pages = bce_rx_pages;
+		break;
+	default:
+		sc->rx_pages = DEFAULT_RX_PAGES;
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.rx_pages!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_rx_pages, DEFAULT_RX_PAGES);
+	}
+
+	/* ToDo: Consider allowing user setting for pg_pages. */
+	sc->pg_pages = min((sc->rx_pages * 4), MAX_PG_PAGES);
+
+	/* Set sysctl values for TX page count. */
+	switch (bce_tx_pages) {
+	case 1:
+		/* fall-through */
+	case 2:
+		/* fall-through */
+	case 4:
+		/* fall-through */
+	case 8:
+		sc->tx_pages = bce_tx_pages;
+		break;
+	default:
+		sc->tx_pages = DEFAULT_TX_PAGES;
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.tx_pages!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_tx_pages, DEFAULT_TX_PAGES);
+	}
+
+	/*
+	 * Validate the TX trip point (i.e. the number of
+	 * TX completions before a status block update is
+	 * generated and an interrupt is asserted.
+	 */
+	if (bce_tx_quick_cons_trip_int <= 100) {
+		sc->bce_tx_quick_cons_trip_int =
+		    bce_tx_quick_cons_trip_int;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.tx_quick_cons_trip_int!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_tx_quick_cons_trip_int,
+		    DEFAULT_TX_QUICK_CONS_TRIP_INT);
+		sc->bce_tx_quick_cons_trip_int =
+		    DEFAULT_TX_QUICK_CONS_TRIP_INT;
+	}
+
+	if (bce_tx_quick_cons_trip <= 100) {
+		sc->bce_tx_quick_cons_trip =
+		    bce_tx_quick_cons_trip;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.tx_quick_cons_trip!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_tx_quick_cons_trip,
+		    DEFAULT_TX_QUICK_CONS_TRIP);
+		sc->bce_tx_quick_cons_trip =
+		    DEFAULT_TX_QUICK_CONS_TRIP;
+	}
+
+	/*
+	 * Validate the TX ticks count (i.e. the maximum amount
+	 * of time to wait after the last TX completion has
+	 * occurred before a status block update is generated
+	 * and an interrupt is asserted.
+	 */
+	if (bce_tx_ticks_int <= 100) {
+		sc->bce_tx_ticks_int =
+		    bce_tx_ticks_int;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.tx_ticks_int!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_tx_ticks_int,
+		    DEFAULT_TX_TICKS_INT);
+		sc->bce_tx_ticks_int =
+		    DEFAULT_TX_TICKS_INT;
+	   }
+
+	if (bce_tx_ticks <= 100) {
+		sc->bce_tx_ticks =
+		    bce_tx_ticks;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.tx_ticks!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_tx_ticks,
+		    DEFAULT_TX_TICKS);
+		sc->bce_tx_ticks =
+		    DEFAULT_TX_TICKS;
+	}
+
+	/*
+	 * Validate the RX trip point (i.e. the number of
+	 * RX frames received before a status block update is
+	 * generated and an interrupt is asserted.
+	 */
+	if (bce_rx_quick_cons_trip_int <= 100) {
+		sc->bce_rx_quick_cons_trip_int =
+		    bce_rx_quick_cons_trip_int;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.rx_quick_cons_trip_int!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_rx_quick_cons_trip_int,
+		    DEFAULT_RX_QUICK_CONS_TRIP_INT);
+		sc->bce_rx_quick_cons_trip_int =
+		    DEFAULT_RX_QUICK_CONS_TRIP_INT;
+	}
+
+	if (bce_rx_quick_cons_trip <= 100) {
+		sc->bce_rx_quick_cons_trip =
+		    bce_rx_quick_cons_trip;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.rx_quick_cons_trip!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_rx_quick_cons_trip,
+		    DEFAULT_RX_QUICK_CONS_TRIP);
+		sc->bce_rx_quick_cons_trip =
+		    DEFAULT_RX_QUICK_CONS_TRIP;
+	}
+
+	/*
+	 * Validate the RX ticks count (i.e. the maximum amount
+	 * of time to wait after the last RX frame has been
+	 * received before a status block update is generated
+	 * and an interrupt is asserted.
+	 */
+	if (bce_rx_ticks_int <= 100) {
+		sc->bce_rx_ticks_int = bce_rx_ticks_int;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.rx_ticks_int!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_rx_ticks_int,
+		    DEFAULT_RX_TICKS_INT);
+		sc->bce_rx_ticks_int = DEFAULT_RX_TICKS_INT;
+	}
+
+	if (bce_rx_ticks <= 100) {
+		sc->bce_rx_ticks = bce_rx_ticks;
+	} else {
+		BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+		    "hw.bce.rx_ticks!  Setting default of %d.\n",
+		    __FILE__, __LINE__, bce_rx_ticks,
+		    DEFAULT_RX_TICKS);
+		sc->bce_rx_ticks = DEFAULT_RX_TICKS;
+	}
+
+	/* Disabling both RX ticks and RX trips will prevent interrupts. */
+	if ((bce_rx_quick_cons_trip == 0) && (bce_rx_ticks == 0)) {
+		BCE_PRINTF("%s(%d): Cannot set both hw.bce.rx_ticks and "
+		    "hw.bce.rx_quick_cons_trip to 0. Setting default values.\n",
+		   __FILE__, __LINE__);
+		sc->bce_rx_ticks = DEFAULT_RX_TICKS;
+		sc->bce_rx_quick_cons_trip = DEFAULT_RX_QUICK_CONS_TRIP;
+	}
+
+	/* Disabling both TX ticks and TX trips will prevent interrupts. */
+	if ((bce_tx_quick_cons_trip == 0) && (bce_tx_ticks == 0)) {
+		BCE_PRINTF("%s(%d): Cannot set both hw.bce.tx_ticks and "
+		    "hw.bce.tx_quick_cons_trip to 0. Setting default values.\n",
+		   __FILE__, __LINE__);
+		sc->bce_tx_ticks = DEFAULT_TX_TICKS;
+		sc->bce_tx_quick_cons_trip = DEFAULT_TX_QUICK_CONS_TRIP;
+	}
+
+}
+
+
+/****************************************************************************/
 /* Device attach function.                                                  */
 /*                                                                          */
 /* Allocates device resources, performs secondary chip identification,      */
@@ -739,6 +1053,8 @@ bce_attach(device_t dev)
 	sc->bce_flags = 0;
 	sc->bce_phy_flags = 0;
 
+	bce_set_tunables(sc);
+
 	pci_enable_busmaster(dev);
 
 	/* Allocate PCI memory resources. */
@@ -1028,37 +1344,13 @@ bce_attach(device_t dev)
 	 * values for the RX and TX chains.
 	 */
 
-#ifdef BCE_DEBUG
-	/* Force more frequent interrupts. */
-	sc->bce_tx_quick_cons_trip_int = 1;
-	sc->bce_tx_quick_cons_trip     = 1;
-	sc->bce_tx_ticks_int           = 0;
-	sc->bce_tx_ticks               = 0;
-
-	sc->bce_rx_quick_cons_trip_int = 1;
-	sc->bce_rx_quick_cons_trip     = 1;
-	sc->bce_rx_ticks_int           = 0;
-	sc->bce_rx_ticks               = 0;
-#else
-	/* Improve throughput at the expense of increased latency. */
-	sc->bce_tx_quick_cons_trip_int = 20;
-	sc->bce_tx_quick_cons_trip     = 20;
-	sc->bce_tx_ticks_int           = 80;
-	sc->bce_tx_ticks               = 80;
-
-	sc->bce_rx_quick_cons_trip_int = 6;
-	sc->bce_rx_quick_cons_trip     = 6;
-	sc->bce_rx_ticks_int           = 18;
-	sc->bce_rx_ticks               = 18;
-#endif
-
 	/* Not used for L2. */
-	sc->bce_comp_prod_trip_int = 0;
-	sc->bce_comp_prod_trip = 0;
-	sc->bce_com_ticks_int = 0;
-	sc->bce_com_ticks = 0;
-	sc->bce_cmd_ticks_int = 0;
-	sc->bce_cmd_ticks = 0;
+	sc->bce_comp_prod_trip_int     = 0;
+	sc->bce_comp_prod_trip         = 0;
+	sc->bce_com_ticks_int          = 0;
+	sc->bce_com_ticks              = 0;
+	sc->bce_cmd_ticks_int          = 0;
+	sc->bce_cmd_ticks              = 0;
 
 	/* Update statistics once every second. */
 	sc->bce_stats_ticks = 1000000 & 0xffff00;
@@ -1112,23 +1404,11 @@ bce_attach(device_t dev)
 	 * This may change later if the MTU size is set to
 	 * something other than 1500.
 	 */
-#ifdef BCE_JUMBO_HDRSPLIT
-	sc->rx_bd_mbuf_alloc_size = MHLEN;
-	/* Make sure offset is 16 byte aligned for hardware. */
-	sc->rx_bd_mbuf_align_pad =
-	    roundup2((MSIZE - MHLEN), 16) - (MSIZE - MHLEN);
-	sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
-	    sc->rx_bd_mbuf_align_pad;
-	sc->pg_bd_mbuf_alloc_size = MCLBYTES;
-#else
-	sc->rx_bd_mbuf_alloc_size = MCLBYTES;
-	sc->rx_bd_mbuf_align_pad =
-	    roundup2(MCLBYTES, 16) - MCLBYTES;
-	sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
-	    sc->rx_bd_mbuf_align_pad;
-#endif
+	bce_get_rx_buffer_sizes(sc,
+	    (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN));
 
-	ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD;
+	/* Recalculate our buffer allocation sizes. */
+	ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD_ALLOC;
 	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
 	IFQ_SET_READY(&ifp->if_snd);
 
@@ -2695,6 +2975,58 @@ bce_nvram_test_exit:
 
 
 /****************************************************************************/
+/* Calculates the size of the buffers to allocate based on the MTU.         */
+/*                                                                          */
+/* Returns:                                                                 */
+/*   Nothing.                                                               */
+/****************************************************************************/
+static void
+bce_get_rx_buffer_sizes(struct bce_softc *sc, int mtu)
+{
+	DBENTER(BCE_VERBOSE_LOAD);
+
+	/* Use a single allocation type when header splitting enabled. */
+	if (bce_hdr_split == TRUE) {
+		sc->rx_bd_mbuf_alloc_size = MHLEN;
+		/* Make sure offset is 16 byte aligned for hardware. */
+		sc->rx_bd_mbuf_align_pad =
+			roundup2((MSIZE - MHLEN), 16) - (MSIZE - MHLEN);
+		sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
+			sc->rx_bd_mbuf_align_pad;
+		sc->pg_bd_mbuf_alloc_size = MCLBYTES;
+	} else {
+		if ((mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +
+		    ETHER_CRC_LEN) > MCLBYTES) {
+			/* Setup for jumbo RX buffer allocations. */
+			sc->rx_bd_mbuf_alloc_size = MJUM9BYTES;
+			sc->rx_bd_mbuf_align_pad  =
+				roundup2(MJUM9BYTES, 16) - MJUM9BYTES;
+			sc->rx_bd_mbuf_data_len =
+			    sc->rx_bd_mbuf_alloc_size -
+			    sc->rx_bd_mbuf_align_pad;
+		} else {
+			/* Setup for standard RX buffer allocations. */
+			sc->rx_bd_mbuf_alloc_size = MCLBYTES;
+			sc->rx_bd_mbuf_align_pad  =
+			    roundup2(MCLBYTES, 16) - MCLBYTES;
+			sc->rx_bd_mbuf_data_len =
+			    sc->rx_bd_mbuf_alloc_size -
+			    sc->rx_bd_mbuf_align_pad;
+		}
+	}
+
+//	DBPRINT(sc, BCE_INFO_LOAD,
+	DBPRINT(sc, BCE_WARN,
+	   "%s(): rx_bd_mbuf_alloc_size = %d, rx_bd_mbuf_data_len = %d, "
+	   "rx_bd_mbuf_align_pad = %d\n", __FUNCTION__,
+	   sc->rx_bd_mbuf_alloc_size, sc->rx_bd_mbuf_data_len,
+	   sc->rx_bd_mbuf_align_pad);
+
+	DBEXIT(BCE_VERBOSE_LOAD);
+
+}
+
+/****************************************************************************/
 /* Identifies the current media type of the controller and sets the PHY     */
 /* address.                                                                 */
 /*                                                                          */
@@ -2929,7 +3261,7 @@ bce_dma_free(struct bce_softc *sc)
 
 
 	/* Free, unmap and destroy all TX buffer descriptor chain pages. */
-	for (i = 0; i < TX_PAGES; i++ ) {
+	for (i = 0; i < sc->tx_pages; i++ ) {
 		if (sc->tx_bd_chain[i] != NULL) {
 			bus_dmamem_free(
 			    sc->tx_bd_chain_tag,
@@ -2957,7 +3289,7 @@ bce_dma_free(struct bce_softc *sc)
 
 
 	/* Free, unmap and destroy all RX buffer descriptor chain pages. */
-	for (i = 0; i < RX_PAGES; i++ ) {
+	for (i = 0; i < sc->rx_pages; i++ ) {
 		if (sc->rx_bd_chain[i] != NULL) {
 			bus_dmamem_free(
 			    sc->rx_bd_chain_tag,
@@ -2984,38 +3316,38 @@ bce_dma_free(struct bce_softc *sc)
 	}
 
 
-#ifdef BCE_JUMBO_HDRSPLIT
 	/* Free, unmap and destroy all page buffer descriptor chain pages. */
-	for (i = 0; i < PG_PAGES; i++ ) {
-		if (sc->pg_bd_chain[i] != NULL) {
-			bus_dmamem_free(
-			    sc->pg_bd_chain_tag,
-			    sc->pg_bd_chain[i],
-			    sc->pg_bd_chain_map[i]);
-			sc->pg_bd_chain[i] = NULL;
+	if (bce_hdr_split == TRUE) {
+		for (i = 0; i < sc->pg_pages; i++ ) {
+			if (sc->pg_bd_chain[i] != NULL) {
+				bus_dmamem_free(
+				    sc->pg_bd_chain_tag,
+				    sc->pg_bd_chain[i],
+				    sc->pg_bd_chain_map[i]);
+				sc->pg_bd_chain[i] = NULL;
+			}
+
+			if (sc->pg_bd_chain_map[i] != NULL) {
+				bus_dmamap_unload(
+				    sc->pg_bd_chain_tag,
+				    sc->pg_bd_chain_map[i]);
+				bus_dmamap_destroy(
+				    sc->pg_bd_chain_tag,
+				    sc->pg_bd_chain_map[i]);
+				sc->pg_bd_chain_map[i] = NULL;
+			}
 		}
 
-		if (sc->pg_bd_chain_map[i] != NULL) {
-			bus_dmamap_unload(
-			    sc->pg_bd_chain_tag,
-			    sc->pg_bd_chain_map[i]);
-			bus_dmamap_destroy(
-			    sc->pg_bd_chain_tag,
-			    sc->pg_bd_chain_map[i]);
-			sc->pg_bd_chain_map[i] = NULL;
+		/* Destroy the page buffer descriptor tag. */
+		if (sc->pg_bd_chain_tag != NULL) {
+			bus_dma_tag_destroy(sc->pg_bd_chain_tag);
+			sc->pg_bd_chain_tag = NULL;
 		}
 	}
 
-	/* Destroy the page buffer descriptor tag. */
-	if (sc->pg_bd_chain_tag != NULL) {
-		bus_dma_tag_destroy(sc->pg_bd_chain_tag);
-		sc->pg_bd_chain_tag = NULL;
-	}
-#endif
-
 
 	/* Unload and destroy the TX mbuf maps. */
-	for (i = 0; i < TOTAL_TX_BD; i++) {
+	for (i = 0; i < MAX_TX_BD_AVAIL; i++) {
 		if (sc->tx_mbuf_map[i] != NULL) {
 			bus_dmamap_unload(sc->tx_mbuf_tag,
 			    sc->tx_mbuf_map[i]);
@@ -3032,7 +3364,7 @@ bce_dma_free(struct bce_softc *sc)
 	}
 
 	/* Unload and destroy the RX mbuf maps. */
-	for (i = 0; i < TOTAL_RX_BD; i++) {
+	for (i = 0; i < MAX_RX_BD_AVAIL; i++) {
 		if (sc->rx_mbuf_map[i] != NULL) {
 			bus_dmamap_unload(sc->rx_mbuf_tag,
 			    sc->rx_mbuf_map[i]);
@@ -3048,24 +3380,24 @@ bce_dma_free(struct bce_softc *sc)
 		sc->rx_mbuf_tag = NULL;
 	}
 
-#ifdef BCE_JUMBO_HDRSPLIT
 	/* Unload and destroy the page mbuf maps. */
-	for (i = 0; i < TOTAL_PG_BD; i++) {
-		if (sc->pg_mbuf_map[i] != NULL) {
-			bus_dmamap_unload(sc->pg_mbuf_tag,
-			    sc->pg_mbuf_map[i]);
-			bus_dmamap_destroy(sc->pg_mbuf_tag,
-	 		    sc->pg_mbuf_map[i]);
-			sc->pg_mbuf_map[i] = NULL;
+	if (bce_hdr_split == TRUE) {
+		for (i = 0; i < MAX_PG_BD_AVAIL; i++) {
+			if (sc->pg_mbuf_map[i] != NULL) {
+				bus_dmamap_unload(sc->pg_mbuf_tag,
+				    sc->pg_mbuf_map[i]);
+				bus_dmamap_destroy(sc->pg_mbuf_tag,
+				    sc->pg_mbuf_map[i]);
+				sc->pg_mbuf_map[i] = NULL;
+			}
 		}
-	}
 
-	/* Destroy the page mbuf tag. */
-	if (sc->pg_mbuf_tag != NULL) {
-		bus_dma_tag_destroy(sc->pg_mbuf_tag);
-		sc->pg_mbuf_tag = NULL;
+		/* Destroy the page mbuf tag. */
+		if (sc->pg_mbuf_tag != NULL) {
+			bus_dma_tag_destroy(sc->pg_mbuf_tag);
+			sc->pg_mbuf_tag = NULL;
+		}
 	}
-#endif
 
 	/* Destroy the parent tag */
 	if (sc->parent_tag != NULL) {
@@ -3308,7 +3640,7 @@ bce_dma_alloc(device_t dev)
 		goto bce_dma_alloc_exit;
 	}
 
-	for (i = 0; i < TX_PAGES; i++) {
+	for (i = 0; i < sc->tx_pages; i++) {
 
 		if(bus_dmamem_alloc(sc->tx_bd_chain_tag,
 		    (void **)&sc->tx_bd_chain[i],
@@ -3359,7 +3691,7 @@ bce_dma_alloc(device_t dev)
 	}
 
 	/* Create DMA maps for the TX mbufs clusters. */
-	for (i = 0; i < TOTAL_TX_BD; i++) {
+	for (i = 0; i < TOTAL_TX_BD_ALLOC; i++) {
 		if (bus_dmamap_create(sc->tx_mbuf_tag, BUS_DMA_NOWAIT,
 			&sc->tx_mbuf_map[i])) {
 			BCE_PRINTF("%s(%d): Unable to create TX mbuf DMA "
@@ -3385,7 +3717,7 @@ bce_dma_alloc(device_t dev)
 		goto bce_dma_alloc_exit;
 	}
 
-	for (i = 0; i < RX_PAGES; i++) {
+	for (i = 0; i < sc->rx_pages; i++) {
 
 		if (bus_dmamem_alloc(sc->rx_bd_chain_tag,
 		    (void **)&sc->rx_bd_chain[i],
@@ -3417,12 +3749,11 @@ bce_dma_alloc(device_t dev)
 	/*
 	 * Create a DMA tag for RX mbufs.
 	 */
-#ifdef BCE_JUMBO_HDRSPLIT
-	max_size = max_seg_size = ((sc->rx_bd_mbuf_alloc_size < MCLBYTES) ?
-		MCLBYTES : sc->rx_bd_mbuf_alloc_size);
-#else
-	max_size = max_seg_size = MJUM9BYTES;
-#endif
+	if (bce_hdr_split == TRUE)
+		max_size = max_seg_size = ((sc->rx_bd_mbuf_alloc_size < MCLBYTES) ?
+		    MCLBYTES : sc->rx_bd_mbuf_alloc_size);
+	else
+		max_size = max_seg_size = MJUM9BYTES;
 	max_segments = 1;
 
 	DBPRINT(sc, BCE_INFO_LOAD, "%s(): Creating rx_mbuf_tag "
@@ -3441,7 +3772,7 @@ bce_dma_alloc(device_t dev)
 	}
 
 	/* Create DMA maps for the RX mbuf clusters. */
-	for (i = 0; i < TOTAL_RX_BD; i++) {
+	for (i = 0; i < TOTAL_RX_BD_ALLOC; i++) {
 		if (bus_dmamap_create(sc->rx_mbuf_tag, BUS_DMA_NOWAIT,
 		    &sc->rx_mbuf_map[i])) {
 			BCE_PRINTF("%s(%d): Unable to create RX mbuf "
@@ -3451,78 +3782,77 @@ bce_dma_alloc(device_t dev)
 		}
 	}
 
-#ifdef BCE_JUMBO_HDRSPLIT
-	/*
-	 * Create a DMA tag for the page buffer descriptor chain,
-	 * allocate and clear the memory, and fetch the physical
-	 * address of the blocks.
-	 */
-	if (bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE,
-	    BCE_DMA_BOUNDARY, BUS_SPACE_MAXADDR, sc->max_bus_addr,
-	    NULL, NULL,	BCE_PG_CHAIN_PAGE_SZ, 1, BCE_PG_CHAIN_PAGE_SZ,
-	    0, NULL, NULL, &sc->pg_bd_chain_tag)) {
-		BCE_PRINTF("%s(%d): Could not allocate page descriptor "
-		    "chain DMA tag!\n",	__FILE__, __LINE__);
-		rc = ENOMEM;
-		goto bce_dma_alloc_exit;
-	}
-
-	for (i = 0; i < PG_PAGES; i++) {
-
-		if (bus_dmamem_alloc(sc->pg_bd_chain_tag,
-		    (void **)&sc->pg_bd_chain[i],
-		    BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
-		    &sc->pg_bd_chain_map[i])) {
-			BCE_PRINTF("%s(%d): Could not allocate page "
-			    "descriptor chain DMA memory!\n",
-			    __FILE__, __LINE__);
+	if (bce_hdr_split == TRUE) {
+		/*
+		 * Create a DMA tag for the page buffer descriptor chain,
+		 * allocate and clear the memory, and fetch the physical
+		 * address of the blocks.
+		 */
+		if (bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE,
+			    BCE_DMA_BOUNDARY, BUS_SPACE_MAXADDR, sc->max_bus_addr,
+			    NULL, NULL,	BCE_PG_CHAIN_PAGE_SZ, 1, BCE_PG_CHAIN_PAGE_SZ,
+			    0, NULL, NULL, &sc->pg_bd_chain_tag)) {
+			BCE_PRINTF("%s(%d): Could not allocate page descriptor "
+			    "chain DMA tag!\n",	__FILE__, __LINE__);
 			rc = ENOMEM;
 			goto bce_dma_alloc_exit;
 		}
 
-		error = bus_dmamap_load(sc->pg_bd_chain_tag,
-		    sc->pg_bd_chain_map[i], sc->pg_bd_chain[i],
-		    BCE_PG_CHAIN_PAGE_SZ, bce_dma_map_addr,
-		    &sc->pg_bd_chain_paddr[i], BUS_DMA_NOWAIT);
+		for (i = 0; i < sc->pg_pages; i++) {
+			if (bus_dmamem_alloc(sc->pg_bd_chain_tag,
+			    (void **)&sc->pg_bd_chain[i],
+			    BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
+			    &sc->pg_bd_chain_map[i])) {
+				BCE_PRINTF("%s(%d): Could not allocate page "
+				    "descriptor chain DMA memory!\n",
+				    __FILE__, __LINE__);
+				rc = ENOMEM;
+				goto bce_dma_alloc_exit;
+			}
 
-		if (error) {
-			BCE_PRINTF("%s(%d): Could not map page descriptor "
-			    "chain DMA memory!\n", __FILE__, __LINE__);
-			rc = ENOMEM;
-			goto bce_dma_alloc_exit;
-		}
+			error = bus_dmamap_load(sc->pg_bd_chain_tag,
+			    sc->pg_bd_chain_map[i], sc->pg_bd_chain[i],
+			    BCE_PG_CHAIN_PAGE_SZ, bce_dma_map_addr,
+			    &sc->pg_bd_chain_paddr[i], BUS_DMA_NOWAIT);
 
-		DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_chain_paddr[%d] = "
-		    "0x%jX\n", __FUNCTION__, i,
-		    (uintmax_t) sc->pg_bd_chain_paddr[i]);
-	}
+			if (error) {
+				BCE_PRINTF("%s(%d): Could not map page descriptor "
+					"chain DMA memory!\n", __FILE__, __LINE__);
+				rc = ENOMEM;
+				goto bce_dma_alloc_exit;
+			}
 
-	/*
-	 * Create a DMA tag for page mbufs.
-	 */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102072300.p17N0OUh025540>