Module Name:    src
Committed By:   hsuenaga
Date:           Wed Jun  3 03:55:47 UTC 2015

Modified Files:
        src/sys/arch/arm/marvell: files.marvell mvsoc.c
        src/sys/dev/marvell: files.armada if_mvxpe.c if_mvxpereg.h
            if_mvxpevar.h
Added Files:
        src/sys/dev/marvell: mvxpbm.c mvxpbmvar.h

Log Message:
separate buffer management codes 'mvxpbm.c' from if_mvxpe.c.

the buffer management(ex. fill the rx descriptors/buffers) is done by H/W in
ARMADA XP/380, and is done by S/W in ARMADA 370. the H/W BM support is not yet
implemented, so all devices use the S/W management mode at this time.


To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/arm/marvell/files.marvell
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/marvell/mvsoc.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/marvell/files.armada \
    src/sys/dev/marvell/if_mvxpe.c src/sys/dev/marvell/if_mvxpereg.h \
    src/sys/dev/marvell/if_mvxpevar.h
cvs rdiff -u -r0 -r1.1 src/sys/dev/marvell/mvxpbm.c \
    src/sys/dev/marvell/mvxpbmvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/marvell/files.marvell
diff -u src/sys/arch/arm/marvell/files.marvell:1.15 src/sys/arch/arm/marvell/files.marvell:1.16
--- src/sys/arch/arm/marvell/files.marvell:1.15	Wed Jun  3 03:34:38 2015
+++ src/sys/arch/arm/marvell/files.marvell	Wed Jun  3 03:55:47 2015
@@ -1,4 +1,4 @@
-#       $NetBSD: files.marvell,v 1.15 2015/06/03 03:34:38 hsuenaga Exp $
+#       $NetBSD: files.marvell,v 1.16 2015/06/03 03:55:47 hsuenaga Exp $
 #
 # Configuration info for Marvell System on Chip support
 #
@@ -58,6 +58,9 @@ attach	mvsata at mvsoc with mvsata_mbus
 # Gigabit Ethernet Controller Interface
 attach	mvgbec at mvsoc with mvgbec_mbus
 
+# ARMADA XP Buffer Manager
+attach	mvxpbm at mvsoc with mvxpbm_mbus
+
 # ARMADA XP Gigabit Ethernet Controller Interface
 attach	mvxpe at mvsoc with mvxpe_mbus
 

Index: src/sys/arch/arm/marvell/mvsoc.c
diff -u src/sys/arch/arm/marvell/mvsoc.c:1.21 src/sys/arch/arm/marvell/mvsoc.c:1.22
--- src/sys/arch/arm/marvell/mvsoc.c:1.21	Wed Jun  3 03:04:21 2015
+++ src/sys/arch/arm/marvell/mvsoc.c	Wed Jun  3 03:55:47 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvsoc.c,v 1.21 2015/06/03 03:04:21 hsuenaga Exp $	*/
+/*	$NetBSD: mvsoc.c,v 1.22 2015/06/03 03:55:47 hsuenaga Exp $	*/
 /*
  * Copyright (c) 2007, 2008, 2013, 2014 KIYOHARA Takashi
  * All rights reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsoc.c,v 1.21 2015/06/03 03:04:21 hsuenaga Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsoc.c,v 1.22 2015/06/03 03:55:47 hsuenaga Exp $");
 
 #include "opt_cputypes.h"
 #include "opt_mvsoc.h"
@@ -685,6 +685,7 @@ static const struct mvsoc_periph {
     { ARMADAXP(MV78130), "mvsdio", 0, ARMADAXP_SDIO_BASE,ARMADAXP_IRQ_SDIO },
     { ARMADAXP(MV78130), "mvxpe", 0, ARMADAXP_GBE0_BASE,ARMADAXP_IRQ_GBE0_TH_RXTX },
 #if NMVXPE > 0
+    { ARMADAXP(MV78130), "mvxpbm", 0, MVA_OFFSET_DEFAULT,IRQ_DEFAULT },
     { ARMADAXP(MV78130), "mvxpe", 1, ARMADAXP_GBE1_BASE,ARMADAXP_IRQ_GBE1_TH_RXTX },
     { ARMADAXP(MV78130), "mvxpe", 2, ARMADAXP_GBE2_BASE,ARMADAXP_IRQ_GBE2_TH_RXTX },
 #else
@@ -716,6 +717,7 @@ static const struct mvsoc_periph {
     { ARMADAXP(MV78160), "mvspi",  0, ARMADAXP_SPI_BASE,ARMADAXP_IRQ_SPI },
     { ARMADAXP(MV78160), "mvsdio", 0, ARMADAXP_SDIO_BASE,ARMADAXP_IRQ_SDIO },
 #if NMVXPE > 0
+    { ARMADAXP(MV78160), "mvxpbm", 0, MVA_OFFSET_DEFAULT,IRQ_DEFAULT },
     { ARMADAXP(MV78160), "mvxpe", 0, ARMADAXP_GBE0_BASE,ARMADAXP_IRQ_GBE0_TH_RXTX },
     { ARMADAXP(MV78160), "mvxpe", 1, ARMADAXP_GBE1_BASE,ARMADAXP_IRQ_GBE1_TH_RXTX },
     { ARMADAXP(MV78160), "mvxpe", 2, ARMADAXP_GBE2_BASE,ARMADAXP_IRQ_GBE2_TH_RXTX },
@@ -751,6 +753,7 @@ static const struct mvsoc_periph {
     { ARMADAXP(MV78230), "mvspi",  0, ARMADAXP_SPI_BASE,ARMADAXP_IRQ_SPI },
     { ARMADAXP(MV78230), "mvsdio", 0, ARMADAXP_SDIO_BASE,ARMADAXP_IRQ_SDIO },
 #if NMVXPE > 0
+    { ARMADAXP(MV78230), "mvxpbm", 0, MVA_OFFSET_DEFAULT,IRQ_DEFAULT },
     { ARMADAXP(MV78230), "mvxpe", 0, ARMADAXP_GBE0_BASE,ARMADAXP_IRQ_GBE0_TH_RXTX },
     { ARMADAXP(MV78230), "mvxpe", 1, ARMADAXP_GBE1_BASE,ARMADAXP_IRQ_GBE1_TH_RXTX },
     { ARMADAXP(MV78230), "mvxpe", 2, ARMADAXP_GBE2_BASE,ARMADAXP_IRQ_GBE2_TH_RXTX },
@@ -784,6 +787,7 @@ static const struct mvsoc_periph {
     { ARMADAXP(MV78260), "mvspi",  0, ARMADAXP_SPI_BASE,ARMADAXP_IRQ_SPI },
     { ARMADAXP(MV78260), "mvsdio", 0, ARMADAXP_SDIO_BASE,ARMADAXP_IRQ_SDIO },
 #if NMVXPE > 0
+    { ARMADAXP(MV78260), "mvxpbm", 0, MVA_OFFSET_DEFAULT,IRQ_DEFAULT },
     { ARMADAXP(MV78260), "mvxpe", 0, ARMADAXP_GBE0_BASE,ARMADAXP_IRQ_GBE0_TH_RXTX },
     { ARMADAXP(MV78260), "mvxpe", 1, ARMADAXP_GBE1_BASE,ARMADAXP_IRQ_GBE1_TH_RXTX },
     { ARMADAXP(MV78260), "mvxpe", 2, ARMADAXP_GBE2_BASE,ARMADAXP_IRQ_GBE2_TH_RXTX },
@@ -820,6 +824,7 @@ static const struct mvsoc_periph {
     { ARMADAXP(MV78460), "mvspi",  0, ARMADAXP_SPI_BASE,ARMADAXP_IRQ_SPI },
     { ARMADAXP(MV78460), "mvsdio", 0, ARMADAXP_SDIO_BASE,ARMADAXP_IRQ_SDIO },
 #if NMVXPE > 0
+    { ARMADAXP(MV78460), "mvxpbm", 0, MVA_OFFSET_DEFAULT,IRQ_DEFAULT },
     { ARMADAXP(MV78460), "mvxpe", 0, ARMADAXP_GBE0_BASE,ARMADAXP_IRQ_GBE0_TH_RXTX },
     { ARMADAXP(MV78460), "mvxpe", 1, ARMADAXP_GBE1_BASE,ARMADAXP_IRQ_GBE1_TH_RXTX },
     { ARMADAXP(MV78460), "mvxpe", 2, ARMADAXP_GBE2_BASE,ARMADAXP_IRQ_GBE2_TH_RXTX },
@@ -849,6 +854,7 @@ static const struct mvsoc_periph {
     { ARMADA370(MV6710), "mvspi",  1, ARMADAXP_SPI_BASE,ARMADAXP_IRQ_SPI },
     { ARMADA370(MV6710), "mvsdio", 0, ARMADAXP_SDIO_BASE,ARMADAXP_IRQ_SDIO },
 #if NMVXPE > 0
+    { ARMADA370(MV6710), "mvxpbm", 0, MVA_OFFSET_DEFAULT,IRQ_DEFAULT },
     { ARMADA370(MV6710), "mvxpe", 0, ARMADAXP_GBE0_BASE,ARMADAXP_IRQ_GBE0_TH_RXTX },
     { ARMADA370(MV6710), "mvxpe", 1, ARMADAXP_GBE1_BASE,ARMADAXP_IRQ_GBE1_TH_RXTX },
 #else

Index: src/sys/dev/marvell/files.armada
diff -u src/sys/dev/marvell/files.armada:1.1 src/sys/dev/marvell/files.armada:1.2
--- src/sys/dev/marvell/files.armada:1.1	Wed Jun  3 03:34:38 2015
+++ src/sys/dev/marvell/files.armada	Wed Jun  3 03:55:47 2015
@@ -1,7 +1,11 @@
-#	$NetBSD: files.armada,v 1.1 2015/06/03 03:34:38 hsuenaga Exp $
+#	$NetBSD: files.armada,v 1.2 2015/06/03 03:55:47 hsuenaga Exp $
 # Configuration info for Marvell ARMADA integrated peripherals
 
+# ARMADA XP Buffer Manger
+device	mvxpbm { [port = -1 ], [irq = -1] }
+file	dev/marvell/mvxpbm.c
+
 # ARMADA XP Gigabit Ethernet Controller Interface
 define	mvxpe { [port = -1 ], [irq = -1] }
-device	mvxpe: ether, ifnet, arp, mii
+device	mvxpe: mvxpbm, ether, ifnet, arp, mii
 file	dev/marvell/if_mvxpe.c			mvxpe		needs-flag
Index: src/sys/dev/marvell/if_mvxpe.c
diff -u src/sys/dev/marvell/if_mvxpe.c:1.1 src/sys/dev/marvell/if_mvxpe.c:1.2
--- src/sys/dev/marvell/if_mvxpe.c:1.1	Sun May  3 14:38:10 2015
+++ src/sys/dev/marvell/if_mvxpe.c	Wed Jun  3 03:55:47 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_mvxpe.c,v 1.1 2015/05/03 14:38:10 hsuenaga Exp $	*/
+/*	$NetBSD: if_mvxpe.c,v 1.2 2015/06/03 03:55:47 hsuenaga Exp $	*/
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
  * All rights reserved.
@@ -25,7 +25,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mvxpe.c,v 1.1 2015/05/03 14:38:10 hsuenaga Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mvxpe.c,v 1.2 2015/06/03 03:55:47 hsuenaga Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -58,6 +58,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_mvxpe.c,v
 
 #include <dev/marvell/marvellreg.h>
 #include <dev/marvell/marvellvar.h>
+#include <dev/marvell/mvxpbmvar.h>
 #include <dev/marvell/if_mvxpereg.h>
 #include <dev/marvell/if_mvxpevar.h>
 
@@ -136,30 +137,20 @@ STATIC void mvxpe_linkup(struct mvxpe_so
 STATIC void mvxpe_linkdown(struct mvxpe_softc *);
 STATIC void mvxpe_linkreset(struct mvxpe_softc *);
 
-/* Packet Buffer Manager(BM) */
-STATIC int mvxpe_bm_init(struct mvxpe_softc *);
-STATIC int mvxpe_bm_init_mbuf_hdr(struct mvxpe_bm_chunk *);
-STATIC struct mvxpe_bm_chunk *mvxpe_bm_alloc(struct mvxpe_softc *);
-STATIC void mvxpe_bm_free_mbuf(struct mbuf *, void *, size_t, void *);
-STATIC void mvxpe_bm_free_chunk(struct mvxpe_bm_chunk *);
-STATIC void mvxpe_bm_sync(struct mvxpe_bm_chunk *, size_t, int);
-STATIC void mvxpe_bm_lock(struct mvxpe_softc *);
-STATIC void mvxpe_bm_unlock(struct mvxpe_softc *);
-
 /* Tx Subroutines */
 STATIC int mvxpe_tx_queue_select(struct mvxpe_softc *, struct mbuf *);
 STATIC int mvxpe_tx_queue(struct mvxpe_softc *, struct mbuf *, int);
 STATIC void mvxpe_tx_set_csumflag(struct ifnet *,
     struct mvxpe_tx_desc *, struct mbuf *);
-STATIC void mvxpe_tx_complete(struct mvxpe_softc *);
-STATIC void mvxpe_tx_queue_del(struct mvxpe_softc *, int);
+STATIC void mvxpe_tx_complete(struct mvxpe_softc *, uint32_t);
+STATIC void mvxpe_tx_queue_complete(struct mvxpe_softc *, int);
 
 /* Rx Subroutines */
-STATIC void mvxpe_rx(struct mvxpe_softc *);
+STATIC void mvxpe_rx(struct mvxpe_softc *, uint32_t);
 STATIC void mvxpe_rx_queue(struct mvxpe_softc *, int, int);
-STATIC int mvxpe_rx_queue_select(struct mvxpe_softc *, int *);
-STATIC void mvxpe_rx_reload(struct mvxpe_softc *);
-STATIC void mvxpe_rx_queue_reload(struct mvxpe_softc *, int);
+STATIC int mvxpe_rx_queue_select(struct mvxpe_softc *, uint32_t, int *);
+STATIC void mvxpe_rx_refill(struct mvxpe_softc *, uint32_t);
+STATIC void mvxpe_rx_queue_refill(struct mvxpe_softc *, int);
 STATIC int mvxpe_rx_queue_add(struct mvxpe_softc *, int);
 STATIC void mvxpe_rx_set_csumflag(struct ifnet *,
     struct mvxpe_rx_desc *, struct mbuf *);
@@ -330,14 +321,19 @@ mvxpe_attach(device_t parent, device_t s
 	aprint_normal_dev(self, "Port Version %#x\n", sc->sc_version);
 
 	/*
-	 * Software based Buffer Manager(BM) subsystem.
-	 * Try to allocate special memory chunks for Rx packets.
-	 * Some version of SoC has hardware based BM(not supported yet)
+	 * Buffer Manager(BM) subsystem.
 	 */
-	if (mvxpe_bm_init(sc) != 0) {
-		aprint_error_dev(self, "BM pool allocation failure\n");
+	sc->sc_bm = mvxpbm_device(mva);
+	if (sc->sc_bm == NULL) {
+		aprint_error_dev(self, "no Buffer Manager.\n");
 		goto fail;
 	}
+	aprint_normal_dev(self,
+	    "Using Buffer Manager: %s\n", mvxpbm_xname(sc->sc_bm));	
+	aprint_normal_dev(sc->sc_dev,
+	    "%zu kbytes managed buffer, %zu bytes * %u entries allocated.\n",
+	    mvxpbm_buf_size(sc->sc_bm) / 1024,
+	    mvxpbm_chunk_size(sc->sc_bm), mvxpbm_chunk_count(sc->sc_bm));
 
 	/*
 	 * make sure DMA engines are in reset state
@@ -526,9 +522,9 @@ fail:
 STATIC int
 mvxpe_evcnt_attach(struct mvxpe_softc *sc)
 {
+#ifdef MVXPE_EVENT_COUNTERS
 	int q;
 
-#ifdef MVXPE_EVENT_COUNTERS
 	/* Master Interrupt Handler */
 	evcnt_attach_dynamic(&sc->sc_ev.ev_i_rxtxth, EVCNT_TYPE_INTR,
 	    NULL, device_xname(sc->sc_dev), "RxTxTH Intr.");
@@ -1103,8 +1099,8 @@ mvxpe_ring_init_queue(struct mvxpe_softc
 	rx->rx_queue_len = rx_default_queue_len[q];
 	if (rx->rx_queue_len > MVXPE_RX_RING_CNT)
 		rx->rx_queue_len = MVXPE_RX_RING_CNT;
-	rx->rx_queue_th_received = rx->rx_queue_len / 4;
-	rx->rx_queue_th_free = rx->rx_queue_len / 2;
+	rx->rx_queue_th_received = rx->rx_queue_len / MVXPE_RXTH_RATIO;
+	rx->rx_queue_th_free = rx->rx_queue_len / MVXPE_RXTH_REFILL_RATIO;
 	rx->rx_queue_th_time = (mvTclk / 1000) / 2; /* 0.5 [ms] */
 
 	/* Tx handle */
@@ -1113,8 +1109,9 @@ mvxpe_ring_init_queue(struct mvxpe_softc
 		MVXPE_TX_DESC_OFF(sc, q, i) = sizeof(struct mvxpe_tx_desc) * i;
 		MVXPE_TX_MBUF(sc, q, i) = NULL;
 		/* Tx handle needs DMA map for busdma_load_mbuf() */
-		if (bus_dmamap_create(sc->sc_dmat, sc->sc_bm.bm_chunk_size,
-		    MVXPE_TX_SEGLIMIT, sc->sc_bm.bm_chunk_size, 0,
+		if (bus_dmamap_create(sc->sc_dmat,
+		    mvxpbm_chunk_size(sc->sc_bm),
+		    MVXPE_TX_SEGLIMIT, mvxpbm_chunk_size(sc->sc_bm), 0,
 		    BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
 		    &MVXPE_TX_MAP(sc, q, i))) {
 			aprint_error_dev(sc->sc_dev,
@@ -1126,8 +1123,8 @@ mvxpe_ring_init_queue(struct mvxpe_softc
 	tx->tx_queue_len = tx_default_queue_len[q];
 	if (tx->tx_queue_len > MVXPE_TX_RING_CNT)
 		tx->tx_queue_len = MVXPE_TX_RING_CNT;
-       	tx->tx_free_cnt = tx->tx_queue_len;
-	tx->tx_queue_th_free = tx->tx_queue_len / 2;
+       	tx->tx_used = 0;
+	tx->tx_queue_th_free = tx->tx_queue_len / MVXPE_TXTH_RATIO;
 }
 
 STATIC void
@@ -1144,7 +1141,7 @@ mvxpe_ring_flush_queue(struct mvxpe_soft
 	for (i = 0; i < MVXPE_RX_RING_CNT; i++) {
 		if (MVXPE_RX_PKTBUF(sc, q, i) == NULL)
 			continue;
-		mvxpe_bm_free_chunk(MVXPE_RX_PKTBUF(sc, q, i));
+		mvxpbm_free_chunk(MVXPE_RX_PKTBUF(sc, q, i));
 		MVXPE_RX_PKTBUF(sc, q, i) = NULL;
 	}
 	rx->rx_dma = rx->rx_cpu = 0;
@@ -1158,7 +1155,7 @@ mvxpe_ring_flush_queue(struct mvxpe_soft
 		MVXPE_TX_MBUF(sc, q, i) = NULL;
 	}
 	tx->tx_dma = tx->tx_cpu = 0;
-       	tx->tx_free_cnt = tx->tx_queue_len;
+       	tx->tx_used = 0;
 }
 
 STATIC void
@@ -1218,18 +1215,23 @@ mvxpe_rx_queue_init(struct ifnet *ifp, i
 	MVXPE_WRITE(sc, MVXPE_PRXDQA(q), MVXPE_RX_RING_MEM_PA(sc, q));
 
 	/* Rx buffer size and descriptor ring size */
-	reg  = MVXPE_PRXDQS_BUFFERSIZE(sc->sc_bm.bm_chunk_size >> 3);
+	reg  = MVXPE_PRXDQS_BUFFERSIZE(mvxpbm_chunk_size(sc->sc_bm) >> 3);
 	reg |= MVXPE_PRXDQS_DESCRIPTORSQUEUESIZE(MVXPE_RX_RING_CNT);
 	MVXPE_WRITE(sc, MVXPE_PRXDQS(q), reg);
 	DPRINTIFNET(ifp, 1, "PRXDQS(%d): %#x\n",
 	    q, MVXPE_READ(sc, MVXPE_PRXDQS(q)));
 
 	/* Rx packet offset address */
-	reg = MVXPE_PRXC_PACKETOFFSET(sc->sc_bm.bm_chunk_packet_offset >> 3);
+	reg = MVXPE_PRXC_PACKETOFFSET(mvxpbm_packet_offset(sc->sc_bm) >> 3);
 	MVXPE_WRITE(sc, MVXPE_PRXC(q), reg);
 	DPRINTIFNET(ifp, 1, "PRXC(%d): %#x\n",
 	    q, MVXPE_READ(sc, MVXPE_PRXC(q)));
 
+	/* Rx DMA SNOOP */
+	reg  = MVXPE_PRXSNP_SNOOPNOOFBYTES(MVXPE_MRU);
+	reg |= MVXPE_PRXSNP_L2DEPOSITNOOFBYTES(MVXPE_MRU);
+	MVXPE_WRITE(sc, MVXPE_PRXSNP(q), reg);
+
 	/* if DMA is not working, register is not updated */
 	KASSERT(MVXPE_READ(sc, MVXPE_PRXDQA(q)) == MVXPE_RX_RING_MEM_PA(sc, q));
 	return 0;
@@ -1412,58 +1414,51 @@ mvxpe_rxtxth_intr(void *arg)
 {
 	struct mvxpe_softc *sc = arg;
 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
-	uint32_t ic, datum = 0;
-	int claimed = 0;
-
+	uint32_t ic, queues, datum = 0;
 
 	DPRINTSC(sc, 2, "got RXTX_TH_Intr\n");
 	MVXPE_EVCNT_INCR(&sc->sc_ev.ev_i_rxtxth);
 
 	mvxpe_sc_lock(sc);
-	for (;;) {
-		ic = MVXPE_READ(sc, MVXPE_PRXTXTIC);
-		if (ic == 0)
-			break;
-		MVXPE_WRITE(sc, MVXPE_PRXTXTIC, ~ic);
-		datum = datum ^ ic;
-		claimed = 1;
-
-		DPRINTIFNET(ifp, 2, "PRXTXTIC: %#x\n", ic);
-
-		/* route maintance interrupt first */
-		if (ic & MVXPE_PRXTXTI_PTXERRORSUMMARY) {
-			DPRINTIFNET(ifp, 1, "PRXTXTIC: +PTXERRORSUMMARY\n");
-			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtxth_txerr);
-		}
-		if ((ic & MVXPE_PRXTXTI_PMISCICSUMMARY)) {
-			DPRINTIFNET(ifp, 2, "PTXTXTIC: +PMISCICSUMMARY\n");
-			mvxpe_misc_intr(sc);
-		}
-		if (ic & MVXPE_PRXTXTI_PRXTXICSUMMARY) {
-			DPRINTIFNET(ifp, 2, "PTXTXTIC: +PRXTXICSUMMARY\n");
-			mvxpe_rxtx_intr(sc);
-		}
-		if (!(ifp->if_flags & IFF_RUNNING))
-			break;
-
-		/* RxTx interrupt */
-		if (ic & (MVXPE_PRXTXTI_RBICTAPQ_MASK)) {
-			DPRINTIFNET(ifp, 2, "PRXTXTIC: +RXEOF\n");
-			mvxpe_rx(sc);
-		}
+	ic = MVXPE_READ(sc, MVXPE_PRXTXTIC);
+	if (ic == 0)
+		return 0;
+	MVXPE_WRITE(sc, MVXPE_PRXTXTIC, ~ic);
+	datum = datum ^ ic;
 
-		if (ic & MVXPE_PRXTXTI_TBTCQ_MASK) {
-			DPRINTIFNET(ifp, 2, "PRXTXTIC: +TBTCQ\n");
-			mvxpe_tx_complete(sc);
-		}
+	DPRINTIFNET(ifp, 2, "PRXTXTIC: %#x\n", ic);
 
-		if (ic & MVXPE_PRXTXTI_RDTAQ_MASK) {
-			DPRINTIFNET(ifp, 2, "PRXTXTIC: +RDTAQ\n");
-			mvxpe_rx_reload(sc);
-		}
-
-		/* don' loop here. we are using interrupt coalescing */
-		break;
+	/* ack maintance interrupt first */
+	if (ic & MVXPE_PRXTXTI_PTXERRORSUMMARY) {
+		DPRINTIFNET(ifp, 1, "PRXTXTIC: +PTXERRORSUMMARY\n");
+		MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtxth_txerr);
+	}
+	if ((ic & MVXPE_PRXTXTI_PMISCICSUMMARY)) {
+		DPRINTIFNET(ifp, 2, "PTXTXTIC: +PMISCICSUMMARY\n");
+		mvxpe_misc_intr(sc);
+	}
+	if (ic & MVXPE_PRXTXTI_PRXTXICSUMMARY) {
+		DPRINTIFNET(ifp, 2, "PTXTXTIC: +PRXTXICSUMMARY\n");
+		mvxpe_rxtx_intr(sc);
+	}
+	if (!(ifp->if_flags & IFF_RUNNING))
+		return 1;
+
+	/* RxTxTH interrupt */
+	queues = MVXPE_PRXTXTI_GET_RBICTAPQ(ic);
+	if (queues) {
+		DPRINTIFNET(ifp, 2, "PRXTXTIC: +RXEOF\n");
+		mvxpe_rx(sc, queues);
+	}
+	queues = MVXPE_PRXTXTI_GET_TBTCQ(ic);
+	if (queues) {
+		DPRINTIFNET(ifp, 2, "PRXTXTIC: +TBTCQ\n");
+		mvxpe_tx_complete(sc, queues);
+	}
+	queues = MVXPE_PRXTXTI_GET_RDTAQ(ic);
+	if (queues) {
+		DPRINTIFNET(ifp, 2, "PRXTXTIC: +RDTAQ\n");
+		mvxpe_rx_refill(sc, queues);
 	}
 	mvxpe_sc_unlock(sc);
 
@@ -1472,7 +1467,7 @@ mvxpe_rxtxth_intr(void *arg)
 
 	rnd_add_uint32(&sc->sc_rnd_source, datum);
 
-	return claimed;
+	return 1;
 }
 
 STATIC int
@@ -1689,8 +1684,8 @@ mvxpe_start(struct ifnet *ifp)
 			break;
 		}
 		mvxpe_tx_unlockq(sc, q);
-		KASSERT(sc->sc_tx_ring[q].tx_free_cnt >= 0);
-		KASSERT(sc->sc_tx_ring[q].tx_free_cnt <=
+		KASSERT(sc->sc_tx_ring[q].tx_used >= 0);
+		KASSERT(sc->sc_tx_ring[q].tx_used <=
 		    sc->sc_tx_ring[q].tx_queue_len);
 		DPRINTIFNET(ifp, 1, "a packet is added to tx ring\n");
 		sc->sc_tx_pending++;
@@ -1763,7 +1758,7 @@ mvxpe_init(struct ifnet *ifp)
 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
 		mvxpe_rx_lockq(sc, q);
 		mvxpe_rx_queue_enable(ifp, q);
-		mvxpe_rx_queue_reload(sc, q);
+		mvxpe_rx_queue_refill(sc, q);
 		mvxpe_rx_unlockq(sc, q);
 
 		mvxpe_tx_lockq(sc, q);
@@ -1876,7 +1871,7 @@ mvxpe_stop(struct ifnet *ifp, int disabl
 		mvxpe_rx_lockq(sc, q);
 		mvxpe_tx_lockq(sc, q);
 
-		/* Disable Rx packet buffer reloading */
+		/* Disable Rx packet buffer refill request */
 		reg  = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received);
 		reg |= MVXPE_PRXDQTH_NODT(0);
 		MVXPE_WRITE(sc, MVXPE_PRXITTH(q), reg);
@@ -1912,7 +1907,7 @@ mvxpe_watchdog(struct ifnet *ifp)
 	 * Reclaim first as there is a possibility of losing Tx completion
 	 * interrupts.
 	 */
-	mvxpe_tx_complete(sc);
+	mvxpe_tx_complete(sc, 0xff);
 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
 		struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
 
@@ -1989,7 +1984,6 @@ mvxpe_mediastatus(struct ifnet *ifp, str
  */
 STATIC void mvxpe_linkupdate(struct mvxpe_softc *sc)
 {
-	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 	int linkup; /* bool */
 
 	KASSERT_SC_MTX(sc);
@@ -2002,7 +1996,10 @@ STATIC void mvxpe_linkupdate(struct mvxp
 	if (sc->sc_linkstate == linkup)
 		return;
 
-	log(LOG_CRIT, "%s: link %s\n", ifp->if_xname, linkup ? "up" : "down");
+#ifdef DEBUG
+	log(LOG_DEBUG,
+	    "%s: link %s\n", device_xname(sc->sc_dev), linkup ? "up" : "down");
+#endif
 	if (linkup)
 		MVXPE_EVCNT_INCR(&sc->sc_ev.ev_link_up);
 	else
@@ -2082,264 +2079,6 @@ mvxpe_linkreset(struct mvxpe_softc *sc)
 }
 
 /*
- * Packet Buffer Manager(BM)
- */
-STATIC int
-mvxpe_bm_init(struct mvxpe_softc *sc)
-{
-	struct mvxpe_bm_softc *bm = &sc->sc_bm;
-	bus_dma_segment_t segs;
-	char *kva, *ptr, *ptr_next, *ptr_data;
-	char *bm_buf_end;
-	paddr_t bm_buf_pa;
-	uint32_t align, pad;
-	size_t bm_buf_size;
-	int nsegs, error;
-
-	error = 0;
-
-	memset(bm, 0, sizeof(*bm));
-	bm->bm_dmat = sc->sc_dmat;
-	bm->bm_chunk_count = 0;
-	bm->bm_chunk_size = MVXPE_BM_SIZE;
-	bm->bm_chunk_header_size = sizeof(struct mvxpe_bm_chunk);
-	bm->bm_chunk_packet_offset = 0;
-	mutex_init(&bm->bm_mtx, MUTEX_DEFAULT, IPL_NET);
-	LIST_INIT(&bm->bm_free);
-	LIST_INIT(&bm->bm_inuse);
-
-	/*
-	 * adjust bm_chunk_size, bm_chunk_header_size, bm_slotsize
-	 * to satisfy alignemnt restrictions. 
-	 *
-	 *    <----------------  bm_slotsize [oct.] ------------------>
-	 *                               <--- bm_chunk_size[oct.] ---->
-	 *    <--- header_size[oct] ---> <-- MBXPE_BM_SIZE[oct.] ----->
-	 *   +-----------------+--------+---------+-----------------+--+
-	 *   | bm_chunk hdr    |pad     |pkt_off  |   packet data   |  |
-	 *   +-----------------+--------+---------+-----------------+--+
-	 *   ^                          ^         ^                    ^
-	 *   |                          |         |                    |
-	 *   ptr                 ptr_data  DMA here         ptr_next
-	 *
-	 * Restrictions:
-	 *   - ptr must be aligned to MVXPE_BM_ADDR_ALIGN
-	 *   - data must be aligned to MVXPE_RXBUF_ALIGN
-	 *   - data size X must be multiple of 8.
-	 */
-	/* assume start of buffer at 0x0000.0000 */
-	ptr = (char *)0;
-	/* align start of packet data */
-	ptr_data = ptr + bm->bm_chunk_header_size;
-	align = (unsigned long)ptr_data & MVXPE_RXBUF_MASK;
-	if (align != 0) {
-		pad = MVXPE_RXBUF_ALIGN - align;
-		bm->bm_chunk_header_size += pad;
-		DPRINTSC(sc, 1, "added padding to BM header, %u bytes\n", pad);
-	}
-	/* align size of packet data */
-	ptr_data = ptr + bm->bm_chunk_header_size;
-	ptr_next = ptr_data + MVXPE_BM_SIZE;
-	align = (unsigned long)ptr_next & MVXPE_BM_ADDR_MASK;
-	if (align != 0) {
-		pad = MVXPE_BM_ADDR_ALIGN - align;
-		ptr_next += pad;
-		DPRINTSC(sc, 1, "added padding to BM pktbuf, %u bytes\n", pad);
-	}
-	bm->bm_slotsize = ptr_next - ptr;
-	bm->bm_chunk_size = ptr_next - ptr_data;
-	KASSERT((bm->bm_chunk_size % 8) == 0);
-	/* align total buffer size to page boundary */
-	bm_buf_size = bm->bm_slotsize * MVXPE_BM_SLOTS;
-	align = (unsigned long)bm_buf_size & (PAGE_SIZE - 1);
-	if (align != 0) {
-		pad = PAGE_SIZE - align;
-		bm_buf_size += pad;
-		DPRINTSC(sc, 1,
-		    "expand buffer to fit page boundary, %u bytes\n", pad);
-	}
-
-	/*
-	 * get the aligned buffer from busdma(9) framework
-	 */
-	if (bus_dmamem_alloc(bm->bm_dmat, bm_buf_size, PAGE_SIZE, 0,
-	    &segs, 1, &nsegs, BUS_DMA_NOWAIT)) {
-		aprint_error_dev(sc->sc_dev, "can't alloc BM buffers\n");
-		return ENOBUFS;
-	}
-	if (bus_dmamem_map(bm->bm_dmat, &segs, nsegs, bm_buf_size,
-	    (void **)&kva, BUS_DMA_NOWAIT)) {
-		aprint_error_dev(sc->sc_dev,
-		    "can't map dma buffers (%zu bytes)\n", bm_buf_size);
-		error = ENOBUFS;
-		goto fail1;
-	}
-	KASSERT(((unsigned long)kva & MVXPE_BM_ADDR_MASK) == 0);
-	if (bus_dmamap_create(bm->bm_dmat, bm_buf_size, 1, bm_buf_size, 0,
-	    BUS_DMA_NOWAIT, &bm->bm_map)) {
-		aprint_error_dev(sc->sc_dev, "can't create dma map\n");
-		error = ENOBUFS;
-		goto fail2;
-	}
-	if (bus_dmamap_load(bm->bm_dmat, bm->bm_map,
-	    kva, bm_buf_size, NULL, BUS_DMA_NOWAIT)) {
-		aprint_error_dev(sc->sc_dev, "can't load dma map\n");
-		error = ENOBUFS;
-		goto fail3;
-	}
-	bm->bm_buf = (void *)kva;
-	bm_buf_end = (void *)(kva + bm_buf_size);
-	bm_buf_pa = segs.ds_addr;
-	DPRINTSC(sc, 1, "memory pool at %p\n", bm->bm_buf);
-
-	/* slice the buffer */
-	mvxpe_bm_lock(sc);
-	for (ptr = bm->bm_buf; ptr + bm->bm_slotsize <= bm_buf_end;
-	    ptr += bm->bm_slotsize) {
-		struct mvxpe_bm_chunk *chunk;
-
-		/* initialzie chunk */
-		ptr_data = ptr + bm->bm_chunk_header_size;
-		chunk = (struct mvxpe_bm_chunk *)ptr;
-		chunk->m = NULL;
-		chunk->sc = sc;
-		chunk->off = (ptr - bm->bm_buf);
-		chunk->pa = (paddr_t)(bm_buf_pa + chunk->off);
-		chunk->buf_off = (ptr_data - bm->bm_buf);
-		chunk->buf_pa = (paddr_t)(bm_buf_pa + chunk->buf_off);
-		chunk->buf_va = (vaddr_t)(bm->bm_buf + chunk->buf_off);
-		chunk->buf_size = bm->bm_chunk_size;
-
-		/* add to array */
-		bm->bm_slots[bm->bm_chunk_count++] = chunk;
-
-		/* add to free list (for software management) */
-		LIST_INSERT_HEAD(&bm->bm_free, chunk, link);
-		mvxpe_bm_sync(chunk, BM_SYNC_ALL, BUS_DMASYNC_PREREAD);
-
-		DPRINTSC(sc, 9, "new chunk %p\n", (void *)chunk->buf_va);
-	}
-	mvxpe_bm_unlock(sc);
-	aprint_normal_dev(sc->sc_dev,
-	    "%zu bytes packet buffer, %zu bytes * %zu entries allocated.\n",
-	    bm_buf_size, bm->bm_chunk_size, bm->bm_chunk_count);
-	return 0;
-
-fail3:
-	bus_dmamap_destroy(bm->bm_dmat, bm->bm_map);
-fail2:
-	bus_dmamem_unmap(bm->bm_dmat, kva, bm_buf_size);
-fail1:
-	bus_dmamem_free(bm->bm_dmat, &segs, nsegs);
-
-	return error;
-}
-
-STATIC int
-mvxpe_bm_init_mbuf_hdr(struct mvxpe_bm_chunk *chunk)
-{
-	struct mvxpe_softc *sc = chunk->sc;
-
-	KASSERT(chunk->m == NULL);
-
-	/* add mbuf header */
-	MGETHDR(chunk->m, M_DONTWAIT, MT_DATA);
-	if (chunk->m == NULL) {
-		aprint_error_dev(sc->sc_dev, "cannot get mbuf\n");
-		return ENOBUFS;
-	}
-	MEXTADD(chunk->m, chunk->buf_va, chunk->buf_size, 0, 
-		mvxpe_bm_free_mbuf, chunk);
-	chunk->m->m_flags |= M_EXT_RW;
-	chunk->m->m_len = chunk->m->m_pkthdr.len = chunk->buf_size;
-	if (sc->sc_bm.bm_chunk_packet_offset)
-		m_adj(chunk->m, sc->sc_bm.bm_chunk_packet_offset);
-
-	return 0;
-}
-
-STATIC struct mvxpe_bm_chunk *
-mvxpe_bm_alloc(struct mvxpe_softc *sc)
-{
-	struct mvxpe_bm_chunk *chunk;
-	struct mvxpe_bm_softc *bm = &sc->sc_bm;
-
-	mvxpe_bm_lock(sc);
-
-	chunk = LIST_FIRST(&bm->bm_free);
-	if (chunk == NULL) {
-		mvxpe_bm_unlock(sc);
-		return NULL;
-	}
-
-	LIST_REMOVE(chunk, link);
-	LIST_INSERT_HEAD(&bm->bm_inuse, chunk, link);
-
-	mvxpe_bm_unlock(sc);
-	return chunk;
-}
-
-STATIC void
-mvxpe_bm_free_mbuf(struct mbuf *m, void *buf, size_t size, void *arg)
-{
-	struct mvxpe_bm_chunk *chunk = (struct mvxpe_bm_chunk *)arg;
-	int s;
-
-	KASSERT(m != NULL);
-	KASSERT(arg != NULL);
-
-	DPRINTFN(3, "free packet %p\n", m);
-	if (m->m_flags & M_PKTHDR)
-		m_tag_delete_chain((m), NULL);
-	chunk->m = NULL;
-	s = splvm();
-	pool_cache_put(mb_cache, m);
-	splx(s);
-	return mvxpe_bm_free_chunk(chunk);
-}
-
-STATIC void
-mvxpe_bm_free_chunk(struct mvxpe_bm_chunk *chunk)
-{
-	struct mvxpe_softc *sc = chunk->sc;
-	struct mvxpe_bm_softc *bm = &sc->sc_bm;
-
-	DPRINTFN(3, "bm chunk free\n");
-
-	mvxpe_bm_lock(sc);
-
-	LIST_REMOVE(chunk, link);
-	LIST_INSERT_HEAD(&bm->bm_free, chunk, link);
-
-	mvxpe_bm_unlock(sc);
-}
-
-STATIC void
-mvxpe_bm_sync(struct mvxpe_bm_chunk *chunk, size_t size, int ops)
-{
-	struct mvxpe_softc *sc = (struct mvxpe_softc *)chunk->sc;
-	struct mvxpe_bm_softc *bm = &sc->sc_bm;
-
-	KASSERT(size <= chunk->buf_size);
-	if (size == 0)
-		size = chunk->buf_size;
-
-	bus_dmamap_sync(bm->bm_dmat, bm->bm_map, chunk->buf_off, size, ops);
-}
-
-STATIC void
-mvxpe_bm_lock(struct mvxpe_softc *sc)
-{
-	mutex_enter(&sc->sc_bm.bm_mtx);
-}
-
-STATIC void
-mvxpe_bm_unlock(struct mvxpe_softc *sc)
-{
-	mutex_exit(&sc->sc_bm.bm_mtx);
-}
-
-/*
  * Tx Subroutines
  */
 STATIC int
@@ -2364,9 +2103,9 @@ mvxpe_tx_queue(struct mvxpe_softc *sc, s
 	int start, used;
 	int i;
 
-	KASSERT(mutex_owned(&tx->tx_ring_mtx));
-	KASSERT(tx->tx_free_cnt >= 0);
-	KASSERT(tx->tx_free_cnt <= tx->tx_queue_len);
+	KASSERT_TX_MTX(sc, q);
+	KASSERT(tx->tx_used >= 0);
+	KASSERT(tx->tx_used <= tx->tx_queue_len);
 
 	/* load mbuf using dmamap of 1st descriptor */
 	if (bus_dmamap_load_mbuf(sc->sc_dmat,
@@ -2376,7 +2115,7 @@ mvxpe_tx_queue(struct mvxpe_softc *sc, s
 	}
 	txsegs = MVXPE_TX_MAP(sc, q, tx->tx_cpu)->dm_segs;
 	txnsegs = MVXPE_TX_MAP(sc, q, tx->tx_cpu)->dm_nsegs;
-	if (txnsegs <= 0 || txnsegs > tx->tx_free_cnt) {
+	if (txnsegs <= 0 || (txnsegs + tx->tx_used) > tx->tx_queue_len) {
 		/* we have no enough descriptors or mbuf is broken */
 		bus_dmamap_unload(sc->sc_dmat, MVXPE_TX_MAP(sc, q, tx->tx_cpu));
 		m_freem(m);
@@ -2411,7 +2150,7 @@ mvxpe_tx_queue(struct mvxpe_softc *sc, s
 		t->bufptr = txsegs[i].ds_addr;
 		t->bytecnt = txsegs[i].ds_len;
 		tx->tx_cpu = tx_counter_adv(tx->tx_cpu, 1);
-		tx->tx_free_cnt--;
+		tx->tx_used++;
 		used++;
 	}
 	/* t is last descriptor here */
@@ -2450,8 +2189,8 @@ mvxpe_tx_queue(struct mvxpe_softc *sc, s
 	    "PTXDI: queue %d, %d\n", q, MVXPE_READ(sc, MVXPE_PTXDI(q)));
 	DPRINTSC(sc, 2, "TQC: %#x\n", MVXPE_READ(sc, MVXPE_TQC));
 	DPRINTIFNET(ifp, 2,
-	    "Tx: tx_cpu = %d, tx_dma = %d, tx_free_cnt = %d\n",
-	    tx->tx_cpu, tx->tx_dma, tx->tx_free_cnt);
+	    "Tx: tx_cpu = %d, tx_dma = %d, tx_used = %d\n",
+	    tx->tx_cpu, tx->tx_dma, tx->tx_used);
 	return 0;
 }
 
@@ -2459,61 +2198,72 @@ STATIC void
 mvxpe_tx_set_csumflag(struct ifnet *ifp,
     struct mvxpe_tx_desc *t, struct mbuf *m)
 {
+	struct ether_header *eh;
 	int csum_flags;
 	uint32_t iphl = 0, ipoff = 0;
 
 	
        	csum_flags = ifp->if_csum_flags_tx & m->m_pkthdr.csum_flags;
 
-	if (csum_flags & (M_CSUM_IPv4| M_CSUM_TCPv4|M_CSUM_UDPv4)) {
+	eh = mtod(m, struct ether_header *);
+	switch (htons(eh->ether_type)) {
+	case ETHERTYPE_IP:
+	case ETHERTYPE_IPV6:
+		ipoff = ETHER_HDR_LEN;
+		break;
+	case ETHERTYPE_VLAN:
+		ipoff = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+		break;
+	}
+
+	if (csum_flags & (M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4)) {
 		iphl = M_CSUM_DATA_IPv4_IPHL(m->m_pkthdr.csum_data);
-		ipoff = M_CSUM_DATA_IPv4_OFFSET(m->m_pkthdr.csum_data);
+		t->command |= MVXPE_TX_CMD_L3_IP4;
 	}
 	else if (csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
 		iphl = M_CSUM_DATA_IPv6_HL(m->m_pkthdr.csum_data);
-		ipoff = M_CSUM_DATA_IPv6_OFFSET(m->m_pkthdr.csum_data);
+		t->command |= MVXPE_TX_CMD_L3_IP6;
 	}
 	else {
 		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NONE;
 		return;
 	}
 
+
 	/* L3 */
 	if (csum_flags & M_CSUM_IPv4) {
-		t->command |= MVXPE_TX_CMD_L3_IP4;
 		t->command |= MVXPE_TX_CMD_IP4_CHECKSUM;
 	}
 
 	/* L4 */
-	if (csum_flags & M_CSUM_TCPv4) {
-		t->command |= MVXPE_TX_CMD_L3_IP4;
+	if ((csum_flags & 
+	    (M_CSUM_TCPv4|M_CSUM_UDPv4|M_CSUM_TCPv6|M_CSUM_UDPv6)) == 0) {
+		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NONE;
+	}
+	else if (csum_flags & M_CSUM_TCPv4) {
+		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
 		t->command |= MVXPE_TX_CMD_L4_TCP;
 	}
 	else if (csum_flags & M_CSUM_UDPv4) {
-		t->command |= MVXPE_TX_CMD_L3_IP4;
+		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
 		t->command |= MVXPE_TX_CMD_L4_UDP;
 	}
 	else if (csum_flags & M_CSUM_TCPv6) {
-		t->command |= MVXPE_TX_CMD_L3_IP6;
+		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
 		t->command |= MVXPE_TX_CMD_L4_TCP;
 	}
 	else if (csum_flags & M_CSUM_UDPv6) {
-		t->command |= MVXPE_TX_CMD_L3_IP6;
+		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
 		t->command |= MVXPE_TX_CMD_L4_UDP;
 	}
 
-	/*
-	 * NetBSD's networking stack is not request H/W csum on fragmented
-	 * packets.
-	 */
 	t->l4ichk = 0;
-	t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
-	t->command |= MVXPE_TX_CMD_W_IP_HEADER_LEN(iphl >> 2);
-	t->command |= MVXPE_TX_CMD_W_L3_OFFSET(ipoff);
+	t->command |= MVXPE_TX_CMD_IP_HEADER_LEN(iphl >> 2);
+	t->command |= MVXPE_TX_CMD_L3_OFFSET(ipoff);
 }
 
 STATIC void
-mvxpe_tx_complete(struct mvxpe_softc *sc)
+mvxpe_tx_complete(struct mvxpe_softc *sc, uint32_t queues)
 {
 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 	int q;
@@ -2522,10 +2272,11 @@ mvxpe_tx_complete(struct mvxpe_softc *sc
 
 	KASSERT_SC_MTX(sc);
 
-	/* XXX: check queue bit array */
 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
+		if (!MVXPE_IS_QUEUE_BUSY(queues, q))
+			continue;
 		mvxpe_tx_lockq(sc, q);
-		mvxpe_tx_queue_del(sc, q);
+		mvxpe_tx_queue_complete(sc, q);
 		mvxpe_tx_unlockq(sc, q);
 	}
 	KASSERT(sc->sc_tx_pending >= 0);
@@ -2534,7 +2285,7 @@ mvxpe_tx_complete(struct mvxpe_softc *sc
 }
 
 STATIC void
-mvxpe_tx_queue_del(struct mvxpe_softc *sc, int q)
+mvxpe_tx_queue_complete(struct mvxpe_softc *sc, int q)
 {
 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
 	struct mvxpe_tx_desc *t;
@@ -2585,14 +2336,14 @@ mvxpe_tx_queue_del(struct mvxpe_softc *s
 		else
 			KASSERT((t->flags & MVXPE_TX_CMD_F) == 0);
 		tx->tx_dma = tx_counter_adv(tx->tx_dma, 1);
-		tx->tx_free_cnt++;
+		tx->tx_used--;
 		if (error)
 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txqe[q]);
 		else
 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txq[q]);
 	}
-	KASSERT(tx->tx_free_cnt >= 0);
-	KASSERT(tx->tx_free_cnt <= tx->tx_queue_len);
+	KASSERT(tx->tx_used >= 0);
+	KASSERT(tx->tx_used <= tx->tx_queue_len);
 	while (ndesc > 255) {
 		ptxsu = MVXPE_PTXSU_NORB(255);
 		MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu);
@@ -2603,22 +2354,22 @@ mvxpe_tx_queue_del(struct mvxpe_softc *s
 		MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu);
 	}
 	DPRINTSC(sc, 2,
-	    "Tx complete q %d, tx_cpu = %d, tx_dma = %d, tx_free_cnt = %d\n",
-	    q, tx->tx_cpu, tx->tx_dma, tx->tx_free_cnt);
+	    "Tx complete q %d, tx_cpu = %d, tx_dma = %d, tx_used = %d\n",
+	    q, tx->tx_cpu, tx->tx_dma, tx->tx_used);
 }
 
 /*
  * Rx Subroutines
  */
 STATIC void
-mvxpe_rx(struct mvxpe_softc *sc)
+mvxpe_rx(struct mvxpe_softc *sc, uint32_t queues)
 {
 	int q, npkt;
 
 	KASSERT_SC_MTX(sc);
 
-	while ( (npkt = mvxpe_rx_queue_select(sc, &q))) {
-		/* mutex is held by rx_queue_sel */
+	while ( (npkt = mvxpe_rx_queue_select(sc, queues, &q))) {
+		/* mutex is held by rx_queue_select */
 		mvxpe_rx_queue(sc, q, npkt);
 		mvxpe_rx_unlockq(sc, q);
 	}
@@ -2630,7 +2381,7 @@ mvxpe_rx_queue(struct mvxpe_softc *sc, i
 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
 	struct mvxpe_rx_desc *r;
-	struct mvxpe_bm_chunk *chunk;
+	struct mvxpbm_chunk *chunk;
 	struct mbuf *m;
 	uint32_t prxsu;
 	int error = 0;
@@ -2646,7 +2397,7 @@ mvxpe_rx_queue(struct mvxpe_softc *sc, i
 		chunk = MVXPE_RX_PKTBUF(sc, q, rx->rx_dma);
 		MVXPE_RX_PKTBUF(sc, q, rx->rx_dma) = NULL;
 		r = MVXPE_RX_DESC(sc, q, rx->rx_dma);
-		mvxpe_bm_sync(chunk, r->bytecnt, BUS_DMASYNC_POSTREAD);
+		mvxpbm_dmamap_sync(chunk, r->bytecnt, BUS_DMASYNC_POSTREAD);
 
 		/* check errors */
 		if (r->status & MVXPE_RX_ES) {
@@ -2686,7 +2437,10 @@ mvxpe_rx_queue(struct mvxpe_softc *sc, i
 		}
 
 		/* extract packet buffer */
-		mvxpe_bm_init_mbuf_hdr(chunk);
+		if (mvxpbm_init_mbuf_hdr(chunk) != 0) {
+			error = 1;
+			goto rx_done;
+		}
 		m = chunk->m;
 		m->m_pkthdr.rcvif = ifp;
 		m->m_pkthdr.len = m->m_len = r->bytecnt - ETHER_CRC_LEN;
@@ -2699,7 +2453,7 @@ mvxpe_rx_queue(struct mvxpe_softc *sc, i
 rx_done:
 		if (chunk) {
 			/* rx error. just return the chunk to BM. */
-			mvxpe_bm_free_chunk(chunk);
+			mvxpbm_free_chunk(chunk);
 		}
 		if (error)
 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_rxqe[q]);
@@ -2733,7 +2487,7 @@ rx_done:
 }
 
 STATIC int
-mvxpe_rx_queue_select(struct mvxpe_softc *sc, int *queue)
+mvxpe_rx_queue_select(struct mvxpe_softc *sc, uint32_t queues, int *queue)
 {
 	uint32_t prxs, npkt;
 	int q;
@@ -2743,6 +2497,9 @@ mvxpe_rx_queue_select(struct mvxpe_softc
 	DPRINTSC(sc, 2, "selecting rx queue\n");
 
 	for (q = MVXPE_QUEUE_SIZE - 1; q >= 0; q--) {
+		if (!MVXPE_IS_QUEUE_BUSY(queues, q))
+			continue;
+
 		prxs = MVXPE_READ(sc, MVXPE_PRXS(q));
 		npkt = MVXPE_PRXS_GET_ODC(prxs);
 		if (npkt == 0)
@@ -2760,7 +2517,7 @@ mvxpe_rx_queue_select(struct mvxpe_softc
 }
 
 STATIC void
-mvxpe_rx_reload(struct mvxpe_softc *sc)
+mvxpe_rx_refill(struct mvxpe_softc *sc, uint32_t queues)
 {
 	int q;
 
@@ -2768,37 +2525,38 @@ mvxpe_rx_reload(struct mvxpe_softc *sc)
 
 	/* XXX: check rx bit array */
 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
-		mvxpe_rx_lockq(sc, q);
-
-		mvxpe_rx_queue_reload(sc, q);
+		if (!MVXPE_IS_QUEUE_BUSY(queues, q))
+			continue;
 
+		mvxpe_rx_lockq(sc, q);
+		mvxpe_rx_queue_refill(sc, q);
 		mvxpe_rx_unlockq(sc, q);
 	}
 }
 
 STATIC void
-mvxpe_rx_queue_reload(struct mvxpe_softc *sc, int q)
+mvxpe_rx_queue_refill(struct mvxpe_softc *sc, int q)
 {
 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
 	uint32_t prxs, prxsu, ndesc;
-	int idx, reload = 0;
+	int idx, refill = 0;
 	int npkt;
 
 	KASSERT_RX_MTX(sc, q);
 
 	prxs = MVXPE_READ(sc, MVXPE_PRXS(q));
 	ndesc = MVXPE_PRXS_GET_NODC(prxs) + MVXPE_PRXS_GET_ODC(prxs);
-	reload = rx->rx_queue_len - ndesc;
-	if (reload <= 0)
+	refill = rx->rx_queue_len - ndesc;
+	if (refill <= 0)
 		return;
 	DPRINTPRXS(2, q);
-	DPRINTSC(sc, 2, "%d buffers to reload.\n", reload);
+	DPRINTSC(sc, 2, "%d buffers to refill.\n", refill);
 
 	idx = rx->rx_cpu;
-	for (npkt = 0; npkt < reload; npkt++)
+	for (npkt = 0; npkt < refill; npkt++)
 		if (mvxpe_rx_queue_add(sc, q) != 0)
 			break;
-	DPRINTSC(sc, 2, "queue %d, %d buffer reloaded.\n", q, npkt);
+	DPRINTSC(sc, 2, "queue %d, %d buffer refilled.\n", q, npkt);
 	if (npkt == 0)
 		return;
 
@@ -2823,12 +2581,12 @@ mvxpe_rx_queue_add(struct mvxpe_softc *s
 {
 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
 	struct mvxpe_rx_desc *r;
-	struct mvxpe_bm_chunk *chunk = NULL;
+	struct mvxpbm_chunk *chunk = NULL;
 
 	KASSERT_RX_MTX(sc, q);
 
 	/* Allocate the packet buffer */
-	chunk = mvxpe_bm_alloc(sc);
+	chunk = mvxpbm_alloc(sc->sc_bm);
 	if (chunk == NULL) {
 		DPRINTSC(sc, 1, "BM chunk allocation failed.\n");
 		return ENOBUFS;
@@ -2837,7 +2595,7 @@ mvxpe_rx_queue_add(struct mvxpe_softc *s
 	/* Add the packet to descritor */
 	KASSERT(MVXPE_RX_PKTBUF(sc, q, rx->rx_cpu) == NULL);
 	MVXPE_RX_PKTBUF(sc, q, rx->rx_cpu) = chunk;
-	mvxpe_bm_sync(chunk, BM_SYNC_ALL, BUS_DMASYNC_PREREAD);
+	mvxpbm_dmamap_sync(chunk, BM_SYNC_ALL, BUS_DMASYNC_PREREAD);
 
 	r = MVXPE_RX_DESC(sc, q, rx->rx_cpu);
 	r->bufptr = chunk->buf_pa;
@@ -3139,8 +2897,10 @@ sysctl_set_queue_length(SYSCTLFN_ARGS)
 	case  MVXPE_SYSCTL_RX:
 		mvxpe_rx_lockq(sc, arg->queue);
 		rx->rx_queue_len = val;
-		rx->rx_queue_th_received = rx->rx_queue_len / 4;
-		rx->rx_queue_th_free = rx->rx_queue_len / 2;
+		rx->rx_queue_th_received = 
+		    rx->rx_queue_len / MVXPE_RXTH_RATIO;
+		rx->rx_queue_th_free = 
+		    rx->rx_queue_len / MVXPE_RXTH_REFILL_RATIO;
 
 		reg  = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received);
 		reg |= MVXPE_PRXDQTH_NODT(rx->rx_queue_th_free);
@@ -3151,7 +2911,8 @@ sysctl_set_queue_length(SYSCTLFN_ARGS)
 	case  MVXPE_SYSCTL_TX:
 		mvxpe_tx_lockq(sc, arg->queue);
 		tx->tx_queue_len = val;
-		tx->tx_queue_th_free = tx->tx_queue_len / 2;
+		tx->tx_queue_th_free =
+		    tx->tx_queue_len / MVXPE_TXTH_RATIO;
 
 		reg  = MVXPE_PTXDQS_TBT(tx->tx_queue_th_free);
 		reg |= MVXPE_PTXDQS_DQS(MVXPE_TX_RING_CNT);
Index: src/sys/dev/marvell/if_mvxpereg.h
diff -u src/sys/dev/marvell/if_mvxpereg.h:1.1 src/sys/dev/marvell/if_mvxpereg.h:1.2
--- src/sys/dev/marvell/if_mvxpereg.h:1.1	Sun May  3 14:38:10 2015
+++ src/sys/dev/marvell/if_mvxpereg.h	Wed Jun  3 03:55:47 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_mvxpereg.h,v 1.1 2015/05/03 14:38:10 hsuenaga Exp $	*/
+/*	$NetBSD: if_mvxpereg.h,v 1.2 2015/06/03 03:55:47 hsuenaga Exp $	*/
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
  * All rights reserved.
@@ -705,12 +705,15 @@
 /* Port RX_TX Threshold Interrupt Cause/Mask (MVXPE_PRXTXTIC/MVXPE_PRXTXTIM) */
 #define MVXPE_PRXTXTI_TBTCQ(q)		(1 << ((q) + 0))
 #define MVXPE_PRXTXTI_TBTCQ_MASK	(0xff << 0)
+#define MVXPE_PRXTXTI_GET_TBTCQ(reg)	(((reg) >> 0) & 0xff)
 					/* Tx Buffer Threshold Cross Queue*/
 #define MVXPE_PRXTXTI_RBICTAPQ(q)	(1 << ((q) + 8))
 #define MVXPE_PRXTXTI_RBICTAPQ_MASK	(0xff << 8)
+#define MVXPE_PRXTXTI_GET_RBICTAPQ(reg)	(((reg) >> 8) & 0xff)
 				/* Rx Buffer Int. Coaleasing Th. Pri. Alrt Q */
 #define MVXPE_PRXTXTI_RDTAQ(q)		(1 << ((q) + 16))
 #define MVXPE_PRXTXTI_RDTAQ_MASK	(0xff << 16)
+#define MVXPE_PRXTXTI_GET_RDTAQ(reg)	(((reg) >> 16) & 0xff)
 					/* Rx Descriptor Threshold Alert Queue*/
 #define MVXPE_PRXTXTI_PRXTXICSUMMARY	(1 << 29)	/* PRXTXI summary */
 #define MVXPE_PRXTXTI_PTXERRORSUMMARY	(1 << 30)	/* PTEXERROR summary */
@@ -719,10 +722,13 @@
 /* Port RX_TX Interrupt Cause/Mask (MVXPE_PRXTXIC/MVXPE_PRXTXIM) */
 #define MVXPE_PRXTXI_TBRQ(q)		(1 << ((q) + 0))
 #define MVXPE_PRXTXI_TBRQ_MASK		(0xff << 0)
+#define MVXPE_PRXTXI_GET_TBRQ(reg)	(((reg) >> 0) & 0xff)
 #define MVXPE_PRXTXI_RPQ(q)		(1 << ((q) + 8))
 #define MVXPE_PRXTXI_RPQ_MASK		(0xff << 8)
+#define MVXPE_PRXTXI_GET_RPQ(reg)	(((reg) >> 8) & 0xff)
 #define MVXPE_PRXTXI_RREQ(q)		(1 << ((q) + 16))
 #define MVXPE_PRXTXI_RREQ_MASK		(0xff << 16)
+#define MVXPE_PRXTXI_GET_RREQ(reg)	(((reg) >> 16) & 0xff)
 #define MVXPE_PRXTXI_PRXTXTHICSUMMARY	(1 << 29)
 #define MVXPE_PRXTXI_PTXERRORSUMMARY	(1 << 30)
 #define MVXPE_PRXTXI_PMISCICSUMMARY	(1 << 31)
@@ -854,18 +860,16 @@ struct mvxpe_rx_desc {
 #define MVXPE_TX_CMD_L			(1 << 20) /* Last buffer */
 #define MVXPE_TX_CMD_PADDING		(1 << 19) /* Pad short frame */
 #define MVXPE_TX_CMD_IP4_CHECKSUM	(1 << 18) /* Do IPv4 Checksum */
-#define MVXPE_TX_CMD_L3_TYPE		(1 << 17) /* L3 Type 0:IP4, 1:IP6 */
 #define MVXPE_TX_CMD_L3_IP4		(0 << 17)
-#define MVXPE_TX_CMD_L3_IP6		(0 << 17)
-#define MVXPE_TX_CMD_L4_TYPE		(1 << 16) /* L4 Type 0:TCP, 1:UDP */
+#define MVXPE_TX_CMD_L3_IP6		(1 << 17)
 #define MVXPE_TX_CMD_L4_TCP		(0 << 16)
 #define MVXPE_TX_CMD_L4_UDP		(1 << 16)
 /* bit 15:13 reserved */
 #define MVXPE_TX_CMD_IP_HEADER_LEN_MASK	(0x1f << 8) /* IP header len >> 2 */
-#define MVXPE_TX_CMD_W_IP_HEADER_LEN(v)	(((v) & 0x1f) << 8)
+#define MVXPE_TX_CMD_IP_HEADER_LEN(v)	(((v) & 0x1f) << 8)
 /* bit 7 reserved */
 #define MVXPE_TX_CMD_L3_OFFSET_MASK	(0x7f << 0) /* offset of L3 hdr. */
-#define MVXPE_TX_CMD_W_L3_OFFSET(v)	(((v) & 0x7f) << 0) 
+#define MVXPE_TX_CMD_L3_OFFSET(v)	(((v) & 0x7f) << 0) 
 
 /*
  * Transmit pakcet extra attributes
Index: src/sys/dev/marvell/if_mvxpevar.h
diff -u src/sys/dev/marvell/if_mvxpevar.h:1.1 src/sys/dev/marvell/if_mvxpevar.h:1.2
--- src/sys/dev/marvell/if_mvxpevar.h:1.1	Sun May  3 14:38:10 2015
+++ src/sys/dev/marvell/if_mvxpevar.h	Wed Jun  3 03:55:47 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_mvxpevar.h,v 1.1 2015/05/03 14:38:10 hsuenaga Exp $	*/
+/*	$NetBSD: if_mvxpevar.h,v 1.2 2015/06/03 03:55:47 hsuenaga Exp $	*/
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
  * All rights reserved.
@@ -26,12 +26,8 @@
  */
 #ifndef _IF_MVXPEVAR_H_
 #define _IF_MVXPEVAR_H_
-/*
- * Comple options
- * XXX: use kernel config
- */
-#define MVXPE_DEBUG 0
-#define MVXPE_EVENT_COUNTERS
+#include <net/if.h>
+#include <dev/marvell/mvxpbmvar.h>
 
 /*
  * Limit of packet sizes.
@@ -48,23 +44,28 @@
  *
  * XXX: packet classifier is not implement yet
  */
-#define MVXPE_RX_QUEUE_LIMIT_0 8
-#define MVXPE_RX_QUEUE_LIMIT_1 8
-#define MVXPE_RX_QUEUE_LIMIT_2 8
-#define MVXPE_RX_QUEUE_LIMIT_3 8
-#define MVXPE_RX_QUEUE_LIMIT_4 8
-#define MVXPE_RX_QUEUE_LIMIT_5 8
-#define MVXPE_RX_QUEUE_LIMIT_6 8
-#define MVXPE_RX_QUEUE_LIMIT_7 256
-
-#define MVXPE_TX_QUEUE_LIMIT_0 256
-#define MVXPE_TX_QUEUE_LIMIT_1 8
-#define MVXPE_TX_QUEUE_LIMIT_2 8
-#define MVXPE_TX_QUEUE_LIMIT_3 8
-#define MVXPE_TX_QUEUE_LIMIT_4 8
-#define MVXPE_TX_QUEUE_LIMIT_5 8
-#define MVXPE_TX_QUEUE_LIMIT_6 8
-#define MVXPE_TX_QUEUE_LIMIT_7 8
+#define MVXPE_RX_QUEUE_LIMIT_0	8
+#define MVXPE_RX_QUEUE_LIMIT_1	8
+#define MVXPE_RX_QUEUE_LIMIT_2	8
+#define MVXPE_RX_QUEUE_LIMIT_3	8
+#define MVXPE_RX_QUEUE_LIMIT_4	8
+#define MVXPE_RX_QUEUE_LIMIT_5	8
+#define MVXPE_RX_QUEUE_LIMIT_6	8
+#define MVXPE_RX_QUEUE_LIMIT_7	IFQ_MAXLEN
+
+#define MVXPE_TX_QUEUE_LIMIT_0	IFQ_MAXLEN
+#define MVXPE_TX_QUEUE_LIMIT_1	8
+#define MVXPE_TX_QUEUE_LIMIT_2	8
+#define MVXPE_TX_QUEUE_LIMIT_3	8
+#define MVXPE_TX_QUEUE_LIMIT_4	8
+#define MVXPE_TX_QUEUE_LIMIT_5	8
+#define MVXPE_TX_QUEUE_LIMIT_6	8
+#define MVXPE_TX_QUEUE_LIMIT_7	8
+
+/* interrupt is triggered when corossing (queuelen / RATIO) */
+#define MVXPE_RXTH_RATIO	8
+#define MVXPE_RXTH_REFILL_RATIO	2
+#define MVXPE_TXTH_RATIO	8
 
 /*
  * Device Register access
@@ -85,6 +86,9 @@
 #define MVXPE_IS_LINKUP(sc) \
 	(MVXPE_READ((sc), MVXPE_PSR) & MVXPE_PSR_LINKUP)
 
+#define MVXPE_IS_QUEUE_BUSY(queues, q) \
+	((((queues) >> (q)) & 0x1))
+
 /*
  * EEE: Lower Power Idle config
  * Default timer is duration of MTU sized frame transmission.
@@ -101,10 +105,10 @@
  * the ethernet device has 8 rx/tx DMA queues. each of queue has its own
  * decriptor list. descriptors are simply index by counter inside the device.
  */
-#define MVXPE_TX_RING_CNT	256
+#define MVXPE_TX_RING_CNT	IFQ_MAXLEN
 #define MVXPE_TX_RING_MSK	(MVXPE_TX_RING_CNT - 1)
 #define MVXPE_TX_RING_NEXT(x)	(((x) + 1) & MVXPE_TX_RING_MSK)
-#define MVXPE_RX_RING_CNT	256
+#define MVXPE_RX_RING_CNT	IFQ_MAXLEN
 #define MVXPE_RX_RING_MSK	(MVXPE_RX_RING_CNT - 1)
 #define MVXPE_RX_RING_NEXT(x)	(((x) + 1) & MVXPE_RX_RING_MSK)
 #define MVXPE_TX_SEGLIMIT	32
@@ -118,7 +122,7 @@ struct mvxpe_rx_ring {
 	struct mvxpe_rx_handle {
 		struct mvxpe_rx_desc	*rxdesc_va;
 		off_t			rxdesc_off; /* from rx_descriptors[0] */
-		struct mvxpe_bm_chunk	*chunk;
+		struct mvxpbm_chunk	*chunk;
 	} rx_handle[MVXPE_RX_RING_CNT];
 
 	/* locks */
@@ -152,7 +156,7 @@ struct mvxpe_tx_ring {
 	kmutex_t			tx_ring_mtx;
 
 	/* Index */
-	int				tx_free_cnt;
+	int				tx_used;
 	int				tx_dma;
 	int				tx_cpu;
 
@@ -184,14 +188,6 @@ rx_counter_adv(int ctr, int n)
 }
 
 /*
- * Buffer alignement
- */
-#define MVXPE_RXBUF_ALIGN	32	/* Cache line size */
-#define MVXPE_RXBUF_MASK	(MVXPE_RXBUF_ALIGN - 1)
-#define MVXPE_BM_ADDR_ALIGN	32
-#define MVXPE_BM_ADDR_MASK	(MVXPE_BM_ADDR_ALIGN - 1)
-
-/*
  * Timeout control
  */
 #define MVXPE_PHY_TIMEOUT	10000	/* msec */
@@ -389,67 +385,6 @@ struct mvxpe_sysctl_mib {
 };
 
 /*
- * Packet Buffer Header
- *
- * this chunks may be managed by H/W Buffer Manger(BM) device,
- * but there is no device driver yet.
- *
- *                            +----------------+ bm_buf
- *                            |chunk header    | |
- * +----------------+         |                | |chunk->buf_off
- * |mbuf (M_EXT set)|<--------|struct mbuf *m  | V
- * +----------------+         +----------------+ chunk->buf_va/buf_pa
- * |   m_ext.ext_buf|-------->|packet buffer   | |
- * +----------------+         |                | |chunk->buf_size
- *                            |                | V
- *                            +----------------+
- *                            |chunk header    |
- *                            |....            |
- */
-#define MVXPE_BM_SLOTS \
-    (MVXPE_RX_RING_CNT * (MVXPE_QUEUE_SIZE + 1))
-#define MVXPE_BM_SIZE \
-    (MVXPE_MRU + MVXPE_HWHEADER_SIZE)
-
-struct mvxpe_bm_chunk {
-	struct mbuf	*m;		/* back pointer to  mbuf header */
-	void		*sc;		/* back pointer to softc */
-	off_t		off;		/* offset of chunk */
-	paddr_t		pa;		/* physical address of chunk */
-
-	off_t		buf_off;	/* offset of packet from sc_bm_buf */
-	paddr_t		buf_pa;		/* physical address of packet */
-	vaddr_t		buf_va;		/* virtual addres of packet */
-	size_t		buf_size;	/* size of buffer (exclude hdr) */
-
-	LIST_ENTRY(mvxpe_bm_chunk) link;
-	/* followed by packet buffer */
-};
-
-struct mvxpe_bm_softc {
-	bus_dma_tag_t bm_dmat;
-	bus_dmamap_t bm_map;
-	kmutex_t bm_mtx;
-
-	/* DMA MAP for entire buffer */
-	char *bm_buf;
-
-	/* memory chunk properties */
-	size_t	bm_slotsize;		/* size of bm_slots include header */
-	size_t	bm_chunk_count;		/* number of chunks */
-	size_t	bm_chunk_size;		/* size of packet buffer */
-	off_t	bm_chunk_header_size;	/* size of hader + padding */ 
-	off_t	bm_chunk_packet_offset;	/* allocate m_leading_space */
-	struct mvxpe_bm_chunk *bm_slots[MVXPE_BM_SLOTS];
-
-	/* for software based management */
-	LIST_HEAD(__mvxpe_bm_freehead, mvxpe_bm_chunk) bm_free;
-	LIST_HEAD(__mvxpe_bm_inusehead, mvxpe_bm_chunk) bm_inuse;
-} sc_bm;
-
-#define BM_SYNC_ALL	0
-
-/*
  * Ethernet Device main context
  */
 struct mvxpe_softc {
@@ -495,9 +430,8 @@ struct mvxpe_softc {
 
 	/*
 	 * Software Buffer Manager
-	 * XXX: to be writtten the independent device driver.
 	 */
-	struct mvxpe_bm_softc sc_bm;
+	struct mvxpbm_softc *sc_bm;
 
 	/*
 	 * Maintance clock

Added files:

Index: src/sys/dev/marvell/mvxpbm.c
diff -u /dev/null src/sys/dev/marvell/mvxpbm.c:1.1
--- /dev/null	Wed Jun  3 03:55:47 2015
+++ src/sys/dev/marvell/mvxpbm.c	Wed Jun  3 03:55:47 2015
@@ -0,0 +1,492 @@
+/*	$NetBSD: mvxpbm.c,v 1.1 2015/06/03 03:55:47 hsuenaga Exp $	*/
+/*
+ * Copyright (c) 2015 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: mvxpbm.c,v 1.1 2015/06/03 03:55:47 hsuenaga Exp $");
+
+#include "opt_multiprocessor.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/mbuf.h>
+
+#include <dev/marvell/marvellreg.h>
+#include <dev/marvell/marvellvar.h>
+
+#include "mvxpbmvar.h"
+
+#ifdef DEBUG
+#define STATIC /* nothing */
+#define DPRINTF(fmt, ...) \
+	do { \
+		if (mvxpbm_debug >= 1) { \
+			printf("%s: ", __func__); \
+			printf((fmt), ##__VA_ARGS__); \
+		} \
+	} while (/*CONSTCOND*/0)
+#define DPRINTFN(level , fmt, ...) \
+	do { \
+		if (mvxpbm_debug >= (level)) { \
+			printf("%s: ", __func__); \
+			printf((fmt), ##__VA_ARGS__); \
+		} \
+	} while (/*CONSTCOND*/0)
+#define DPRINTDEV(dev, level, fmt, ...) \
+	do { \
+		if (mvxpbm_debug >= (level)) { \
+			device_printf((dev), \
+			    "%s: "fmt , __func__, ##__VA_ARGS__); \
+		} \
+	} while (/*CONSTCOND*/0)
+#define DPRINTSC(sc, level, fmt, ...) \
+	do { \
+		device_t dev = (sc)->sc_dev; \
+		if (mvxpbm_debug >= (level)) { \
+			device_printf(dev, \
+			    "%s: " fmt, __func__, ##__VA_ARGS__); \
+		} \
+	} while (/*CONSTCOND*/0)
+#else
+#define STATIC static
+#define DPRINTF(fmt, ...)
+#define DPRINTFN(level, fmt, ...)
+#define DPRINTDEV(dev, level, fmt, ...)
+#define DPRINTSC(sc, level, fmt, ...)
+#endif
+
+/* autoconf(9) */
+STATIC int mvxpbm_match(device_t, cfdata_t, void *);
+STATIC void mvxpbm_attach(device_t, device_t, void *);
+STATIC int mvxpbm_evcnt_attach(struct mvxpbm_softc *);
+CFATTACH_DECL_NEW(mvxpbm_mbus, sizeof(struct mvxpbm_softc),
+    mvxpbm_match, mvxpbm_attach, NULL, NULL);
+
+/* DMA buffers */
+STATIC int mvxpbm_alloc_buffer(struct mvxpbm_softc *);
+
+/* mbuf subroutines */
+STATIC void mvxpbm_free_mbuf(struct mbuf *, void *, size_t, void *);
+
+/* singleton device instance */
+static struct mvxpbm_softc sc_emul;
+static struct mvxpbm_softc *sc0;
+
+/* debug level */
+#ifdef DEBUG
+static int mvxpbm_debug = 0;
+#endif
+
+/*
+ * autoconf(9)
+ */
+STATIC int
+mvxpbm_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct marvell_attach_args *mva = aux;
+
+	if (strcmp(mva->mva_name, match->cf_name) != 0)
+		return 0;
+	if (mva->mva_unit > MVXPBM_UNIT_MAX)
+		return 0;
+	if (sc0 != NULL)
+		return 0;
+	if (mva->mva_offset != MVA_OFFSET_DEFAULT) {
+		/* Hardware BM is not supported yet. */
+		return 0;
+	}
+
+	return 1;
+}
+
+STATIC void
+mvxpbm_attach(device_t parnet, device_t self, void *aux)
+{
+	struct marvell_attach_args *mva = aux;
+	struct mvxpbm_softc *sc = device_private(self);
+
+	aprint_naive("\n");
+	aprint_normal(": Marvell ARMADA Buffer Manager\n");
+	memset(sc, 0, sizeof(*sc));
+	sc->sc_dev = self;
+	sc->sc_iot = mva->mva_iot;
+	sc->sc_dmat = mva->mva_dmat;
+
+	if (mva->mva_offset == MVA_OFFSET_DEFAULT) { 
+		aprint_normal_dev(sc->sc_dev, "Software emulation.\n");
+		sc->sc_emul = 1;
+	}
+
+	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET);
+	LIST_INIT(&sc->sc_free);
+	LIST_INIT(&sc->sc_inuse);
+
+	/* DMA buffers */
+	if (mvxpbm_alloc_buffer(sc) != 0)
+		return;
+
+	/* event counters */
+	mvxpbm_evcnt_attach(sc);
+
+	sc0 = sc;
+	return;
+
+}
+
+STATIC int
+mvxpbm_evcnt_attach(struct mvxpbm_softc *sc)
+{
+	return 0;
+}
+
+/*
+ * DMA buffers
+ */
+STATIC int
+mvxpbm_alloc_buffer(struct mvxpbm_softc *sc)
+{
+	bus_dma_segment_t segs;
+	char *kva, *ptr, *ptr_next, *ptr_data;
+	char *bm_buf_end;
+	uint32_t align, pad;
+	int nsegs;
+	int error;
+
+	/*
+	 * set default buffer sizes. this will changed to satisfy 
+	 * alignment restrictions.
+	 */
+	sc->sc_chunk_count = 0;
+	sc->sc_chunk_size = MVXPBM_PACKET_SIZE;
+	sc->sc_chunk_header_size = sizeof(struct mvxpbm_chunk);
+	sc->sc_chunk_packet_offset = 64;
+
+	/*
+	 * adjust bm_chunk_size, bm_chunk_header_size, bm_slotsize
+	 * to satisfy alignemnt restrictions. 
+	 *
+	 *    <----------------  bm_slotsize [oct.] ------------------>
+	 *                               <--- bm_chunk_size[oct.] ---->
+	 *    <--- header_size[oct] ---> <-- MBXPE_BM_SIZE[oct.] --->
+	 *   +-----------------+--------+---------+-----------------+--+
+	 *   | bm_chunk hdr    |pad     |pkt_off  |   packet data   |  |
+	 *   +-----------------+--------+---------+-----------------+--+
+	 *   ^                          ^         ^                    ^
+	 *   |                          |         |                    |
+	 *   ptr                 ptr_data  DMA here         ptr_next
+	 *
+	 * Restrictions:
+	 *   - total buffer size must be multiple of MVXPBM_BUF_ALIGN
+	 *   - ptr must be aligned to MVXPBM_CHUNK_ALIGN
+	 *   - ptr_data must be aligned to MVXPEBM_DATA_ALIGN
+	 *   - bm_chunk_size must be multiple of 8[bytes].
+	 */
+	/* start calclation from  0x0000.0000 */
+	ptr = (char *)0;
+
+	/* align start of packet data */
+	ptr_data = ptr + sc->sc_chunk_header_size;
+	align = (unsigned long)ptr_data & MVXPBM_DATA_MASK;
+	if (align != 0) {
+		pad = MVXPBM_DATA_ALIGN - align;
+		sc->sc_chunk_header_size += pad;
+		DPRINTSC(sc, 1, "added padding to BM header, %u bytes\n", pad);
+	}
+
+	/* align size of packet data */
+	ptr_data = ptr + sc->sc_chunk_header_size;
+	ptr_next = ptr_data + MVXPBM_PACKET_SIZE;
+	align = (unsigned long)ptr_next & MVXPBM_CHUNK_MASK;
+	if (align != 0) {
+		pad = MVXPBM_CHUNK_ALIGN - align;
+		ptr_next += pad;
+		DPRINTSC(sc, 1, "added padding to BM pktbuf, %u bytes\n", pad);
+	}
+	sc->sc_slotsize = ptr_next - ptr;
+	sc->sc_chunk_size = ptr_next - ptr_data;
+	KASSERT((sc->sc_chunk_size % MVXPBM_DATA_UNIT) == 0);
+
+	/* align total buffer size to Mbus window boundary */
+	sc->sc_buf_size = sc->sc_slotsize * MVXPBM_NUM_SLOTS;
+	align = (unsigned long)sc->sc_buf_size & MVXPBM_BUF_MASK;
+	if (align != 0) {
+		pad = MVXPBM_BUF_ALIGN - align;
+		sc->sc_buf_size += pad;
+		DPRINTSC(sc, 1,
+		    "expand buffer to fit page boundary, %u bytes\n", pad);
+	}
+
+	/*
+	 * get the aligned buffer from busdma(9) framework
+	 */
+	if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_buf_size, MVXPBM_BUF_ALIGN, 0,
+	    &segs, 1, &nsegs, BUS_DMA_NOWAIT)) {
+		aprint_error_dev(sc->sc_dev, "can't alloc BM buffers\n");
+		return ENOBUFS;
+	}
+	if (bus_dmamem_map(sc->sc_dmat, &segs, nsegs, sc->sc_buf_size,
+	    (void **)&kva, BUS_DMA_NOWAIT)) {
+		aprint_error_dev(sc->sc_dev,
+		    "can't map dma buffers (%zu bytes)\n", sc->sc_buf_size);
+		error = ENOBUFS;
+		goto fail1;
+	}
+	if (bus_dmamap_create(sc->sc_dmat, sc->sc_buf_size, 1, sc->sc_buf_size,
+	    0, BUS_DMA_NOWAIT, &sc->sc_buf_map)) {
+		aprint_error_dev(sc->sc_dev, "can't create dma map\n");
+		error = ENOBUFS;
+		goto fail2;
+	}
+	if (bus_dmamap_load(sc->sc_dmat, sc->sc_buf_map,
+	    kva, sc->sc_buf_size, NULL, BUS_DMA_NOWAIT)) {
+		aprint_error_dev(sc->sc_dev, "can't load dma map\n");
+		error = ENOBUFS;
+		goto fail3;
+	}
+	sc->sc_buf = (void *)kva;
+	sc->sc_buf_pa = segs.ds_addr;
+	bm_buf_end = (void *)(kva + sc->sc_buf_size);
+	DPRINTSC(sc, 1, "memory pool at %p\n", sc->sc_buf);
+
+	/* slice the buffer */
+	mvxpbm_lock(sc);
+	for (ptr = sc->sc_buf; ptr + sc->sc_slotsize <= bm_buf_end;
+	    ptr += sc->sc_slotsize) {
+		struct mvxpbm_chunk *chunk;
+
+		/* initialzie chunk */
+		ptr_data = ptr + sc->sc_chunk_header_size;
+		chunk = (struct mvxpbm_chunk *)ptr;
+		chunk->m = NULL;
+		chunk->sc = sc;
+		chunk->off = (ptr - sc->sc_buf);
+		chunk->pa = (paddr_t)(sc->sc_buf_pa + chunk->off);
+		chunk->buf_off = (ptr_data - sc->sc_buf);
+		chunk->buf_pa = (paddr_t)(sc->sc_buf_pa + chunk->buf_off);
+		chunk->buf_va = (vaddr_t)(sc->sc_buf + chunk->buf_off);
+		chunk->buf_size = sc->sc_chunk_size;
+
+		/* add to free list (for software management) */
+		LIST_INSERT_HEAD(&sc->sc_free, chunk, link);
+		mvxpbm_dmamap_sync(chunk, BM_SYNC_ALL, BUS_DMASYNC_PREREAD);
+		sc->sc_chunk_count++;
+
+		DPRINTSC(sc, 9, "new chunk %p\n", (void *)chunk->buf_va);
+	}
+	mvxpbm_unlock(sc);
+	return 0;
+
+fail3:
+	bus_dmamap_destroy(sc->sc_dmat, sc->sc_buf_map);
+fail2:
+	bus_dmamem_unmap(sc->sc_dmat, kva, sc->sc_buf_size);
+fail1:
+	bus_dmamem_free(sc->sc_dmat, &segs, nsegs);
+
+	return error;
+}
+
+/*
+ * mbuf subroutines
+ */
+STATIC void
+mvxpbm_free_mbuf(struct mbuf *m, void *buf, size_t size, void *arg)
+{
+	struct mvxpbm_chunk *chunk = (struct mvxpbm_chunk *)arg;
+	int s;
+
+	KASSERT(m != NULL);
+	KASSERT(arg != NULL);
+
+	DPRINTFN(3, "free packet %p\n", m);
+	if (m->m_flags & M_PKTHDR)
+		m_tag_delete_chain((m), NULL);
+	chunk->m = NULL;
+	s = splvm();
+	pool_cache_put(mb_cache, m);
+	splx(s);
+	return mvxpbm_free_chunk(chunk);
+}
+
+/*
+ * Exported APIs
+ */
+/* get mvxpbm device context */
+struct mvxpbm_softc *
+mvxpbm_device(struct marvell_attach_args *mva)
+{
+	struct mvxpbm_softc *sc;
+
+	if (sc0 != NULL)
+		return sc0;
+	if (mva == NULL)
+		return NULL;
+
+	/* allocate software emulation context */
+	sc = &sc_emul;
+	memset(sc, 0, sizeof(*sc));
+	sc->sc_emul = 1;
+	sc->sc_iot = mva->mva_iot;
+	sc->sc_dmat = mva->mva_dmat;
+
+	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET);
+	LIST_INIT(&sc->sc_free);
+	LIST_INIT(&sc->sc_inuse);
+
+	if (mvxpbm_alloc_buffer(sc) != 0)
+		return NULL;
+	mvxpbm_evcnt_attach(sc);
+	sc0 = sc;
+	return sc0;
+}
+
+/* allocate new memory chunk */
+struct mvxpbm_chunk *
+mvxpbm_alloc(struct mvxpbm_softc *sc)
+{
+	struct mvxpbm_chunk *chunk;
+
+	mvxpbm_lock(sc);
+
+	chunk = LIST_FIRST(&sc->sc_free);
+	if (chunk == NULL) {
+		mvxpbm_unlock(sc);
+		return NULL;
+	}
+
+	LIST_REMOVE(chunk, link);
+	LIST_INSERT_HEAD(&sc->sc_inuse, chunk, link);
+
+	mvxpbm_unlock(sc);
+	return chunk;
+}
+
+/* free memory chunk */
+void
+mvxpbm_free_chunk(struct mvxpbm_chunk *chunk)
+{
+	struct mvxpbm_softc *sc = chunk->sc;
+
+	KASSERT(chunk->m == NULL);
+	DPRINTFN(3, "bm chunk free\n");
+
+	mvxpbm_lock(sc);
+
+	LIST_REMOVE(chunk, link);
+	LIST_INSERT_HEAD(&sc->sc_free, chunk, link);
+
+	mvxpbm_unlock(sc);
+}
+
+/* prepare mbuf header after Rx */
+int
+mvxpbm_init_mbuf_hdr(struct mvxpbm_chunk *chunk)
+{
+	struct mvxpbm_softc *sc = chunk->sc;
+
+	KASSERT(chunk->m == NULL);
+
+	/* add new mbuf header */
+	MGETHDR(chunk->m, M_DONTWAIT, MT_DATA);
+	if (chunk->m == NULL) {
+		aprint_error_dev(sc->sc_dev, "cannot get mbuf\n");
+		return ENOBUFS;
+	}
+	MEXTADD(chunk->m, chunk->buf_va, chunk->buf_size, 0, 
+		mvxpbm_free_mbuf, chunk);
+	chunk->m->m_flags |= M_EXT_RW;
+	chunk->m->m_len = chunk->m->m_pkthdr.len = chunk->buf_size;
+	if (sc->sc_chunk_packet_offset)
+		m_adj(chunk->m, sc->sc_chunk_packet_offset);
+
+	return 0;
+}
+
+/* sync DMA seguments */
+void
+mvxpbm_dmamap_sync(struct mvxpbm_chunk *chunk, size_t size, int ops)
+{
+	struct mvxpbm_softc *sc = chunk->sc;
+
+	KASSERT(size <= chunk->buf_size);
+	if (size == 0)
+		size = chunk->buf_size;
+
+	bus_dmamap_sync(sc->sc_dmat, sc->sc_buf_map, chunk->buf_off, size, ops);
+}
+
+/* lock */
+void
+mvxpbm_lock(struct mvxpbm_softc *sc)
+{
+	mutex_enter(&sc->sc_mtx);
+}
+
+void
+mvxpbm_unlock(struct mvxpbm_softc *sc)
+{
+	mutex_exit(&sc->sc_mtx);
+}
+
+/* get params */
+const char *
+mvxpbm_xname(struct mvxpbm_softc *sc)
+{
+	if (sc->sc_emul) {
+		return "software_bm";
+	}
+	return device_xname(sc->sc_dev);
+}
+
+size_t
+mvxpbm_chunk_size(struct mvxpbm_softc *sc)
+{
+	return sc->sc_chunk_size;
+}
+
+uint32_t
+mvxpbm_chunk_count(struct mvxpbm_softc *sc)
+{
+	return sc->sc_chunk_count;
+}
+
+off_t
+mvxpbm_packet_offset(struct mvxpbm_softc *sc)
+{
+	return sc->sc_chunk_packet_offset;
+}
+
+paddr_t
+mvxpbm_buf_pbase(struct mvxpbm_softc *sc)
+{
+	return sc->sc_buf_pa;
+}
+
+size_t
+mvxpbm_buf_size(struct mvxpbm_softc *sc)
+{
+	return sc->sc_buf_size;
+}
Index: src/sys/dev/marvell/mvxpbmvar.h
diff -u /dev/null src/sys/dev/marvell/mvxpbmvar.h:1.1
--- /dev/null	Wed Jun  3 03:55:47 2015
+++ src/sys/dev/marvell/mvxpbmvar.h	Wed Jun  3 03:55:47 2015
@@ -0,0 +1,139 @@
+/*	$NetBSD: mvxpbmvar.h,v 1.1 2015/06/03 03:55:47 hsuenaga Exp $	*/
+/*
+ * Copyright (c) 2015 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _MVXPBMVAR_H_
+#define _MVXPBMVAR_H_
+#include <dev/marvell/marvellvar.h>
+
+/*
+ * Max number of unit.
+ */
+#define MVXPBM_UNIT_MAX		1
+
+/*
+ * Buffer alignement
+ */
+#define MVXPBM_NUM_SLOTS	2048	/* minimum number of slots */
+#define MVXPBM_PACKET_SIZE	2000	/* minimum packet size */
+
+#define MVXPBM_BUF_ALIGN	65536	/* Mbus window size granularity */
+#define MVXPBM_BUF_MASK		(MVXPBM_BUF_ALIGN - 1)
+#define MVXPBM_CHUNK_ALIGN	32	/* Cache line size */
+#define MVXPBM_CHUNK_MASK	(MVXPBM_CHUNK_ALIGN - 1)
+#define MVXPBM_DATA_ALIGN	32	/* Cache line size */
+#define MVXPBM_DATA_MASK	(MVXPBM_DATA_ALIGN - 1)
+#define MVXPBM_DATA_UNIT	8
+
+/*
+ * Packet Buffer Header
+ *
+ * this chunks may be managed by H/W Buffer Manger(BM) device,
+ * but there is no device driver yet.
+ *
+ *                            +----------------+ bm_buf
+ *                            |chunk header    | |
+ * +----------------+         |                | |chunk->buf_off
+ * |mbuf (M_EXT set)|<--------|struct mbuf *m  | V
+ * +----------------+         +----------------+ chunk->buf_va/buf_pa
+ * |   m_ext.ext_buf|-------->|packet buffer   | |
+ * +----------------+         |                | |chunk->buf_size
+ *                            |                | V
+ *                            +----------------+
+ *                            |chunk header    |
+ *                            |....            |
+ */
+
+struct mvxpbm_chunk {
+	struct mbuf	*m;		/* back pointer to  mbuf header */
+	void		*sc;		/* back pointer to softc */
+	off_t		off;		/* offset of chunk */
+	paddr_t		pa;		/* physical address of chunk */
+
+	off_t		buf_off;	/* offset of packet from sc_bm_buf */
+	paddr_t		buf_pa;		/* physical address of packet */
+	vaddr_t		buf_va;		/* virtual addres of packet */
+	size_t		buf_size;	/* size of buffer (exclude hdr) */
+
+	LIST_ENTRY(mvxpbm_chunk) link;
+	/* followed by packet buffer */
+};
+
+struct mvxpbm_softc {
+	device_t	sc_dev;
+	bus_dma_tag_t	sc_dmat;
+	bus_space_tag_t sc_iot;
+	kmutex_t	sc_mtx;
+
+	/* software emulated */
+	int		sc_emul;
+
+	/* DMA MAP for entire buffer */
+	bus_dmamap_t	sc_buf_map;
+	char		*sc_buf;
+	paddr_t		sc_buf_pa;
+	size_t		sc_buf_size;
+
+	/* memory chunk properties */
+	size_t		sc_slotsize;		/* size of bm_slots include header */
+	uint32_t	sc_chunk_count;		/* number of chunks */
+	size_t		sc_chunk_size;		/* size of packet buffer */
+	size_t		sc_chunk_header_size;	/* size of hader + padding */ 
+	off_t		sc_chunk_packet_offset;	/* allocate m_leading_space */
+
+	/* for software based management */
+	LIST_HEAD(__mvxpbm_freehead, mvxpbm_chunk) sc_free;
+	LIST_HEAD(__mvxpbm_inusehead, mvxpbm_chunk) sc_inuse;
+};
+
+#define BM_SYNC_ALL	0
+
+/* get mvxpbm device context */
+struct mvxpbm_softc *mvxpbm_device(struct marvell_attach_args *);
+
+/* allocate new memory chunk */
+struct mvxpbm_chunk *mvxpbm_alloc(struct mvxpbm_softc *);
+
+/* free memory chunk */
+void mvxpbm_free_chunk(struct mvxpbm_chunk *);
+
+/* prepare mbuf header after Rx */
+int mvxpbm_init_mbuf_hdr(struct mvxpbm_chunk *);
+
+/* sync DMA seguments */
+void mvxpbm_dmamap_sync(struct mvxpbm_chunk *, size_t, int);
+
+/* lock */
+void mvxpbm_lock(struct mvxpbm_softc *);
+void mvxpbm_unlock(struct mvxpbm_softc *);
+
+/* get params */
+const char *mvxpbm_xname(struct mvxpbm_softc *);
+size_t mvxpbm_chunk_size(struct mvxpbm_softc *);
+uint32_t mvxpbm_chunk_count(struct mvxpbm_softc *);
+off_t mvxpbm_packet_offset(struct mvxpbm_softc *);
+paddr_t mvxpbm_buf_pbase(struct mvxpbm_softc *);
+size_t mvxpbm_buf_size(struct mvxpbm_softc *);
+#endif /* _MVXPBMVAR_H_ */

Reply via email to