summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/bge/bge_main2.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/bge/bge_main2.c')
-rw-r--r--usr/src/uts/common/io/bge/bge_main2.c683
1 files changed, 641 insertions, 42 deletions
diff --git a/usr/src/uts/common/io/bge/bge_main2.c b/usr/src/uts/common/io/bge/bge_main2.c
index f191f313c0..bd7e883ca1 100644
--- a/usr/src/uts/common/io/bge/bge_main2.c
+++ b/usr/src/uts/common/io/bge/bge_main2.c
@@ -20,7 +20,13 @@
*/
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
+ */
+
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
*/
#include "bge_impl.h"
@@ -29,6 +35,12 @@
#include <sys/mac.h>
#include <sys/mac_flow.h>
+
+#ifndef STRINGIFY
+#define XSTRINGIFY(x) #x
+#define STRINGIFY(x) XSTRINGIFY(x)
+#endif
+
/*
* This is the string displayed by modinfo, etc.
*/
@@ -47,18 +59,21 @@ static char subdev_propname[] = "subsystem-id";
static char subven_propname[] = "subsystem-vendor-id";
static char rxrings_propname[] = "bge-rx-rings";
static char txrings_propname[] = "bge-tx-rings";
+static char eee_propname[] = "bge-eee";
static char fm_cap[] = "fm-capable";
static char default_mtu[] = "default_mtu";
static int bge_add_intrs(bge_t *, int);
static void bge_rem_intrs(bge_t *);
static int bge_unicst_set(void *, const uint8_t *, int);
+static int bge_addmac(void *, const uint8_t *);
+static int bge_remmac(void *, const uint8_t *);
/*
* Describes the chip's DMA engine
*/
static ddi_dma_attr_t dma_attr = {
- DMA_ATTR_V0, /* dma_attr version */
+ DMA_ATTR_V0, /* dma_attr_version */
0x0000000000000000ull, /* dma_attr_addr_lo */
0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */
0x00000000FFFFFFFFull, /* dma_attr_count_max */
@@ -66,7 +81,7 @@ static ddi_dma_attr_t dma_attr = {
0x00000FFF, /* dma_attr_burstsizes */
0x00000001, /* dma_attr_minxfer */
0x000000000000FFFFull, /* dma_attr_maxxfer */
- 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */
+ 0x00000000FFFFFFFFull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
0x00000001, /* dma_attr_granular */
DDI_DMA_FLAGERR /* dma_attr_flags */
@@ -103,7 +118,9 @@ static ddi_device_acc_attr_t bge_data_accattr = {
static int bge_m_start(void *);
static void bge_m_stop(void *);
static int bge_m_promisc(void *, boolean_t);
+static int bge_m_unicst(void * pArg, const uint8_t *);
static int bge_m_multicst(void *, boolean_t, const uint8_t *);
+static void bge_m_resources(void * arg);
static void bge_m_ioctl(void *, queue_t *, mblk_t *);
static boolean_t bge_m_getcapab(void *, mac_capab_t, void *);
static int bge_unicst_set(void *, const uint8_t *,
@@ -121,26 +138,48 @@ static int bge_get_priv_prop(bge_t *, const char *, uint_t,
static void bge_priv_propinfo(const char *,
mac_prop_info_handle_t);
-#define BGE_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | \
- MC_GETPROP | MC_PROPINFO)
-
static mac_callbacks_t bge_m_callbacks = {
- BGE_M_CALLBACK_FLAGS,
+ MC_IOCTL
+#ifdef MC_RESOURCES
+ | MC_RESOURCES
+#endif
+#ifdef MC_SETPROP
+ | MC_SETPROP
+#endif
+#ifdef MC_GETPROP
+ | MC_GETPROP
+#endif
+#ifdef MC_PROPINFO
+ | MC_PROPINFO
+#endif
+ | MC_GETCAPAB,
bge_m_stat,
bge_m_start,
bge_m_stop,
bge_m_promisc,
bge_m_multicst,
- NULL,
+ bge_m_unicst,
bge_m_tx,
+#ifdef MC_RESOURCES
+ bge_m_resources,
+#else
NULL,
+#endif
bge_m_ioctl,
bge_m_getcapab,
+#ifdef MC_OPEN
NULL,
NULL,
+#endif
+#ifdef MC_SETPROP
bge_m_setprop,
+#endif
+#ifdef MC_GETPROP
bge_m_getprop,
+#endif
+#ifdef MC_PROPINFO
bge_m_propinfo
+#endif
};
char *bge_priv_prop[] = {
@@ -489,7 +528,6 @@ bge_m_stop(void *arg)
} else
bge_stop(bgep);
- bgep->link_update_timer = 0;
bgep->link_state = LINK_STATE_UNKNOWN;
mac_link_update(bgep->mh, bgep->link_state);
@@ -542,6 +580,11 @@ bge_m_start(void *arg)
if ((bgep->asf_status == ASF_STAT_RUN) &&
(bgep->asf_pseudostop)) {
bgep->bge_mac_state = BGE_MAC_STARTED;
+ /* forcing a mac link update here */
+ bge_phys_check(bgep);
+ bgep->link_state = (bgep->param_link_up) ? LINK_STATE_UP :
+ LINK_STATE_DOWN;
+ mac_link_update(bgep->mh, bgep->link_state);
mutex_exit(bgep->genlock);
return (0);
}
@@ -601,7 +644,7 @@ bge_unicst_set(void *arg, const uint8_t *macaddr, int slot)
{
bge_t *bgep = arg; /* private device info */
- BGE_TRACE(("bge_m_unicst_set($%p, %s)", arg,
+ BGE_TRACE(("bge_unicst_set($%p, %s)", arg,
ether_sprintf((void *)macaddr)));
/*
* Remember the new current address in the driver state
@@ -668,7 +711,7 @@ bge_unicst_set(void *arg, const uint8_t *macaddr, int slot)
}
}
#endif
- BGE_DEBUG(("bge_m_unicst_set($%p) done", arg));
+ BGE_DEBUG(("bge_unicst_set($%p) done", arg));
if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) {
ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
mutex_exit(bgep->genlock);
@@ -1244,6 +1287,21 @@ bge_priv_propinfo(const char *pr_name, mac_prop_info_handle_t mph)
mac_prop_info_set_default_str(mph, valstr);
}
+
+static int
+bge_m_unicst(void * arg, const uint8_t * mac_addr)
+{
+ bge_t *bgep = arg;
+ int i;
+
+ /* XXX sets the mac address for all ring slots... OK? */
+ for (i = 0; i < MIN(bgep->chipid.rx_rings, MAC_ADDRESS_REGS_MAX); i++)
+ bge_addmac(&bgep->recv[i], mac_addr);
+
+ return (0);
+}
+
+
/*
* Compute the index of the required bit in the multicast hash map.
* This must mirror the way the hardware actually does it!
@@ -1404,6 +1462,37 @@ bge_m_promisc(void *arg, boolean_t on)
return (0);
}
+#ifdef MC_RESOURCES
+
+static void
+bge_blank(void * arg, time_t tick_cnt, uint_t pkt_cnt)
+{
+ (void)arg;
+ (void)tick_cnt;
+ (void)pkt_cnt;
+}
+
+static void
+bge_m_resources(void * arg)
+{
+ bge_t *bgep = arg;
+ mac_rx_fifo_t mrf;
+ int i;
+
+ mrf.mrf_type = MAC_RX_FIFO;
+ mrf.mrf_blank = bge_blank;
+ mrf.mrf_arg = (void *)bgep;
+ mrf.mrf_normal_blank_time = 25;
+ mrf.mrf_normal_pkt_count = 8;
+
+ for (i = 0; i < BGE_RECV_RINGS_MAX; i++) {
+ bgep->macRxResourceHandles[i] =
+ mac_resource_add(bgep->mh, (mac_resource_t *)&mrf);
+ }
+}
+
+#endif /* MC_RESOURCES */
+
/*
* Find the slot for the specified unicast address
*/
@@ -1427,7 +1516,7 @@ bge_unicst_find(bge_t *bgep, const uint8_t *mac_addr)
* specified ring 'arg'.
*/
static int
-bge_addmac(void *arg, const uint8_t *mac_addr)
+bge_addmac(void *arg, const uint8_t * mac_addr)
{
recv_ring_t *rrp = (recv_ring_t *)arg;
bge_t *bgep = rrp->bgep;
@@ -1579,8 +1668,9 @@ bge_remmac(void *arg, const uint8_t *mac_addr)
return (0);
}
+
static int
-bge_flag_intr_enable(mac_intr_handle_t ih)
+bge_flag_intr_enable(mac_ring_driver_t ih)
{
recv_ring_t *rrp = (recv_ring_t *)ih;
bge_t *bgep = rrp->bgep;
@@ -1593,7 +1683,7 @@ bge_flag_intr_enable(mac_intr_handle_t ih)
}
static int
-bge_flag_intr_disable(mac_intr_handle_t ih)
+bge_flag_intr_disable(mac_ring_driver_t ih)
{
recv_ring_t *rrp = (recv_ring_t *)ih;
bge_t *bgep = rrp->bgep;
@@ -1645,9 +1735,8 @@ bge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
infop->mri_stat = bge_rx_ring_stat;
mintr = &infop->mri_intr;
- mintr->mi_handle = (mac_intr_handle_t)rx_ring;
- mintr->mi_enable = bge_flag_intr_enable;
- mintr->mi_disable = bge_flag_intr_disable;
+ mintr->mi_enable = (mac_intr_enable_t)bge_flag_intr_enable;
+ mintr->mi_disable = (mac_intr_disable_t)bge_flag_intr_disable;
break;
}
@@ -1666,7 +1755,7 @@ bge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
*/
void
bge_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
- mac_group_info_t *infop, mac_group_handle_t gh)
+ mac_group_info_t * infop, mac_group_handle_t gh)
{
bge_t *bgep = arg;
@@ -1694,11 +1783,13 @@ bge_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
}
}
+
/*ARGSUSED*/
static boolean_t
bge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
{
bge_t *bgep = arg;
+ mac_capab_rings_t *cap_rings;
switch (cap) {
case MAC_CAPAB_HCKSUM: {
@@ -1707,26 +1798,30 @@ bge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
*txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
break;
}
- case MAC_CAPAB_RINGS: {
- mac_capab_rings_t *cap_rings = cap_data;
+
+ case MAC_CAPAB_RINGS:
+ cap_rings = (mac_capab_rings_t *)cap_data;
/* Temporarily disable multiple tx rings. */
if (cap_rings->mr_type != MAC_RING_TYPE_RX)
return (B_FALSE);
cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
- cap_rings->mr_rnum = cap_rings->mr_gnum =
+ cap_rings->mr_rnum =
+ cap_rings->mr_gnum =
MIN(bgep->chipid.rx_rings, MAC_ADDRESS_REGS_MAX);
cap_rings->mr_rget = bge_fill_ring;
cap_rings->mr_gget = bge_fill_group;
break;
- }
+
default:
return (B_FALSE);
}
return (B_TRUE);
}
+#ifdef NOT_SUPPORTED_XXX
+
/*
* Loopback ioctl code
*/
@@ -1827,6 +1922,8 @@ bge_loop_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
}
}
+#endif /* NOT_SUPPORTED_XXX */
+
/*
* Specific bge IOCTLs, the gld module handles the generic ones.
*/
@@ -1866,6 +1963,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
case BGE_HARD_RESET:
break;
+#ifdef NOT_SUPPORTED_XXX
case LB_GET_INFO_SIZE:
case LB_GET_INFO:
case LB_GET_MODE:
@@ -1873,6 +1971,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
/* FALLTHRU */
case LB_SET_MODE:
break;
+#endif
}
@@ -1916,12 +2015,14 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
status = bge_chip_ioctl(bgep, wq, mp, iocp);
break;
+#ifdef NOT_SUPPORTED_XXX
case LB_GET_INFO_SIZE:
case LB_GET_INFO:
case LB_GET_MODE:
case LB_SET_MODE:
status = bge_loop_ioctl(bgep, wq, mp, iocp);
break;
+#endif
}
@@ -1994,7 +2095,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
*/
#undef BGE_DBG
-#define BGE_DBG BGE_DBG_INIT /* debug flag for this code */
+#define BGE_DBG BGE_DBG_MEM /* debug flag for this code */
/*
* Allocate an area of memory and a DMA handle for accessing it
*/
@@ -2588,8 +2689,11 @@ bge_alloc_bufs(bge_t *bgep)
/*
* Enable PCI relaxed ordering only for RX/TX data buffers
*/
- if (bge_relaxed_ordering)
- dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING;
+ if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))) {
+ if (bge_relaxed_ordering)
+ dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING;
+ }
/*
* Allocate memory & handles for RX buffers
@@ -2602,6 +2706,9 @@ bge_alloc_bufs(bge_t *bgep)
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
+ BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Rx Buffers (rxbuffsize = %d)",
+ rxbuffsize/BGE_SPLIT,
+ rxbuffsize));
/*
* Allocate memory & handles for TX buffers
@@ -2614,8 +2721,15 @@ bge_alloc_bufs(bge_t *bgep)
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
+ BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Tx Buffers (txbuffsize = %d)",
+ txbuffsize/BGE_SPLIT,
+ txbuffsize));
- dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING;
+ if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))) {
+ /* no relaxed ordering for descriptors rings? */
+ dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING;
+ }
/*
* Allocate memory & handles for receive return rings
@@ -2628,14 +2742,21 @@ bge_alloc_bufs(bge_t *bgep)
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
+ BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Rx Descs cons (rx_rings = %d, rxdescsize = %d)",
+ rxdescsize/rx_rings,
+ rx_rings,
+ rxdescsize));
/*
- * Allocate memory & handles for buffer (producer) descriptor rings
+ * Allocate memory & handles for buffer (producer) descriptor rings.
+ * Note that split=rx_rings.
*/
err = bge_alloc_dma_mem(bgep, rxbuffdescsize, &bge_desc_accattr,
DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &bgep->rx_desc[split]);
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
+ BGE_DEBUG(("DMA ALLOC: allocated 1 chunks for Rx Descs prod (rxbuffdescsize = %d)",
+ rxdescsize));
/*
* Allocate memory & handles for TX descriptor rings,
@@ -2645,65 +2766,260 @@ bge_alloc_bufs(bge_t *bgep)
DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &bgep->tx_desc);
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
+ BGE_DEBUG(("DMA ALLOC: allocated 1 chunks for Tx Descs / Status Block / Stats (txdescdize = %d)",
+ txdescsize));
/*
* Now carve up each of the allocated areas ...
*/
+
+ /* rx buffers */
for (split = 0; split < BGE_SPLIT; ++split) {
area = bgep->rx_buff[split];
+
+ BGE_DEBUG(("RXB CHNK %d INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
bge_slice_chunk(&bgep->buff[BGE_STD_BUFF_RING].buf[split],
&area, BGE_STD_SLOTS_USED/BGE_SPLIT,
bgep->chipid.std_buf_size);
+
+ BGE_DEBUG(("RXB SLCE %d STND: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].mem_va,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].alength,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].offset,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].cookie.dmac_laddress,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].cookie.dmac_size,
+ BGE_STD_SLOTS_USED/BGE_SPLIT,
+ bgep->chipid.std_buf_size));
+
bge_slice_chunk(&bgep->buff[BGE_JUMBO_BUFF_RING].buf[split],
&area, bgep->chipid.jumbo_slots/BGE_SPLIT,
bgep->chipid.recv_jumbo_size);
+
+ if ((bgep->chipid.jumbo_slots / BGE_SPLIT) > 0)
+ {
+ BGE_DEBUG(("RXB SLCE %d JUMB: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].mem_va,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].alength,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].offset,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].cookie.dmac_laddress,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].cookie.dmac_size,
+ bgep->chipid.jumbo_slots/BGE_SPLIT,
+ bgep->chipid.recv_jumbo_size));
+ }
+
bge_slice_chunk(&bgep->buff[BGE_MINI_BUFF_RING].buf[split],
&area, BGE_MINI_SLOTS_USED/BGE_SPLIT,
BGE_MINI_BUFF_SIZE);
+
+ if ((BGE_MINI_SLOTS_USED / BGE_SPLIT) > 0)
+ {
+ BGE_DEBUG(("RXB SLCE %d MINI: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].mem_va,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].alength,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].offset,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].cookie.dmac_laddress,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].cookie.dmac_size,
+ BGE_MINI_SLOTS_USED/BGE_SPLIT,
+ BGE_MINI_BUFF_SIZE));
+ }
+
+ BGE_DEBUG(("RXB CHNK %d DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
}
+ /* tx buffers */
for (split = 0; split < BGE_SPLIT; ++split) {
area = bgep->tx_buff[split];
- for (ring = 0; ring < tx_rings; ++ring)
+
+ BGE_DEBUG(("TXB CHNK %d INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
+ for (ring = 0; ring < tx_rings; ++ring) {
bge_slice_chunk(&bgep->send[ring].buf[0][split],
&area, BGE_SEND_BUF_NUM/BGE_SPLIT,
bgep->chipid.snd_buff_size);
- for (; ring < BGE_SEND_RINGS_MAX; ++ring)
+
+ BGE_DEBUG(("TXB SLCE %d RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split, ring,
+ bgep->send[ring].buf[0][split].mem_va,
+ bgep->send[ring].buf[0][split].alength,
+ bgep->send[ring].buf[0][split].offset,
+ bgep->send[ring].buf[0][split].cookie.dmac_laddress,
+ bgep->send[ring].buf[0][split].cookie.dmac_size,
+ BGE_SEND_BUF_NUM/BGE_SPLIT,
+ bgep->chipid.snd_buff_size));
+ }
+
+ for (; ring < BGE_SEND_RINGS_MAX; ++ring) {
bge_slice_chunk(&bgep->send[ring].buf[0][split],
&area, 0, bgep->chipid.snd_buff_size);
+ }
+
+ BGE_DEBUG(("TXB CHNK %d DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
}
- for (ring = 0; ring < rx_rings; ++ring)
+ for (ring = 0; ring < rx_rings; ++ring) {
bge_slice_chunk(&bgep->recv[ring].desc, &bgep->rx_desc[ring],
bgep->chipid.recv_slots, sizeof (bge_rbd_t));
- area = bgep->rx_desc[rx_rings];
- for (; ring < BGE_RECV_RINGS_MAX; ++ring)
+ BGE_DEBUG(("RXD CONS RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ ring,
+ bgep->recv[ring].desc.mem_va,
+ bgep->recv[ring].desc.alength,
+ bgep->recv[ring].desc.offset,
+ bgep->recv[ring].desc.cookie.dmac_laddress,
+ bgep->recv[ring].desc.cookie.dmac_size,
+ bgep->chipid.recv_slots,
+ sizeof(bge_rbd_t)));
+ }
+
+ /* dma alloc for rxbuffdescsize is located at bgep->rx_desc[#rings] */
+ area = bgep->rx_desc[rx_rings]; /* note rx_rings = one beyond rings */
+
+ for (; ring < BGE_RECV_RINGS_MAX; ++ring) /* skip unused rings */
bge_slice_chunk(&bgep->recv[ring].desc, &area,
0, sizeof (bge_rbd_t));
+
+ BGE_DEBUG(("RXD PROD INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
bge_slice_chunk(&bgep->buff[BGE_STD_BUFF_RING].desc, &area,
BGE_STD_SLOTS_USED, sizeof (bge_rbd_t));
+ BGE_DEBUG(("RXD PROD STND: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->buff[BGE_STD_BUFF_RING].desc.mem_va,
+ bgep->buff[BGE_STD_BUFF_RING].desc.alength,
+ bgep->buff[BGE_STD_BUFF_RING].desc.offset,
+ bgep->buff[BGE_STD_BUFF_RING].desc.cookie.dmac_laddress,
+ bgep->buff[BGE_STD_BUFF_RING].desc.cookie.dmac_size,
+ BGE_STD_SLOTS_USED,
+ sizeof(bge_rbd_t)));
+
bge_slice_chunk(&bgep->buff[BGE_JUMBO_BUFF_RING].desc, &area,
bgep->chipid.jumbo_slots, sizeof (bge_rbd_t));
+ BGE_DEBUG(("RXD PROD JUMB: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.mem_va,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.alength,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.offset,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.cookie.dmac_laddress,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.cookie.dmac_size,
+ bgep->chipid.jumbo_slots,
+ sizeof(bge_rbd_t)));
+
bge_slice_chunk(&bgep->buff[BGE_MINI_BUFF_RING].desc, &area,
BGE_MINI_SLOTS_USED, sizeof (bge_rbd_t));
+ BGE_DEBUG(("RXD PROD MINI: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->buff[BGE_MINI_BUFF_RING].desc.mem_va,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.alength,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.offset,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.cookie.dmac_laddress,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.cookie.dmac_size,
+ BGE_MINI_SLOTS_USED,
+ sizeof(bge_rbd_t)));
+
+ BGE_DEBUG(("RXD PROD DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
ASSERT(area.alength == 0);
area = bgep->tx_desc;
- for (ring = 0; ring < tx_rings; ++ring)
+
+ BGE_DEBUG(("TXD INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
+ for (ring = 0; ring < tx_rings; ++ring) {
bge_slice_chunk(&bgep->send[ring].desc, &area,
BGE_SEND_SLOTS_USED, sizeof (bge_sbd_t));
- for (; ring < BGE_SEND_RINGS_MAX; ++ring)
+
+ BGE_DEBUG(("TXD RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ ring,
+ bgep->send[ring].desc.mem_va,
+ bgep->send[ring].desc.alength,
+ bgep->send[ring].desc.offset,
+ bgep->send[ring].desc.cookie.dmac_laddress,
+ bgep->send[ring].desc.cookie.dmac_size,
+ BGE_SEND_SLOTS_USED,
+ sizeof(bge_sbd_t)));
+ }
+
+ for (; ring < BGE_SEND_RINGS_MAX; ++ring) /* skip unused rings */
bge_slice_chunk(&bgep->send[ring].desc, &area,
0, sizeof (bge_sbd_t));
+
bge_slice_chunk(&bgep->statistics, &area, 1, sizeof (bge_statistics_t));
+ BGE_DEBUG(("TXD STATISTICS: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->statistics.mem_va,
+ bgep->statistics.alength,
+ bgep->statistics.offset,
+ bgep->statistics.cookie.dmac_laddress,
+ bgep->statistics.cookie.dmac_size,
+ 1,
+ sizeof(bge_statistics_t)));
+
bge_slice_chunk(&bgep->status_block, &area, 1, sizeof (bge_status_t));
+ BGE_DEBUG(("TXD STATUS BLOCK: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->status_block.mem_va,
+ bgep->status_block.alength,
+ bgep->status_block.offset,
+ bgep->status_block.cookie.dmac_laddress,
+ bgep->status_block.cookie.dmac_size,
+ 1,
+ sizeof(bge_status_t)));
+
+ BGE_DEBUG(("TXD DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
ASSERT(area.alength == BGE_STATUS_PADDING);
+
DMA_ZERO(bgep->status_block);
return (DDI_SUCCESS);
}
+#undef BGE_DBG
+#define BGE_DBG BGE_DBG_INIT /* debug flag for this code */
+
/*
* This routine frees the transmit and receive buffers and descriptors.
* Make sure the chip is stopped before calling it!
@@ -2840,7 +3156,6 @@ bge_find_mac_address(bge_t *bgep, chip_id_t *cidp)
cidp->vendor_addr.set ? "" : "not "));
}
-
/*ARGSUSED*/
int
bge_check_acc_handle(bge_t *bgep, ddi_acc_handle_t handle)
@@ -2961,6 +3276,7 @@ bge_unattach(bge_t *bgep)
ddi_periodic_delete(bgep->periodic_id);
bgep->periodic_id = NULL;
}
+
if (bgep->progress & PROGRESS_KSTATS)
bge_fini_kstats(bgep);
if (bgep->progress & PROGRESS_PHY)
@@ -3008,8 +3324,11 @@ bge_unattach(bge_t *bgep)
ddi_remove_softintr(bgep->drain_id);
if (bgep->progress & PROGRESS_BUFS)
bge_free_bufs(bgep);
- if (bgep->progress & PROGRESS_REGS)
+ if (bgep->progress & PROGRESS_REGS) {
ddi_regs_map_free(&bgep->io_handle);
+ if (bgep->ape_enabled)
+ ddi_regs_map_free(&bgep->ape_handle);
+ }
if (bgep->progress & PROGRESS_CFG)
pci_config_teardown(&bgep->cfg_handle);
@@ -3093,6 +3412,209 @@ bge_resume(dev_info_t *devinfo)
return (DDI_SUCCESS);
}
+static int
+bge_fw_img_is_valid(bge_t *bgep, uint32_t offset)
+{
+ uint32_t val;
+
+ if (bge_nvmem_read32(bgep, offset, &val) ||
+ (val & 0xfc000000) != 0x0c000000 ||
+ bge_nvmem_read32(bgep, offset + 4, &val) ||
+ val != 0)
+ return (0);
+
+ return (1);
+}
+
+static void
+bge_read_mgmtfw_ver(bge_t *bgep)
+{
+ uint32_t val;
+ uint32_t offset;
+ uint32_t start;
+ int i, vlen;
+
+ for (offset = NVM_DIR_START;
+ offset < NVM_DIR_END;
+ offset += NVM_DIRENT_SIZE) {
+ if (bge_nvmem_read32(bgep, offset, &val))
+ return;
+
+ if ((val >> NVM_DIRTYPE_SHIFT) == NVM_DIRTYPE_ASFINI)
+ break;
+ }
+
+ if (offset == NVM_DIR_END)
+ return;
+
+ if (bge_nvmem_read32(bgep, offset - 4, &start))
+ return;
+
+ if (bge_nvmem_read32(bgep, offset + 4, &offset) ||
+ !bge_fw_img_is_valid(bgep, offset) ||
+ bge_nvmem_read32(bgep, offset + 8, &val))
+ return;
+
+ offset += val - start;
+
+ vlen = strlen(bgep->fw_version);
+
+ bgep->fw_version[vlen++] = ',';
+ bgep->fw_version[vlen++] = ' ';
+
+ for (i = 0; i < 4; i++) {
+ uint32_t v;
+
+ if (bge_nvmem_read32(bgep, offset, &v))
+ return;
+
+ v = BE_32(v);
+
+ offset += sizeof(v);
+
+ if (vlen > BGE_FW_VER_SIZE - sizeof(v)) {
+ memcpy(&bgep->fw_version[vlen], &v, BGE_FW_VER_SIZE - vlen);
+ break;
+ }
+
+ memcpy(&bgep->fw_version[vlen], &v, sizeof(v));
+ vlen += sizeof(v);
+ }
+}
+
+static void
+bge_read_dash_ver(bge_t *bgep)
+{
+ int vlen;
+ uint32_t apedata;
+ char *fwtype;
+
+ if (!bgep->ape_enabled || !bgep->asf_enabled)
+ return;
+
+ apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG);
+ if (apedata != APE_SEG_SIG_MAGIC)
+ return;
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS);
+ if (!(apedata & APE_FW_STATUS_READY))
+ return;
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_VERSION);
+
+ if (bge_ape_get32(bgep, BGE_APE_FW_FEATURES) &
+ BGE_APE_FW_FEATURE_NCSI) {
+ bgep->ape_has_ncsi = B_TRUE;
+ fwtype = "NCSI";
+ } else if ((bgep->chipid.device == DEVICE_ID_5725) ||
+ (bgep->chipid.device == DEVICE_ID_5727)) {
+ fwtype = "SMASH";
+ } else {
+ fwtype = "DASH";
+ }
+
+ vlen = strlen(bgep->fw_version);
+
+ snprintf(&bgep->fw_version[vlen], BGE_FW_VER_SIZE - vlen,
+ " %s v%d.%d.%d.%d", fwtype,
+ (apedata & APE_FW_VERSION_MAJMSK) >> APE_FW_VERSION_MAJSFT,
+ (apedata & APE_FW_VERSION_MINMSK) >> APE_FW_VERSION_MINSFT,
+ (apedata & APE_FW_VERSION_REVMSK) >> APE_FW_VERSION_REVSFT,
+ (apedata & APE_FW_VERSION_BLDMSK));
+}
+
+static void
+bge_read_bc_ver(bge_t *bgep)
+{
+ uint32_t val;
+ uint32_t offset;
+ uint32_t start;
+ uint32_t ver_offset;
+ int i, dst_off;
+ uint32_t major;
+ uint32_t minor;
+ boolean_t newver = B_FALSE;
+
+ if (bge_nvmem_read32(bgep, 0xc, &offset) ||
+ bge_nvmem_read32(bgep, 0x4, &start))
+ return;
+
+ if (bge_nvmem_read32(bgep, offset, &val))
+ return;
+
+ if ((val & 0xfc000000) == 0x0c000000) {
+ if (bge_nvmem_read32(bgep, offset + 4, &val))
+ return;
+
+ if (val == 0)
+ newver = B_TRUE;
+ }
+
+ dst_off = strlen(bgep->fw_version);
+
+ if (newver) {
+ if (((BGE_FW_VER_SIZE - dst_off) < 16) ||
+ bge_nvmem_read32(bgep, offset + 8, &ver_offset))
+ return;
+
+ offset = offset + ver_offset - start;
+ for (i = 0; i < 16; i += 4) {
+ if (bge_nvmem_read32(bgep, offset + i, &val))
+ return;
+ val = BE_32(val);
+ memcpy(bgep->fw_version + dst_off + i, &val,
+ sizeof(val));
+ }
+ } else {
+ if (bge_nvmem_read32(bgep, NVM_PTREV_BCVER, &ver_offset))
+ return;
+
+ major = (ver_offset & NVM_BCVER_MAJMSK) >> NVM_BCVER_MAJSFT;
+ minor = ver_offset & NVM_BCVER_MINMSK;
+ snprintf(&bgep->fw_version[dst_off], BGE_FW_VER_SIZE - dst_off,
+ "v%d.%02d", major, minor);
+ }
+}
+
+static void
+bge_read_fw_ver(bge_t *bgep)
+{
+ uint32_t val;
+ uint32_t magic;
+
+ *bgep->fw_version = 0;
+
+ if ((bgep->chipid.nvtype == BGE_NVTYPE_NONE) ||
+ (bgep->chipid.nvtype == BGE_NVTYPE_UNKNOWN)) {
+ snprintf(bgep->fw_version, sizeof(bgep->fw_version), "sb");
+ return;
+ }
+
+ mutex_enter(bgep->genlock);
+
+ bge_nvmem_read32(bgep, 0, &magic);
+
+ if (magic == EEPROM_MAGIC) {
+ bge_read_bc_ver(bgep);
+ } else {
+ /* ignore other configs for now */
+ mutex_exit(bgep->genlock);
+ return;
+ }
+
+ if (bgep->ape_enabled) {
+ if (bgep->asf_enabled) {
+ bge_read_dash_ver(bgep);
+ }
+ } else if (bgep->asf_enabled) {
+ bge_read_mgmtfw_ver(bgep);
+ }
+
+ mutex_exit(bgep->genlock);
+
+ bgep->fw_version[BGE_FW_VER_SIZE - 1] = 0; /* safety */
+}
+
/*
* attach(9E) -- Attach a device to the system
*
@@ -3108,6 +3630,10 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
int instance;
int err;
int intr_types;
+ int *props = NULL;
+ uint_t numProps;
+ uint32_t regval;
+ uint32_t pci_state_reg;
#ifdef BGE_IPMI_ASF
uint32_t mhcrValue;
#ifdef __sparc
@@ -3209,15 +3735,20 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
* has been set in PCI_CONF_COMM already, we need to write the
* byte-swapped value to it. So we just write zero first for simplicity.
*/
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, 0);
+#else
+ mhcrValue = MHCR_ENABLE_INDIRECT_ACCESS |
+ MHCR_ENABLE_TAGGED_STATUS_MODE |
+ MHCR_MASK_INTERRUPT_MODE |
+ MHCR_MASK_PCI_INT_OUTPUT |
+ MHCR_CLEAR_INTERRUPT_INTA;
+#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcrValue);
bge_ind_put32(bgep, MEMORY_ARBITER_MODE_REG,
bge_ind_get32(bgep, MEMORY_ARBITER_MODE_REG) |
MEMORY_ARBITER_ENABLE);
-#else
- mhcrValue = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR);
-#endif
if (mhcrValue & MHCR_ENABLE_ENDIAN_WORD_SWAP) {
bgep->asf_wordswapped = B_TRUE;
} else {
@@ -3231,7 +3762,7 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
}
bgep->progress |= PROGRESS_CFG;
cidp = &bgep->chipid;
- bzero(cidp, sizeof (*cidp));
+ bzero(cidp, sizeof(*cidp));
bge_chip_cfg_init(bgep, cidp, B_FALSE);
if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) {
ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_LOST);
@@ -3264,6 +3795,8 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
DDI_PROP_DONTPASS, rxrings_propname, cidp->rx_rings);
cidp->tx_rings = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
DDI_PROP_DONTPASS, txrings_propname, cidp->tx_rings);
+ cidp->eee = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
+ DDI_PROP_DONTPASS, eee_propname, cidp->eee);
cidp->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
DDI_PROP_DONTPASS, default_mtu, BGE_DEFAULT_MTU);
@@ -3282,6 +3815,36 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
goto attach_fail;
}
bgep->io_regs = regs;
+
+ bgep->ape_enabled = B_FALSE;
+ bgep->ape_regs = NULL;
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ err = ddi_regs_map_setup(devinfo, BGE_PCI_APEREGS_RNUMBER,
+ &regs, 0, 0, &bge_reg_accattr, &bgep->ape_handle);
+ if (err != DDI_SUCCESS) {
+ ddi_regs_map_free(&bgep->io_handle);
+ bge_problem(bgep, "ddi_regs_map_setup() failed");
+ goto attach_fail;
+ }
+ bgep->ape_regs = regs;
+ bgep->ape_enabled = B_TRUE;
+
+ /*
+ * Allow reads and writes to the
+ * APE register and memory space.
+ */
+
+ pci_state_reg = pci_config_get32(bgep->cfg_handle,
+ PCI_CONF_BGE_PCISTATE);
+ pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR |
+ PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR;
+ pci_config_put32(bgep->cfg_handle,
+ PCI_CONF_BGE_PCISTATE, pci_state_reg);
+
+ bge_ape_lock_init(bgep);
+ }
+
bgep->progress |= PROGRESS_REGS;
/*
@@ -3293,6 +3856,29 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
goto attach_fail;
}
+ err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, bgep->devinfo,
+ 0, "reg", &props, &numProps);
+ if ((err == DDI_PROP_SUCCESS) && (numProps > 0)) {
+ bgep->pci_bus = PCI_REG_BUS_G(props[0]);
+ bgep->pci_dev = PCI_REG_DEV_G(props[0]);
+ bgep->pci_func = PCI_REG_FUNC_G(props[0]);
+ ddi_prop_free(props);
+ }
+
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ regval = bge_reg_get32(bgep, CPMU_STATUS_REG);
+ if ((bgep->chipid.device == DEVICE_ID_5719) ||
+ (bgep->chipid.device == DEVICE_ID_5720)) {
+ bgep->pci_func =
+ ((regval & CPMU_STATUS_FUNC_NUM_5719) >>
+ CPMU_STATUS_FUNC_NUM_5719_SHIFT);
+ } else {
+ bgep->pci_func = ((regval & CPMU_STATUS_FUNC_NUM) >>
+ CPMU_STATUS_FUNC_NUM_SHIFT);
+ }
+ }
+
err = bge_alloc_bufs(bgep);
if (err != DDI_SUCCESS) {
bge_problem(bgep, "DMA buffer allocation failed");
@@ -3477,6 +4063,16 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
* Determine whether to override the chip's own MAC address
*/
bge_find_mac_address(bgep, cidp);
+ {
+ int slot;
+ for (slot = 0; slot < MAC_ADDRESS_REGS_MAX; slot++) {
+ ethaddr_copy(cidp->vendor_addr.addr,
+ bgep->curr_addr[slot].addr);
+ bgep->curr_addr[slot].set = 1;
+ }
+ }
+
+ bge_read_fw_ver(bgep);
bgep->unicst_addr_total = MAC_ADDRESS_REGS_MAX;
bgep->unicst_addr_avail = MAC_ADDRESS_REGS_MAX;
@@ -3492,7 +4088,10 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
macp->m_max_sdu = cidp->ethmax_size - sizeof (struct ether_header);
macp->m_margin = VLAN_TAGSZ;
macp->m_priv_props = bge_priv_prop;
- macp->m_v12n = MAC_VIRT_LEVEL1;
+
+#if defined(ILLUMOS)
+ bge_m_unicst(bgep, cidp->vendor_addr.addr);
+#endif
/*
* Finally, we're ready to register ourselves with the MAC layer