summaryrefslogtreecommitdiff
path: root/sys/arch/octeon
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2021-02-13 17:12:39 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2021-02-13 17:12:39 +0000
commit7eefd48f3c50cb2f130e678de7fc407dbac69c38 (patch)
tree55200b77ae132a8b9d08e6a1ece811ed407f4e24 /sys/arch/octeon
parentd08b3eb3a7a75d3d80c67d44af5ce38cc5c51f82 (diff)
Revise cnmac(4)'s address filter setup
Set up the DMAC filter in one go instead of doing it separately for unicast and multicast DMACs. This attempts to make the code a little more readable. The setup should now run a bit faster as well because it now does fewer register accesses. Tested on CN5020, CN6120 and CN7130.
Diffstat (limited to 'sys/arch/octeon')
-rw-r--r--sys/arch/octeon/dev/cn30xxgmx.c137
-rw-r--r--sys/arch/octeon/dev/cn30xxgmxreg.h9
-rw-r--r--sys/arch/octeon/dev/cn30xxgmxvar.h4
-rw-r--r--sys/arch/octeon/dev/if_cnmac.c11
4 files changed, 47 insertions, 114 deletions
diff --git a/sys/arch/octeon/dev/cn30xxgmx.c b/sys/arch/octeon/dev/cn30xxgmx.c
index f27b180e493..9b601c97abf 100644
--- a/sys/arch/octeon/dev/cn30xxgmx.c
+++ b/sys/arch/octeon/dev/cn30xxgmx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cn30xxgmx.c,v 1.49 2021/02/04 16:16:10 visa Exp $ */
+/* $OpenBSD: cn30xxgmx.c,v 1.50 2021/02/13 17:12:38 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -47,22 +47,7 @@
#include <octeon/dev/cn30xxpipvar.h>
#include <octeon/dev/cn30xxsmivar.h>
-#define dprintf(...)
-#define OCTEON_ETH_KASSERT KASSERT
-
-#define ADDR2UINT64(u, a) \
- do { \
- u = \
- (((uint64_t)a[0] << 40) | ((uint64_t)a[1] << 32) | \
- ((uint64_t)a[2] << 24) | ((uint64_t)a[3] << 16) | \
- ((uint64_t)a[4] << 8) | ((uint64_t)a[5] << 0)); \
- } while (0)
-#define UINT642ADDR(a, u) \
- do { \
- a[0] = (uint8_t)((u) >> 40); a[1] = (uint8_t)((u) >> 32); \
- a[2] = (uint8_t)((u) >> 24); a[3] = (uint8_t)((u) >> 16); \
- a[4] = (uint8_t)((u) >> 8); a[5] = (uint8_t)((u) >> 0); \
- } while (0)
+#define GMX_NCAM 8
#define _GMX_RD8(sc, off) \
bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off))
@@ -127,11 +112,6 @@ int cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *,
uint64_t);
#endif
-static const int cn30xxgmx_rx_adr_cam_regs[] = {
- GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2,
- GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5
-};
-
struct cn30xxgmx_port_ops cn30xxgmx_port_ops_agl = {
.port_ops_enable = cn30xxgmx_agl_enable,
.port_ops_speed = cn30xxgmx_agl_speed,
@@ -643,42 +623,17 @@ cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc *sc, int cnt)
}
int
-cn30xxgmx_set_mac_addr(struct cn30xxgmx_port_softc *sc, uint8_t *addr)
-{
- uint64_t mac;
- int i;
-
- ADDR2UINT64(mac, addr);
-
- cn30xxgmx_link_enable(sc, 0);
-
- sc->sc_mac = mac;
- _GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
- for (i = 0; i < 6; i++)
- _GMX_PORT_WR8(sc, cn30xxgmx_rx_adr_cam_regs[i], addr[i]);
-
- cn30xxgmx_link_enable(sc, 1);
-
- return 0;
-}
-
-int
cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *sc)
{
struct ifnet *ifp = &sc->sc_port_ac->ac_if;
struct arpcom *ac = sc->sc_port_ac;
struct ether_multi *enm;
struct ether_multistep step;
- uint64_t cam_en = 0x01ULL;
+ uint64_t cam[ETHER_ADDR_LEN];
+ uint64_t cam_en = 0;
uint64_t ctl = 0;
- int multi = 0;
-
- cn30xxgmx_link_enable(sc, 0);
-
- SET(ctl, RXN_ADR_CTL_CAM_MODE);
- CLR(ctl, RXN_ADR_CTL_MCST_ACCEPT | RXN_ADR_CTL_MCST_AFCAM |
- RXN_ADR_CTL_MCST_REJECT);
- CLR(ifp->if_flags, IFF_ALLMULTI);
+ uint64_t mac;
+ int i, cidx;
/*
* Always accept broadcast frames.
@@ -687,63 +642,53 @@ cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *sc)
if (ISSET(ifp->if_flags, IFF_PROMISC)) {
SET(ifp->if_flags, IFF_ALLMULTI);
- CLR(ctl, RXN_ADR_CTL_CAM_MODE);
SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
- cam_en = 0x00ULL;
- } else if (ac->ac_multirangecnt > 0 || ac->ac_multicnt > 7) {
+ } else if (ac->ac_multirangecnt > 0 || ac->ac_multicnt >= GMX_NCAM) {
SET(ifp->if_flags, IFF_ALLMULTI);
+ SET(ctl, RXN_ADR_CTL_CAM_MODE);
SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
} else {
- /*
- * Note first entry is self MAC address; other 7 entires are
- * available for multicast addresses.
- */
- ETHER_FIRST_MULTI(step, sc->sc_port_ac, enm);
- while (enm != NULL) {
- int i;
-
- dprintf("%d: %02x:%02x:%02x:%02x:%02x:%02x\n"
- multi + 1,
- enm->enm_addrlo[0], enm->enm_addrlo[1],
- enm->enm_addrlo[2], enm->enm_addrlo[3],
- enm->enm_addrlo[4], enm->enm_addrlo[5]);
- multi++;
-
- SET(cam_en, 1ULL << multi); /* XXX */
-
- for (i = 0; i < 6; i++) {
- uint64_t tmp;
-
- /* XXX */
- tmp = _GMX_PORT_RD8(sc,
- cn30xxgmx_rx_adr_cam_regs[i]);
- CLR(tmp, 0xffULL << (8 * multi));
- SET(tmp, (uint64_t)enm->enm_addrlo[i] <<
- (8 * multi));
- _GMX_PORT_WR8(sc, cn30xxgmx_rx_adr_cam_regs[i],
- tmp);
- }
+ CLR(ifp->if_flags, IFF_ALLMULTI);
+ SET(ctl, RXN_ADR_CTL_CAM_MODE);
+ SET(ctl, RXN_ADR_CTL_MCST_AFCAM);
+ }
- for (i = 0; i < 6; i++)
- dprintf("cam%d = %016llx\n", i,
- _GMX_PORT_RD8(sc,
- cn30xxgmx_rx_adr_cam_regs[i]));
+ mac = 0;
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ mac |= (uint64_t)ac->ac_enaddr[i] <<
+ ((ETHER_ADDR_LEN - 1 - i) * 8);
+ /*
+ * The first CAM entry is used for the local unicast MAC.
+ * The remaining entries are used for multicast MACs.
+ */
+ memset(cam, 0, sizeof(cam));
+ cidx = 0;
+ if (!ISSET(ifp->if_flags, IFF_PROMISC)) {
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ cam[i] |= (uint64_t)ac->ac_enaddr[i] << (cidx * 8);
+ cam_en |= 1U << cidx;
+ cidx++;
+ }
+ if (!ISSET(ifp->if_flags, IFF_ALLMULTI)) {
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL && cidx < GMX_NCAM) {
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ cam[i] |= (uint64_t)enm->enm_addrlo[i] <<
+ (cidx * 8);
+ cam_en |= 1U << cidx;
+ cidx++;
ETHER_NEXT_MULTI(step, enm);
}
-
- if (multi)
- SET(ctl, RXN_ADR_CTL_MCST_AFCAM);
- else
- SET(ctl, RXN_ADR_CTL_MCST_REJECT);
-
- OCTEON_ETH_KASSERT(enm == NULL);
}
- dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en);
+ cn30xxgmx_link_enable(sc, 0);
+ _GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM(i), cam[i]);
_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
-
+ (void)_GMX_PORT_RD8(sc, GMX0_RX0_ADR_CAM_EN);
cn30xxgmx_link_enable(sc, 1);
return 0;
diff --git a/sys/arch/octeon/dev/cn30xxgmxreg.h b/sys/arch/octeon/dev/cn30xxgmxreg.h
index c601a40aba9..55edb362112 100644
--- a/sys/arch/octeon/dev/cn30xxgmxreg.h
+++ b/sys/arch/octeon/dev/cn30xxgmxreg.h
@@ -3,7 +3,7 @@
* DONT EDIT THIS FILE
*/
-/* $OpenBSD: cn30xxgmxreg.h,v 1.7 2020/09/08 13:54:48 visa Exp $ */
+/* $OpenBSD: cn30xxgmxreg.h,v 1.8 2021/02/13 17:12:38 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -64,12 +64,7 @@
#define GMX0_RX0_STATS_PKTS_BAD 0x0c0
#define GMX0_RX0_ADR_CTL 0x100
#define GMX0_RX0_ADR_CAM_EN 0x108
-#define GMX0_RX0_ADR_CAM0 0x180
-#define GMX0_RX0_ADR_CAM1 0x188
-#define GMX0_RX0_ADR_CAM2 0x190
-#define GMX0_RX0_ADR_CAM3 0x198
-#define GMX0_RX0_ADR_CAM4 0x1a0
-#define GMX0_RX0_ADR_CAM5 0x1a8
+#define GMX0_RX0_ADR_CAM(i) (0x180 + (i) * 8)
#define GMX0_TX0_CLK 0x208
#define GMX0_TX0_THRESH 0x210
#define GMX0_TX0_APPEND 0x218
diff --git a/sys/arch/octeon/dev/cn30xxgmxvar.h b/sys/arch/octeon/dev/cn30xxgmxvar.h
index 066ba8b2347..1368b5bf14c 100644
--- a/sys/arch/octeon/dev/cn30xxgmxvar.h
+++ b/sys/arch/octeon/dev/cn30xxgmxvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cn30xxgmxvar.h,v 1.11 2020/09/08 13:54:48 visa Exp $ */
+/* $OpenBSD: cn30xxgmxvar.h,v 1.12 2021/02/13 17:12:38 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -61,7 +61,6 @@ struct cn30xxgmx_port_softc {
bus_space_handle_t sc_port_regh;
int sc_port_no; /* GMX0:0, GMX0:1, ... */
int sc_port_type;
- uint64_t sc_mac;
uint64_t sc_link;
struct mii_data *sc_port_mii;
struct arpcom *sc_port_ac;
@@ -111,7 +110,6 @@ int cn30xxgmx_rx_frm_ctl_enable(struct cn30xxgmx_port_softc *,
int cn30xxgmx_rx_frm_ctl_disable(struct cn30xxgmx_port_softc *,
uint64_t rx_frm_ctl);
int cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc *, int);
-int cn30xxgmx_set_mac_addr(struct cn30xxgmx_port_softc *, uint8_t *);
int cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *);
int cn30xxgmx_port_enable(struct cn30xxgmx_port_softc *, int);
int cn30xxgmx_reset_speed(struct cn30xxgmx_port_softc *);
diff --git a/sys/arch/octeon/dev/if_cnmac.c b/sys/arch/octeon/dev/if_cnmac.c
index c3f20ff5f09..ebb341f5948 100644
--- a/sys/arch/octeon/dev/if_cnmac.c
+++ b/sys/arch/octeon/dev/if_cnmac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_cnmac.c,v 1.80 2020/12/12 11:48:52 jan Exp $ */
+/* $OpenBSD: if_cnmac.c,v 1.81 2021/02/13 17:12:38 visa Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -247,7 +247,6 @@ cnmac_attach(struct device *parent, struct device *self, void *aux)
struct cnmac_softc *sc = (void *)self;
struct cn30xxgmx_attach_args *ga = aux;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- uint8_t enaddr[ETHER_ADDR_LEN];
if (cnmac_npowgroups >= OCTEON_POW_GROUP_MAX) {
printf(": out of POW groups\n");
@@ -275,8 +274,8 @@ cnmac_attach(struct device *parent, struct device *self, void *aux)
*/
sc->sc_ip_offset = 0/* XXX */;
- cnmac_board_mac_addr(enaddr);
- printf(", address %s\n", ether_sprintf(enaddr));
+ cnmac_board_mac_addr(sc->sc_arpcom.ac_enaddr);
+ printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
ml_init(&sc->sc_sendq);
sc->sc_soft_req_thresh = 15/* XXX */;
@@ -319,12 +318,9 @@ cnmac_attach(struct device *parent, struct device *self, void *aux)
ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_TCPv4 |
IFCAP_CSUM_UDPv4 | IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
- cn30xxgmx_set_mac_addr(sc->sc_gmx_port, enaddr);
cn30xxgmx_set_filter(sc->sc_gmx_port);
if_attach(ifp);
-
- memcpy(sc->sc_arpcom.ac_enaddr, enaddr, ETHER_ADDR_LEN);
ether_ifattach(ifp);
cnmac_buf_init(sc);
@@ -1011,7 +1007,6 @@ cnmac_init(struct ifnet *ifp)
cn30xxpip_stats_init(sc->sc_pip);
cn30xxgmx_stats_init(sc->sc_gmx_port);
- cn30xxgmx_set_mac_addr(sc->sc_gmx_port, sc->sc_arpcom.ac_enaddr);
cn30xxgmx_set_filter(sc->sc_gmx_port);
timeout_add_sec(&sc->sc_tick_misc_ch, 1);