Module Name: src
Committed By: simonb
Date: Tue Jun 23 05:17:13 UTC 2020
Modified Files:
src/sys/arch/mips/cavium/dev: if_cnmac.c if_cnmacvar.h octeon_gmx.c
octeon_gmxreg.h octeon_gmxvar.h
Log Message:
Redo cnmac attachments - cnmacM @ gmxN @ pip0 @ iobus
Support SGMII mode used on CN70XX.
Most functional changes from OpenBSD octeon port. Still more to come from
the OpenBSD driver.
To generate a diff of this commit:
cvs rdiff -u -r1.23 -r1.24 src/sys/arch/mips/cavium/dev/if_cnmac.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/mips/cavium/dev/if_cnmacvar.h
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/mips/cavium/dev/octeon_gmx.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/mips/cavium/dev/octeon_gmxreg.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/mips/cavium/dev/octeon_gmxvar.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/mips/cavium/dev/if_cnmac.c
diff -u src/sys/arch/mips/cavium/dev/if_cnmac.c:1.23 src/sys/arch/mips/cavium/dev/if_cnmac.c:1.24
--- src/sys/arch/mips/cavium/dev/if_cnmac.c:1.23 Mon Jun 22 02:26:19 2020
+++ src/sys/arch/mips/cavium/dev/if_cnmac.c Tue Jun 23 05:17:13 2020
@@ -1,11 +1,33 @@
-/* $NetBSD: if_cnmac.c,v 1.23 2020/06/22 02:26:19 simonb Exp $ */
+/* $NetBSD: if_cnmac.c,v 1.24 2020/06/23 05:17:13 simonb Exp $ */
-#include <sys/cdefs.h>
-#if 0
-__KERNEL_RCSID(0, "$NetBSD: if_cnmac.c,v 1.23 2020/06/22 02:26:19 simonb Exp $");
-#endif
+/*
+ * Copyright (c) 2007 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 "opt_octeon.h"
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: if_cnmac.c,v 1.24 2020/06/23 05:17:13 simonb Exp $");
/*
* If no free send buffer is available, free all the sent buffers and bail out.
@@ -30,7 +52,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_cnmac.c,v
#include <sys/syslog.h>
#include <net/if.h>
-#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_ether.h>
#include <net/route.h>
@@ -52,23 +73,24 @@ __KERNEL_RCSID(0, "$NetBSD: if_cnmac.c,v
#include <mips/cpuregs.h>
#include <mips/cavium/octeonreg.h>
+#include <mips/cavium/octeonvar.h>
#include <mips/cavium/include/iobusvar.h>
#include <mips/cavium/dev/octeon_ciureg.h>
+#include <mips/cavium/dev/octeon_faureg.h>
+#include <mips/cavium/dev/octeon_fpareg.h>
#include <mips/cavium/dev/octeon_gmxreg.h>
#include <mips/cavium/dev/octeon_pipreg.h>
#include <mips/cavium/dev/octeon_powreg.h>
-#include <mips/cavium/dev/octeon_faureg.h>
-#include <mips/cavium/dev/octeon_fpareg.h>
+#include <mips/cavium/dev/octeon_fauvar.h>
#include <mips/cavium/dev/octeon_fpavar.h>
#include <mips/cavium/dev/octeon_gmxvar.h>
-#include <mips/cavium/dev/octeon_fauvar.h>
-#include <mips/cavium/dev/octeon_powvar.h>
#include <mips/cavium/dev/octeon_ipdvar.h>
#include <mips/cavium/dev/octeon_pipvar.h>
#include <mips/cavium/dev/octeon_pkovar.h>
-#include <mips/cavium/dev/octeon_asxvar.h>
+#include <mips/cavium/dev/octeon_powvar.h>
#include <mips/cavium/dev/octeon_smivar.h>
+
#include <mips/cavium/dev/if_cnmacvar.h>
/*
@@ -86,8 +108,6 @@ static void cnmac_attach(device_t, devic
static void cnmac_pip_init(struct cnmac_softc *);
static void cnmac_ipd_init(struct cnmac_softc *);
static void cnmac_pko_init(struct cnmac_softc *);
-static void cnmac_asx_init(struct cnmac_softc *);
-static void cnmac_smi_init(struct cnmac_softc *);
static void cnmac_board_mac_addr(uint8_t *, size_t, struct cnmac_softc *);
@@ -107,11 +127,8 @@ static inline void cnmac_send_queue_add(
uint64_t *);
static inline void cnmac_send_queue_del(struct cnmac_softc *, struct mbuf **,
uint64_t **);
-static inline int cnmac_buf_free_work(struct cnmac_softc *, uint64_t *,
- uint64_t);
-static inline void cnmac_buf_ext_free_m(struct mbuf *, void *, size_t, void *);
-static inline void cnmac_buf_ext_free_ext(struct mbuf *, void *, size_t,
- void *);
+static inline int cnmac_buf_free_work(struct cnmac_softc *, uint64_t *);
+static inline void cnmac_buf_ext_free(struct mbuf *, void *, size_t, void *);
static int cnmac_ioctl(struct ifnet *, u_long, void *);
static void cnmac_watchdog(struct ifnet *);
@@ -122,7 +139,8 @@ static void cnmac_start(struct ifnet *);
static inline int cnmac_send_cmd(struct cnmac_softc *, uint64_t, uint64_t,
int *);
static inline uint64_t cnmac_send_makecmd_w1(int, paddr_t);
-static inline uint64_t cnmac_send_makecmd_w0(uint64_t, uint64_t, size_t, int);
+static inline uint64_t cnmac_send_makecmd_w0(uint64_t, uint64_t, size_t, int,
+ int);
static inline int cnmac_send_makecmd_gbuf(struct cnmac_softc *, struct mbuf *,
uint64_t *, int *);
static inline int cnmac_send_makecmd(struct cnmac_softc *, struct mbuf *,
@@ -140,25 +158,12 @@ static void cnmac_tick_misc(void *);
static inline int cnmac_recv_mbuf(struct cnmac_softc *, uint64_t *,
struct mbuf **);
-static inline int cnmac_recv_check_code(struct cnmac_softc *, uint64_t);
-static inline int cnmac_recv_check_jumbo(struct cnmac_softc *, uint64_t);
-static inline int cnmac_recv_check_link(struct cnmac_softc *, uint64_t);
static inline int cnmac_recv_check(struct cnmac_softc *, uint64_t);
static inline int cnmac_recv(struct cnmac_softc *, uint64_t *);
-static void cnmac_recv_redir(struct ifnet *, struct mbuf *);
-static inline void cnmac_recv_intr(void *, uint64_t *);
+static int cnmac_intr(void *);
-/* Device driver context */
-static struct cnmac_softc *cnmac_gsc[GMX_PORT_NUNITS];
-static void *cnmac_pow_recv_ih;
-
-/* sysctl'able parameters */
+/* device parameters */
int cnmac_param_pko_cmd_w0_n2 = 1;
-int cnmac_param_pip_dyn_rs = 1;
-int cnmac_param_redir = 0;
-int cnmac_param_pktbuf = 0;
-int cnmac_param_rate = 0;
-int cnmac_param_intr = 0;
CFATTACH_DECL_NEW(cnmac, sizeof(struct cnmac_softc),
cnmac_match, cnmac_attach, NULL, NULL);
@@ -177,12 +182,14 @@ static const struct cnmac_pool_param {
_ENTRY(SG)
#undef _ENTRY
};
-struct octfpa_buf *cnmac_pools[8/* XXX */];
+struct octfpa_buf *cnmac_pools[FPA_NPOOLS];
#define cnmac_fb_pkt cnmac_pools[OCTEON_POOL_NO_PKT]
#define cnmac_fb_wqe cnmac_pools[OCTEON_POOL_NO_WQE]
#define cnmac_fb_cmd cnmac_pools[OCTEON_POOL_NO_CMD]
#define cnmac_fb_sg cnmac_pools[OCTEON_POOL_NO_SG]
+static int cnmac_npowgroups = 0;
+
static void
cnmac_buf_init(struct cnmac_softc *sc)
{
@@ -225,12 +232,18 @@ cnmac_attach(device_t parent, device_t s
prop_object_t clk;
uint8_t enaddr[ETHER_ADDR_LEN];
+ if (cnmac_npowgroups >= OCTEON_POW_GROUP_MAX) {
+ printf(": out of POW groups\n");
+ }
+
sc->sc_dev = self;
sc->sc_regt = ga->ga_regt;
sc->sc_port = ga->ga_portno;
sc->sc_port_type = ga->ga_port_type;
sc->sc_gmx = ga->ga_gmx;
sc->sc_gmx_port = ga->ga_gmx_port;
+ sc->sc_smi = ga->ga_smi;
+ sc->sc_powgroup = cnmac_npowgroups++;
if (sc->sc_port >= CVMSEG_LM_ETHER_COUNT) {
/*
@@ -255,11 +268,9 @@ cnmac_attach(device_t parent, device_t s
}
cnmac_board_mac_addr(enaddr, sizeof(enaddr), sc);
- printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev),
+ printf("%s: Ethernet address %s\n", device_xname(self),
ether_sprintf(enaddr));
- cnmac_gsc[sc->sc_port] = sc;
-
SIMPLEQ_INIT(&sc->sc_sendq);
sc->sc_soft_req_thresh = 15/* XXX */;
sc->sc_ext_callback_cnt = 0;
@@ -269,19 +280,19 @@ cnmac_attach(device_t parent, device_t s
callout_init(&sc->sc_tick_misc_ch, 0);
callout_init(&sc->sc_tick_free_ch, 0);
+ const int dv_unit = device_unit(self);
octfau_op_init(&sc->sc_fau_done,
- OCTEON_CVMSEG_ETHER_OFFSET(sc->sc_port, csm_ether_fau_done),
- OCT_FAU_REG_ADDR_END - (8 * (sc->sc_port + 1))/* XXX */);
+ OCTEON_CVMSEG_ETHER_OFFSET(dv_unit, csm_ether_fau_done),
+ OCT_FAU_REG_ADDR_END - (8 * (dv_unit + 1))/* XXX */);
octfau_op_set_8(&sc->sc_fau_done, 0);
cnmac_pip_init(sc);
cnmac_ipd_init(sc);
cnmac_pko_init(sc);
- cnmac_asx_init(sc);
- cnmac_smi_init(sc);
+
+ cnmac_configure_common(sc);
sc->sc_gmx_port->sc_ipd = sc->sc_ipd;
- sc->sc_gmx_port->sc_port_asx = sc->sc_asx;
sc->sc_gmx_port->sc_port_mii = &sc->sc_mii;
sc->sc_gmx_port->sc_port_ec = &sc->sc_ethercom;
/* XXX */
@@ -292,7 +303,7 @@ cnmac_attach(device_t parent, device_t s
cnmac_mediainit(sc);
- strncpy(ifp->if_xname, device_xname(sc->sc_dev), sizeof(ifp->if_xname));
+ strncpy(ifp->if_xname, device_xname(self), sizeof(ifp->if_xname));
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = cnmac_ioctl;
@@ -303,10 +314,18 @@ cnmac_attach(device_t parent, device_t s
IFQ_SET_MAXLEN(&ifp->if_snd, uimax(GATHER_QUEUE_SIZE, IFQ_MAXLEN));
IFQ_SET_READY(&ifp->if_snd);
- /* XXX: not yet tx checksum */
+
ifp->if_capabilities =
+#if 0 /* XXX: no tx checksum yet */
+ IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
+ IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
+ IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx |
+ IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_TCPv6_Rx |
+ IFCAP_CSUM_UDPv6_Tx | IFCAP_CSUM_UDPv6_Rx;
+#else
IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |
IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx;
+#endif
/* 802.1Q VLAN-sized frames are supported */
sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
@@ -317,32 +336,25 @@ cnmac_attach(device_t parent, device_t s
ether_ifattach(ifp, enaddr);
octgmx_set_filter(sc->sc_gmx_port);
- /* XXX */
- sc->sc_rate_recv_check_link_cap.tv_sec = 1;
- sc->sc_rate_recv_check_jumbo_cap.tv_sec = 1;
- sc->sc_rate_recv_check_code_cap.tv_sec = 1;
- sc->sc_rate_recv_fixup_odd_nibble_short_cap.tv_sec = 1;
- sc->sc_rate_recv_fixup_odd_nibble_preamble_cap.tv_sec = 1;
- sc->sc_rate_recv_fixup_odd_nibble_crc_cap.tv_sec = 1;
- /* XXX */
-
#if 1
cnmac_buf_init(sc);
#endif
- if (cnmac_pow_recv_ih == NULL)
- cnmac_pow_recv_ih
- = octpow_intr_establish(OCTEON_POW_GROUP_PIP,
- IPL_NET, cnmac_recv_intr, NULL, NULL);
+ sc->sc_ih = octeon_intr_establish(POW_WORKQ_IRQ(sc->sc_powgroup),
+ IPL_NET, cnmac_intr, sc);
+ if (sc->sc_ih == NULL)
+ panic("%s: could not set up interrupt", device_xname(self));
dict = device_properties(sc->sc_gmx->sc_dev);
clk = prop_dictionary_get(dict, "rgmii-tx");
- KASSERT(clk != NULL);
- sc->sc_gmx_port->sc_clk_tx_setting = prop_number_signed_value(clk);
+ if (clk)
+ sc->sc_gmx_port->sc_clk_tx_setting =
+ prop_number_signed_value(clk);
clk = prop_dictionary_get(dict, "rgmii-rx");
- KASSERT(clk != NULL);
- sc->sc_gmx_port->sc_clk_rx_setting = prop_number_signed_value(clk);
+ if (clk)
+ sc->sc_gmx_port->sc_clk_rx_setting =
+ prop_number_signed_value(clk);
}
/* ---- submodules */
@@ -356,9 +368,10 @@ cnmac_pip_init(struct cnmac_softc *sc)
pip_aa.aa_port = sc->sc_port;
pip_aa.aa_regt = sc->sc_regt;
pip_aa.aa_tag_type = POW_TAG_TYPE_ORDERED/* XXX */;
- pip_aa.aa_receive_group = OCTEON_POW_GROUP_PIP;
+ pip_aa.aa_receive_group = sc->sc_powgroup;
pip_aa.aa_ip_offset = sc->sc_ip_offset;
octpip_init(&pip_aa, &sc->sc_pip);
+ octpip_port_config(sc->sc_pip);
}
/* XXX */
@@ -388,28 +401,6 @@ cnmac_pko_init(struct cnmac_softc *sc)
octpko_init(&pko_aa, &sc->sc_pko);
}
-/* XXX */
-static void
-cnmac_asx_init(struct cnmac_softc *sc)
-{
- struct octasx_attach_args asx_aa;
-
- asx_aa.aa_port = sc->sc_port;
- asx_aa.aa_regt = sc->sc_regt;
- octasx_init(&asx_aa, &sc->sc_asx);
-}
-
-static void
-cnmac_smi_init(struct cnmac_softc *sc)
-{
- struct octsmi_attach_args smi_aa;
-
- smi_aa.aa_port = sc->sc_port;
- smi_aa.aa_regt = sc->sc_regt;
- octsmi_init(&smi_aa, &sc->sc_smi);
- octsmi_set_clock(sc->sc_smi, 0x1464ULL); /* XXX */
-}
-
/* ---- XXX */
#define ADDR2UINT64(u, a) \
@@ -663,10 +654,11 @@ cnmac_send_queue_del(struct cnmac_softc
}
static inline int
-cnmac_buf_free_work(struct cnmac_softc *sc, uint64_t *work, uint64_t word2)
+cnmac_buf_free_work(struct cnmac_softc *sc, uint64_t *work)
{
+
/* XXX when jumbo frame */
- if (ISSET(word2, PIP_WQE_WORD2_IP_BUFS)) {
+ if (ISSET(work[2], PIP_WQE_WORD2_IP_BUFS)) {
paddr_t addr;
paddr_t start_buffer;
@@ -682,35 +674,13 @@ cnmac_buf_free_work(struct cnmac_softc *
}
static inline void
-cnmac_buf_ext_free_m(struct mbuf *m, void *buf, size_t size, void *arg)
-{
- uint64_t *work = (void *)arg;
- int s = splnet();
-
- octfpa_buf_put(cnmac_fb_wqe, work);
-
- KASSERT(m != NULL);
-
- pool_cache_put(mb_cache, m);
-
- splx(s);
-}
-
-static inline void
-cnmac_buf_ext_free_ext(struct mbuf *m, void *buf, size_t size, void *arg)
+cnmac_buf_ext_free(struct mbuf *m, void *buf, size_t size, void *arg)
{
- uint64_t *work = (void *)arg;
- int s = splnet();
-
- octfpa_buf_put(cnmac_fb_wqe, work);
-
octfpa_buf_put(cnmac_fb_pkt, buf);
KASSERT(m != NULL);
pool_cache_put(mb_cache, m);
-
- splx(s);
}
/* ---- ifnet interfaces */
@@ -742,18 +712,17 @@ cnmac_ioctl(struct ifnet *ifp, u_long cm
break;
default:
error = ether_ioctl(ifp, cmd, data);
- if (error == ENETRESET) {
- /*
- * Multicast list has changed; set the hardware filter
- * accordingly.
- */
- if (ISSET(ifp->if_flags, IFF_RUNNING))
- octgmx_set_filter(sc->sc_gmx_port);
- error = 0;
- }
break;
}
+
+ if (error == ENETRESET) {
+ if (ISSET(ifp->if_flags, IFF_RUNNING))
+ octgmx_set_filter(sc->sc_gmx_port);
+ error = 0;
+ }
+
cnmac_start(ifp);
+
splx(s);
return error;
@@ -762,8 +731,10 @@ cnmac_ioctl(struct ifnet *ifp, u_long cm
/* ---- send (output) */
static inline uint64_t
-cnmac_send_makecmd_w0(uint64_t fau0, uint64_t fau1, size_t len, int segs)
+cnmac_send_makecmd_w0(uint64_t fau0, uint64_t fau1, size_t len, int segs,
+ int ipoffp1)
{
+
return octpko_cmd_word0(
OCT_FAU_OP_SIZE_64, /* sz1 */
OCT_FAU_OP_SIZE_64, /* sz0 */
@@ -779,9 +750,10 @@ cnmac_send_makecmd_w0(uint64_t fau0, uin
static inline uint64_t
cnmac_send_makecmd_w1(int size, paddr_t addr)
{
+
return octpko_cmd_word1(
0, 0, /* i, back */
- FPA_GATHER_BUFFER_POOL, /* pool */
+ OCTEON_POOL_NO_SG, /* pool */
size, addr); /* size, addr */
}
@@ -798,11 +770,6 @@ cnmac_send_makecmd_gbuf(struct cnmac_sof
if (__predict_false(m->m_len == 0))
continue;
-#if 0
- KASSERT(((uint32_t)m->m_data & (PAGE_SIZE - 1))
- == (kvtophys((vaddr_t)m->m_data) & (PAGE_SIZE - 1)));
-#endif
-
/* Aligned 4k */
laddr = (uintptr_t)m->m_data & (PAGE_SIZE - 1);
@@ -842,6 +809,7 @@ cnmac_send_makecmd(struct cnmac_softc *s
uint64_t *gbuf, uint64_t *rpko_cmd_w0, uint64_t *rpko_cmd_w1)
{
uint64_t pko_cmd_w0, pko_cmd_w1;
+ int ipoffp1;
int segs;
int result = 0;
@@ -852,6 +820,10 @@ cnmac_send_makecmd(struct cnmac_softc *s
goto done;
}
+ /* Get the IP packet offset for TCP/UDP checksum offloading. */
+ ipoffp1 = (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4 | M_CSUM_UDPv4))
+ ? (ETHER_HDR_LEN + 1) : 0;
+
/*
* segs == 1 -> link mode (single continuous buffer)
* WORD1[size] is number of bytes pointed by segment
@@ -860,7 +832,7 @@ cnmac_send_makecmd(struct cnmac_softc *s
* WORD1[size] is number of segments
*/
pko_cmd_w0 = cnmac_send_makecmd_w0(sc->sc_fau_done.fd_regno,
- 0, m->m_pkthdr.len, segs);
+ 0, m->m_pkthdr.len, segs, ipoffp1);
if (segs == 1) {
pko_cmd_w1 = cnmac_send_makecmd_w1(
m->m_pkthdr.len, kvtophys((vaddr_t)m->m_data));
@@ -1006,19 +978,8 @@ cnmac_start(struct ifnet *ifp)
if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
goto last;
- /* XXX assume that OCTEON doesn't buffer packets */
- if (__predict_false(!octgmx_link_status(sc->sc_gmx_port))) {
- /* Dequeue and drop them */
- while (1) {
- IFQ_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
-
- m_freem(m);
- IF_DROP(&ifp->if_snd);
- }
+ if (__predict_false(!octgmx_link_status(sc->sc_gmx_port)))
goto last;
- }
for (;;) {
IFQ_POLL(&ifp->if_snd, m);
@@ -1068,22 +1029,6 @@ cnmac_start(struct ifnet *ifp)
if (wdc > 0)
octpko_op_doorbell_write(sc->sc_port, sc->sc_port, wdc);
-/*
- * Don't schedule send-buffer-free callout every time - those buffers are freed
- * by "free tick". This makes some packets like NFS slower.
- */
-#ifdef CNMAC_USENFS
- if (__predict_false(sc->sc_ext_callback_cnt > 0)) {
- int timo;
-
- /* ??? */
- timo = hz - (100 * sc->sc_ext_callback_cnt);
- if (timo < 10)
- timo = 10;
- callout_schedule(&sc->sc_tick_free_ch, timo);
- }
-#endif
-
last:
cnmac_send_queue_flush_fetch(sc);
}
@@ -1152,12 +1097,11 @@ cnmac_stop(struct ifnet *ifp, int disabl
/* Mark the interface as down and cancel the watchdog timer. */
CLR(ifp->if_flags, IFF_RUNNING | IFF_OACTIVE);
ifp->if_timer = 0;
+
}
/* ---- misc */
-#define PKO_INDEX_MASK ((1ULL << 12/* XXX */) - 1)
-
static int
cnmac_reset(struct cnmac_softc *sc)
{
@@ -1179,7 +1123,7 @@ cnmac_configure(struct cnmac_softc *sc)
octpko_port_config(sc->sc_pko);
octpko_port_enable(sc->sc_pko, 1);
- octpip_port_config(sc->sc_pip);
+ octpow_config(sc->sc_pow, sc->sc_powgroup);
octgmx_tx_stats_rd_clr(sc->sc_gmx_port, 1);
octgmx_rx_stats_rd_clr(sc->sc_gmx_port, 1);
@@ -1199,13 +1143,8 @@ cnmac_configure_common(struct cnmac_soft
once = 1;
octipd_config(sc->sc_ipd);
-#ifdef CNMAC_IPD_RED
- octipd_red(sc->sc_ipd, RECV_QUEUE_SIZE >> 2, RECV_QUEUE_SIZE >> 3);
-#endif
octpko_config(sc->sc_pko);
- octpow_config(sc->sc_pow, OCTEON_POW_GROUP_PIP);
-
return 0;
}
@@ -1215,10 +1154,9 @@ static inline int
cnmac_recv_mbuf(struct cnmac_softc *sc, uint64_t *work, struct mbuf **rm)
{
struct mbuf *m;
- void (*ext_free)(struct mbuf *, void *, size_t, void *);
- void *ext_buf;
+ vaddr_t addr;
+ vaddr_t ext_buf;
size_t ext_size;
- void *data;
uint64_t word1 = work[1];
uint64_t word2 = work[2];
uint64_t word3 = work[3];
@@ -1226,41 +1164,26 @@ cnmac_recv_mbuf(struct cnmac_softc *sc,
MGETHDR(m, M_NOWAIT, MT_DATA);
if (m == NULL)
return 1;
- KASSERT(m != NULL);
- if ((word2 & PIP_WQE_WORD2_IP_BUFS) == 0) {
- /* Dynamic short */
- ext_free = cnmac_buf_ext_free_m;
- ext_buf = &work[4];
- ext_size = 96;
+ octfpa_buf_put(cnmac_fb_wqe, work);
+
+ if (__SHIFTOUT(word2, PIP_WQE_WORD2_IP_BUFS) != 1)
+ panic("%s: expected one buffer, got %" PRId64, __func__,
+ __SHIFTOUT(word2, PIP_WQE_WORD2_IP_BUFS));
- data = &work[4 + sc->sc_ip_offset / sizeof(uint64_t)];
- } else {
- vaddr_t addr;
- vaddr_t start_buffer;
#ifdef __mips_n32
- KASSERT((word3 & ~MIPS_PHYS_MASK) == 0);
- addr = MIPS_PHYS_TO_KSEG0(word3 & PIP_WQE_WORD3_ADDR);
+ KASSERT((word3 & ~MIPS_PHYS_MASK) == 0);
+ addr = MIPS_PHYS_TO_KSEG0(word3 & PIP_WQE_WORD3_ADDR);
#else
- addr = MIPS_PHYS_TO_XKPHYS_CACHED(word3 & PIP_WQE_WORD3_ADDR);
+ addr = MIPS_PHYS_TO_XKPHYS_CACHED(word3 & PIP_WQE_WORD3_ADDR);
#endif
- start_buffer = addr & ~(2048 - 1);
- ext_free = cnmac_buf_ext_free_ext;
- ext_buf = (void *)start_buffer;
- ext_size = 2048;
-
- data = (void *)addr;
- }
+ ext_size = OCTEON_POOL_SIZE_PKT;
+ ext_buf = addr & ~(ext_size - 1);
+ MEXTADD(m, ext_buf, ext_size, 0, cnmac_buf_ext_free, NULL);
- /* Embed sc pointer into work[0] for _ext_free evcnt */
- work[0] = (uintptr_t)sc;
-
- MEXTADD(m, ext_buf, ext_size, 0, ext_free, work);
- KASSERT(ISSET(m->m_flags, M_EXT));
-
- m->m_data = data;
+ m->m_data = (void *)addr;
m->m_len = m->m_pkthdr.len = (word1 & PIP_WQE_WORD1_LEN) >> 48;
m_set_rcvif(m, &sc->sc_ethercom.ec_if);
@@ -1275,101 +1198,34 @@ cnmac_recv_mbuf(struct cnmac_softc *sc,
}
static inline int
-cnmac_recv_check_code(struct cnmac_softc *sc, uint64_t word2)
+cnmac_recv_check(struct cnmac_softc *sc, uint64_t word2)
{
- uint64_t opecode = word2 & PIP_WQE_WORD2_NOIP_OPECODE;
+ static struct timeval rxerr_log_interval = { 0, 2500000 };
+ uint64_t opecode;
if (__predict_true(!ISSET(word2, PIP_WQE_WORD2_NOIP_RE)))
return 0;
+ opecode = word2 & PIP_WQE_WORD2_NOIP_OPECODE;
+ if ((sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG) &&
+ ratecheck(&sc->sc_rxerr_log_last, &rxerr_log_interval))
+ log(LOG_DEBUG, "%s: rx error (%"PRId64")\n",
+ device_xname(sc->sc_dev), opecode);
+
/* This error is harmless */
- if (opecode == PIP_OVER_ERR)
+ if (opecode == PIP_WQE_WORD2_RE_OPCODE_OVRRUN)
return 0;
return 1;
}
static inline int
-cnmac_recv_check_jumbo(struct cnmac_softc *sc, uint64_t word2)
-{
- if (__predict_false((word2 & PIP_WQE_WORD2_IP_BUFS) > (1ULL << 56)))
- return 1;
- return 0;
-}
-
-static inline int
-cnmac_recv_check_link(struct cnmac_softc *sc, uint64_t word2)
-{
- if (__predict_false(!octgmx_link_status(sc->sc_gmx_port)))
- return 1;
- return 0;
-}
-
-static inline int
-cnmac_recv_check(struct cnmac_softc *sc, uint64_t word2)
-{
- if (__predict_false(cnmac_recv_check_link(sc, word2)) != 0) {
- if (ratecheck(&sc->sc_rate_recv_check_link_last,
- &sc->sc_rate_recv_check_link_cap))
- log(LOG_DEBUG,
- "%s: link is not up, the packet was dropped\n",
- device_xname(sc->sc_dev));
- return 1;
- }
-
-#if 0 /* XXX Performance tuning (Jumbo-frame is not supported yet!) */
- if (__predict_false(cnmac_recv_check_jumbo(sc, word2)) != 0) {
- /* XXX jumbo frame */
- if (ratecheck(&sc->sc_rate_recv_check_jumbo_last,
- &sc->sc_rate_recv_check_jumbo_cap))
- log(LOG_DEBUG,
- "jumbo frame was received\n");
- return 1;
- }
-#endif
-
- if (__predict_false(cnmac_recv_check_code(sc, word2)) != 0) {
-
- if ((word2 & PIP_WQE_WORD2_NOIP_OPECODE) ==
- PIP_WQE_WORD2_RE_OPCODE_LENGTH) {
- /* No logging */
- /* XXX increment special error count */
- } else if ((word2 & PIP_WQE_WORD2_NOIP_OPECODE) ==
- PIP_WQE_WORD2_RE_OPCODE_PARTIAL) {
- /* Not an error, it's because of overload */
- } else {
-
- if (ratecheck(&sc->sc_rate_recv_check_code_last,
- &sc->sc_rate_recv_check_code_cap))
- log(LOG_WARNING,
- "%s: reception error, packet dropped "
- "(error code = %" PRId64 ")\n",
- device_xname(sc->sc_dev), word2 & PIP_WQE_WORD2_NOIP_OPECODE);
- }
- return 1;
- }
-
- return 0;
-}
-
-static inline int
cnmac_recv(struct cnmac_softc *sc, uint64_t *work)
{
- int result = 0;
struct ifnet *ifp;
struct mbuf *m;
uint64_t word2;
- /* XXX XXX XXX */
- /*
- * Performance tuning
- * pre-send iobdma request
- */
- if (sc->sc_soft_req_cnt > sc->sc_soft_req_thresh) {
- cnmac_send_queue_flush_prefetch(sc);
- }
- /* XXX XXX XXX */
-
KASSERT(sc != NULL);
KASSERT(work != NULL);
@@ -1378,17 +1234,16 @@ cnmac_recv(struct cnmac_softc *sc, uint6
KASSERT(ifp != NULL);
+ if (!ISSET(ifp->if_flags, IFF_RUNNING))
+ goto drop;
+
if (__predict_false(cnmac_recv_check(sc, word2) != 0)) {
if_statinc(ifp, if_ierrors);
- result = 1;
- cnmac_buf_free_work(sc, work, word2);
goto drop;
}
if (__predict_false(cnmac_recv_mbuf(sc, work, &m) != 0)) {
if_statinc(ifp, if_ierrors);
- result = 1;
- cnmac_buf_free_work(sc, work, word2);
goto drop;
}
@@ -1398,90 +1253,60 @@ cnmac_recv(struct cnmac_softc *sc, uint6
octipd_offload(word2, m->m_data, &m->m_pkthdr.csum_flags);
- /* XXX XXX XXX */
- if (sc->sc_soft_req_cnt > sc->sc_soft_req_thresh) {
- cnmac_send_queue_flush_fetch(sc);
- cnmac_send_queue_flush(sc);
- }
-
- /* XXX XXX XXX */
- if (sc->sc_flush)
- cnmac_send_queue_flush_sync(sc);
- /* XXX XXX XXX */
-
if_percpuq_enqueue(ifp->if_percpuq, m);
return 0;
drop:
- /* XXX XXX XXX */
- if (sc->sc_soft_req_cnt > sc->sc_soft_req_thresh) {
- cnmac_send_queue_flush_fetch(sc);
- }
- /* XXX XXX XXX */
-
- return result;
+ cnmac_buf_free_work(sc, work);
+ return 1;
}
-static void
-cnmac_recv_redir(struct ifnet *ifp, struct mbuf *m)
+static int
+cnmac_intr(void *arg)
{
- struct cnmac_softc *rsc = ifp->if_softc;
- struct cnmac_softc *sc = NULL;
- int i, wdc = 0;
-
- for (i = 0; i < 3 /* XXX */; i++) {
- if (rsc->sc_redir & (1 << i))
- sc = cnmac_gsc[i];
- }
-
- if (sc == NULL) {
- m_freem(m);
- return;
- }
- cnmac_send_queue_flush_prefetch(sc);
+ struct cnmac_softc *sc = arg;
+ uint64_t *work;
+ uint64_t wqmask = __BIT(sc->sc_powgroup);
+ uint32_t coreid = 0; /* XXX octeon_get_coreid() */
+ uint32_t port;
+
+ _POW_WR8(sc->sc_pow, POW_PP_GRP_MSK_OFFSET(coreid), wqmask);
+
+ octpow_tag_sw_wait();
+ octpow_work_request_async(OCTEON_CVMSEG_OFFSET(csm_pow_intr),
+ POW_NO_WAIT);
- cnmac_send_queue_flush_fetch(sc);
+ for (;;) {
+ work = (uint64_t *)octpow_work_response_async(
+ OCTEON_CVMSEG_OFFSET(csm_pow_intr));
+ if (work == NULL)
+ break;
- if (cnmac_send_queue_is_full(sc)) {
- m_freem(m);
- return;
- }
- if (sc->sc_soft_req_cnt > sc->sc_soft_req_thresh)
- cnmac_send_queue_flush(sc);
+ octpow_tag_sw_wait();
+ octpow_work_request_async(OCTEON_CVMSEG_OFFSET(csm_pow_intr),
+ POW_NO_WAIT);
+
+ port = __SHIFTOUT(work[1], PIP_WQE_WORD1_IPRT);
+ if (port != sc->sc_port) {
+ printf("%s: unexpected wqe port %u, should be %u\n",
+ device_xname(sc->sc_dev), port, sc->sc_port);
+ goto wqe_error;
+ }
- if (cnmac_send(sc, m, &wdc)) {
- IF_DROP(&ifp->if_snd);
- m_freem(m);
- } else {
- octpko_op_doorbell_write(sc->sc_port, sc->sc_port, wdc);
- sc->sc_soft_req_cnt++;
+ (void)cnmac_recv(sc, work);
}
- if (sc->sc_flush)
- cnmac_send_queue_flush_sync(sc);
-}
-
-static inline void
-cnmac_recv_intr(void *data, uint64_t *work)
-{
- struct cnmac_softc *sc;
- int port;
-
- KASSERT(work != NULL);
-
- port = (work[1] & PIP_WQE_WORD1_IPRT) >> 42;
+ _POW_WR8(sc->sc_pow, POW_WQ_INT_OFFSET, wqmask);
- KASSERT(port < GMX_PORT_NUNITS);
-
- sc = cnmac_gsc[port];
-
- KASSERT(sc != NULL);
- KASSERT(port == sc->sc_port);
-
- /* XXX process all work queue entries anyway */
+ return 1;
- (void)cnmac_recv(sc, work);
+wqe_error:
+ printf("word0: 0x%016" PRIx64 "\n", work[0]);
+ printf("word1: 0x%016" PRIx64 "\n", work[1]);
+ printf("word2: 0x%016" PRIx64 "\n", work[2]);
+ printf("word3: 0x%016" PRIx64 "\n", work[3]);
+ panic("wqe_error");
}
/* ---- tick */
@@ -1545,291 +1370,3 @@ cnmac_tick_misc(void *arg)
callout_schedule(&sc->sc_tick_misc_ch, hz);
}
-
-/* ---- Odd nibble preamble workaround (software CRC processing) */
-
-/* ---- sysctl */
-
-static int cnmac_sysctl_verify(SYSCTLFN_ARGS);
-static int cnmac_sysctl_pool(SYSCTLFN_ARGS);
-static int cnmac_sysctl_rd(SYSCTLFN_ARGS);
-
-static int cnmac_sysctl_pkocmdw0n2_num;
-static int cnmac_sysctl_pipdynrs_num;
-static int cnmac_sysctl_redir_num;
-static int cnmac_sysctl_pkt_pool_num;
-static int cnmac_sysctl_wqe_pool_num;
-static int cnmac_sysctl_cmd_pool_num;
-static int cnmac_sysctl_sg_pool_num;
-static int cnmac_sysctl_pktbuf_num;
-
-/*
- * Set up sysctl(3) MIB, hw.cnmac.*.
- */
-SYSCTL_SETUP(sysctl_octeon_eth, "sysctl cnmac subtree setup")
-{
- int rc;
- int cnmac_sysctl_root_num;
- const struct sysctlnode *node;
-
- if ((rc = sysctl_createv(clog, 0, NULL, NULL,
- 0, CTLTYPE_NODE, "hw", NULL,
- NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) {
- goto err;
- }
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- 0, CTLTYPE_NODE, "cnmac",
- SYSCTL_DESCR("cnmac interface controls"),
- NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_root_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
- CTLTYPE_INT, "pko_cmd_w0_n2",
- SYSCTL_DESCR("PKO command WORD0 N2 bit"),
- cnmac_sysctl_verify, 0,
- &cnmac_param_pko_cmd_w0_n2,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_pkocmdw0n2_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
- CTLTYPE_INT, "pip_dyn_rs",
- SYSCTL_DESCR("PIP dynamic short in WQE"),
- cnmac_sysctl_verify, 0,
- &cnmac_param_pip_dyn_rs,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_pipdynrs_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
- CTLTYPE_INT, "redir",
- SYSCTL_DESCR("input port redirection"),
- cnmac_sysctl_verify, 0,
- &cnmac_param_redir,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_redir_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT,
- CTLTYPE_INT, "pkt_pool",
- SYSCTL_DESCR("packet pool available"),
- cnmac_sysctl_pool, 0, NULL,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_pkt_pool_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT,
- CTLTYPE_INT, "wqe_pool",
- SYSCTL_DESCR("wqe pool available"),
- cnmac_sysctl_pool, 0, NULL,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_wqe_pool_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT,
- CTLTYPE_INT, "cmd_pool",
- SYSCTL_DESCR("cmd pool available"),
- cnmac_sysctl_pool, 0, NULL,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_cmd_pool_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT,
- CTLTYPE_INT, "sg_pool",
- SYSCTL_DESCR("sg pool available"),
- cnmac_sysctl_pool, 0, NULL,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_sg_pool_num = node->sysctl_num;
-
- if ((rc = sysctl_createv(clog, 0, NULL, &node,
- CTLFLAG_PERMANENT | CTLFLAG_READONLY,
- CTLTYPE_INT, "pktbuf",
- SYSCTL_DESCR("input packet buffer size on POW"),
- cnmac_sysctl_rd, 0,
- &cnmac_param_pktbuf,
- 0, CTL_HW, cnmac_sysctl_root_num, CTL_CREATE,
- CTL_EOL)) != 0) {
- goto err;
- }
-
- cnmac_sysctl_pktbuf_num = node->sysctl_num;
-
- return;
-
-err:
- aprint_error("%s: syctl_createv failed (rc = %d)\n", __func__, rc);
-}
-
-static int
-cnmac_sysctl_verify(SYSCTLFN_ARGS)
-{
- int error, v;
- struct sysctlnode node;
- struct cnmac_softc *sc;
- int i;
- int s;
-
- node = *rnode;
- v = *(int *)rnode->sysctl_data;
- node.sysctl_data = &v;
- error = sysctl_lookup(SYSCTLFN_CALL(&node));
- if (error || newp == NULL)
- return error;
-
- if (node.sysctl_num == cnmac_sysctl_pkocmdw0n2_num) {
- if (v < 0 || v > 1)
- return EINVAL;
- *(int *)rnode->sysctl_data = v;
- return 0;
- }
-
- if (node.sysctl_num == cnmac_sysctl_pipdynrs_num) {
- if (v < 0 || v > 1)
- return EINVAL;
- *(int *)rnode->sysctl_data = v;
- s = splnet();
- for (i = 0; i < 3/* XXX */; i++) {
- sc = cnmac_gsc[i]; /* XXX */
- octpip_prt_cfg_enable(sc->sc_pip,
- PIP_PRT_CFGN_DYN_RS, v);
- }
- splx(s);
- return 0;
- }
-
- if (node.sysctl_num == cnmac_sysctl_redir_num) {
- if (v & ~((0x7 << (4 * 0)) | (0x7 << (4 * 1)) | (0x7 << (4 * 2))))
- return EINVAL;
- *(int *)rnode->sysctl_data = v;
- s = splnet();
- for (i = 0; i < 3/* XXX */; i++) {
- struct ifnet *ifp;
-
- sc = cnmac_gsc[i]; /* XXX */
- ifp = &sc->sc_ethercom.ec_if;
-
- sc->sc_redir
- = (cnmac_param_redir >> (4 * i)) & 0x7;
- if (sc->sc_redir == 0) {
- if (ISSET(ifp->if_flags, IFF_PROMISC)) {
- CLR(ifp->if_flags, IFF_PROMISC);
- cnmac_mii_statchg(ifp);
- /* octgmx_set_filter(sc->sc_gmx_port); */
- }
- ifp->_if_input = ether_input;
- }
- else {
- if (!ISSET(ifp->if_flags, IFF_PROMISC)) {
- SET(ifp->if_flags, IFF_PROMISC);
- cnmac_mii_statchg(ifp);
- /* octgmx_set_filter(sc->sc_gmx_port); */
- }
- ifp->_if_input = cnmac_recv_redir;
- }
- }
- splx(s);
- return 0;
- }
-
- return EINVAL;
-}
-
-static int
-cnmac_sysctl_pool(SYSCTLFN_ARGS)
-{
- int error, newval = 0;
- struct sysctlnode node;
- int s;
-
- node = *rnode;
- node.sysctl_data = &newval;
- s = splnet();
- if (node.sysctl_num == cnmac_sysctl_pkt_pool_num) {
- error = octfpa_available_fpa_pool(&newval,
- OCTEON_POOL_NO_PKT);
- } else if (node.sysctl_num == cnmac_sysctl_wqe_pool_num) {
- error = octfpa_available_fpa_pool(&newval,
- OCTEON_POOL_NO_WQE);
- } else if (node.sysctl_num == cnmac_sysctl_cmd_pool_num) {
- error = octfpa_available_fpa_pool(&newval,
- OCTEON_POOL_NO_CMD);
- } else if (node.sysctl_num == cnmac_sysctl_sg_pool_num) {
- error = octfpa_available_fpa_pool(&newval,
- OCTEON_POOL_NO_SG);
- } else {
- splx(s);
- return EINVAL;
- }
- splx(s);
- if (error)
- return error;
- error = sysctl_lookup(SYSCTLFN_CALL(&node));
- if (error || newp == NULL)
- return error;
-
- return 0;
-}
-
-static int
-cnmac_sysctl_rd(SYSCTLFN_ARGS)
-{
- int error, v;
- struct sysctlnode node;
- int s;
-
- node = *rnode;
- v = *(int *)rnode->sysctl_data;
- node.sysctl_data = &v;
- error = sysctl_lookup(SYSCTLFN_CALL(&node));
- if (error || newp != NULL)
- return error;
-
- if (node.sysctl_num == cnmac_sysctl_pktbuf_num) {
- uint64_t tmp;
- int n;
-
- s = splnet();
- tmp = octfpa_query(0);
- n = (int)tmp;
- splx(s);
- *(int *)rnode->sysctl_data = n;
- cnmac_param_pktbuf = n;
- *(int *)oldp = n;
- return 0;
- }
-
- return EINVAL;
-}
Index: src/sys/arch/mips/cavium/dev/if_cnmacvar.h
diff -u src/sys/arch/mips/cavium/dev/if_cnmacvar.h:1.3 src/sys/arch/mips/cavium/dev/if_cnmacvar.h:1.4
--- src/sys/arch/mips/cavium/dev/if_cnmacvar.h:1.3 Mon Jun 22 02:26:19 2020
+++ src/sys/arch/mips/cavium/dev/if_cnmacvar.h Tue Jun 23 05:17:13 2020
@@ -1,32 +1,28 @@
-/* $NetBSD: if_cnmacvar.h,v 1.3 2020/06/22 02:26:19 simonb Exp $ */
+/* $NetBSD: if_cnmacvar.h,v 1.4 2020/06/23 05:17:13 simonb Exp $ */
#undef DEBUG
-#undef TENBASET_DBG
-#undef REGISTER_DUMP
#ifdef DEBUG
-#define dprintf printf
+#define dprintf printf
#else
-#define dprintf(...)
+#define dprintf(...)
#endif
-#define IS_MAC_MULTICASTBIT(addr) \
+#define IS_MAC_MULTICASTBIT(addr) \
((addr)[0] & 0x01)
-#define SEND_QUEUE_SIZE (32)
-#define GATHER_QUEUE_SIZE (1024)
-#define FREE_QUEUE_SIZE GATHER_QUEUE_SIZE
-#define RECV_QUEUE_SIZE (GATHER_QUEUE_SIZE * 2)
+#define SEND_QUEUE_SIZE (32)
+#define GATHER_QUEUE_SIZE (1024)
+#define FREE_QUEUE_SIZE GATHER_QUEUE_SIZE
+#define RECV_QUEUE_SIZE (GATHER_QUEUE_SIZE * 2)
-#ifdef CNMAC_FIXUP_ODD_NIBBLE_DYNAMIC
-#define PROC_NIBBLE_SOFT_THRESHOLD 2000
-#endif
+/* Number of mbufs per port to keep in the packet pool */
+#define CNMAC_MBUFS_PER_PORT 256
/* XXX MUST BE REPLACED WITH BUS_DMA!!! */
paddr_t kvtophys(vaddr_t);
/* XXX MUST BE REPLACED WITH BUS_DMA!!! */
struct _send_queue_entry;
-struct octasx_softc;
struct octsmi_softc;
struct octgmx_port_softc;
struct octipd_softc;
@@ -41,22 +37,11 @@ struct cnmac_softc {
bus_space_tag_t sc_regt;
bus_dma_tag_t sc_dmat;
-#if 1
- /* XXX backward compatibility; debugging purpose only */
- bus_space_handle_t sc_gmx_regh;
- bus_space_handle_t sc_gmx_port_regh;
- bus_space_handle_t sc_asx_regh;
- bus_space_handle_t sc_pow_regh;
- bus_space_handle_t sc_fpa_regh;
- bus_space_handle_t sc_smi_regh;
- bus_space_handle_t sc_pip_regh;
-#endif
+ void *sc_ih;
- void *sc_pow_recv_ih;
struct octpip_softc *sc_pip;
struct octipd_softc *sc_ipd;
struct octpko_softc *sc_pko;
- struct octasx_softc *sc_asx;
struct octsmi_softc *sc_smi;
struct octgmx_softc *sc_gmx;
struct octgmx_port_softc
@@ -71,10 +56,6 @@ struct cnmac_softc {
struct callout sc_tick_misc_ch;
struct callout sc_tick_free_ch;
-#ifdef CNMAC_INTR_FEEDBACK
- struct callout sc_resume_ch;
-#endif
-
int64_t sc_soft_req_cnt;
int64_t sc_soft_req_thresh;
int64_t sc_hard_done_cnt;
@@ -87,6 +68,7 @@ struct cnmac_softc {
uint32_t sc_port;
uint32_t sc_port_type;
uint32_t sc_init_flag;
+ int sc_powgroup;
/*
* Redirection - received (input) packets are redirected (directly sent)
@@ -106,17 +88,7 @@ struct cnmac_softc {
size_t sc_ip_offset;
- struct timeval sc_rate_recv_check_link_last;
- struct timeval sc_rate_recv_check_link_cap;
- struct timeval sc_rate_recv_check_jumbo_last;
- struct timeval sc_rate_recv_check_jumbo_cap;
- struct timeval sc_rate_recv_check_code_last;
- struct timeval sc_rate_recv_check_code_cap;
- struct timeval sc_rate_recv_fixup_odd_nibble_short_last;
- struct timeval sc_rate_recv_fixup_odd_nibble_short_cap;
- struct timeval sc_rate_recv_fixup_odd_nibble_preamble_last;
- struct timeval sc_rate_recv_fixup_odd_nibble_preamble_cap;
- struct timeval sc_rate_recv_fixup_odd_nibble_crc_last;
- struct timeval sc_rate_recv_fixup_odd_nibble_crc_cap;
+ struct timeval sc_rxerr_log_last;
+
int sc_quirks;
};
Index: src/sys/arch/mips/cavium/dev/octeon_gmx.c
diff -u src/sys/arch/mips/cavium/dev/octeon_gmx.c:1.14 src/sys/arch/mips/cavium/dev/octeon_gmx.c:1.15
--- src/sys/arch/mips/cavium/dev/octeon_gmx.c:1.14 Mon Jun 22 02:26:20 2020
+++ src/sys/arch/mips/cavium/dev/octeon_gmx.c Tue Jun 23 05:17:13 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: octeon_gmx.c,v 1.14 2020/06/22 02:26:20 simonb Exp $ */
+/* $NetBSD: octeon_gmx.c,v 1.15 2020/06/23 05:17:13 simonb Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -26,19 +26,12 @@
* SUCH DAMAGE.
*/
-/*
- * support GMX0 interface only
- * take no thought for other GMX interface
- */
-
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.14 2020/06/22 02:26:20 simonb Exp $");
-
-#include "opt_octeon.h"
+__KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.15 2020/06/23 05:17:13 simonb Exp $");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/types.h>
+#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/device.h>
#include <sys/lock.h>
@@ -48,14 +41,35 @@ __KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c
#include <mips/locore.h>
#include <mips/include/cpuregs.h>
-#include <sys/bus.h>
+#include <mips/cavium/dev/octeon_asxvar.h>
#include <mips/cavium/dev/octeon_ciureg.h>
#include <mips/cavium/dev/octeon_gmxreg.h>
-#include <mips/cavium/include/iobusvar.h>
-#include <mips/cavium/dev/octeon_ipdvar.h>
-#include <mips/cavium/dev/octeon_asxvar.h>
#include <mips/cavium/dev/octeon_gmxvar.h>
+#include <mips/cavium/dev/octeon_ipdvar.h>
+#include <mips/cavium/dev/octeon_pipvar.h>
+#include <mips/cavium/dev/octeon_smivar.h>
+
+#include <mips/cavium/include/iobusvar.h>
+
+/*
+ * CNnnXX packet interface
+ *
+ *
+ * CN30XX - 1 GMX interface x 3 ports
+ * CN31XX - 1 GMX interface x 3 ports
+ * CN38XX - 2 GMX interfaces x 4 ports
+ * CN50XX - 1 GMX interface x 3 ports
+ * CN52XX - 1 GMX interface x 4 ports
+ * CN56XX - 2 GMX interfaces x 4 ports
+ * CN58XX - 2 GMX interfaces x 4 ports
+ * CN61XX - 2 GMX interfaces x 4 ports
+ * CN63XX - 1 GMX interface x 4 ports
+ * CN66XX - 2 GMX interfaces x 4 ports
+ * CN68XX - 5 GMX interfaces x 4 ports
+ * CN70XX - 2 GMX interfaces x 4 ports
+ * CNF71XX - 1 GMX interface x 2 ports
+ */
#define dprintf(...)
#define CNMAC_KASSERT KASSERT
@@ -83,22 +97,30 @@ __KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c
#define _GMX_PORT_WR8(sc, off, v) \
bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v))
+#define PCS_READ_8(sc, reg) \
+ bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, (reg))
+#define PCS_WRITE_8(sc, reg, val) \
+ bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, (reg), (val))
+
struct octgmx_port_ops {
int (*port_ops_enable)(struct octgmx_port_softc *, int);
int (*port_ops_speed)(struct octgmx_port_softc *);
int (*port_ops_timing)(struct octgmx_port_softc *);
- int (*port_ops_set_mac_addr)(struct octgmx_port_softc *, uint8_t *,
- uint64_t);
- int (*port_ops_set_filter)(struct octgmx_port_softc *);
};
static int octgmx_match(device_t, struct cfdata *, void *);
static void octgmx_attach(device_t, device_t, void *);
static int octgmx_print(void *, const char *);
-static int octgmx_submatch(device_t, struct cfdata *, const int *, void *);
static int octgmx_init(struct octgmx_softc *);
+
+static int octgmx_link_enable(struct octgmx_port_softc *, int);
static int octgmx_rx_frm_ctl_xable(struct octgmx_port_softc *, uint64_t,
int);
+static void octgmx_tx_int_enable(struct octgmx_port_softc *, int);
+static void octgmx_rx_int_enable(struct octgmx_port_softc *, int);
+static int octgmx_rx_frm_ctl_enable(struct octgmx_port_softc *, uint64_t);
+static int octgmx_rx_frm_ctl_disable(struct octgmx_port_softc *, uint64_t);
+static int octgmx_tx_thresh(struct octgmx_port_softc *, int);
static int octgmx_rgmii_enable(struct octgmx_port_softc *, int);
static int octgmx_rgmii_speed(struct octgmx_port_softc *);
@@ -106,9 +128,10 @@ static int octgmx_rgmii_speed_newlink(st
uint64_t *);
static int octgmx_rgmii_speed_speed(struct octgmx_port_softc *);
static int octgmx_rgmii_timing(struct octgmx_port_softc *);
-static int octgmx_rgmii_set_mac_addr(struct octgmx_port_softc *, uint8_t *,
- uint64_t);
-static int octgmx_rgmii_set_filter(struct octgmx_port_softc *);
+
+static int octgmx_sgmii_enable(struct octgmx_port_softc *, int);
+static int octgmx_sgmii_speed(struct octgmx_port_softc *);
+static int octgmx_sgmii_timing(struct octgmx_port_softc *);
static const int octgmx_rx_adr_cam_regs[] = {
GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2,
@@ -123,16 +146,18 @@ struct octgmx_port_ops octgmx_port_ops_g
.port_ops_enable = octgmx_rgmii_enable,
.port_ops_speed = octgmx_rgmii_speed,
.port_ops_timing = octgmx_rgmii_timing,
- .port_ops_set_mac_addr = octgmx_rgmii_set_mac_addr,
- .port_ops_set_filter = octgmx_rgmii_set_filter
};
struct octgmx_port_ops octgmx_port_ops_rgmii = {
.port_ops_enable = octgmx_rgmii_enable,
.port_ops_speed = octgmx_rgmii_speed,
.port_ops_timing = octgmx_rgmii_timing,
- .port_ops_set_mac_addr = octgmx_rgmii_set_mac_addr,
- .port_ops_set_filter = octgmx_rgmii_set_filter
+};
+
+struct octgmx_port_ops octgmx_port_ops_sgmii = {
+ .port_ops_enable = octgmx_sgmii_enable,
+ .port_ops_speed = octgmx_sgmii_speed,
+ .port_ops_timing = octgmx_sgmii_timing,
};
struct octgmx_port_ops octgmx_port_ops_spi42 = {
@@ -143,8 +168,16 @@ struct octgmx_port_ops *octgmx_port_ops[
[GMX_MII_PORT] = &octgmx_port_ops_mii,
[GMX_GMII_PORT] = &octgmx_port_ops_gmii,
[GMX_RGMII_PORT] = &octgmx_port_ops_rgmii,
+ [GMX_SGMII_PORT] = &octgmx_port_ops_sgmii,
[GMX_SPI42_PORT] = &octgmx_port_ops_spi42
};
+static const char *octgmx_port_types[] = {
+ [GMX_MII_PORT] = "MII",
+ [GMX_GMII_PORT] = "GMII",
+ [GMX_RGMII_PORT] = "RGMII",
+ [GMX_SGMII_PORT] = "SGMII",
+ [GMX_SPI42_PORT] = "SPI-4.2"
+};
CFATTACH_DECL_NEW(octgmx, sizeof(struct octgmx_softc),
octgmx_match, octgmx_attach, NULL, NULL);
@@ -166,10 +199,11 @@ octgmx_attach(device_t parent, device_t
{
struct octgmx_softc *sc = device_private(self);
struct iobus_attach_args *aa = aux;
+ struct octsmi_softc *smi;
+ struct octgmx_port_softc *port_sc;
struct octgmx_attach_args gmx_aa;
- int status;
+ int port, status;
int i;
- struct octgmx_port_softc *port_sc;
sc->sc_dev = self;
sc->sc_regt = aa->aa_bust;
@@ -178,7 +212,7 @@ octgmx_attach(device_t parent, device_t
aprint_normal("\n");
status = bus_space_map(sc->sc_regt, aa->aa_unit->addr,
- GMX0_BASE_IF_SIZE, 0, &sc->sc_regh);
+ GMX_PORT_SIZE, 0, &sc->sc_regh);
if (status != 0)
panic(": can't map register");
@@ -188,27 +222,54 @@ octgmx_attach(device_t parent, device_t
M_WAITOK | M_ZERO);
for (i = 0; i < sc->sc_nports; i++) {
+ port = GMX_PORT_NUM(sc->sc_unitno, i);
+ smi = octsmi_lookup(/*XXX*/0, port);
+ if (smi == NULL)
+ continue;
+
port_sc = &sc->sc_ports[i];
port_sc->sc_port_gmx = sc;
- port_sc->sc_port_no = i;
+ port_sc->sc_port_no = port;
port_sc->sc_port_type = sc->sc_port_types[i];
port_sc->sc_port_ops = octgmx_port_ops[port_sc->sc_port_type];
status = bus_space_map(sc->sc_regt,
- aa->aa_unit->addr + GMX0_BASE_PORT_SIZE * i,
- GMX0_BASE_PORT_SIZE, 0, &port_sc->sc_port_regh);
+ aa->aa_unit->addr + GMX_PORT_SIZE * i,
+ GMX_PORT_SIZE, 0, &port_sc->sc_port_regh);
if (status != 0)
panic(": can't map port register");
+ switch (port_sc->sc_port_type) {
+ case GMX_MII_PORT:
+ case GMX_GMII_PORT:
+ case GMX_RGMII_PORT: {
+ struct octasx_attach_args asx_aa;
+
+ asx_aa.aa_port = i;
+ asx_aa.aa_regt = aa->aa_bust;
+ octasx_init(&asx_aa, &port_sc->sc_port_asx);
+ break;
+ }
+ case GMX_SGMII_PORT:
+ if (bus_space_map(sc->sc_regt,
+ PCS_BASE(sc->sc_unitno, i), PCS_SIZE, 0,
+ &port_sc->sc_port_pcs_regh))
+ panic("could not map PCS registers");
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+
(void)memset(&gmx_aa, 0, sizeof(gmx_aa));
gmx_aa.ga_regt = aa->aa_bust;
gmx_aa.ga_addr = aa->aa_unit->addr;
gmx_aa.ga_name = "cnmac";
- gmx_aa.ga_portno = i;
+ gmx_aa.ga_portno = port_sc->sc_port_no;
gmx_aa.ga_port_type = sc->sc_port_types[i];
+ gmx_aa.ga_smi = smi;
gmx_aa.ga_gmx = sc;
gmx_aa.ga_gmx_port = port_sc;
- config_found_sm_loc(self, "octgmx", NULL, &gmx_aa,
- octgmx_print, octgmx_submatch);
+ config_found(self, &gmx_aa, octgmx_print);
}
}
@@ -216,41 +277,23 @@ static int
octgmx_print(void *aux, const char *pnp)
{
struct octgmx_attach_args *ga = aux;
- static const char *types[] = {
- [GMX_MII_PORT] = "MII",
- [GMX_GMII_PORT] = "GMII",
- [GMX_RGMII_PORT] = "RGMII"
- };
-
-#if DEBUG
- if (pnp)
- aprint_normal("%s at %s\n", ga->ga_name, pnp);
-#endif
- aprint_normal(": address=0x%016" PRIx64 ": %s\n", ga->ga_addr,
- types[ga->ga_port_type]);
+ aprint_normal(": address=0x%" PRIx64 ": %s\n", ga->ga_addr,
+ octgmx_port_types[ga->ga_port_type]);
return UNCONF;
}
static int
-octgmx_submatch(device_t parent, struct cfdata *cf,
- const int *ldesc, void *aux)
-{
- return config_match(parent, cf, aux);
-}
-
-static int
octgmx_init(struct octgmx_softc *sc)
{
int result = 0;
uint64_t inf_mode;
- /* XXX */
const mips_prid_t cpu_id = mips_options.mips_cpu_id;
inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, GMX0_INF_MODE);
if ((inf_mode & INF_MODE_EN) == 0) {
- aprint_normal("port are disable\n");
+ aprint_normal("ports are disabled\n");
sc->sc_nports = 0;
return 1;
}
@@ -306,6 +349,21 @@ octgmx_init(struct octgmx_softc *sc)
sc->sc_nports = 2;
#endif
break;
+ case MIPS_CN70XX:
+ switch (inf_mode & INF_MODE_MODE) {
+ case INF_MODE_MODE_SGMII:
+ sc->sc_nports = 4;
+ for (int i = 0; i < sc->sc_nports; i++)
+ sc->sc_port_types[i] = GMX_SGMII_PORT;
+ break;
+#ifdef notyet
+ case INF_MODE_MODE_XAUI:
+#endif
+ default:
+ sc->sc_nports = 0;
+ result = 1;
+ }
+ break;
default:
aprint_normal("unsupported octeon model: 0x%x\n", cpu_id);
sc->sc_nports = 0;
@@ -317,7 +375,7 @@ octgmx_init(struct octgmx_softc *sc)
}
/* XXX RGMII specific */
-int
+static int
octgmx_link_enable(struct octgmx_port_softc *sc, int enable)
{
uint64_t prt_cfg;
@@ -344,13 +402,13 @@ octgmx_link_enable(struct octgmx_port_so
int
octgmx_stats_init(struct octgmx_port_softc *sc)
{
- _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0x0ULL);
- _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0x0ULL);
- _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0x0ULL);
- _GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0x0ULL);
- _GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0x0ULL);
- _GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0x0ULL);
- _GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0x0ULL);
+ _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0);
+ _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0);
+ _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0);
+ _GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0);
+ _GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0);
+ _GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0);
+ _GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0);
return 0;
}
@@ -358,42 +416,34 @@ octgmx_stats_init(struct octgmx_port_sof
int
octgmx_tx_stats_rd_clr(struct octgmx_port_softc *sc, int enable)
{
- _GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
+ _GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, enable ? 1 : 0);
return 0;
}
int
octgmx_rx_stats_rd_clr(struct octgmx_port_softc *sc, int enable)
{
- _GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
+ _GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, enable ? 1 : 0);
return 0;
}
-void
-octgmx_rx_stats_dec_bad(struct octgmx_port_softc *sc)
-{
- uint64_t tmp;
-
- tmp = _GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_BAD);
- _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, tmp - 1);
-}
-
static int
octgmx_tx_ovr_bp_enable(struct octgmx_port_softc *sc, int enable)
{
uint64_t ovr_bp;
+ int index = GMX_PORT_INDEX(sc->sc_port_no);
ovr_bp = _GMX_RD8(sc, GMX0_TX_OVR_BP);
if (enable) {
- CLR(ovr_bp, __SHIFTIN(__BIT(sc->sc_port_no), TX_OVR_BP_EN));
- SET(ovr_bp, __SHIFTIN(__BIT(sc->sc_port_no), TX_OVR_BP_BP));
+ CLR(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_EN));
+ SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_BP));
/* XXX really??? */
- SET(ovr_bp, __SHIFTIN(__BIT(sc->sc_port_no), TX_OVR_BP_IGN_FULL));
+ SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_IGN_FULL));
} else {
- SET(ovr_bp, __SHIFTIN(__BIT(sc->sc_port_no), TX_OVR_BP_EN));
- CLR(ovr_bp, __SHIFTIN(__BIT(sc->sc_port_no), TX_OVR_BP_BP));
+ SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_EN));
+ CLR(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_BP));
/* XXX really??? */
- SET(ovr_bp, __SHIFTIN(__BIT(sc->sc_port_no), TX_OVR_BP_IGN_FULL));
+ SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_IGN_FULL));
}
_GMX_WR8(sc, GMX0_TX_OVR_BP, ovr_bp);
return 0;
@@ -411,7 +461,7 @@ octgmx_rx_pause_enable(struct octgmx_por
return 0;
}
-void
+static void
octgmx_tx_int_enable(struct octgmx_port_softc *sc, int enable)
{
uint64_t tx_int_xxx = 0;
@@ -426,7 +476,7 @@ octgmx_tx_int_enable(struct octgmx_port_
_GMX_WR8(sc, GMX0_TX_INT_EN, enable ? tx_int_xxx : 0);
}
-void
+static void
octgmx_rx_int_enable(struct octgmx_port_softc *sc, int enable)
{
uint64_t rx_int_xxx = 0;
@@ -455,21 +505,20 @@ octgmx_rx_int_enable(struct octgmx_port_
_GMX_PORT_WR8(sc, GMX0_RX0_INT_EN, enable ? rx_int_xxx : 0);
}
-int
+static int
octgmx_rx_frm_ctl_enable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl)
{
- /*
- * XXX Jumbo-frame Workarounds
- * Current implementation of cnmac is required to
- * configure GMX0_RX0_JABBER[CNT] as follows:
- * RX0_FRM_MAX(1536) <= GMX0_RX0_JABBER <= 1536(0x600)
- */
- _GMX_PORT_WR8(sc, GMX0_RX0_JABBER, GMX_FRM_MAX_SIZ);
+ struct ifnet *ifp = &sc->sc_port_ec->ec_if;
+ unsigned int maxlen;
+
+ maxlen = roundup(ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
+ ETHER_VLAN_ENCAP_LEN, 8);
+ _GMX_PORT_WR8(sc, GMX0_RX0_JABBER, maxlen);
return octgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 1);
}
-int
+static int
octgmx_rx_frm_ctl_disable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl)
{
return octgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 0);
@@ -491,7 +540,7 @@ octgmx_rx_frm_ctl_xable(struct octgmx_po
return 0;
}
-int
+static int
octgmx_tx_thresh(struct octgmx_port_softc *sc, int cnt)
{
_GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt);
@@ -499,19 +548,145 @@ octgmx_tx_thresh(struct octgmx_port_soft
}
int
-octgmx_set_mac_addr(struct octgmx_port_softc *sc, uint8_t *addr)
+octgmx_set_mac_addr(struct octgmx_port_softc *sc, const uint8_t *addr)
{
- uint64_t mac = 0;
+ uint64_t mac;
+ int i;
ADDR2UINT64(mac, addr);
- (*sc->sc_port_ops->port_ops_set_mac_addr)(sc, addr, mac);
+
+ octgmx_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, octgmx_rx_adr_cam_regs[i], addr[i]);
+
+ octgmx_link_enable(sc, 1);
+
return 0;
}
int
octgmx_set_filter(struct octgmx_port_softc *sc)
{
- (*sc->sc_port_ops->port_ops_set_filter)(sc);
+ struct ethercom *ec = sc->sc_port_ec;
+ struct ifnet *ifp = &ec->ec_if;
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ uint64_t ctl = 0;
+ int multi = 0;
+ uint64_t cam_en = 1; /* enable CAM 0 for self MAC addr */
+
+ octgmx_link_enable(sc, 0);
+
+ if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
+ dprintf("accept broadcast\n");
+ SET(ctl, RXN_ADR_CTL_BCST);
+ }
+ if (ISSET(ifp->if_flags, IFF_PROMISC)) {
+ dprintf("promiscas(reject cam)\n");
+ CLR(ctl, RXN_ADR_CTL_CAM_MODE);
+ } else {
+ dprintf("not promiscas(accept cam)\n");
+ SET(ctl, RXN_ADR_CTL_CAM_MODE);
+ }
+
+ /*
+ * Note first entry is self MAC address; other 7 entires are available
+ * for multicast addresses.
+ */
+
+ ETHER_LOCK(ec);
+ ETHER_FIRST_MULTI(step, ec, enm);
+ while (enm != NULL) {
+ int i;
+
+ dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - "
+ "hi(%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],
+ enm->enm_addrhi[0], enm->enm_addrhi[1],
+ enm->enm_addrhi[2], enm->enm_addrhi[3],
+ enm->enm_addrhi[4], enm->enm_addrhi[5]);
+ if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+ dprintf("all multicast\n");
+ SET(ifp->if_flags, IFF_ALLMULTI);
+ ETHER_UNLOCK(ec);
+ goto setmulti;
+ }
+ multi++;
+
+ /* XXX XXX XXX */
+ if (multi >= 8) {
+ SET(ifp->if_flags, IFF_ALLMULTI);
+ ETHER_UNLOCK(ec);
+ goto setmulti;
+ }
+ /* XXX XXX XXX */
+
+ /* XXX XXX XXX */
+ SET(cam_en, __BIT(multi));
+ /* XXX XXX XXX */
+
+ for (i = 0; i < 6; i++) {
+ uint64_t tmp;
+
+ /* XXX XXX XXX */
+ tmp = _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i]);
+ CLR(tmp, 0xffULL << (8 * multi));
+ SET(tmp, (uint64_t)enm->enm_addrlo[i] << (8 * multi));
+ _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[i], tmp);
+ /* XXX XXX XXX */
+
+ }
+ for (i = 0; i < 6; i++)
+ dprintf("cam%d = 0x%016lx\n", i,
+ _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i]));
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ ETHER_UNLOCK(ec);
+ CLR(ifp->if_flags, IFF_ALLMULTI);
+
+ CNMAC_KASSERT(enm == NULL);
+
+setmulti:
+ /* XXX XXX XXX */
+ if (ISSET(ifp->if_flags, IFF_ALLMULTI) ||
+ ISSET(ifp->if_flags, IFF_PROMISC)) {
+ /* XXX XXX XXX */
+ dprintf("accept all multicast\n");
+ ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_ACCEPT, RXN_ADR_CTL_MCST);
+ /* XXX XXX XXX */
+ } else if (multi) {
+ /* XXX XXX XXX */
+ dprintf("use cam\n");
+ ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_AFCAM, RXN_ADR_CTL_MCST);
+ /* XXX XXX XXX */
+ } else {
+ /* XXX XXX XXX */
+ dprintf("reject all multicast\n");
+ ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_REJECT, RXN_ADR_CTL_MCST);
+ /* XXX XXX XXX */
+ }
+ /* XXX XXX XXX */
+
+ /* XXX XXX XXX */
+ if (ISSET(ifp->if_flags, IFF_PROMISC)) {
+ cam_en = 0x00ULL;
+ } else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) {
+ cam_en = 0x01ULL;
+ }
+ /* XXX XXX XXX */
+
+ dprintf("ctl = %#lx, cam_en = %#lx\n", ctl, cam_en);
+ _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
+ _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
+
+ octgmx_link_enable(sc, 1);
+
return 0;
}
@@ -623,8 +798,6 @@ octgmx_rgmii_speed(struct octgmx_port_so
}
ifp->if_baudrate = baudrate;
- /* XXX XXX XXX */
-
octgmx_link_enable(sc, 0);
/*
@@ -644,30 +817,10 @@ octgmx_rgmii_speed(struct octgmx_port_so
static int
octgmx_rgmii_speed_newlink(struct octgmx_port_softc *sc, uint64_t *rnewlink)
{
- uint64_t newlink = 0;
+ uint64_t newlink;
- if (sc->sc_quirks & CNMAC_QUIRKS_NO_RX_INBND) {
- newlink = 0;
- switch (IFM_SUBTYPE(sc->sc_port_mii->mii_media_active)) {
- default:
- SET(newlink, RXN_RX_INBND_SPEED_125);
- break;
- case IFM_100_TX:
- SET(newlink, RXN_RX_INBND_SPEED_25);
- break;
- case IFM_10_T:
- SET(newlink, RXN_RX_INBND_SPEED_2_5);
- break;
- }
- SET(newlink,
- ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX) ?
- RXN_RX_INBND_DUPLEX : 0);
- SET(newlink,
- ISSET(sc->sc_port_mii->mii_media_status, IFM_ACTIVE) ?
- RXN_RX_INBND_STATUS : 0);
- } else {
- newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
- }
+ /* Inband status does not seem to work */
+ newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
*rnewlink = newlink;
return 0;
@@ -833,8 +986,6 @@ octgmx_rgmii_timing(struct octgmx_port_s
RXN_FRM_CTL_CTL_DRP |
RXN_FRM_CTL_PRE_STRP |
RXN_FRM_CTL_PRE_CHK;
- if (!(sc->sc_quirks & CNMAC_QUIRKS_NO_PRE_ALIGN))
- rx_frm_ctl |= RXN_FRM_CTL_PRE_ALIGN;
octgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
/* RGMII RX Clock-Delay Registers
@@ -855,158 +1006,148 @@ octgmx_rgmii_timing(struct octgmx_port_s
}
static int
-octgmx_rgmii_set_mac_addr(struct octgmx_port_softc *sc, uint8_t *addr,
- uint64_t mac)
+octgmx_sgmii_enable(struct octgmx_port_softc *sc, int enable)
{
+ uint64_t ctl_reg, status, timer_count;
+ uint64_t cpu_freq_mhz = curcpu()->ci_cpu_freq / 1000000;
+ int done;
int i;
- octgmx_link_enable(sc, 0);
+ if (!enable)
+ return 0;
- sc->sc_mac = mac;
- _GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
- for (i = 0; i < 6; i++)
- _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[i], addr[i]);
+ /* Set link timer interval to 1.6ms. Timer multiple is 1024 (2^10). */
+ /*
+ * XXX Should set timer to 10ms if not in SGMII mode (ie,
+ * "cavium,sgmii-mac-1000x-mode" property exists
+ */
+ timer_count = PCS_READ_8(sc, PCS_LINK_TIMER_COUNT);
+ CLR(timer_count, PCS_LINK_TIMER_COUNT_MASK);
+ SET(timer_count,
+ __SHIFTIN((1600 * cpu_freq_mhz) >> 10, PCS_LINK_TIMER_COUNT_MASK));
+ PCS_WRITE_8(sc, PCS_LINK_TIMER_COUNT, timer_count);
+
+ /* Reset the PCS. */
+ ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
+ SET(ctl_reg, PCS_MR_CONTROL_RESET);
+ PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
+
+ /* Wait for the reset to complete. */
+ done = 0;
+ for (i = 0; i < 1000000; i++) {
+ ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL);
+ if (!ISSET(ctl_reg, PCS_MR_CONTROL_RESET)) {
+ done = 1;
+ break;
+ }
+ }
+ if (!done) {
+ printf("SGMII reset timeout on port %d\n", sc->sc_port_no);
+ return 1;
+ }
- octgmx_link_enable(sc, 1);
+ /* Start a new SGMII autonegotiation. */
+ SET(ctl_reg, PCS_MR_CONTROL_AN_EN);
+ SET(ctl_reg, PCS_MR_CONTROL_RST_AN);
+ CLR(ctl_reg, PCS_MR_CONTROL_PWR_DN);
+ PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg);
+
+ /* Wait for the SGMII autonegotiation to complete. */
+ done = 0;
+ for (i = 0; i < 1000000; i++) {
+ status = PCS_READ_8(sc, PCS_MR_STATUS);
+ if (ISSET(status, PCS_MR_STATUS_AN_CPT)) {
+ done = 1;
+ break;
+ }
+ }
+ if (!done) {
+ printf("SGMII autonegotiation timeout on port %d\n",
+ sc->sc_port_no);
+ return 1;
+ }
return 0;
}
-#define CNMAC_USE_GMX_CAM
-
static int
-octgmx_rgmii_set_filter(struct octgmx_port_softc *sc)
+octgmx_sgmii_speed(struct octgmx_port_softc *sc)
{
- struct ethercom *ec = sc->sc_port_ec;
- struct ifnet *ifp = &ec->ec_if;
-#ifdef CNMAC_USE_GMX_CAM
- struct ether_multi *enm;
- struct ether_multistep step;
-#endif
- uint64_t ctl = 0;
- int multi = 0;
- /* XXX XXX XXX */
- uint64_t cam_en = 0x01ULL;
- /* XXX XXX XXX */
+ uint64_t misc_ctl, prt_cfg;
+ int tx_burst, tx_slot;
octgmx_link_enable(sc, 0);
- if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
- dprintf("accept broadcast\n");
- SET(ctl, RXN_ADR_CTL_BCST);
- }
- if (ISSET(ifp->if_flags, IFF_PROMISC)) {
- dprintf("promiscas(reject cam)\n");
- CLR(ctl, RXN_ADR_CTL_CAM_MODE);
- } else {
- dprintf("not promiscas(accept cam)\n");
- SET(ctl, RXN_ADR_CTL_CAM_MODE);
- }
-
-#ifdef CNMAC_USE_GMX_CAM
- /*
- * Note first entry is self MAC address; other 7 entires are available
- * for multicast addresses.
- */
+ prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
- ETHER_LOCK(ec);
- ETHER_FIRST_MULTI(step, ec, enm);
- while (enm != NULL) {
- int i;
+ if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX))
+ SET(prt_cfg, PRTN_CFG_DUPLEX);
+ else
+ CLR(prt_cfg, PRTN_CFG_DUPLEX);
- dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - "
- "hi(%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],
- enm->enm_addrhi[0], enm->enm_addrhi[1],
- enm->enm_addrhi[2], enm->enm_addrhi[3],
- enm->enm_addrhi[4], enm->enm_addrhi[5]);
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
- dprintf("all multicast\n");
- SET(ifp->if_flags, IFF_ALLMULTI);
- ETHER_UNLOCK(ec);
- goto setmulti;
- }
- multi++;
+ misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL);
+ CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT);
- /* XXX XXX XXX */
- if (multi >= 8) {
- SET(ifp->if_flags, IFF_ALLMULTI);
- ETHER_UNLOCK(ec);
- goto setmulti;
- }
- /* XXX XXX XXX */
+ /* Disable the GMX port if the link is down. */
+ if (octgmx_link_status(sc))
+ CLR(misc_ctl, PCS_MISC_CTL_GMXENO);
+ else
+ SET(misc_ctl, PCS_MISC_CTL_GMXENO);
- /* XXX XXX XXX */
- SET(cam_en, __BIT(multi));
- /* XXX XXX XXX */
+ switch (sc->sc_port_ec->ec_if.if_baudrate) {
+ case IF_Mbps(10):
+ tx_slot = 0x40;
+ tx_burst = 0;
+ CLR(prt_cfg, PRTN_CFG_SPEED);
+ SET(prt_cfg, PRTN_CFG_SPEED_MSB);
+ CLR(prt_cfg, PRTN_CFG_SLOTTIME);
+ misc_ctl |= 25 & PCS_MISC_CTL_SAMP_PT;
+ break;
+ case IF_Mbps(100):
+ tx_slot = 0x40;
+ tx_burst = 0;
+ CLR(prt_cfg, PRTN_CFG_SPEED);
+ CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
+ CLR(prt_cfg, PRTN_CFG_SLOTTIME);
+ misc_ctl |= 5 & PCS_MISC_CTL_SAMP_PT;
+ break;
+ case IF_Gbps(1):
+ default:
+ tx_slot = 0x200;
+ tx_burst = 0x2000;
+ SET(prt_cfg, PRTN_CFG_SPEED);
+ CLR(prt_cfg, PRTN_CFG_SPEED_MSB);
+ SET(prt_cfg, PRTN_CFG_SLOTTIME);
+ misc_ctl |= 1 & PCS_MISC_CTL_SAMP_PT;
+ break;
+ }
- for (i = 0; i < 6; i++) {
- uint64_t tmp;
+ PCS_WRITE_8(sc, PCS_MISC_CTL, misc_ctl);
- /* XXX XXX XXX */
- tmp = _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i]);
- CLR(tmp, 0xffULL << (8 * multi));
- SET(tmp, (uint64_t)enm->enm_addrlo[i] << (8 * multi));
- _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[i], tmp);
- /* XXX XXX XXX */
-
- }
- for (i = 0; i < 6; i++)
- dprintf("cam%d = %016llx\n", i,
- _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i]));
- ETHER_NEXT_MULTI(step, enm);
- }
- ETHER_UNLOCK(ec);
- CLR(ifp->if_flags, IFF_ALLMULTI);
+ _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
+ _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
+ _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
- CNMAC_KASSERT(enm == NULL);
-#else
- /*
- * XXX
- * Never use DMAC filter for multicast addresses, but register only
- * single entry for self address. FreeBSD code do so.
- */
- SET(ifp->if_flags, IFF_ALLMULTI);
- goto setmulti;
-#endif
+ octgmx_link_enable(sc, 1);
-setmulti:
- /* XXX XXX XXX */
- if (ISSET(ifp->if_flags, IFF_ALLMULTI) ||
- ISSET(ifp->if_flags, IFF_PROMISC)) {
- /* XXX XXX XXX */
- dprintf("accept all multicast\n");
- ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_ACCEPT, RXN_ADR_CTL_MCST);
- /* XXX XXX XXX */
- } else if (multi) {
- /* XXX XXX XXX */
- dprintf("use cam\n");
- ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_AFCAM, RXN_ADR_CTL_MCST);
- /* XXX XXX XXX */
- } else {
- /* XXX XXX XXX */
- dprintf("reject all multicast\n");
- ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_REJECT, RXN_ADR_CTL_MCST);
- /* XXX XXX XXX */
- }
- /* XXX XXX XXX */
+ return 0;
+}
- /* XXX XXX XXX */
- if (ISSET(ifp->if_flags, IFF_PROMISC)) {
- cam_en = 0x00ULL;
- } else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) {
- cam_en = 0x01ULL;
- }
- /* XXX XXX XXX */
+static int
+octgmx_sgmii_timing(struct octgmx_port_softc *sc)
+{
+ uint64_t rx_frm_ctl;
- dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en);
- _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
- _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
+ octgmx_tx_thresh(sc, 32);
- octgmx_link_enable(sc, 1);
+ rx_frm_ctl =
+ RXN_FRM_CTL_PRE_FREE |
+ RXN_FRM_CTL_CTL_SMAC |
+ RXN_FRM_CTL_CTL_MCST |
+ RXN_FRM_CTL_CTL_DRP |
+ RXN_FRM_CTL_PRE_STRP |
+ RXN_FRM_CTL_PRE_CHK;
+ octgmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
return 0;
}
@@ -1045,98 +1186,3 @@ octgmx_stats(struct octgmx_port_softc *s
if_statadd_ref(nsr, if_oerrors, (uint32_t)(tmp >> 32));
IF_STAT_PUTREF(ifp);
}
-
-/* ---- DMAC filter */
-
-#ifdef notyet
-/*
- * DMAC filter configuration
- * accept all
- * reject 0 addrs (virtually accept all?)
- * reject N addrs
- * accept N addrs
- * accept 0 addrs (virtually reject all?)
- * reject all
- */
-
-/* XXX local namespace */
-#define _POLICY OCTEON_GMX_FILTER_POLICY
-#define _POLICY_ACCEPT_ALL OCTEON_GMX_FILTER_POLICY_ACCEPT_ALL
-#define _POLICY_ACCEPT OCTEON_GMX_FILTER_POLICY_ACCEPT
-#define _POLICY_REJECT OCTEON_GMX_FILTER_POLICY_REJECT
-#define _POLICY_REJECT_ALL OCTEON_GMX_FILTER_POLICY_REJECT_ALL
-
-static int octgmx_setfilt_addrs(struct octgmx_port_softc *, size_t,
- uint8_t **);
-
-int
-octgmx_setfilt(struct octgmx_port_softc *sc, enum _POLICY policy, size_t naddrs,
- uint8_t **addrs)
-{
- uint64_t rx_adr_ctl;
-
- KASSERT(policy >= _POLICY_ACCEPT_ALL);
- KASSERT(policy <= _POLICY_REJECT_ALL);
-
- rx_adr_ctl = _GMX_PORT_RD8(sc, GMX0_RX0_ADR_CTL);
- CLR(rx_adr_ctl, RXN_ADR_CTL_CAM_MODE | RXN_ADR_CTL_MCST);
-
- switch (policy) {
- case _POLICY_ACCEPT_ALL:
- case _POLICY_REJECT_ALL:
- KASSERT(naddrs == 0);
- KASSERT(addrs == NULL);
-
- SET(rx_adr_ctl,
- __SHIFTIN((policy == _POLICY_ACCEPT_ALL) ?
- RXN_ADR_CTL_MCST_ACCEPT : RXN_ADR_CTL_MCST_REJECT),
- RXN_ADR_CTL_MCST);
- break;
- case _POLICY_ACCEPT:
- case _POLICY_REJECT:
- if (naddrs > OCTEON_GMX_FILTER_NADDRS_MAX)
- return E2BIG;
- SET(rx_adr_ctl, (policy == _POLICY_ACCEPT) ?
- RXN_ADR_CTL_CAM_MODE : 0);
- SET(rx_adr_ctl,
- __SHIFTIN(RXN_ADR_CTL_MCST_AFCAM, RXN_ADR_CTL_MCST);
- /* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
- octgmx_setfilt_addrs(sc, naddrs, addrs);
- break;
- }
-
- /* set GMX0_RXN_ADR_CTL[MCST] */
- _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, rx_adr_ctl);
-
- return 0;
-}
-
-static int
-octgmx_setfilt_addrs(struct octgmx_port_softc *sc, size_t naddrs,
- uint8_t **addrs)
-{
- uint64_t rx_adr_cam_en;
- uint64_t rx_adr_cam_addrs[OCTEON_GMX_FILTER_NADDRS_MAX];
- int i, j;
-
- KASSERT(naddrs <= OCTEON_GMX_FILTER_NADDRS_MAX);
-
- rx_adr_cam_en = 0;
- (void)memset(rx_adr_cam_addrs, 0, sizeof(rx_adr_cam_addrs));
-
- for (i = 0; i < naddrs; i++) {
- SET(rx_adr_cam_en, __BIT(i));
- for (j = 0; j < 6; j++)
- SET(rx_adr_cam_addrs[j],
- (uint64_t)addrs[i][j] << (8 * i));
- }
-
- /* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
- _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, rx_adr_cam_en);
- for (j = 0; j < 6; j++)
- _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[j],
- rx_adr_cam_addrs[j]);
-
- return 0;
-}
-#endif
Index: src/sys/arch/mips/cavium/dev/octeon_gmxreg.h
diff -u src/sys/arch/mips/cavium/dev/octeon_gmxreg.h:1.4 src/sys/arch/mips/cavium/dev/octeon_gmxreg.h:1.5
--- src/sys/arch/mips/cavium/dev/octeon_gmxreg.h:1.4 Mon Jun 22 12:26:11 2020
+++ src/sys/arch/mips/cavium/dev/octeon_gmxreg.h Tue Jun 23 05:17:13 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: octeon_gmxreg.h,v 1.4 2020/06/22 12:26:11 simonb Exp $ */
+/* $NetBSD: octeon_gmxreg.h,v 1.5 2020/06/23 05:17:13 simonb Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -169,7 +169,9 @@
/* GMX Port Configuration Registers */
-#define PRTN_CFG_XXX_63_4 UINT64_C(0xfffffffffffffff0)
+#define PRTN_CFG_XXX_63_9 UINT64_C(0xfffffffffffffe00)
+#define PRTN_CFG_SPEED_MSB UINT64_C(0x0000000000000100)
+#define PRTN_CFG_XXX_7_4 UINT64_C(0x00000000000000f0)
#define PRTN_CFG_SLOTTIME UINT64_C(0x0000000000000008)
#define PRTN_CFG_DUPLEX UINT64_C(0x0000000000000004)
#define PRTN_CFG_SPEED UINT64_C(0x0000000000000002)
@@ -611,19 +613,87 @@
#define INF_MODE_P0MII UINT64_C(0x0000000000000004)
#define INF_MODE_EN UINT64_C(0x0000000000000002)
#define INF_MODE_TYPE UINT64_C(0x0000000000000001)
+/* Interface mode, applicable on CN68xx and CN7xxx (?) */
+#define INF_MODE_MODE UINT64_C(0x0000000000000070)
+#define INF_MODE_MODE_SGMII UINT64_C(0x0000000000000020)
+#define INF_MODE_MODE_XAUI UINT64_C(0x0000000000000030)
+
+#define MIO_QLM_CFG(x) (UINT64_C(0x0001180000001590) + (x)*8)
+
+#define MIO_QLM_CFG_CFG UINT64_C(0x000000000000000f)
/* -------------------------------------------------------------------------- */
/* for bus_space(9) */
-#define GMX_IF_NUNITS 1
-#define GMX_PORT_NUNITS 3
+#define GMX_PORT_NUNITS (5 * 16)
+#define GMX_PORT_NUM(g, i) ((g) * 16 + (i))
+#define GMX_PORT_IFACE(port) ((port) / 16)
+#define GMX_PORT_INDEX(port) ((port) % 16)
+
+#define GMX_BLOCK_SIZE 0x8000000
+#define GMX_CN68XX_BLOCK_SIZE 0x100000 /* different on CN68XX only */
+
+#define GMX0_BASE_PORT0 UINT64_C(0x0001180008000000)
+#define GMX_PORT_SIZE 0x800
+#define GMX_IF_SIZE(n) (GMX_PORT_SIZE * (n))
+#define GMX_BASE_PORT(n, m) /* address of GMX(n) * PORT(m) */ \
+ (GMX0_BASE_PORT0 + (n) * GMX_BLOCK_SIZE + GMX_IF_SIZE(m))
+#define GMX_CN68XX_BASE_PORT(n, m) /* address of GMX(n) * PORT(m) */ \
+ (GMX0_BASE_PORT0 + (n) * GMX_CN68XX_BLOCK_SIZE + GMX_IF_SIZE(m))
+
+/* -------------------------------------------------------------------------- */
+
+/* Low-level SGMII link controll */
+
+#define PCS_BASE(g, i) (UINT64_C(0x00011800b0001000) + 0x8000000 * (g) + 0x400 * (i))
+#define PCS_SIZE 0x98
-#define GMX0_BASE_PORT0 0x0001180008000000ULL
-#define GMX0_BASE_PORT1 0x0001180008000800ULL
-#define GMX0_BASE_PORT2 0x0001180008001000ULL
-#define GMX0_BASE_PORT_SIZE 0x00800
-#define GMX0_BASE_IF0 0x0001180008000000ULL
-#define GMX0_BASE_IF_SIZE (GMX0_BASE_PORT_SIZE * GMX_PORT_NUNITS)
+#define PCS_MR_CONTROL 0x00
+#define PCS_MR_STATUS 0x08
+#define PCS_LINK_TIMER_COUNT 0x40
+#define PCS_MISC_CTL 0x78
+
+#define PCS_MR_CONTROL_RES_16_63 UINT64_C(0xffffffffffff0000)
+#define PCS_MR_CONTROL_RESET UINT64_C(0x0000000000008000)
+#define PCS_MR_CONTROL_LOOPBCK1 UINT64_C(0x0000000000004000)
+#define PCS_MR_CONTROL_SPDLSB UINT64_C(0x0000000000002000)
+#define PCS_MR_CONTROL_AN_EN UINT64_C(0x0000000000001000)
+#define PCS_MR_CONTROL_PWR_DN UINT64_C(0x0000000000000800)
+#define PCS_MR_CONTROL_RES_10_10 UINT64_C(0x0000000000000400)
+#define PCS_MR_CONTROL_RST_AN UINT64_C(0x0000000000000200)
+#define PCS_MR_CONTROL_DUPLEX UINT64_C(0x0000000000000100)
+#define PCS_MR_CONTROL_COLTST UINT64_C(0x0000000000000080)
+#define PCS_MR_CONTROL_SPDMSB UINT64_C(0x0000000000000040)
+#define PCS_MR_CONTROL_UNI UINT64_C(0x0000000000000020)
+#define PCS_MR_CONTROL_RES_0_4 UINT64_C(0x000000000000001f)
+
+#define PCS_MR_STATUS_RES_16_63 UINT64_C(0xffffffffffff0000)
+#define PCS_MR_STATUS_HUN_T4 UINT64_C(0x0000000000008000)
+#define PCS_MR_STATUS_HUN_XFD UINT64_C(0x0000000000004000)
+#define PCS_MR_STATUS_HUN_XHD UINT64_C(0x0000000000002000)
+#define PCS_MR_STATUS_TEN_FD UINT64_C(0x0000000000001000)
+#define PCS_MR_STATUS_TEN_HD UINT64_C(0x0000000000000800)
+#define PCS_MR_STATUS_HUN_T2FD UINT64_C(0x0000000000000400)
+#define PCS_MR_STATUS_HUN_T2HD UINT64_C(0x0000000000000200)
+#define PCS_MR_STATUS_EXT_ST UINT64_C(0x0000000000000100)
+#define PCS_MR_STATUS_RES_7_7 UINT64_C(0x0000000000000080)
+#define PCS_MR_STATUS_PRB_SUP UINT64_C(0x0000000000000040)
+#define PCS_MR_STATUS_AN_CPT UINT64_C(0x0000000000000020)
+#define PCS_MR_STATUS_RM_FLT UINT64_C(0x0000000000000010)
+#define PCS_MR_STATUS_AN_ABIL UINT64_C(0x0000000000000008)
+#define PCS_MR_STATUS_LNK_ST UINT64_C(0x0000000000000004)
+#define PCS_MR_STATUS_RES_1_1 UINT64_C(0x0000000000000002)
+#define PCS_MR_STATUS_EXTND UINT64_C(0x0000000000000001)
+
+#define PCS_LINK_TIMER_COUNT_MASK UINT64_C(0x000000000000ffff)
+
+#define PCS_MISC_CTL_SGMII UINT64_C(0x0000000000001000)
+#define PCS_MISC_CTL_GMXENO UINT64_C(0x0000000000000800)
+#define PCS_MISC_CTL_LOOPBCK2 UINT64_C(0x0000000000000400)
+#define PCS_MISC_CTL_MAC_PHY UINT64_C(0x0000000000000200)
+#define PCS_MISC_CTL_MODE UINT64_C(0x0000000000000100)
+#define PCS_MISC_CTL_AN_OVRD UINT64_C(0x0000000000000080)
+#define PCS_MISC_CTL_SAMP_PT UINT64_C(0x000000000000007f)
#endif /* _OCTEON_GMXREG_H_ */
Index: src/sys/arch/mips/cavium/dev/octeon_gmxvar.h
diff -u src/sys/arch/mips/cavium/dev/octeon_gmxvar.h:1.6 src/sys/arch/mips/cavium/dev/octeon_gmxvar.h:1.7
--- src/sys/arch/mips/cavium/dev/octeon_gmxvar.h:1.6 Mon Jun 22 02:26:20 2020
+++ src/sys/arch/mips/cavium/dev/octeon_gmxvar.h Tue Jun 23 05:17:13 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: octeon_gmxvar.h,v 1.6 2020/06/22 02:26:20 simonb Exp $ */
+/* $NetBSD: octeon_gmxvar.h,v 1.7 2020/06/23 05:17:13 simonb Exp $ */
/*
* Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -29,8 +29,6 @@
#ifndef _OCTEON_GMXVAR_H_
#define _OCTEON_GMXVAR_H_
-#include "opt_octeon.h"
-
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_ether.h>
@@ -40,7 +38,8 @@
#define GMX_MII_PORT 1
#define GMX_GMII_PORT 2
#define GMX_RGMII_PORT 3
-#define GMX_SPI42_PORT 4
+#define GMX_SGMII_PORT 4
+#define GMX_SPI42_PORT 5
#define GMX_FRM_MAX_SIZ 0x600
@@ -66,6 +65,7 @@ struct octgmx_port_softc {
struct octgmx_port_ops
*sc_port_ops;
struct octasx_softc *sc_port_asx;
+ bus_space_handle_t sc_port_pcs_regh;
struct octipd_softc *sc_ipd;
int sc_port_flowflags;
@@ -93,50 +93,31 @@ struct octgmx_attach_args {
const char *ga_name;
int ga_portno;
int ga_port_type;
+ struct octsmi_softc *ga_smi;
struct octgmx_softc *ga_gmx;
struct octgmx_port_softc
*ga_gmx_port;
};
-#define OCTEON_GMX_FILTER_NADDRS_MAX 8 /* XXX elsewhere */
-
-enum OCTEON_GMX_FILTER_POLICY {
- OCTEON_GMX_FILTER_POLICY_ACCEPT_ALL,
- OCTEON_GMX_FILTER_POLICY_ACCEPT,
- OCTEON_GMX_FILTER_POLICY_REJECT,
- OCTEON_GMX_FILTER_POLICY_REJECT_ALL
-};
-
-int octgmx_link_enable(struct octgmx_port_softc *, int);
-int octgmx_tx_stats_rd_clr(struct octgmx_port_softc *, int);
-int octgmx_rx_stats_rd_clr(struct octgmx_port_softc *, int);
-void octgmx_rx_stats_dec_bad(struct octgmx_port_softc *);
+int octgmx_port_enable(struct octgmx_port_softc *, int);
int octgmx_stats_init(struct octgmx_port_softc *);
-void octgmx_tx_int_enable(struct octgmx_port_softc *, int);
-void octgmx_rx_int_enable(struct octgmx_port_softc *, int);
-int octgmx_setfilt(struct octgmx_port_softc *,
- enum OCTEON_GMX_FILTER_POLICY, size_t, uint8_t **);
-int octgmx_rx_frm_ctl_enable(struct octgmx_port_softc *, uint64_t);
-int octgmx_rx_frm_ctl_disable(struct octgmx_port_softc *, uint64_t);
-int octgmx_tx_thresh(struct octgmx_port_softc *, int);
-int octgmx_set_mac_addr(struct octgmx_port_softc *, uint8_t *);
+void octgmx_stats(struct octgmx_port_softc *);
+int octgmx_set_mac_addr(struct octgmx_port_softc *, const uint8_t *);
int octgmx_set_filter(struct octgmx_port_softc *);
-int octgmx_port_enable(struct octgmx_port_softc *, int);
+int octgmx_tx_stats_rd_clr(struct octgmx_port_softc *, int);
+int octgmx_rx_stats_rd_clr(struct octgmx_port_softc *, int);
int octgmx_reset_speed(struct octgmx_port_softc *);
int octgmx_reset_flowctl(struct octgmx_port_softc *);
int octgmx_reset_timing(struct octgmx_port_softc *);
-int octgmx_reset_board(struct octgmx_port_softc *);
-void octgmx_stats(struct octgmx_port_softc *);
-uint64_t octgmx_get_rx_int_reg(struct octgmx_port_softc *sc);
-uint64_t octgmx_get_tx_int_reg(struct octgmx_port_softc *sc);
static __inline int octgmx_link_status(struct octgmx_port_softc *);
-/* XXX RGMII specific */
static __inline int
octgmx_link_status(struct octgmx_port_softc *sc)
{
- return (sc->sc_link & RXN_RX_INBND_STATUS) ? 1 : 0;
+
+ return ((sc->sc_port_mii->mii_media_status & (IFM_AVALID | IFM_ACTIVE))
+ == (IFM_AVALID | IFM_ACTIVE));
}
#endif /* _OCTEON_GMXVAR_H_ */