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_ */