summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Long <scottl@FreeBSD.org>2006-10-24 10:11:39 +0000
committerScott Long <scottl@FreeBSD.org>2006-10-24 10:11:39 +0000
commit5b52136cd77f032a5f7066bfe8928249cd2d5ae6 (patch)
treeb6c259f441f3769c4ef89e7a2b2913e5e779adcd
parent6bdf12f3d42b5a75547d7b11a5033f437a094b47 (diff)
Notes
-rw-r--r--sys/dev/bce/if_bce.c590
-rw-r--r--sys/dev/bce/if_bcereg.h27
2 files changed, 288 insertions, 329 deletions
diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
index 1550a95c03d5..c3c470d87e50 100644
--- a/sys/dev/bce/if_bce.c
+++ b/sys/dev/bce/if_bce.c
@@ -276,7 +276,6 @@ static int bce_nvram_write (struct bce_softc *, u32, u8 *, int);
/* */
/****************************************************************************/
static void bce_dma_map_addr (void *, bus_dma_segment_t *, int, int);
-static void bce_dma_map_tx_desc (void *, bus_dma_segment_t *, int, bus_size_t, int);
static int bce_dma_alloc (device_t);
static void bce_dma_free (struct bce_softc *);
static void bce_release_resources (struct bce_softc *);
@@ -300,7 +299,7 @@ static int bce_init_rx_chain (struct bce_softc *);
static void bce_free_rx_chain (struct bce_softc *);
static void bce_free_tx_chain (struct bce_softc *);
-static int bce_tx_encap (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *);
+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);
@@ -309,6 +308,7 @@ static int bce_ifmedia_upd (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_mgmt_init_locked(struct bce_softc *sc);
static void bce_init_context (struct bce_softc *);
static void bce_get_mac_addr (struct bce_softc *);
@@ -467,10 +467,10 @@ bce_attach(device_t dev)
/* Allocate PCI memory resources. */
rid = PCIR_BAR(0);
sc->bce_res = bus_alloc_resource_any(
- dev, /* dev */
- SYS_RES_MEMORY, /* type */
- &rid, /* rid */
- RF_ACTIVE | PCI_RF_DENSE); /* flags */
+ dev, /* dev */
+ SYS_RES_MEMORY, /* type */
+ &rid, /* rid */
+ RF_ACTIVE | PCI_RF_DENSE); /* flags */
if (sc->bce_res == NULL) {
BCE_PRINTF(sc, "%s(%d): PCI memory allocation failed\n",
@@ -781,6 +781,11 @@ bce_attach(device_t dev)
/* Add the supported sysctls to the kernel. */
bce_add_sysctls(sc);
+ /* Get the firmware running so IPMI still works */
+ BCE_LOCK(sc);
+ bce_mgmt_init_locked(sc);
+ BCE_UNLOCK(sc);
+
goto bce_attach_exit;
bce_attach_fail:
@@ -1352,7 +1357,6 @@ bce_nvram_erase_page(struct bce_softc *sc, u32 offset)
REG_WR(sc, BCE_NVM_COMMAND, cmd);
/* Wait for completion. */
- */
for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
u32 val;
@@ -2126,135 +2130,24 @@ bce_dma_free(struct bce_softc *sc)
static void
bce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- struct bce_dmamap_arg *map_arg = arg;
- struct bce_softc *sc = map_arg->sc;
+ bus_addr_t *busaddr = arg;
/* Simulate a mapping failure. */
DBRUNIF(DB_RANDOMTRUE(bce_debug_dma_map_addr_failure),
- BCE_PRINTF(sc, "%s(%d): Simulating DMA mapping error.\n",
+ printf("bce: %s(%d): Simulating DMA mapping error.\n",
__FILE__, __LINE__);
error = ENOMEM);
/* Check for an error and signal the caller that an error occurred. */
- if (error || (nseg > map_arg->maxsegs)) {
- BCE_PRINTF(sc, "%s(%d): DMA mapping error! error = %d, "
- "nseg = %d, maxsegs = %d\n",
- __FILE__, __LINE__, error, nseg, map_arg->maxsegs);
- map_arg->maxsegs = 0;
- goto bce_dma_map_addr_exit;
- }
-
- map_arg->busaddr = segs->ds_addr;
-
-bce_dma_map_addr_exit:
- return;
-}
-
-
-/****************************************************************************/
-/* Map TX buffers into TX buffer descriptors. */
-/* */
-/* Given a series of DMA memory containting an outgoing frame, map the */
-/* segments into the tx_bd structure used by the hardware. */
-/* */
-/* Returns: */
-/* Nothing. */
-/****************************************************************************/
-static void
-bce_dma_map_tx_desc(void *arg, bus_dma_segment_t *segs,
- int nseg, bus_size_t mapsize, int error)
-{
- struct bce_dmamap_arg *map_arg;
- struct bce_softc *sc;
- struct tx_bd *txbd = NULL;
- int i = 0;
- u16 prod, chain_prod;
- u32 prod_bseq;
-#ifdef BCE_DEBUG
- u16 debug_prod;
-#endif
-
- map_arg = arg;
- sc = map_arg->sc;
-
if (error) {
- DBPRINT(sc, BCE_WARN, "%s(): Called with error = %d\n",
- __FUNCTION__, error);
+ printf("bce %s(%d): DMA mapping error! error = %d, "
+ "nseg = %d\n", __FILE__, __LINE__, error, nseg);
+ *busaddr = 0;
return;
}
- /* Signal error to caller if there's too many segments */
- if (nseg > map_arg->maxsegs) {
- DBPRINT(sc, BCE_WARN,
- "%s(): Mapped TX descriptors: max segs = %d, "
- "actual segs = %d\n",
- __FUNCTION__, map_arg->maxsegs, nseg);
-
- map_arg->maxsegs = 0;
- return;
- }
-
- /* prod points to an empty tx_bd at this point. */
- prod = map_arg->prod;
- chain_prod = map_arg->chain_prod;
- prod_bseq = map_arg->prod_bseq;
-
-#ifdef BCE_DEBUG
- debug_prod = chain_prod;
-#endif
-
- DBPRINT(sc, BCE_INFO_SEND,
- "%s(): Start: prod = 0x%04X, chain_prod = %04X, "
- "prod_bseq = 0x%08X\n",
- __FUNCTION__, prod, chain_prod, prod_bseq);
-
- /*
- * Cycle through each mbuf segment that makes up
- * the outgoing frame, gathering the mapping info
- * for that segment and creating a tx_bd to for
- * the mbuf.
- */
-
- txbd = &map_arg->tx_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
-
- /* Setup the first tx_bd for the first segment. */
- txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
- txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
- txbd->tx_bd_mss_nbytes = htole16(segs[i].ds_len);
- txbd->tx_bd_vlan_tag_flags = htole16(map_arg->tx_flags |
- TX_BD_FLAGS_START);
- prod_bseq += segs[i].ds_len;
-
- /* Setup any remaing segments. */
- for (i = 1; i < nseg; i++) {
- prod = NEXT_TX_BD(prod);
- chain_prod = TX_CHAIN_IDX(prod);
-
- txbd = &map_arg->tx_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
-
- txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
- txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
- txbd->tx_bd_mss_nbytes = htole16(segs[i].ds_len);
- txbd->tx_bd_vlan_tag_flags = htole16(map_arg->tx_flags);
-
- prod_bseq += segs[i].ds_len;
- }
-
- /* Set the END flag on the last TX buffer descriptor. */
- txbd->tx_bd_vlan_tag_flags |= htole16(TX_BD_FLAGS_END);
-
- DBRUN(BCE_INFO_SEND, bce_dump_tx_chain(sc, debug_prod, nseg));
-
- DBPRINT(sc, BCE_INFO_SEND,
- "%s(): End: prod = 0x%04X, chain_prod = %04X, "
- "prod_bseq = 0x%08X\n",
- __FUNCTION__, prod, chain_prod, prod_bseq);
-
- /* prod points to the last tx_bd at this point. */
- map_arg->maxsegs = nseg;
- map_arg->prod = prod;
- map_arg->chain_prod = chain_prod;
- map_arg->prod_bseq = prod_bseq;
+ *busaddr = segs->ds_addr;
+ return;
}
@@ -2272,28 +2165,28 @@ bce_dma_alloc(device_t dev)
{
struct bce_softc *sc;
int i, error, rc = 0;
- struct bce_dmamap_arg map_arg;
+ bus_addr_t busaddr;
sc = device_get_softc(dev);
-
+
DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
/*
* Allocate the parent bus DMA tag appropriate for PCI.
*/
if (bus_dma_tag_create(NULL, /* parent */
- BCE_DMA_ALIGN, /* alignment */
- BCE_DMA_BOUNDARY, /* boundary */
- sc->max_bus_addr, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, /* filterfunc */
- NULL, /* filterarg */
- MAXBSIZE, /* maxsize */
- BUS_SPACE_UNRESTRICTED, /* nsegments */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
- 0, /* flags */
- NULL, /* locfunc */
- NULL, /* lockarg */
+ 1, /* alignment */
+ BCE_DMA_BOUNDARY, /* boundary */
+ sc->max_bus_addr, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, /* filterfunc */
+ NULL, /* filterarg */
+ MAXBSIZE, /* maxsize */
+ BUS_SPACE_UNRESTRICTED, /* nsegments */
+ BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+ 0, /* flags */
+ NULL, /* locfunc */
+ NULL, /* lockarg */
&sc->parent_tag)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate parent DMA tag!\n",
__FILE__, __LINE__);
@@ -2307,19 +2200,19 @@ bce_dma_alloc(device_t dev)
* address of the block.
*/
if (bus_dma_tag_create(
- sc->parent_tag, /* parent */
+ sc->parent_tag, /* parent */
BCE_DMA_ALIGN, /* alignment */
BCE_DMA_BOUNDARY, /* boundary */
sc->max_bus_addr, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
- NULL, /* filterfunc */
- NULL, /* filterarg */
+ NULL, /* filterfunc */
+ NULL, /* filterarg */
BCE_STATUS_BLK_SZ, /* maxsize */
- 1, /* nsegments */
+ 1, /* nsegments */
BCE_STATUS_BLK_SZ, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockarg */
&sc->status_tag)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate status block DMA tag!\n",
__FILE__, __LINE__);
@@ -2328,9 +2221,9 @@ bce_dma_alloc(device_t dev)
}
if(bus_dmamem_alloc(
- sc->status_tag, /* dmat */
+ sc->status_tag, /* dmat */
(void **)&sc->status_block, /* vaddr */
- BUS_DMA_NOWAIT, /* flags */
+ BUS_DMA_NOWAIT, /* flags */
&sc->status_map)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate status block DMA memory!\n",
__FILE__, __LINE__);
@@ -2340,26 +2233,23 @@ bce_dma_alloc(device_t dev)
bzero((char *)sc->status_block, BCE_STATUS_BLK_SZ);
- map_arg.sc = sc;
- map_arg.maxsegs = 1;
-
error = bus_dmamap_load(
- sc->status_tag, /* dmat */
+ sc->status_tag, /* dmat */
sc->status_map, /* map */
sc->status_block, /* buf */
BCE_STATUS_BLK_SZ, /* buflen */
bce_dma_map_addr, /* callback */
- &map_arg, /* callbackarg */
+ &busaddr, /* callbackarg */
BUS_DMA_NOWAIT); /* flags */
- if(error || (map_arg.maxsegs == 0)) {
+ if (error) {
BCE_PRINTF(sc, "%s(%d): Could not map status block DMA memory!\n",
__FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
- sc->status_block_paddr = map_arg.busaddr;
+ sc->status_block_paddr = busaddr;
/* DRC - Fix for 64 bit addresses. */
DBPRINT(sc, BCE_INFO, "status_block_paddr = 0x%08X\n",
(u32) sc->status_block_paddr);
@@ -2370,19 +2260,19 @@ bce_dma_alloc(device_t dev)
* address of the block.
*/
if (bus_dma_tag_create(
- sc->parent_tag, /* parent */
+ sc->parent_tag, /* parent */
BCE_DMA_ALIGN, /* alignment */
BCE_DMA_BOUNDARY, /* boundary */
sc->max_bus_addr, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
- NULL, /* filterfunc */
- NULL, /* filterarg */
+ NULL, /* filterfunc */
+ NULL, /* filterarg */
BCE_STATS_BLK_SZ, /* maxsize */
- 1, /* nsegments */
+ 1, /* nsegments */
BCE_STATS_BLK_SZ, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockarg */
&sc->stats_tag)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate statistics block DMA tag!\n",
__FILE__, __LINE__);
@@ -2391,9 +2281,9 @@ bce_dma_alloc(device_t dev)
}
if (bus_dmamem_alloc(
- sc->stats_tag, /* dmat */
+ sc->stats_tag, /* dmat */
(void **)&sc->stats_block, /* vaddr */
- BUS_DMA_NOWAIT, /* flags */
+ BUS_DMA_NOWAIT, /* flags */
&sc->stats_map)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate statistics block DMA memory!\n",
__FILE__, __LINE__);
@@ -2403,26 +2293,23 @@ bce_dma_alloc(device_t dev)
bzero((char *)sc->stats_block, BCE_STATS_BLK_SZ);
- map_arg.sc = sc;
- map_arg.maxsegs = 1;
-
error = bus_dmamap_load(
- sc->stats_tag, /* dmat */
+ sc->stats_tag, /* dmat */
sc->stats_map, /* map */
sc->stats_block, /* buf */
BCE_STATS_BLK_SZ, /* buflen */
bce_dma_map_addr, /* callback */
- &map_arg, /* callbackarg */
+ &busaddr, /* callbackarg */
BUS_DMA_NOWAIT); /* flags */
- if(error || (map_arg.maxsegs == 0)) {
+ if(error) {
BCE_PRINTF(sc, "%s(%d): Could not map statistics block DMA memory!\n",
__FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
- sc->stats_block_paddr = map_arg.busaddr;
+ sc->stats_block_paddr = busaddr;
/* DRC - Fix for 64 bit address. */
DBPRINT(sc,BCE_INFO, "stats_block_paddr = 0x%08X\n",
(u32) sc->stats_block_paddr);
@@ -2433,19 +2320,19 @@ bce_dma_alloc(device_t dev)
* physical address of the block.
*/
if(bus_dma_tag_create(
- sc->parent_tag, /* parent */
- BCM_PAGE_SIZE, /* alignment */
- BCE_DMA_BOUNDARY, /* boundary */
- sc->max_bus_addr, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, /* filterfunc */
- NULL, /* filterarg */
- BCE_TX_CHAIN_PAGE_SZ, /* maxsize */
- 1, /* nsegments */
- BCE_TX_CHAIN_PAGE_SZ, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
+ sc->parent_tag, /* parent */
+ BCM_PAGE_SIZE, /* alignment */
+ BCE_DMA_BOUNDARY, /* boundary */
+ sc->max_bus_addr, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, /* filterfunc */
+ NULL, /* filterarg */
+ BCE_TX_CHAIN_PAGE_SZ, /* maxsize */
+ 1, /* nsegments */
+ BCE_TX_CHAIN_PAGE_SZ, /* maxsegsize */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockarg */
&sc->tx_bd_chain_tag)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate TX descriptor chain DMA tag!\n",
__FILE__, __LINE__);
@@ -2456,9 +2343,9 @@ bce_dma_alloc(device_t dev)
for (i = 0; i < TX_PAGES; i++) {
if(bus_dmamem_alloc(
- sc->tx_bd_chain_tag, /* tag */
+ sc->tx_bd_chain_tag, /* tag */
(void **)&sc->tx_bd_chain[i], /* vaddr */
- BUS_DMA_NOWAIT, /* flags */
+ BUS_DMA_NOWAIT, /* flags */
&sc->tx_bd_chain_map[i])) {
BCE_PRINTF(sc, "%s(%d): Could not allocate TX descriptor "
"chain DMA memory!\n", __FILE__, __LINE__);
@@ -2466,26 +2353,23 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- map_arg.maxsegs = 1;
- map_arg.sc = sc;
-
error = bus_dmamap_load(
- sc->tx_bd_chain_tag, /* dmat */
- sc->tx_bd_chain_map[i], /* map */
- sc->tx_bd_chain[i], /* buf */
- BCE_TX_CHAIN_PAGE_SZ, /* buflen */
- bce_dma_map_addr, /* callback */
- &map_arg, /* callbackarg */
- BUS_DMA_NOWAIT); /* flags */
+ sc->tx_bd_chain_tag, /* dmat */
+ sc->tx_bd_chain_map[i], /* map */
+ sc->tx_bd_chain[i], /* buf */
+ BCE_TX_CHAIN_PAGE_SZ, /* buflen */
+ bce_dma_map_addr, /* callback */
+ &busaddr, /* callbackarg */
+ BUS_DMA_NOWAIT); /* flags */
- if(error || (map_arg.maxsegs == 0)) {
+ if (error) {
BCE_PRINTF(sc, "%s(%d): Could not map TX descriptor chain DMA memory!\n",
__FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
- sc->tx_bd_chain_paddr[i] = map_arg.busaddr;
+ sc->tx_bd_chain_paddr[i] = busaddr;
/* DRC - Fix for 64 bit systems. */
DBPRINT(sc, BCE_INFO, "tx_bd_chain_paddr[%d] = 0x%08X\n",
i, (u32) sc->tx_bd_chain_paddr[i]);
@@ -2494,19 +2378,19 @@ bce_dma_alloc(device_t dev)
/* Create a DMA tag for TX mbufs. */
if (bus_dma_tag_create(
sc->parent_tag, /* parent */
- BCE_DMA_ALIGN, /* alignment */
- BCE_DMA_BOUNDARY, /* boundary */
+ 1, /* alignment */
+ BCE_DMA_BOUNDARY, /* boundary */
sc->max_bus_addr, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
- NULL, /* filterfunc */
- NULL, /* filterarg */
+ NULL, /* filterfunc */
+ NULL, /* filterarg */
MCLBYTES * BCE_MAX_SEGMENTS, /* maxsize */
BCE_MAX_SEGMENTS, /* nsegments */
- MCLBYTES, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
- &sc->tx_mbuf_tag)) {
+ MCLBYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockarg */
+ &sc->tx_mbuf_tag)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate TX mbuf DMA tag!\n",
__FILE__, __LINE__);
rc = ENOMEM;
@@ -2531,18 +2415,18 @@ bce_dma_alloc(device_t dev)
*/
if (bus_dma_tag_create(
sc->parent_tag, /* parent */
- BCM_PAGE_SIZE, /* alignment */
- BCE_DMA_BOUNDARY, /* boundary */
+ BCM_PAGE_SIZE, /* alignment */
+ BCE_DMA_BOUNDARY, /* boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
sc->max_bus_addr, /* lowaddr */
- NULL, /* filter */
- NULL, /* filterarg */
- BCE_RX_CHAIN_PAGE_SZ, /* maxsize */
- 1, /* nsegments */
- BCE_RX_CHAIN_PAGE_SZ, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
+ NULL, /* filter */
+ NULL, /* filterarg */
+ BCE_RX_CHAIN_PAGE_SZ, /* maxsize */
+ 1, /* nsegments */
+ BCE_RX_CHAIN_PAGE_SZ, /* maxsegsize */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockarg */
&sc->rx_bd_chain_tag)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate RX descriptor chain DMA tag!\n",
__FILE__, __LINE__);
@@ -2553,9 +2437,9 @@ bce_dma_alloc(device_t dev)
for (i = 0; i < RX_PAGES; i++) {
if (bus_dmamem_alloc(
- sc->rx_bd_chain_tag, /* tag */
+ sc->rx_bd_chain_tag, /* tag */
(void **)&sc->rx_bd_chain[i], /* vaddr */
- BUS_DMA_NOWAIT, /* flags */
+ BUS_DMA_NOWAIT, /* flags */
&sc->rx_bd_chain_map[i])) {
BCE_PRINTF(sc, "%s(%d): Could not allocate RX descriptor chain "
"DMA memory!\n", __FILE__, __LINE__);
@@ -2565,26 +2449,23 @@ bce_dma_alloc(device_t dev)
bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ);
- map_arg.maxsegs = 1;
- map_arg.sc = sc;
-
error = bus_dmamap_load(
- sc->rx_bd_chain_tag, /* dmat */
+ sc->rx_bd_chain_tag, /* dmat */
sc->rx_bd_chain_map[i], /* map */
- sc->rx_bd_chain[i], /* buf */
+ sc->rx_bd_chain[i], /* buf */
BCE_RX_CHAIN_PAGE_SZ, /* buflen */
- bce_dma_map_addr, /* callback */
- &map_arg, /* callbackarg */
- BUS_DMA_NOWAIT); /* flags */
+ bce_dma_map_addr, /* callback */
+ &busaddr, /* callbackarg */
+ BUS_DMA_NOWAIT); /* flags */
- if(error || (map_arg.maxsegs == 0)) {
+ if (error) {
BCE_PRINTF(sc, "%s(%d): Could not map RX descriptor chain DMA memory!\n",
__FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
- sc->rx_bd_chain_paddr[i] = map_arg.busaddr;
+ sc->rx_bd_chain_paddr[i] = busaddr;
/* DRC - Fix for 64 bit systems. */
DBPRINT(sc, BCE_INFO, "rx_bd_chain_paddr[%d] = 0x%08X\n",
i, (u32) sc->rx_bd_chain_paddr[i]);
@@ -2594,19 +2475,19 @@ bce_dma_alloc(device_t dev)
* Create a DMA tag for RX mbufs.
*/
if (bus_dma_tag_create(
- sc->parent_tag, /* parent */
- BCE_DMA_ALIGN, /* alignment */
- BCE_DMA_BOUNDARY, /* boundary */
- sc->max_bus_addr, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, /* filterfunc */
- NULL, /* filterarg */
- MJUM9BYTES, /* maxsize */
- BCE_MAX_SEGMENTS, /* nsegments */
- MJUM9BYTES, /* maxsegsize */
- 0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
+ sc->parent_tag, /* parent */
+ 1, /* alignment */
+ BCE_DMA_BOUNDARY, /* boundary */
+ sc->max_bus_addr, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, /* filterfunc */
+ NULL, /* filterarg */
+ MJUM9BYTES, /* maxsize */
+ BCE_MAX_SEGMENTS, /* nsegments */
+ MJUM9BYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockarg */
&sc->rx_mbuf_tag)) {
BCE_PRINTF(sc, "%s(%d): Could not allocate RX mbuf DMA tag!\n",
__FILE__, __LINE__);
@@ -3242,6 +3123,7 @@ bce_stop(struct bce_softc *sc)
DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
+ bce_mgmt_init_locked(sc);
}
@@ -4571,6 +4453,43 @@ bce_init_locked_exit:
return;
}
+static void
+bce_mgmt_init_locked(struct bce_softc *sc)
+{
+ u32 val;
+ struct ifnet *ifp;
+
+ DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
+
+ BCE_LOCK_ASSERT(sc);
+
+ ifp = sc->bce_ifp;
+
+ /* Check if the driver is still running and bail out if it is. */
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ goto bce_mgmt_init_locked_exit;
+
+ /* Initialize the on-boards CPUs */
+ bce_init_cpus(sc);
+
+ val = (BCM_PAGE_BITS - 8) << 24;
+ REG_WR(sc, BCE_RV2P_CONFIG, val);
+
+ /* Enable all critical blocks in the MAC. */
+ REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
+ BCE_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE |
+ BCE_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE |
+ BCE_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE);
+ REG_RD(sc, BCE_MISC_ENABLE_SET_BITS);
+ DELAY(20);
+
+ bce_ifmedia_upd(ifp);
+bce_mgmt_init_locked_exit:
+ DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
+
+ return;
+}
+
/****************************************************************************/
/* Handles controller initialization when called from an unlocked routine. */
@@ -4597,77 +4516,136 @@ bce_init(void *xsc)
/* 0 for success, positive value for failure. */
/****************************************************************************/
static int
-bce_tx_encap(struct bce_softc *sc, struct mbuf *m_head, u16 *prod,
- u16 *chain_prod, u32 *prod_bseq)
+bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head)
{
- u32 vlan_tag_flags = 0;
- struct m_tag *mtag;
- struct bce_dmamap_arg map_arg;
+ bus_dma_segment_t segs[BCE_MAX_SEGMENTS];
bus_dmamap_t map;
- int i, error, rc = 0;
+ struct tx_bd *txbd = NULL;
+ struct m_tag *mtag;
+ struct mbuf *m0;
+ u32 vlan_tag_flags = 0;
+ u32 prod_bseq;
+ u16 chain_prod, prod;
+
+#ifdef BCE_DEBUG
+ u16 debug_prod;
+#endif
+ int i, error, nsegs, rc = 0;
/* Transfer any checksum offload flags to the bd. */
- if (m_head->m_pkthdr.csum_flags) {
- if (m_head->m_pkthdr.csum_flags & CSUM_IP)
+ m0 = *m_head;
+ if (m0->m_pkthdr.csum_flags) {
+ if (m0->m_pkthdr.csum_flags & CSUM_IP)
vlan_tag_flags |= TX_BD_FLAGS_IP_CKSUM;
- if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
+ if (m0->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
}
/* Transfer any VLAN tags to the bd. */
- mtag = VLAN_OUTPUT_TAG(sc->bce_ifp, m_head);
+ mtag = VLAN_OUTPUT_TAG(sc->bce_ifp, m0);
if (mtag != NULL)
vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG |
(VLAN_TAG_VALUE(mtag) << 16));
/* Map the mbuf into DMAable memory. */
- map = sc->tx_mbuf_map[*chain_prod];
- map_arg.sc = sc;
- map_arg.prod = *prod;
- map_arg.chain_prod = *chain_prod;
- map_arg.prod_bseq = *prod_bseq;
- map_arg.tx_flags = vlan_tag_flags;
- map_arg.maxsegs = USABLE_TX_BD - sc->used_tx_bd -
- BCE_TX_SLACK_SPACE;
-
- KASSERT(map_arg.maxsegs > 0, ("Invalid TX maxsegs value!"));
-
- for (i = 0; i < TX_PAGES; i++)
- map_arg.tx_chain[i] = sc->tx_bd_chain[i];
+ prod = sc->tx_prod;
+ chain_prod = TX_CHAIN_IDX(prod);
+ map = sc->tx_mbuf_map[chain_prod];
/* Map the mbuf into our DMA address space. */
- error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, map, m_head,
- bce_dma_map_tx_desc, &map_arg, BUS_DMA_NOWAIT);
+ error = bus_dmamap_load_mbuf_sg(sc->tx_mbuf_tag, map, m0,
+ segs, &nsegs, BUS_DMA_NOWAIT);
- if (error || map_arg.maxsegs == 0) {
+ if (error == EFBIG) {
- /* Try to defrag the mbuf if there are too many segments. */
- if (error == EFBIG && map_arg.maxsegs != 0) {
- struct mbuf *m0;
-
+ /* Try to defrag the mbuf if there are too many segments. */
DBPRINT(sc, BCE_WARN, "%s(): fragmented mbuf (%d pieces)\n",
__FUNCTION__, map_arg.maxsegs);
- m0 = m_defrag(m_head, M_DONTWAIT);
- if (m0 != NULL) {
- m_head = m0;
- error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag,
- map, m_head, bce_dma_map_tx_desc, &map_arg,
- BUS_DMA_NOWAIT);
- }
- }
+ m0 = m_defrag(*m_head, M_DONTWAIT);
+ if (m0 == NULL) {
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (ENOBUFS);
+ }
+
+ *m_head = m0;
+ error = bus_dmamap_load_mbuf_sg(sc->tx_mbuf_tag, map, m0,
+ segs, &nsegs, BUS_DMA_NOWAIT);
+
+ /* Still getting an error after a defrag. */
+ if (error == ENOMEM) {
+ return (error);
+ } else if (error != 0) {
+ BCE_PRINTF(sc,
+ "%s(%d): Error mapping mbuf into TX chain!\n",
+ __FILE__, __LINE__);
+ m_freem(m0);
+ *m_head = NULL;
+ return (ENOBUFS);
+ }
+ } else if (error == ENOMEM) {
+ return (error);
+ } else if (error != 0) {
+ m_freem(m0);
+ *m_head = NULL;
+ return (error);
+ }
+
+ /*
+ * The chip seems to require that at least 16 descriptors be kept
+ * empty at all times. Make sure we honor that.
+ * XXX Would it be faster to assume worst case scenario for nsegs
+ * and do this calculation higher up?
+ */
+ if (nsegs > (USABLE_TX_BD - sc->used_tx_bd - BCE_TX_SLACK_SPACE)) {
+ bus_dmamap_unload(sc->tx_mbuf_tag, map);
+ return (ENOBUFS);
+ }
+
+ /* prod points to an empty tx_bd at this point. */
+ prod_bseq = sc->tx_prod_bseq;
+
+#ifdef BCE_DEBUG
+ debug_prod = chain_prod;
+#endif
+
+ DBPRINT(sc, BCE_INFO_SEND,
+ "%s(): Start: prod = 0x%04X, chain_prod = %04X, "
+ "prod_bseq = 0x%08X\n",
+ __FUNCTION__, *prod, chain_prod, prod_bseq);
+
+ /*
+ * Cycle through each mbuf segment that makes up
+ * the outgoing frame, gathering the mapping info
+ * for that segment and creating a tx_bd to for
+ * the mbuf.
+ */
+ for (i = 0; i < nsegs ; i++) {
- /* Still getting an error after a defrag. */
- if (error) {
- BCE_PRINTF(sc,
- "%s(%d): Error mapping mbuf into TX chain!\n",
- __FILE__, __LINE__);
- rc = ENOBUFS;
- goto bce_tx_encap_exit;
- }
+ chain_prod = TX_CHAIN_IDX(prod);
+ txbd= &sc->tx_bd_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
+ txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
+ txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
+ txbd->tx_bd_mss_nbytes = htole16(segs[i].ds_len);
+ txbd->tx_bd_vlan_tag_flags = htole16(vlan_tag_flags);
+ prod_bseq += segs[i].ds_len;
+ if (i == 0)
+ txbd->tx_bd_vlan_tag_flags |=htole16(TX_BD_FLAGS_START);
+ prod = NEXT_TX_BD(prod);
}
+ /* Set the END flag on the last TX buffer descriptor. */
+ txbd->tx_bd_vlan_tag_flags |= htole16(TX_BD_FLAGS_END);
+
+ DBRUN(BCE_INFO_SEND, bce_dump_tx_chain(sc, debug_prod, nseg));
+
+ DBPRINT(sc, BCE_INFO_SEND,
+ "%s(): End: prod = 0x%04X, chain_prod = %04X, "
+ "prod_bseq = 0x%08X\n",
+ __FUNCTION__, prod, chain_prod, prod_bseq);
+
/*
* Ensure that the map for this transmission
* is placed at the array index of the last
@@ -4677,26 +4655,22 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf *m_head, u16 *prod,
* delete the map before all of the segments
* have been freed.
*/
- sc->tx_mbuf_map[*chain_prod] =
- sc->tx_mbuf_map[map_arg.chain_prod];
- sc->tx_mbuf_map[map_arg.chain_prod] = map;
- sc->tx_mbuf_ptr[map_arg.chain_prod] = m_head;
- sc->used_tx_bd += map_arg.maxsegs;
+ sc->tx_mbuf_map[TX_CHAIN_IDX(sc->tx_prod)] =
+ sc->tx_mbuf_map[chain_prod];
+ sc->tx_mbuf_map[chain_prod] = map;
+ sc->tx_mbuf_ptr[chain_prod] = m0;
+ sc->used_tx_bd += nsegs;
DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark),
sc->tx_hi_watermark = sc->used_tx_bd);
DBRUNIF(1, sc->tx_mbuf_alloc++);
- DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_mbuf_chain(sc, *chain_prod,
- map_arg.maxsegs));
+ DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_mbuf_chain(sc, chain_prod, nsegs));
/* prod still points the last used tx_bd at this point. */
- *prod = map_arg.prod;
- *chain_prod = map_arg.chain_prod;
- *prod_bseq = map_arg.prod_bseq;
-
-bce_tx_encap_exit:
+ sc->tx_prod = prod;
+ sc->tx_prod_bseq = prod_bseq;
return(rc);
}
@@ -4715,7 +4689,6 @@ bce_start_locked(struct ifnet *ifp)
struct mbuf *m_head = NULL;
int count = 0;
u16 tx_prod, tx_chain_prod;
- u32 tx_prod_bseq;
/* If there's no link or the transmit queue is empty then just exit. */
if (!sc->bce_link || IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
@@ -4727,15 +4700,14 @@ bce_start_locked(struct ifnet *ifp)
/* prod points to the next free tx_bd. */
tx_prod = sc->tx_prod;
tx_chain_prod = TX_CHAIN_IDX(tx_prod);
- tx_prod_bseq = sc->tx_prod_bseq;
DBPRINT(sc, BCE_INFO_SEND,
"%s(): Start: tx_prod = 0x%04X, tx_chain_prod = %04X, "
"tx_prod_bseq = 0x%08X\n",
- __FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq);
+ __FUNCTION__, tx_prod, tx_chain_prod, sc->tx_prod_bseq);
/* Keep adding entries while there is space in the ring. */
- while(sc->tx_mbuf_ptr[tx_chain_prod] == NULL) {
+ while (sc->tx_mbuf_ptr[tx_chain_prod] == NULL) {
/* Check for any frames to send. */
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
@@ -4748,7 +4720,7 @@ bce_start_locked(struct ifnet *ifp)
* head of the queue and set the OACTIVE flag
* to wait for the NIC to drain the chain.
*/
- if (bce_tx_encap(sc, m_head, &tx_prod, &tx_chain_prod, &tx_prod_bseq)) {
+ if (bce_tx_encap(sc, &m_head)) {
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
DBPRINT(sc, BCE_INFO_SEND,
@@ -4761,9 +4733,6 @@ bce_start_locked(struct ifnet *ifp)
/* Send a copy of the frame to any BPF listeners. */
BPF_MTAP(ifp, m_head);
-
- tx_prod = NEXT_TX_BD(tx_prod);
- tx_chain_prod = TX_CHAIN_IDX(tx_prod);
}
if (count == 0) {
@@ -4774,13 +4743,12 @@ bce_start_locked(struct ifnet *ifp)
}
/* Update the driver's counters. */
- sc->tx_prod = tx_prod;
- sc->tx_prod_bseq = tx_prod_bseq;
+ tx_chain_prod = TX_CHAIN_IDX(sc->tx_prod);
DBPRINT(sc, BCE_INFO_SEND,
"%s(): End: tx_prod = 0x%04X, tx_chain_prod = 0x%04X, "
"tx_prod_bseq = 0x%08X\n",
- __FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq);
+ __FUNCTION__, tx_prod, tx_chain_prod, sc->tx_prod_bseq);
/* Start the transmit. */
REG_WR16(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BIDX, sc->tx_prod);
diff --git a/sys/dev/bce/if_bcereg.h b/sys/dev/bce/if_bcereg.h
index 4b30f1401f37..e6eae0e4eb53 100644
--- a/sys/dev/bce/if_bcereg.h
+++ b/sys/dev/bce/if_bcereg.h
@@ -63,7 +63,6 @@
#include <netinet/in.h>
#include <netinet/ip.h>
-#include <machine/clock.h> /* for DELAY */
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
@@ -4614,7 +4613,16 @@ struct fw_info {
#define BCE_BUS_SPACE_MAXADDR 0xFFFFFFFFFF
#endif
+/*
+ * XXX Checksum offload involving IP fragments seems to cause problems on
+ * transmit. Disable it for now, hopefully there will be a more elegant
+ * solution later.
+ */
+#ifdef BCE_IP_CSUM
#define BCE_IF_HWASSIST (CSUM_IP | CSUM_TCP | CSUM_UDP)
+#else
+#define BCE_IF_HWASSIST (CSUM_TCP | CSUM_UDP)
+#endif
#if __FreeBSD_version < 700000
#define BCE_IF_CAPABILITIES (IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \
@@ -4645,23 +4653,6 @@ struct fw_info {
#define BCE_STATS_BLK_SZ sizeof(struct statistics_block)
#define BCE_TX_CHAIN_PAGE_SZ BCM_PAGE_SIZE
#define BCE_RX_CHAIN_PAGE_SZ BCM_PAGE_SIZE
-/*
- * Mbuf pointers. We need these to keep track of the virtual addresses
- * of our mbuf chains since we can only convert from physical to virtual,
- * not the other way around.
- */
-
-struct bce_dmamap_arg {
- struct bce_softc *sc; /* Pointer back to device context */
- bus_addr_t busaddr; /* Physical address of mapped memory */
- u32 tx_flags; /* Flags for frame transmit */
- u16 prod;
- u16 chain_prod;
- int maxsegs; /* Max segments supported for this mapped memory */
- u32 prod_bseq;
- struct tx_bd *tx_chain[TX_PAGES];
-};
-
struct bce_softc
{