rge.c revision 208265
1198157Srrs/*- 2198157Srrs * Copyright (c) 2003-2009 RMI Corporation 3198157Srrs * All rights reserved. 4198157Srrs * 5198157Srrs * Redistribution and use in source and binary forms, with or without 6198157Srrs * modification, are permitted provided that the following conditions 7198157Srrs * are met: 8198157Srrs * 1. Redistributions of source code must retain the above copyright 9198157Srrs * notice, this list of conditions and the following disclaimer. 10198157Srrs * 2. Redistributions in binary form must reproduce the above copyright 11198157Srrs * notice, this list of conditions and the following disclaimer in the 12198157Srrs * documentation and/or other materials provided with the distribution. 13198157Srrs * 3. Neither the name of RMI Corporation, nor the names of its contributors, 14198157Srrs * may be used to endorse or promote products derived from this software 15198157Srrs * without specific prior written permission. 16198157Srrs * 17198157Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18198157Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19198157Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20198157Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21198157Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22198157Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23198157Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24198157Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25198157Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26198157Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27198157Srrs * SUCH DAMAGE. 28198157Srrs * 29202066Simp * RMI_BSD 30202066Simp */ 31198157Srrs 32202066Simp#include <sys/cdefs.h> 33202066Simp__FBSDID("$FreeBSD: head/sys/mips/rmi/dev/xlr/rge.c 208265 2010-05-18 17:01:07Z rpaulo $"); 34202066Simp 35198157Srrs#ifdef HAVE_KERNEL_OPTION_HEADERS 36198157Srrs#include "opt_device_polling.h" 37198157Srrs#endif 38198157Srrs 39198157Srrs#include <sys/types.h> 40198157Srrs#include <sys/endian.h> 41198157Srrs#include <sys/systm.h> 42198157Srrs#include <sys/sockio.h> 43198157Srrs#include <sys/param.h> 44198157Srrs#include <sys/lock.h> 45198157Srrs#include <sys/mutex.h> 46198157Srrs#include <sys/proc.h> 47198157Srrs#include <sys/limits.h> 48198157Srrs#include <sys/bus.h> 49198157Srrs#include <sys/mbuf.h> 50198157Srrs#include <sys/malloc.h> 51198157Srrs#include <sys/kernel.h> 52198157Srrs#include <sys/module.h> 53198157Srrs#include <sys/socket.h> 54198157Srrs#define __RMAN_RESOURCE_VISIBLE 55198157Srrs#include <sys/rman.h> 56198157Srrs#include <sys/taskqueue.h> 57208165Srrs#include <sys/smp.h> 58198157Srrs 59198157Srrs#include <net/if.h> 60198157Srrs#include <net/if_arp.h> 61198157Srrs#include <net/ethernet.h> 62198157Srrs#include <net/if_dl.h> 63198157Srrs#include <net/if_media.h> 64198157Srrs 65198157Srrs#include <net/bpf.h> 66198157Srrs 67198157Srrs#include <net/if_types.h> 68198157Srrs#include <net/if_vlan_var.h> 69198157Srrs 70198157Srrs#include <netinet/in_systm.h> 71198157Srrs#include <netinet/in.h> 72198157Srrs#include <netinet/ip.h> 73198157Srrs 74198157Srrs#include <vm/vm.h> 75198157Srrs#include <vm/pmap.h> 76198157Srrs 77198157Srrs#include <machine/reg.h> 78198157Srrs#include <machine/cpu.h> 79198157Srrs#include <machine/mips_opcode.h> 80198157Srrs#include <machine/asm.h> 81198789Srrs#include <mips/rmi/rmi_mips_exts.h> 82198157Srrs#include <machine/cpuregs.h> 83198157Srrs 84198157Srrs#include <machine/param.h> 85198157Srrs#include <machine/intr_machdep.h> 86198157Srrs#include <machine/clock.h> /* for DELAY */ 87208165Srrs#include <machine/cpuregs.h> 88198626Srrs#include <machine/bus.h> /* */ 89198157Srrs#include <machine/resource.h> 90198608Srrs#include <mips/rmi/interrupt.h> 91198608Srrs#include <mips/rmi/msgring.h> 92198608Srrs#include <mips/rmi/iomap.h> 93198608Srrs#include <mips/rmi/debug.h> 94198608Srrs#include <mips/rmi/pic.h> 95198608Srrs#include <mips/rmi/xlrconfig.h> 96198608Srrs#include <mips/rmi/shared_structs.h> 97198608Srrs#include <mips/rmi/board.h> 98198157Srrs 99202066Simp#include <mips/rmi/dev/xlr/atx_cpld.h> 100202066Simp#include <mips/rmi/dev/xlr/xgmac_mdio.h> 101198157Srrs 102198157Srrs#include <dev/mii/mii.h> 103198157Srrs#include <dev/mii/miivar.h> 104198157Srrs#include <dev/mii/brgphyreg.h> 105198608Srrs 106198157Srrs#include <sys/sysctl.h> 107202092Simp#include <mips/rmi/dev/xlr/rge.h> 108198157Srrs 109198157Srrs/* #include "opt_rge.h" */ 110198157Srrs 111198608Srrs#include "miibus_if.h" 112198608Srrs 113198157SrrsMODULE_DEPEND(rge, ether, 1, 1, 1); 114198157SrrsMODULE_DEPEND(rge, miibus, 1, 1, 1); 115198157Srrs 116198157Srrs/* #define DEBUG */ 117198157Srrs 118198157Srrs#define RGE_TX_THRESHOLD 1024 119198157Srrs#define RGE_TX_Q_SIZE 1024 120198157Srrs 121198157Srrs#ifdef DEBUG 122198157Srrs#undef dbg_msg 123198626Srrsint mac_debug = 1; 124198626Srrs 125198157Srrs#define dbg_msg(fmt, args...) \ 126198157Srrs do {\ 127198157Srrs if (mac_debug) {\ 128198157Srrs printf("[%s@%d|%s]: cpu_%d: " fmt, \ 129198157Srrs __FILE__, __LINE__, __FUNCTION__, PCPU_GET(cpuid), ##args);\ 130198157Srrs }\ 131198157Srrs } while(0); 132198157Srrs 133198157Srrs#define DUMP_PACKETS 134198157Srrs#else 135198157Srrs#undef dbg_msg 136198157Srrs#define dbg_msg(fmt, args...) 137198626Srrsint mac_debug = 0; 138198626Srrs 139198157Srrs#endif 140198157Srrs 141198157Srrs#define MAC_B2B_IPG 88 142198157Srrs 143198157Srrs/* frame sizes need to be cacheline aligned */ 144198157Srrs#define MAX_FRAME_SIZE 1536 145198157Srrs#define MAX_FRAME_SIZE_JUMBO 9216 146198157Srrs 147198157Srrs#define MAC_SKB_BACK_PTR_SIZE SMP_CACHE_BYTES 148198157Srrs#define MAC_PREPAD 0 149198157Srrs#define BYTE_OFFSET 2 150198157Srrs#define XLR_RX_BUF_SIZE (MAX_FRAME_SIZE+BYTE_OFFSET+MAC_PREPAD+MAC_SKB_BACK_PTR_SIZE+SMP_CACHE_BYTES) 151198157Srrs#define MAC_CRC_LEN 4 152198157Srrs#define MAX_NUM_MSGRNG_STN_CC 128 153198157Srrs 154198157Srrs#define MAX_NUM_DESC 1024 155198157Srrs#define MAX_SPILL_SIZE (MAX_NUM_DESC + 128) 156198157Srrs 157198157Srrs#define MAC_FRIN_TO_BE_SENT_THRESHOLD 16 158198157Srrs 159198157Srrs#define MAX_FRIN_SPILL (MAX_SPILL_SIZE << 2) 160198157Srrs#define MAX_FROUT_SPILL (MAX_SPILL_SIZE << 2) 161198157Srrs#define MAX_CLASS_0_SPILL (MAX_SPILL_SIZE << 2) 162198157Srrs#define MAX_CLASS_1_SPILL (MAX_SPILL_SIZE << 2) 163198157Srrs#define MAX_CLASS_2_SPILL (MAX_SPILL_SIZE << 2) 164198157Srrs#define MAX_CLASS_3_SPILL (MAX_SPILL_SIZE << 2) 165198157Srrs 166198157Srrs/***************************************************************** 167198157Srrs * Phoenix Generic Mac driver 168198157Srrs *****************************************************************/ 169198157Srrs 170198157Srrsextern uint32_t cpu_ltop_map[32]; 171198157Srrs 172198157Srrs#ifdef ENABLED_DEBUG 173198626Srrsstatic int port_counters[4][8] __aligned(XLR_CACHELINE_SIZE); 174198626Srrs 175198157Srrs#define port_inc_counter(port, counter) atomic_add_int(&port_counters[port][(counter)], 1) 176198157Srrs#define port_set_counter(port, counter, value) atomic_set_int(&port_counters[port][(counter)], (value)) 177198157Srrs#else 178198626Srrs#define port_inc_counter(port, counter) /* Nothing */ 179198626Srrs#define port_set_counter(port, counter, value) /* Nothing */ 180198157Srrs#endif 181198157Srrs 182198157Srrsint xlr_rge_tx_prepend[MAXCPU]; 183198157Srrsint xlr_rge_tx_done[MAXCPU]; 184198157Srrsint xlr_rge_get_p2d_failed[MAXCPU]; 185198157Srrsint xlr_rge_msg_snd_failed[MAXCPU]; 186198157Srrsint xlr_rge_tx_ok_done[MAXCPU]; 187198157Srrsint xlr_rge_rx_done[MAXCPU]; 188198157Srrsint xlr_rge_repl_done[MAXCPU]; 189198157Srrs 190198626Srrsstatic __inline__ unsigned int 191198157Srrsldadd_wu(unsigned int value, unsigned long *addr) 192198157Srrs{ 193198626Srrs __asm__ __volatile__(".set push\n" 194198626Srrs ".set noreorder\n" 195198626Srrs "move $8, %2\n" 196198626Srrs "move $9, %3\n" 197198626Srrs /* "ldaddwu $8, $9\n" */ 198198626Srrs ".word 0x71280011\n" 199198626Srrs "move %0, $8\n" 200198626Srrs ".set pop\n" 201198626Srrs : "=&r"(value), "+m"(*addr) 202198626Srrs : "0"(value), "r"((unsigned long)addr) 203198626Srrs : "$8", "$9"); 204198626Srrs 205198157Srrs return value; 206198157Srrs} 207198157Srrs 208208165Srrsstatic __inline__ uint32_t 209208165Srrsxlr_enable_kx(void) 210208165Srrs{ 211208165Srrs uint32_t sr = mips_rd_status(); 212208165Srrs 213208165Srrs mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX); 214208165Srrs return sr; 215208165Srrs} 216208165Srrs 217198157Srrs/* #define mac_stats_add(x, val) ({(x) += (val);}) */ 218198157Srrs#define mac_stats_add(x, val) ldadd_wu(val, &x) 219198157Srrs 220198157Srrs#define XLR_MAX_CORE 8 221198157Srrs#define RGE_LOCK_INIT(_sc, _name) \ 222198157Srrs mtx_init(&(_sc)->rge_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) 223198157Srrs#define RGE_LOCK(_sc) mtx_lock(&(_sc)->rge_mtx) 224198157Srrs#define RGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rge_mtx, MA_OWNED) 225198157Srrs#define RGE_UNLOCK(_sc) mtx_unlock(&(_sc)->rge_mtx) 226198157Srrs#define RGE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rge_mtx) 227198157Srrs 228198157Srrs#define XLR_MAX_MACS 8 229198157Srrs#define XLR_MAX_TX_FRAGS 14 230198626Srrs#define MAX_P2D_DESC_PER_PORT 512 231198157Srrsstruct p2d_tx_desc { 232198626Srrs uint64_t frag[XLR_MAX_TX_FRAGS + 2]; 233198157Srrs}; 234198626Srrs 235198157Srrs#define MAX_TX_RING_SIZE (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT * sizeof(struct p2d_tx_desc)) 236198157Srrs 237198157Srrsstruct rge_softc *dev_mac[XLR_MAX_MACS]; 238198626Srrsstatic int dev_mac_xgs0; 239198626Srrsstatic int dev_mac_gmac0; 240198157Srrs 241198626Srrsstatic int gmac_common_init_done; 242198157Srrs 243198157Srrs 244198626Srrsstatic int rge_probe(device_t); 245198626Srrsstatic int rge_attach(device_t); 246198626Srrsstatic int rge_detach(device_t); 247198626Srrsstatic int rge_suspend(device_t); 248198626Srrsstatic int rge_resume(device_t); 249198626Srrsstatic void rge_release_resources(struct rge_softc *); 250198626Srrsstatic void rge_rx(struct rge_softc *, vm_paddr_t paddr, int); 251198626Srrsstatic void rge_intr(void *); 252198626Srrsstatic void rge_start_locked(struct ifnet *, int); 253198626Srrsstatic void rge_start(struct ifnet *); 254198626Srrsstatic int rge_ioctl(struct ifnet *, u_long, caddr_t); 255198626Srrsstatic void rge_init(void *); 256198626Srrsstatic void rge_stop(struct rge_softc *); 257198626Srrsstatic int rge_shutdown(device_t); 258198626Srrsstatic void rge_reset(struct rge_softc *); 259198157Srrs 260198157Srrsstatic struct mbuf *get_mbuf(void); 261198626Srrsstatic void free_buf(vm_paddr_t paddr); 262198626Srrsstatic void *get_buf(void); 263198157Srrs 264198626Srrsstatic void xlr_mac_get_hwaddr(struct rge_softc *); 265198626Srrsstatic void xlr_mac_setup_hwaddr(struct driver_data *); 266198626Srrsstatic void rmi_xlr_mac_set_enable(struct driver_data *priv, int flag); 267198626Srrsstatic void rmi_xlr_xgmac_init(struct driver_data *priv); 268198626Srrsstatic void rmi_xlr_gmac_init(struct driver_data *priv); 269198626Srrsstatic void mac_common_init(void); 270198626Srrsstatic int rge_mii_write(device_t, int, int, int); 271198626Srrsstatic int rge_mii_read(device_t, int, int); 272198626Srrsstatic void rmi_xlr_mac_mii_statchg(device_t); 273198626Srrsstatic int rmi_xlr_mac_mediachange(struct ifnet *); 274198626Srrsstatic void rmi_xlr_mac_mediastatus(struct ifnet *, struct ifmediareq *); 275198626Srrsstatic void xlr_mac_set_rx_mode(struct rge_softc *sc); 276198626Srrsvoid 277198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code, 278198626Srrs int stid, struct msgrng_msg *msg, 279198626Srrs void *data); 280198626Srrsstatic void mac_frin_replenish(void *); 281198626Srrsstatic int rmi_xlr_mac_open(struct rge_softc *); 282198626Srrsstatic int rmi_xlr_mac_close(struct rge_softc *); 283198626Srrsstatic int 284198157Srrsmac_xmit(struct mbuf *, struct rge_softc *, 285198626Srrs struct driver_data *, int, struct p2d_tx_desc *); 286198626Srrsstatic int rmi_xlr_mac_xmit(struct mbuf *, struct rge_softc *, int, struct p2d_tx_desc *); 287198157Srrsstatic struct rge_softc_stats *rmi_xlr_mac_get_stats(struct rge_softc *sc); 288198626Srrsstatic void rmi_xlr_mac_set_multicast_list(struct rge_softc *sc); 289198626Srrsstatic int rmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu); 290198626Srrsstatic int rmi_xlr_mac_fill_rxfr(struct rge_softc *sc); 291198626Srrsstatic void rmi_xlr_config_spill_area(struct driver_data *priv); 292198626Srrsstatic int rmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed); 293198626Srrsstatic int 294198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s, 295198626Srrs xlr_mac_duplex_t duplex, xlr_mac_fc_t fc); 296198157Srrsstatic void serdes_regs_init(struct driver_data *priv); 297198157Srrsstatic int rmi_xlr_gmac_reset(struct driver_data *priv); 298198157Srrs 299198157Srrs/*Statistics...*/ 300198157Srrsstatic int get_p2d_desc_failed = 0; 301198626Srrsstatic int msg_snd_failed = 0; 302198157Srrs 303198157SrrsSYSCTL_INT(_hw, OID_AUTO, get_p2d_failed, CTLFLAG_RW, 304198626Srrs &get_p2d_desc_failed, 0, "p2d desc failed"); 305198157SrrsSYSCTL_INT(_hw, OID_AUTO, msg_snd_failed, CTLFLAG_RW, 306198626Srrs &msg_snd_failed, 0, "msg snd failed"); 307198157Srrs 308198626Srrsstruct callout xlr_tx_stop_bkp; 309198157Srrs 310198157Srrsstatic device_method_t rge_methods[] = { 311198157Srrs /* Device interface */ 312198157Srrs DEVMETHOD(device_probe, rge_probe), 313198157Srrs DEVMETHOD(device_attach, rge_attach), 314198157Srrs DEVMETHOD(device_detach, rge_detach), 315198157Srrs DEVMETHOD(device_shutdown, rge_shutdown), 316198157Srrs DEVMETHOD(device_suspend, rge_suspend), 317198157Srrs DEVMETHOD(device_resume, rge_resume), 318198157Srrs 319198157Srrs /* MII interface */ 320198157Srrs DEVMETHOD(miibus_readreg, rge_mii_read), 321198608Srrs DEVMETHOD(miibus_statchg, rmi_xlr_mac_mii_statchg), 322198157Srrs DEVMETHOD(miibus_writereg, rge_mii_write), 323198157Srrs {0, 0} 324198157Srrs}; 325198157Srrs 326198626Srrsstatic driver_t rge_driver = { 327198157Srrs "rge", 328198157Srrs rge_methods, 329198157Srrs sizeof(struct rge_softc) 330198157Srrs}; 331198157Srrs 332198157Srrsstatic devclass_t rge_devclass; 333198157Srrs 334198157SrrsDRIVER_MODULE(rge, iodi, rge_driver, rge_devclass, 0, 0); 335198157SrrsDRIVER_MODULE(miibus, rge, miibus_driver, miibus_devclass, 0, 0); 336198157Srrs 337198157Srrs#ifndef __STR 338198157Srrs#define __STR(x) #x 339198157Srrs#endif 340198157Srrs#ifndef STR 341198157Srrs#define STR(x) __STR(x) 342198157Srrs#endif 343198157Srrs 344198626Srrsvoid *xlr_tx_ring_mem; 345198157Srrs 346198157Srrsstruct tx_desc_node { 347198157Srrs struct p2d_tx_desc *ptr; 348198626Srrs TAILQ_ENTRY(tx_desc_node) list; 349198157Srrs}; 350198626Srrs 351198157Srrs#define XLR_MAX_TX_DESC_NODES (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT) 352198157Srrsstruct tx_desc_node tx_desc_nodes[XLR_MAX_TX_DESC_NODES]; 353198157Srrsstatic volatile int xlr_tot_avail_p2d[XLR_MAX_CORE]; 354198157Srrsstatic int xlr_total_active_core = 0; 355198157Srrs 356198157Srrs/* 357198157Srrs * This should contain the list of all free tx frag desc nodes pointing to tx 358198157Srrs * p2d arrays 359198157Srrs */ 360198626Srrsstatic 361198157SrrsTAILQ_HEAD(, tx_desc_node) tx_frag_desc[XLR_MAX_CORE] = 362198626Srrs{ 363198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[0]), 364198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[1]), 365198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[2]), 366198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[3]), 367198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[4]), 368198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[5]), 369198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[6]), 370198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[7]), 371198626Srrs}; 372198157Srrs 373198157Srrs/* This contains a list of free tx frag node descriptors */ 374199139Srrsstatic 375198626SrrsTAILQ_HEAD(, tx_desc_node) free_tx_frag_desc[XLR_MAX_CORE] = 376198626Srrs{ 377198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[0]), 378198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[1]), 379198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[2]), 380198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[3]), 381198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[4]), 382198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[5]), 383198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[6]), 384198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[7]), 385198626Srrs}; 386198157Srrs 387198157Srrsstatic struct mtx tx_desc_lock[XLR_MAX_CORE]; 388198157Srrs 389198157Srrsstatic inline void 390198626Srrsmac_make_desc_rfr(struct msgrng_msg *msg, 391198626Srrs vm_paddr_t addr) 392198157Srrs{ 393198157Srrs msg->msg0 = (uint64_t) addr & 0xffffffffe0ULL; 394198157Srrs msg->msg1 = msg->msg2 = msg->msg3 = 0; 395198157Srrs} 396198157Srrs 397198157Srrs#define MAC_TX_DESC_ALIGNMENT (XLR_CACHELINE_SIZE - 1) 398198157Srrs 399198157Srrsstatic void 400198157Srrsinit_p2d_allocation(void) 401198157Srrs{ 402198626Srrs int active_core[8] = {0}; 403198626Srrs int i = 0; 404198157Srrs uint32_t cpumask; 405198157Srrs int cpu; 406198157Srrs 407198157Srrs cpumask = PCPU_GET(cpumask) | PCPU_GET(other_cpus); 408198157Srrs 409198157Srrs for (i = 0; i < 32; i++) { 410198157Srrs if (cpumask & (1 << i)) { 411208165Srrs cpu = i; 412198626Srrs if (!active_core[cpu / 4]) { 413198626Srrs active_core[cpu / 4] = 1; 414198157Srrs xlr_total_active_core++; 415198157Srrs } 416198157Srrs } 417198157Srrs } 418198626Srrs for (i = 0; i < XLR_MAX_CORE; i++) { 419198626Srrs if (active_core[i]) 420198626Srrs xlr_tot_avail_p2d[i] = XLR_MAX_TX_DESC_NODES / xlr_total_active_core; 421198157Srrs } 422198626Srrs printf("Total Active Core %d\n", xlr_total_active_core); 423198157Srrs} 424198157Srrs 425198157Srrs 426198157Srrsstatic void 427198157Srrsinit_tx_ring(void) 428198157Srrs{ 429198626Srrs int i; 430198626Srrs int j = 0; 431198157Srrs struct tx_desc_node *start, *node; 432198157Srrs struct p2d_tx_desc *tx_desc; 433198626Srrs vm_paddr_t paddr; 434198626Srrs vm_offset_t unmapped_addr; 435198157Srrs 436198626Srrs for (i = 0; i < XLR_MAX_CORE; i++) 437198157Srrs mtx_init(&tx_desc_lock[i], "xlr tx_desc", NULL, MTX_SPIN); 438198157Srrs 439198157Srrs start = &tx_desc_nodes[0]; 440198157Srrs /* TODO: try to get this from KSEG0 */ 441198157Srrs xlr_tx_ring_mem = contigmalloc((MAX_TX_RING_SIZE + XLR_CACHELINE_SIZE), 442198626Srrs M_DEVBUF, M_NOWAIT | M_ZERO, 0, 443198626Srrs 0x10000000, XLR_CACHELINE_SIZE, 0); 444198157Srrs 445198157Srrs if (xlr_tx_ring_mem == NULL) { 446198157Srrs panic("TX ring memory allocation failed"); 447198157Srrs } 448198626Srrs paddr = vtophys((vm_offset_t)xlr_tx_ring_mem); 449198157Srrs 450198157Srrs unmapped_addr = MIPS_PHYS_TO_KSEG0(paddr); 451198157Srrs 452198157Srrs 453198157Srrs tx_desc = (struct p2d_tx_desc *)unmapped_addr; 454198157Srrs 455198157Srrs for (i = 0; i < XLR_MAX_TX_DESC_NODES; i++) { 456198157Srrs node = start + i; 457198157Srrs node->ptr = tx_desc; 458198157Srrs tx_desc++; 459198157Srrs TAILQ_INSERT_HEAD(&tx_frag_desc[j], node, list); 460198626Srrs j = (i / (XLR_MAX_TX_DESC_NODES / xlr_total_active_core)); 461198157Srrs } 462198157Srrs} 463198157Srrs 464198157Srrsstatic inline struct p2d_tx_desc * 465198157Srrsget_p2d_desc(void) 466198157Srrs{ 467198157Srrs struct tx_desc_node *node; 468198157Srrs struct p2d_tx_desc *tx_desc = NULL; 469208165Srrs int cpu = xlr_core_id(); 470198157Srrs 471198157Srrs mtx_lock_spin(&tx_desc_lock[cpu]); 472198157Srrs node = TAILQ_FIRST(&tx_frag_desc[cpu]); 473198157Srrs if (node) { 474198157Srrs xlr_tot_avail_p2d[cpu]--; 475198157Srrs TAILQ_REMOVE(&tx_frag_desc[cpu], node, list); 476198157Srrs tx_desc = node->ptr; 477198157Srrs TAILQ_INSERT_HEAD(&free_tx_frag_desc[cpu], node, list); 478198626Srrs } else { 479198626Srrs /* Increment p2d desc fail count */ 480198157Srrs get_p2d_desc_failed++; 481198157Srrs } 482198157Srrs mtx_unlock_spin(&tx_desc_lock[cpu]); 483198157Srrs return tx_desc; 484198157Srrs} 485198626Srrsstatic void 486198157Srrsfree_p2d_desc(struct p2d_tx_desc *tx_desc) 487198157Srrs{ 488198157Srrs struct tx_desc_node *node; 489208165Srrs int cpu = xlr_core_id(); 490198157Srrs 491198157Srrs mtx_lock_spin(&tx_desc_lock[cpu]); 492198157Srrs node = TAILQ_FIRST(&free_tx_frag_desc[cpu]); 493198157Srrs KASSERT((node != NULL), ("Free TX frag node list is empty\n")); 494198157Srrs 495198157Srrs TAILQ_REMOVE(&free_tx_frag_desc[cpu], node, list); 496198157Srrs node->ptr = tx_desc; 497198157Srrs TAILQ_INSERT_HEAD(&tx_frag_desc[cpu], node, list); 498198157Srrs xlr_tot_avail_p2d[cpu]++; 499198157Srrs mtx_unlock_spin(&tx_desc_lock[cpu]); 500198157Srrs 501198157Srrs} 502198157Srrs 503198626Srrsstatic int 504198157Srrsbuild_frag_list(struct mbuf *m_head, struct msgrng_msg *p2p_msg, struct p2d_tx_desc *tx_desc) 505198157Srrs{ 506198626Srrs struct mbuf *m; 507198626Srrs vm_paddr_t paddr; 508198626Srrs uint64_t p2d_len; 509198626Srrs int nfrag; 510198626Srrs vm_paddr_t p1, p2; 511198626Srrs uint32_t len1, len2; 512198626Srrs vm_offset_t taddr; 513198626Srrs uint64_t fr_stid; 514198626Srrs 515208165Srrs fr_stid = (xlr_core_id() << 3) + xlr_thr_id() + 4; 516198157Srrs 517198157Srrs if (tx_desc == NULL) 518198157Srrs return 1; 519198157Srrs 520198157Srrs nfrag = 0; 521198157Srrs for (m = m_head; m != NULL; m = m->m_next) { 522198157Srrs if ((nfrag + 1) >= XLR_MAX_TX_FRAGS) { 523198157Srrs free_p2d_desc(tx_desc); 524198157Srrs return 1; 525198157Srrs } 526198157Srrs if (m->m_len != 0) { 527198157Srrs paddr = vtophys(mtod(m, vm_offset_t)); 528198157Srrs p1 = paddr + m->m_len; 529198626Srrs p2 = vtophys(((vm_offset_t)m->m_data + m->m_len)); 530198157Srrs if (p1 != p2) { 531198157Srrs len1 = (uint32_t) 532198626Srrs (PAGE_SIZE - (paddr & PAGE_MASK)); 533198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 534198626Srrs ((uint64_t) len1 << 40) | paddr; 535198157Srrs nfrag++; 536198626Srrs taddr = (vm_offset_t)m->m_data + len1; 537198157Srrs p2 = vtophys(taddr); 538198157Srrs len2 = m->m_len - len1; 539203754Srrs if (len2 == 0) 540203754Srrs continue; 541198157Srrs if (nfrag >= XLR_MAX_TX_FRAGS) 542198157Srrs panic("TX frags exceeded"); 543198157Srrs 544198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 545198626Srrs ((uint64_t) len2 << 40) | p2; 546198157Srrs 547198157Srrs taddr += len2; 548198157Srrs p1 = vtophys(taddr); 549198157Srrs 550198157Srrs if ((p2 + len2) != p1) { 551198608Srrs printf("p1 = %p p2 = %p\n", (void *)p1, (void *)p2); 552198157Srrs printf("len1 = %x len2 = %x\n", len1, 553198626Srrs len2); 554198157Srrs printf("m_data %p\n", m->m_data); 555198157Srrs DELAY(1000000); 556198157Srrs panic("Multiple Mbuf segment discontiguous\n"); 557198157Srrs } 558198157Srrs } else { 559198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 560198626Srrs ((uint64_t) m->m_len << 40) | paddr; 561198157Srrs } 562198157Srrs nfrag++; 563198157Srrs } 564198157Srrs } 565198157Srrs /* set eop in the last tx p2d desc */ 566198157Srrs tx_desc->frag[nfrag - 1] |= (1ULL << 63); 567198626Srrs paddr = vtophys((vm_offset_t)tx_desc); 568198157Srrs tx_desc->frag[nfrag] = (1ULL << 63) | (fr_stid << 54) | paddr; 569198157Srrs nfrag++; 570198626Srrs tx_desc->frag[XLR_MAX_TX_FRAGS] = (uint64_t) (vm_offset_t)tx_desc; 571198626Srrs tx_desc->frag[XLR_MAX_TX_FRAGS + 1] = (uint64_t) (vm_offset_t)m_head; 572198157Srrs 573198157Srrs p2d_len = (nfrag * 8); 574198157Srrs p2p_msg->msg0 = (1ULL << 63) | (1ULL << 62) | (127ULL << 54) | 575198626Srrs (p2d_len << 40) | paddr; 576198157Srrs 577198157Srrs return 0; 578198157Srrs} 579198626Srrsstatic void 580198157Srrsrelease_tx_desc(struct msgrng_msg *msg, int rel_buf) 581198157Srrs{ 582199139Srrs struct p2d_tx_desc *tx_desc, *chk_addr; 583198626Srrs struct mbuf *m; 584198157Srrs 585199139Srrs tx_desc = (struct p2d_tx_desc *)MIPS_PHYS_TO_KSEG0(msg->msg0); 586199139Srrs chk_addr = (struct p2d_tx_desc *)(uint32_t) (tx_desc->frag[XLR_MAX_TX_FRAGS] & 0x00000000ffffffff); 587199139Srrs if (tx_desc != chk_addr) { 588199139Srrs printf("Address %p does not match with stored addr %p - we leaked a descriptor\n", 589199139Srrs tx_desc, chk_addr); 590199139Srrs return; 591199139Srrs } 592198157Srrs if (rel_buf) { 593199139Srrs m = (struct mbuf *)(uint32_t) (tx_desc->frag[XLR_MAX_TX_FRAGS + 1] & 0x00000000ffffffff); 594198157Srrs m_freem(m); 595198157Srrs } 596198157Srrs free_p2d_desc(tx_desc); 597198157Srrs} 598198157Srrs 599198157Srrs 600198626Srrsstatic struct mbuf * 601198157Srrsget_mbuf(void) 602198157Srrs{ 603198626Srrs struct mbuf *m_new = NULL; 604198157Srrs 605198157Srrs if ((m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR)) == NULL) 606198157Srrs return NULL; 607198157Srrs 608198157Srrs m_new->m_len = MCLBYTES; 609198157Srrs m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 610198157Srrs return m_new; 611198157Srrs} 612198157Srrs 613198626Srrsstatic void 614198157Srrsfree_buf(vm_paddr_t paddr) 615198157Srrs{ 616198626Srrs struct mbuf *m; 617208165Srrs uint32_t mag, um, sr; 618198157Srrs 619208165Srrs sr = xlr_enable_kx(); 620208165Srrs um = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE); 621208165Srrs mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t)); 622208165Srrs mips_wr_status(sr); 623208165Srrs 624199139Srrs if (mag != 0xf00bad) { 625208165Srrs printf("Something is wrong kseg:%lx found mag:%x not 0xf00bad\n", 626208165Srrs (u_long)paddr, mag); 627199139Srrs return; 628199139Srrs } 629199139Srrs m = (struct mbuf *)um; 630198157Srrs if (m != NULL) 631198157Srrs m_freem(m); 632198157Srrs} 633198157Srrs 634198157Srrsstatic void * 635198157Srrsget_buf(void) 636198157Srrs{ 637198626Srrs struct mbuf *m_new = NULL; 638208165Srrs unsigned int *md; 639198157Srrs#ifdef INVARIANTS 640198626Srrs vm_paddr_t temp1, temp2; 641198157Srrs#endif 642198157Srrs 643198157Srrs m_new = get_mbuf(); 644198157Srrs if (m_new == NULL) 645198157Srrs return NULL; 646198157Srrs 647198157Srrs m_adj(m_new, XLR_CACHELINE_SIZE - ((unsigned int)m_new->m_data & 0x1f)); 648198157Srrs md = (unsigned int *)m_new->m_data; 649198157Srrs md[0] = (unsigned int)m_new; /* Back Ptr */ 650198157Srrs md[1] = 0xf00bad; 651198157Srrs m_adj(m_new, XLR_CACHELINE_SIZE); 652198157Srrs 653198157Srrs#ifdef INVARIANTS 654198626Srrs temp1 = vtophys((vm_offset_t)m_new->m_data); 655198626Srrs temp2 = vtophys((vm_offset_t)m_new->m_data + 1536); 656198157Srrs if ((temp1 + 1536) != temp2) 657198157Srrs panic("ALLOCED BUFFER IS NOT CONTIGUOUS\n"); 658198157Srrs#endif 659198157Srrs return (void *)m_new->m_data; 660198157Srrs} 661198157Srrs 662198157Srrs/********************************************************************** 663198157Srrs **********************************************************************/ 664198626Srrsstatic void 665198157Srrsrmi_xlr_mac_set_enable(struct driver_data *priv, int flag) 666198157Srrs{ 667198626Srrs uint32_t regval; 668198626Srrs int tx_threshold = 1518; 669198157Srrs 670198157Srrs if (flag) { 671198157Srrs regval = xlr_read_reg(priv->mmio, R_TX_CONTROL); 672198157Srrs regval |= (1 << O_TX_CONTROL__TxEnable) | 673198626Srrs (tx_threshold << O_TX_CONTROL__TxThreshold); 674198157Srrs 675198157Srrs xlr_write_reg(priv->mmio, R_TX_CONTROL, regval); 676198157Srrs 677198157Srrs regval = xlr_read_reg(priv->mmio, R_RX_CONTROL); 678198157Srrs regval |= 1 << O_RX_CONTROL__RxEnable; 679198157Srrs if (priv->mode == XLR_PORT0_RGMII) 680198157Srrs regval |= 1 << O_RX_CONTROL__RGMII; 681198157Srrs xlr_write_reg(priv->mmio, R_RX_CONTROL, regval); 682198157Srrs 683198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1); 684198157Srrs regval |= (O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen); 685198157Srrs xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval); 686198157Srrs } else { 687198157Srrs regval = xlr_read_reg(priv->mmio, R_TX_CONTROL); 688198157Srrs regval &= ~((1 << O_TX_CONTROL__TxEnable) | 689198626Srrs (tx_threshold << O_TX_CONTROL__TxThreshold)); 690198157Srrs 691198157Srrs xlr_write_reg(priv->mmio, R_TX_CONTROL, regval); 692198157Srrs 693198157Srrs regval = xlr_read_reg(priv->mmio, R_RX_CONTROL); 694198157Srrs regval &= ~(1 << O_RX_CONTROL__RxEnable); 695198157Srrs xlr_write_reg(priv->mmio, R_RX_CONTROL, regval); 696198157Srrs 697198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1); 698198157Srrs regval &= ~(O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen); 699198157Srrs xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval); 700198157Srrs } 701198157Srrs} 702198157Srrs 703198157Srrs/********************************************************************** 704198157Srrs **********************************************************************/ 705198626Srrsstatic __inline__ int 706198157Srrsxlr_mac_send_fr(struct driver_data *priv, 707198626Srrs vm_paddr_t addr, int len) 708198157Srrs{ 709198626Srrs int stid = priv->rfrbucket; 710198157Srrs struct msgrng_msg msg; 711208165Srrs int vcpu = xlr_cpu_id(); 712198157Srrs 713198626Srrs mac_make_desc_rfr(&msg, addr); 714198157Srrs 715198157Srrs /* Send the packet to MAC */ 716208165Srrs dbg_msg("mac_%d: Sending free packet %lx to stid %d\n", 717208165Srrs priv->instance, (u_long)addr, stid); 718198157Srrs if (priv->type == XLR_XGMAC) { 719198157Srrs while (message_send(1, MSGRNG_CODE_XGMAC, stid, &msg)); 720198157Srrs } else { 721198157Srrs while (message_send(1, MSGRNG_CODE_MAC, stid, &msg)); 722198157Srrs xlr_rge_repl_done[vcpu]++; 723198157Srrs } 724198157Srrs 725198157Srrs return 0; 726198157Srrs} 727198157Srrs 728198157Srrs/**************************************************************/ 729198157Srrs 730198626Srrsstatic void 731198157Srrsxgmac_mdio_setup(volatile unsigned int *_mmio) 732198157Srrs{ 733198626Srrs int i; 734198626Srrs uint32_t rd_data; 735198626Srrs 736198157Srrs for (i = 0; i < 4; i++) { 737198157Srrs rd_data = xmdio_read(_mmio, 1, 0x8000 + i); 738198157Srrs rd_data = rd_data & 0xffffdfff; /* clear isolate bit */ 739198157Srrs xmdio_write(_mmio, 1, 0x8000 + i, rd_data); 740198157Srrs } 741198157Srrs} 742198157Srrs 743198157Srrs/********************************************************************** 744198157Srrs * Init MII interface 745198157Srrs * 746198157Srrs * Input parameters: 747198157Srrs * s - priv structure 748198157Srrs ********************************************************************* */ 749198157Srrs#define PHY_STATUS_RETRIES 25000 750198157Srrs 751198626Srrsstatic void 752198157Srrsrmi_xlr_mac_mii_init(struct driver_data *priv) 753198157Srrs{ 754198626Srrs xlr_reg_t *mii_mmio = priv->mii_mmio; 755198157Srrs 756198157Srrs /* use the lowest clock divisor - divisor 28 */ 757198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_CONFIG, 0x07); 758198157Srrs} 759198157Srrs 760198157Srrs/********************************************************************** 761198157Srrs * Read a PHY register. 762198157Srrs * 763198157Srrs * Input parameters: 764198157Srrs * s - priv structure 765198157Srrs * phyaddr - PHY's address 766198157Srrs * regidx = index of register to read 767198157Srrs * 768198157Srrs * Return value: 769198157Srrs * value read, or 0 if an error occurred. 770198157Srrs ********************************************************************* */ 771198157Srrs 772198626Srrsstatic int 773198626Srrsrge_mii_read_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx) 774198157Srrs{ 775198626Srrs int i = 0; 776198157Srrs 777198157Srrs /* setup the phy reg to be used */ 778198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS, 779198626Srrs (phyaddr << 8) | (regidx << 0)); 780198157Srrs /* Issue the read command */ 781198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND, 782198626Srrs (1 << O_MII_MGMT_COMMAND__rstat)); 783198157Srrs 784198157Srrs /* poll for the read cycle to complete */ 785198157Srrs for (i = 0; i < PHY_STATUS_RETRIES; i++) { 786198157Srrs if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0) 787198157Srrs break; 788198157Srrs } 789198157Srrs 790198157Srrs /* clear the read cycle */ 791198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND, 0); 792198157Srrs 793198157Srrs if (i == PHY_STATUS_RETRIES) { 794198157Srrs return 0xffffffff; 795198157Srrs } 796198157Srrs /* Read the data back */ 797198157Srrs return xlr_read_reg(mii_mmio, R_MII_MGMT_STATUS); 798198157Srrs} 799198157Srrs 800198626Srrsstatic int 801198608Srrsrge_mii_read(device_t dev, int phyaddr, int regidx) 802198157Srrs{ 803198157Srrs struct rge_softc *sc = device_get_softc(dev); 804198626Srrs 805198157Srrs return rge_mii_read_internal(sc->priv.mii_mmio, phyaddr, regidx); 806198157Srrs} 807198157Srrs 808198157Srrs/********************************************************************** 809198157Srrs * Set MII hooks to newly selected media 810198157Srrs * 811198157Srrs * Input parameters: 812198157Srrs * ifp - Interface Pointer 813198157Srrs * 814198157Srrs * Return value: 815198157Srrs * nothing 816198157Srrs ********************************************************************* */ 817198626Srrsstatic int 818198157Srrsrmi_xlr_mac_mediachange(struct ifnet *ifp) 819198157Srrs{ 820198157Srrs struct rge_softc *sc = ifp->if_softc; 821198157Srrs 822198157Srrs if (ifp->if_flags & IFF_UP) 823198157Srrs mii_mediachg(&sc->rge_mii); 824198157Srrs 825198157Srrs return 0; 826198157Srrs} 827198157Srrs 828198157Srrs/********************************************************************** 829198157Srrs * Get the current interface media status 830198157Srrs * 831198157Srrs * Input parameters: 832198157Srrs * ifp - Interface Pointer 833198157Srrs * ifmr - Interface media request ptr 834198157Srrs * 835198157Srrs * Return value: 836198157Srrs * nothing 837198157Srrs ********************************************************************* */ 838198157Srrsstatic void 839198157Srrsrmi_xlr_mac_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 840198157Srrs{ 841198157Srrs struct rge_softc *sc = ifp->if_softc; 842198157Srrs 843198626Srrs /* Check whether this is interface is active or not. */ 844198157Srrs ifmr->ifm_status = IFM_AVALID; 845198626Srrs if (sc->link_up) { 846198157Srrs ifmr->ifm_status |= IFM_ACTIVE; 847198626Srrs } else { 848198157Srrs ifmr->ifm_active = IFM_ETHER; 849198157Srrs } 850198157Srrs} 851198157Srrs 852198157Srrs/********************************************************************** 853198157Srrs * Write a value to a PHY register. 854198157Srrs * 855198157Srrs * Input parameters: 856198157Srrs * s - priv structure 857198157Srrs * phyaddr - PHY to use 858198157Srrs * regidx - register within the PHY 859198157Srrs * regval - data to write to register 860198157Srrs * 861198157Srrs * Return value: 862198157Srrs * nothing 863198157Srrs ********************************************************************* */ 864198608Srrsstatic void 865198626Srrsrge_mii_write_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx, int regval) 866198157Srrs{ 867198626Srrs int i = 0; 868198157Srrs 869198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS, 870198626Srrs (phyaddr << 8) | (regidx << 0)); 871198157Srrs 872198157Srrs /* Write the data which starts the write cycle */ 873198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_WRITE_DATA, regval); 874198157Srrs 875198157Srrs /* poll for the write cycle to complete */ 876198157Srrs for (i = 0; i < PHY_STATUS_RETRIES; i++) { 877198157Srrs if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0) 878198157Srrs break; 879198157Srrs } 880198157Srrs 881198157Srrs return; 882198157Srrs} 883198157Srrs 884198608Srrsstatic int 885198608Srrsrge_mii_write(device_t dev, int phyaddr, int regidx, int regval) 886198157Srrs{ 887198157Srrs struct rge_softc *sc = device_get_softc(dev); 888198157Srrs 889198157Srrs rge_mii_write_internal(sc->priv.mii_mmio, phyaddr, regidx, regval); 890198608Srrs return (0); 891198157Srrs} 892198157Srrs 893198626Srrsstatic void 894198608Srrsrmi_xlr_mac_mii_statchg(struct device *dev) 895198157Srrs{ 896198157Srrs} 897198157Srrs 898198157Srrsstatic void 899198157Srrsserdes_regs_init(struct driver_data *priv) 900198157Srrs{ 901198626Srrs xlr_reg_t *mmio_gpio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GPIO_OFFSET); 902198157Srrs int i; 903198157Srrs 904198157Srrs /* Initialize SERDES CONTROL Registers */ 905198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 0, 0x6DB0); 906198626Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 1, 0xFFFF); 907198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 2, 0xB6D0); 908198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 3, 0x00FF); 909198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 4, 0x0000); 910198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 5, 0x0000); 911198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 6, 0x0005); 912198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 7, 0x0001); 913198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 8, 0x0000); 914198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 9, 0x0000); 915198626Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 10, 0x0000); 916198157Srrs 917198626Srrs /* 918198157Srrs * For loop delay and GPIO programming crud from Linux driver, 919198157Srrs */ 920198626Srrs for (i = 0; i < 10000000; i++) { 921198626Srrs } 922198157Srrs mmio_gpio[0x20] = 0x7e6802; 923198157Srrs mmio_gpio[0x10] = 0x7104; 924198626Srrs for (i = 0; i < 100000000; i++) { 925198626Srrs } 926198157Srrs return; 927198626Srrs} 928198157Srrs 929199139Srrsstatic void 930198626Srrsserdes_autoconfig(struct driver_data *priv) 931198157Srrs{ 932198626Srrs int delay = 100000; 933198157Srrs 934198626Srrs /* Enable Auto negotiation in the PCS Layer */ 935198626Srrs rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x1000); 936198626Srrs DELAY(delay); 937198626Srrs rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x0200); 938198626Srrs DELAY(delay); 939198157Srrs 940198626Srrs rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x1000); 941198626Srrs DELAY(delay); 942198626Srrs rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x0200); 943198626Srrs DELAY(delay); 944198157Srrs 945198626Srrs rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x1000); 946198626Srrs DELAY(delay); 947198626Srrs rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x0200); 948198626Srrs DELAY(delay); 949198157Srrs 950198626Srrs rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x1000); 951198626Srrs DELAY(delay); 952198626Srrs rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x0200); 953198626Srrs DELAY(delay); 954198157Srrs 955198157Srrs} 956198157Srrs 957198157Srrs/***************************************************************** 958198157Srrs * Initialize GMAC 959198157Srrs *****************************************************************/ 960198626Srrsstatic void 961198157Srrsrmi_xlr_config_pde(struct driver_data *priv) 962198157Srrs{ 963198626Srrs int i = 0, cpu = 0, bucket = 0; 964198626Srrs uint64_t bucket_map = 0; 965198626Srrs 966198157Srrs /* uint32_t desc_pack_ctrl = 0; */ 967198626Srrs uint32_t cpumask; 968198157Srrs 969208165Srrs cpumask = PCPU_GET(cpumask); 970208165Srrs#ifdef SMP 971208165Srrs /* 972208165Srrs * rge may be called before SMP start in a BOOTP/NFSROOT 973208165Srrs * setup. we will distribute packets to other cpus only when 974208165Srrs * the SMP is started. 975208165Srrs */ 976208165Srrs if (smp_started) 977208165Srrs cpumask |= PCPU_GET(other_cpus); 978208165Srrs#endif 979198157Srrs 980208165Srrs for (i = 0; i < MAXCPU; i++) { 981198157Srrs if (cpumask & (1 << i)) { 982208165Srrs cpu = i; 983198626Srrs bucket = ((cpu >> 2) << 3); 984198157Srrs bucket_map |= (1ULL << bucket); 985198157Srrs } 986198157Srrs } 987208165Srrs printf("rmi_xlr_config_pde: bucket_map=%llx\n", bucket_map); 988198157Srrs 989198157Srrs /* bucket_map = 0x1; */ 990198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_0, (bucket_map & 0xffffffff)); 991198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_0 + 1, 992198626Srrs ((bucket_map >> 32) & 0xffffffff)); 993198157Srrs 994198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_1, (bucket_map & 0xffffffff)); 995198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_1 + 1, 996198626Srrs ((bucket_map >> 32) & 0xffffffff)); 997198157Srrs 998198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_2, (bucket_map & 0xffffffff)); 999198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_2 + 1, 1000198626Srrs ((bucket_map >> 32) & 0xffffffff)); 1001198157Srrs 1002198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_3, (bucket_map & 0xffffffff)); 1003198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_3 + 1, 1004198626Srrs ((bucket_map >> 32) & 0xffffffff)); 1005198157Srrs} 1006198157Srrs 1007198626Srrsstatic void 1008208165Srrsrge_smp_update_pde(void *dummy __unused) 1009208165Srrs{ 1010208165Srrs int i; 1011208165Srrs struct driver_data *priv; 1012208165Srrs struct rge_softc *sc; 1013208165Srrs 1014208165Srrs printf("Updating packet distribution for SMP\n"); 1015208165Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 1016208165Srrs sc = dev_mac[i]; 1017208165Srrs if (!sc) 1018208165Srrs continue; 1019208165Srrs priv = &(sc->priv); 1020208165Srrs rmi_xlr_mac_set_enable(priv, 0); 1021208165Srrs rmi_xlr_config_pde(priv); 1022208165Srrs rmi_xlr_mac_set_enable(priv, 1); 1023208165Srrs } 1024208165Srrs} 1025208165Srrs 1026208165SrrsSYSINIT(rge_smp_update_pde, SI_SUB_SMP, SI_ORDER_ANY, rge_smp_update_pde, NULL); 1027208165Srrs 1028208165Srrs 1029208165Srrsstatic void 1030198157Srrsrmi_xlr_config_parser(struct driver_data *priv) 1031198157Srrs{ 1032198157Srrs /* 1033198157Srrs * Mark it as no classification The parser extract is gauranteed to 1034198157Srrs * be zero with no classfication 1035198157Srrs */ 1036198157Srrs xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x00); 1037198157Srrs 1038198157Srrs xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x01); 1039198157Srrs 1040198157Srrs /* configure the parser : L2 Type is configured in the bootloader */ 1041198157Srrs /* extract IP: src, dest protocol */ 1042198157Srrs xlr_write_reg(priv->mmio, R_L3CTABLE, 1043198626Srrs (9 << 20) | (1 << 19) | (1 << 18) | (0x01 << 16) | 1044198626Srrs (0x0800 << 0)); 1045198157Srrs xlr_write_reg(priv->mmio, R_L3CTABLE + 1, 1046198626Srrs (12 << 25) | (4 << 21) | (16 << 14) | (4 << 10)); 1047198157Srrs 1048198157Srrs} 1049198157Srrs 1050198626Srrsstatic void 1051198157Srrsrmi_xlr_config_classifier(struct driver_data *priv) 1052198157Srrs{ 1053198626Srrs int i = 0; 1054198157Srrs 1055198157Srrs if (priv->type == XLR_XGMAC) { 1056198157Srrs /* xgmac translation table doesn't have sane values on reset */ 1057198157Srrs for (i = 0; i < 64; i++) 1058198157Srrs xlr_write_reg(priv->mmio, R_TRANSLATETABLE + i, 0x0); 1059198157Srrs 1060198157Srrs /* 1061198157Srrs * use upper 7 bits of the parser extract to index the 1062198157Srrs * translate table 1063198157Srrs */ 1064198157Srrs xlr_write_reg(priv->mmio, R_PARSERCONFIGREG, 0x0); 1065198157Srrs } 1066198157Srrs} 1067198157Srrs 1068198157Srrsenum { 1069198626Srrs SGMII_SPEED_10 = 0x00000000, 1070198626Srrs SGMII_SPEED_100 = 0x02000000, 1071198626Srrs SGMII_SPEED_1000 = 0x04000000, 1072198157Srrs}; 1073198157Srrs 1074198626Srrsstatic void 1075198157Srrsrmi_xlr_gmac_config_speed(struct driver_data *priv) 1076198157Srrs{ 1077198157Srrs int phy_addr = priv->phy_addr; 1078198626Srrs xlr_reg_t *mmio = priv->mmio; 1079198157Srrs struct rge_softc *sc = priv->sc; 1080198157Srrs 1081198157Srrs priv->speed = rge_mii_read_internal(priv->mii_mmio, phy_addr, 28); 1082198157Srrs priv->link = rge_mii_read_internal(priv->mii_mmio, phy_addr, 1) & 0x4; 1083198157Srrs priv->speed = (priv->speed >> 3) & 0x03; 1084198157Srrs 1085198157Srrs if (priv->speed == xlr_mac_speed_10) { 1086198157Srrs if (priv->mode != XLR_RGMII) 1087198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_10); 1088198157Srrs xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7137); 1089198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x02); 1090198157Srrs printf("%s: [10Mbps]\n", device_get_nameunit(sc->rge_dev)); 1091198626Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1092198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1093198626Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1094198157Srrs } else if (priv->speed == xlr_mac_speed_100) { 1095198157Srrs if (priv->mode != XLR_RGMII) 1096198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100); 1097198157Srrs xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7137); 1098198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x01); 1099198157Srrs printf("%s: [100Mbps]\n", device_get_nameunit(sc->rge_dev)); 1100198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1101198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1102198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1103198157Srrs } else { 1104198157Srrs if (priv->speed != xlr_mac_speed_1000) { 1105198157Srrs if (priv->mode != XLR_RGMII) 1106198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100); 1107198157Srrs printf("PHY reported unknown MAC speed, defaulting to 100Mbps\n"); 1108198157Srrs xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7137); 1109198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x01); 1110198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1111198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1112198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1113198157Srrs } else { 1114198157Srrs if (priv->mode != XLR_RGMII) 1115198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_1000); 1116198157Srrs xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7237); 1117198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x00); 1118198157Srrs printf("%s: [1000Mbps]\n", device_get_nameunit(sc->rge_dev)); 1119198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1120198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1121198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1122198157Srrs } 1123198157Srrs } 1124198626Srrs 1125198157Srrs if (!priv->link) { 1126198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER; 1127198157Srrs sc->link_up = 0; 1128198157Srrs } else { 1129198157Srrs sc->link_up = 1; 1130198157Srrs } 1131198157Srrs} 1132198157Srrs 1133198157Srrs/***************************************************************** 1134198157Srrs * Initialize XGMAC 1135198157Srrs *****************************************************************/ 1136198626Srrsstatic void 1137198157Srrsrmi_xlr_xgmac_init(struct driver_data *priv) 1138198157Srrs{ 1139198626Srrs int i = 0; 1140198626Srrs xlr_reg_t *mmio = priv->mmio; 1141198626Srrs int id = priv->instance; 1142198157Srrs struct rge_softc *sc = priv->sc; 1143198157Srrs volatile unsigned short *cpld; 1144198157Srrs 1145198157Srrs cpld = (volatile unsigned short *)0xBD840000; 1146198157Srrs 1147198157Srrs xlr_write_reg(priv->mmio, R_DESC_PACK_CTRL, 1148198626Srrs (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize) | (4 << 20)); 1149198157Srrs xlr_write_reg(priv->mmio, R_BYTEOFFSET0, BYTE_OFFSET); 1150198157Srrs rmi_xlr_config_pde(priv); 1151198157Srrs rmi_xlr_config_parser(priv); 1152198157Srrs rmi_xlr_config_classifier(priv); 1153198157Srrs 1154198157Srrs xlr_write_reg(priv->mmio, R_MSG_TX_THRESHOLD, 1); 1155198157Srrs 1156198157Srrs /* configure the XGMAC Registers */ 1157198157Srrs xlr_write_reg(mmio, R_XGMAC_CONFIG_1, 0x50000026); 1158198157Srrs 1159198157Srrs /* configure the XGMAC_GLUE Registers */ 1160198157Srrs xlr_write_reg(mmio, R_DMACR0, 0xffffffff); 1161198157Srrs xlr_write_reg(mmio, R_DMACR1, 0xffffffff); 1162198157Srrs xlr_write_reg(mmio, R_DMACR2, 0xffffffff); 1163198157Srrs xlr_write_reg(mmio, R_DMACR3, 0xffffffff); 1164198157Srrs xlr_write_reg(mmio, R_STATCTRL, 0x04); 1165198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1166198157Srrs 1167198157Srrs xlr_write_reg(mmio, R_XGMACPADCALIBRATION, 0x030); 1168198157Srrs xlr_write_reg(mmio, R_EGRESSFIFOCARVINGSLOTS, 0x0f); 1169198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1170198157Srrs xlr_write_reg(mmio, R_XGMAC_MIIM_CONFIG, 0x3e); 1171198157Srrs 1172198157Srrs /* 1173198157Srrs * take XGMII phy out of reset 1174198157Srrs */ 1175198157Srrs /* 1176198157Srrs * we are pulling everything out of reset because writing a 0 would 1177198157Srrs * reset other devices on the chip 1178198157Srrs */ 1179198157Srrs cpld[ATX_CPLD_RESET_1] = 0xffff; 1180198157Srrs cpld[ATX_CPLD_MISC_CTRL] = 0xffff; 1181198157Srrs cpld[ATX_CPLD_RESET_2] = 0xffff; 1182198157Srrs 1183198157Srrs xgmac_mdio_setup(mmio); 1184198157Srrs 1185198157Srrs rmi_xlr_config_spill_area(priv); 1186198157Srrs 1187198157Srrs if (id == 0) { 1188198157Srrs for (i = 0; i < 16; i++) { 1189198157Srrs xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i, 1190198626Srrs bucket_sizes. 1191198626Srrs bucket[MSGRNG_STNID_XGS0_TX + i]); 1192198157Srrs } 1193198157Srrs 1194198157Srrs xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE, 1195198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC0JFR]); 1196198157Srrs xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE, 1197198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC0RFR]); 1198198157Srrs 1199198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1200198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1201198626Srrs cc_table_xgs_0. 1202198626Srrs counters[i >> 3][i & 0x07]); 1203198157Srrs } 1204198157Srrs } else if (id == 1) { 1205198157Srrs for (i = 0; i < 16; i++) { 1206198157Srrs xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i, 1207198626Srrs bucket_sizes. 1208198626Srrs bucket[MSGRNG_STNID_XGS1_TX + i]); 1209198157Srrs } 1210198157Srrs 1211198157Srrs xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE, 1212198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC1JFR]); 1213198157Srrs xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE, 1214198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC1RFR]); 1215198157Srrs 1216198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1217198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1218198626Srrs cc_table_xgs_1. 1219198626Srrs counters[i >> 3][i & 0x07]); 1220198157Srrs } 1221198157Srrs } 1222198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1223198157Srrs sc->rge_mii.mii_media.ifm_media |= (IFM_AVALID | IFM_ACTIVE); 1224198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1225198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1226198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media |= (IFM_AVALID | IFM_ACTIVE); 1227198157Srrs 1228198157Srrs priv->init_frin_desc = 1; 1229198157Srrs} 1230198157Srrs 1231198157Srrs/******************************************************* 1232198157Srrs * Initialization gmac 1233198157Srrs *******************************************************/ 1234198157Srrsstatic int 1235198157Srrsrmi_xlr_gmac_reset(struct driver_data *priv) 1236198157Srrs{ 1237198157Srrs volatile uint32_t val; 1238198157Srrs xlr_reg_t *mmio = priv->mmio; 1239198157Srrs int i, maxloops = 100; 1240198157Srrs 1241198626Srrs /* Disable MAC RX */ 1242198626Srrs val = xlr_read_reg(mmio, R_MAC_CONFIG_1); 1243198626Srrs val &= ~0x4; 1244198626Srrs xlr_write_reg(mmio, R_MAC_CONFIG_1, val); 1245198157Srrs 1246198626Srrs /* Disable Core RX */ 1247198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1248198626Srrs val &= ~0x1; 1249198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1250198157Srrs 1251198626Srrs /* wait for rx to halt */ 1252198626Srrs for (i = 0; i < maxloops; i++) { 1253198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1254198626Srrs if (val & 0x2) 1255198626Srrs break; 1256198626Srrs DELAY(1000); 1257198626Srrs } 1258198157Srrs if (i == maxloops) 1259198157Srrs return -1; 1260198157Srrs 1261198626Srrs /* Issue a soft reset */ 1262198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1263198626Srrs val |= 0x4; 1264198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1265198626Srrs 1266198626Srrs /* wait for reset to complete */ 1267198626Srrs for (i = 0; i < maxloops; i++) { 1268198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1269198626Srrs if (val & 0x8) 1270198626Srrs break; 1271198626Srrs DELAY(1000); 1272198626Srrs } 1273198157Srrs if (i == maxloops) 1274198157Srrs return -1; 1275198157Srrs 1276198626Srrs /* Clear the soft reset bit */ 1277198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1278198626Srrs val &= ~0x4; 1279198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1280198157Srrs return 0; 1281198157Srrs} 1282198157Srrs 1283198626Srrsstatic void 1284198157Srrsrmi_xlr_gmac_init(struct driver_data *priv) 1285198157Srrs{ 1286198626Srrs int i = 0; 1287198626Srrs xlr_reg_t *mmio = priv->mmio; 1288198626Srrs int id = priv->instance; 1289198157Srrs struct stn_cc *gmac_cc_config; 1290198626Srrs uint32_t value = 0; 1291198626Srrs int blk = id / 4, port = id % 4; 1292198157Srrs 1293198157Srrs rmi_xlr_mac_set_enable(priv, 0); 1294198157Srrs 1295198157Srrs rmi_xlr_config_spill_area(priv); 1296198157Srrs 1297198157Srrs xlr_write_reg(mmio, R_DESC_PACK_CTRL, 1298198626Srrs (BYTE_OFFSET << O_DESC_PACK_CTRL__ByteOffset) | 1299198626Srrs (1 << O_DESC_PACK_CTRL__MaxEntry) | 1300198626Srrs (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize)); 1301198157Srrs 1302198157Srrs rmi_xlr_config_pde(priv); 1303198157Srrs rmi_xlr_config_parser(priv); 1304198157Srrs rmi_xlr_config_classifier(priv); 1305198157Srrs 1306198157Srrs xlr_write_reg(mmio, R_MSG_TX_THRESHOLD, 3); 1307198157Srrs xlr_write_reg(mmio, R_MAC_CONFIG_1, 0x35); 1308198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, (0x7 << 6)); 1309198157Srrs 1310198626Srrs if (priv->mode == XLR_PORT0_RGMII) { 1311198157Srrs printf("Port 0 set in RGMII mode\n"); 1312198157Srrs value = xlr_read_reg(mmio, R_RX_CONTROL); 1313198157Srrs value |= 1 << O_RX_CONTROL__RGMII; 1314198157Srrs xlr_write_reg(mmio, R_RX_CONTROL, value); 1315198157Srrs } 1316198157Srrs rmi_xlr_mac_mii_init(priv); 1317198157Srrs 1318198626Srrs 1319198157Srrs#if 0 1320198157Srrs priv->advertising = ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half | 1321198626Srrs ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half | 1322198626Srrs ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | 1323198626Srrs ADVERTISED_MII; 1324198157Srrs#endif 1325198157Srrs 1326198157Srrs /* 1327198157Srrs * Enable all MDIO interrupts in the phy RX_ER bit seems to be get 1328198157Srrs * set about every 1 sec in GigE mode, ignore it for now... 1329198157Srrs */ 1330198157Srrs rge_mii_write_internal(priv->mii_mmio, priv->phy_addr, 25, 0xfffffffe); 1331198157Srrs 1332198626Srrs if (priv->mode != XLR_RGMII) { 1333198157Srrs serdes_regs_init(priv); 1334198157Srrs serdes_autoconfig(priv); 1335198157Srrs } 1336198626Srrs rmi_xlr_gmac_config_speed(priv); 1337198157Srrs 1338198157Srrs value = xlr_read_reg(mmio, R_IPG_IFG); 1339198157Srrs xlr_write_reg(mmio, R_IPG_IFG, ((value & ~0x7f) | MAC_B2B_IPG)); 1340198157Srrs xlr_write_reg(mmio, R_DMACR0, 0xffffffff); 1341198157Srrs xlr_write_reg(mmio, R_DMACR1, 0xffffffff); 1342198157Srrs xlr_write_reg(mmio, R_DMACR2, 0xffffffff); 1343198157Srrs xlr_write_reg(mmio, R_DMACR3, 0xffffffff); 1344198157Srrs xlr_write_reg(mmio, R_STATCTRL, 0x04); 1345198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1346198157Srrs xlr_write_reg(mmio, R_INTMASK, 0); 1347198157Srrs xlr_write_reg(mmio, R_FREEQCARVE, 0); 1348198157Srrs 1349198157Srrs xlr_write_reg(mmio, R_GMAC_TX0_BUCKET_SIZE + port, 1350198626Srrs xlr_board_info.bucket_sizes->bucket[priv->txbucket]); 1351198157Srrs xlr_write_reg(mmio, R_GMAC_JFR0_BUCKET_SIZE, 1352198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_0]); 1353198157Srrs xlr_write_reg(mmio, R_GMAC_RFR0_BUCKET_SIZE, 1354198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_0]); 1355198157Srrs xlr_write_reg(mmio, R_GMAC_JFR1_BUCKET_SIZE, 1356198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_1]); 1357198157Srrs xlr_write_reg(mmio, R_GMAC_RFR1_BUCKET_SIZE, 1358198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_1]); 1359198157Srrs 1360198157Srrs dbg_msg("Programming credit counter %d : %d -> %d\n", blk, R_GMAC_TX0_BUCKET_SIZE + port, 1361198626Srrs xlr_board_info.bucket_sizes->bucket[priv->txbucket]); 1362198157Srrs 1363198157Srrs gmac_cc_config = xlr_board_info.gmac_block[blk].credit_config; 1364198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1365198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1366198626Srrs gmac_cc_config->counters[i >> 3][i & 0x07]); 1367198157Srrs dbg_msg("%d: %d -> %d\n", priv->instance, 1368198626Srrs R_CC_CPU0_0 + i, gmac_cc_config->counters[i >> 3][i & 0x07]); 1369198157Srrs } 1370198157Srrs priv->init_frin_desc = 1; 1371198157Srrs} 1372198157Srrs 1373198157Srrs/********************************************************************** 1374198157Srrs * Set promiscuous mode 1375198157Srrs **********************************************************************/ 1376198626Srrsstatic void 1377198157Srrsxlr_mac_set_rx_mode(struct rge_softc *sc) 1378198157Srrs{ 1379198157Srrs struct driver_data *priv = &(sc->priv); 1380198626Srrs uint32_t regval; 1381198157Srrs 1382198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_FILTER_CONFIG); 1383198626Srrs 1384198157Srrs if (sc->flags & IFF_PROMISC) { 1385198157Srrs regval |= (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) | 1386198626Srrs (1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) | 1387198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) | 1388198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN); 1389198157Srrs } else { 1390198157Srrs regval &= ~((1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) | 1391198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN)); 1392198157Srrs } 1393198157Srrs 1394198157Srrs xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG, regval); 1395198157Srrs} 1396198157Srrs 1397198157Srrs/********************************************************************** 1398198157Srrs * Configure LAN speed for the specified MAC. 1399198157Srrs ********************************************************************* */ 1400198626Srrsstatic int 1401198157Srrsrmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed) 1402198157Srrs{ 1403198157Srrs return 0; 1404198157Srrs} 1405198157Srrs 1406198157Srrs/********************************************************************** 1407198157Srrs * Set Ethernet duplex and flow control options for this MAC 1408198157Srrs ********************************************************************* */ 1409198626Srrsstatic int 1410198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s, 1411198626Srrs xlr_mac_duplex_t duplex, xlr_mac_fc_t fc) 1412198157Srrs{ 1413198157Srrs return 0; 1414198157Srrs} 1415198157Srrs 1416198157Srrs/***************************************************************** 1417198157Srrs * Kernel Net Stack <-> MAC Driver Interface 1418198157Srrs *****************************************************************/ 1419198157Srrs/********************************************************************** 1420198157Srrs **********************************************************************/ 1421198157Srrs#define MAC_TX_FAIL 2 1422198157Srrs#define MAC_TX_PASS 0 1423198157Srrs#define MAC_TX_RETRY 1 1424198157Srrs 1425198626Srrsstatic __inline__ void 1426198157Srrsmessage_send_block(unsigned int size, unsigned int code, 1427198626Srrs unsigned int stid, struct msgrng_msg *msg) 1428198157Srrs{ 1429198626Srrs unsigned int dest = 0; 1430198157Srrs unsigned long long status = 0; 1431198157Srrs 1432198157Srrs msgrng_load_tx_msg0(msg->msg0); 1433198157Srrs msgrng_load_tx_msg1(msg->msg1); 1434198157Srrs msgrng_load_tx_msg2(msg->msg2); 1435198157Srrs msgrng_load_tx_msg3(msg->msg3); 1436198157Srrs 1437198157Srrs dest = ((size - 1) << 16) | (code << 8) | (stid); 1438198157Srrs 1439198157Srrs do { 1440198157Srrs msgrng_send(dest); 1441198157Srrs status = msgrng_read_status(); 1442198157Srrs } while (status & 0x6); 1443198157Srrs 1444198157Srrs} 1445198157Srrs 1446198626Srrsint xlr_dev_queue_xmit_hack = 0; 1447198157Srrs 1448198626Srrsstatic int 1449198157Srrsmac_xmit(struct mbuf *m, struct rge_softc *sc, 1450198626Srrs struct driver_data *priv, int len, struct p2d_tx_desc *tx_desc) 1451198157Srrs{ 1452198157Srrs struct msgrng_msg msg; 1453198626Srrs int stid = priv->txbucket; 1454198626Srrs uint32_t tx_cycles = 0; 1455198626Srrs unsigned long mflags = 0; 1456198157Srrs int vcpu = PCPU_GET(cpuid); 1457198157Srrs int rv; 1458198157Srrs 1459198157Srrs tx_cycles = mips_rd_count(); 1460198157Srrs 1461198157Srrs if (build_frag_list(m, &msg, tx_desc) != 0) 1462198157Srrs return MAC_TX_FAIL; 1463198157Srrs 1464198157Srrs else { 1465198157Srrs msgrng_access_enable(mflags); 1466198157Srrs if ((rv = message_send_retry(1, MSGRNG_CODE_MAC, stid, &msg)) != 0) { 1467198157Srrs msg_snd_failed++; 1468198157Srrs msgrng_access_disable(mflags); 1469198157Srrs release_tx_desc(&msg, 0); 1470198157Srrs xlr_rge_msg_snd_failed[vcpu]++; 1471198626Srrs dbg_msg("Failed packet to cpu %d, rv = %d, stid %d, msg0=%llx\n", 1472198626Srrs vcpu, rv, stid, msg.msg0); 1473198157Srrs return MAC_TX_FAIL; 1474198157Srrs } 1475198157Srrs msgrng_access_disable(mflags); 1476198157Srrs port_inc_counter(priv->instance, PORT_TX); 1477198157Srrs } 1478198157Srrs 1479198157Srrs /* Send the packet to MAC */ 1480198157Srrs dbg_msg("Sent tx packet to stid %d, msg0=%llx, msg1=%llx \n", stid, msg.msg0, msg.msg1); 1481198157Srrs#ifdef DUMP_PACKETS 1482198157Srrs { 1483198626Srrs int i = 0; 1484198626Srrs unsigned char *buf = (char *)m->m_data; 1485198626Srrs 1486198157Srrs printf("Tx Packet: length=%d\n", len); 1487198157Srrs for (i = 0; i < 64; i++) { 1488198157Srrs if (i && (i % 16) == 0) 1489198157Srrs printf("\n"); 1490198157Srrs printf("%02x ", buf[i]); 1491198157Srrs } 1492198157Srrs printf("\n"); 1493198157Srrs } 1494198157Srrs#endif 1495198157Srrs xlr_inc_counter(NETIF_TX); 1496198157Srrs return MAC_TX_PASS; 1497198157Srrs} 1498198157Srrs 1499198626Srrsstatic int 1500198157Srrsrmi_xlr_mac_xmit(struct mbuf *m, struct rge_softc *sc, int len, struct p2d_tx_desc *tx_desc) 1501198157Srrs{ 1502198157Srrs struct driver_data *priv = &(sc->priv); 1503198626Srrs int ret = -ENOSPC; 1504198157Srrs 1505198157Srrs dbg_msg("IN\n"); 1506198157Srrs 1507198157Srrs xlr_inc_counter(NETIF_STACK_TX); 1508198157Srrs 1509198157Srrsretry: 1510198157Srrs ret = mac_xmit(m, sc, priv, len, tx_desc); 1511198157Srrs 1512198157Srrs if (ret == MAC_TX_RETRY) 1513198157Srrs goto retry; 1514198157Srrs 1515198157Srrs dbg_msg("OUT, ret = %d\n", ret); 1516198157Srrs if (ret == MAC_TX_FAIL) { 1517198157Srrs /* FULL */ 1518198157Srrs dbg_msg("Msg Ring Full. Stopping upper layer Q\n"); 1519198157Srrs port_inc_counter(priv->instance, PORT_STOPQ); 1520198157Srrs } 1521198157Srrs return ret; 1522198157Srrs} 1523198157Srrs 1524198626Srrsstatic void 1525198157Srrsmac_frin_replenish(void *args /* ignored */ ) 1526198157Srrs{ 1527208165Srrs int cpu = xlr_core_id(); 1528198626Srrs int done = 0; 1529198626Srrs int i = 0; 1530198157Srrs 1531198157Srrs xlr_inc_counter(REPLENISH_ENTER); 1532198157Srrs /* 1533198157Srrs * xlr_set_counter(REPLENISH_ENTER_COUNT, 1534198157Srrs * atomic_read(frin_to_be_sent)); 1535198157Srrs */ 1536198157Srrs xlr_set_counter(REPLENISH_CPU, PCPU_GET(cpuid)); 1537198157Srrs 1538198157Srrs for (;;) { 1539198157Srrs 1540198157Srrs done = 0; 1541198157Srrs 1542198157Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 1543198157Srrs /* int offset = 0; */ 1544198626Srrs unsigned long msgrng_flags; 1545198626Srrs void *m; 1546198626Srrs uint32_t cycles; 1547198157Srrs struct rge_softc *sc; 1548198157Srrs struct driver_data *priv; 1549198626Srrs int frin_to_be_sent; 1550198157Srrs 1551198157Srrs sc = dev_mac[i]; 1552198157Srrs if (!sc) 1553198157Srrs goto skip; 1554198157Srrs 1555198157Srrs priv = &(sc->priv); 1556198157Srrs frin_to_be_sent = priv->frin_to_be_sent[cpu]; 1557198157Srrs 1558198157Srrs /* if (atomic_read(frin_to_be_sent) < 0) */ 1559198157Srrs if (frin_to_be_sent < 0) { 1560198626Srrs panic("BUG?: [%s]: gmac_%d illegal value for frin_to_be_sent=%d\n", 1561198626Srrs __FUNCTION__, i, 1562198626Srrs frin_to_be_sent); 1563198157Srrs } 1564198157Srrs /* if (!atomic_read(frin_to_be_sent)) */ 1565198157Srrs if (!frin_to_be_sent) 1566198157Srrs goto skip; 1567198157Srrs 1568198157Srrs cycles = mips_rd_count(); 1569198157Srrs { 1570198157Srrs m = get_buf(); 1571198157Srrs if (!m) { 1572198157Srrs device_printf(sc->rge_dev, "No buffer\n"); 1573198157Srrs goto skip; 1574198157Srrs } 1575198157Srrs } 1576198157Srrs xlr_inc_counter(REPLENISH_FRIN); 1577198157Srrs msgrng_access_enable(msgrng_flags); 1578198157Srrs if (xlr_mac_send_fr(priv, vtophys(m), MAX_FRAME_SIZE)) { 1579198157Srrs free_buf(vtophys(m)); 1580198157Srrs printf("[%s]: rx free message_send failed!\n", __FUNCTION__); 1581198157Srrs msgrng_access_disable(msgrng_flags); 1582198157Srrs break; 1583198157Srrs } 1584198157Srrs msgrng_access_disable(msgrng_flags); 1585198157Srrs xlr_set_counter(REPLENISH_CYCLES, 1586198626Srrs (read_c0_count() - cycles)); 1587198157Srrs atomic_subtract_int((&priv->frin_to_be_sent[cpu]), 1); 1588198157Srrs 1589198157Srrs continue; 1590198157Srrs skip: 1591198157Srrs done++; 1592198157Srrs } 1593198157Srrs if (done == XLR_MAX_MACS) 1594198157Srrs break; 1595198157Srrs } 1596198157Srrs} 1597198157Srrs 1598203010Srrsstatic volatile uint32_t g_tx_frm_tx_ok=0; 1599198157Srrs 1600198626Srrsstatic void 1601198157Srrsrge_tx_bkp_func(void *arg, int npending) 1602198157Srrs{ 1603198626Srrs int i = 0; 1604198626Srrs 1605198626Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 1606198157Srrs if (!dev_mac[i] || !dev_mac[i]->active) 1607198157Srrs continue; 1608198157Srrs rge_start_locked(dev_mac[i]->rge_ifp, RGE_TX_THRESHOLD); 1609198157Srrs } 1610198157Srrs atomic_subtract_int(&g_tx_frm_tx_ok, 1); 1611198157Srrs} 1612198157Srrs 1613198157Srrs/* This function is called from an interrupt handler */ 1614198626Srrsvoid 1615198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code, 1616198626Srrs int stid, struct msgrng_msg *msg, 1617198626Srrs void *data /* ignored */ ) 1618198157Srrs{ 1619198626Srrs uint64_t phys_addr = 0; 1620198626Srrs unsigned long addr = 0; 1621198626Srrs uint32_t length = 0; 1622198626Srrs int ctrl = 0, port = 0; 1623198157Srrs struct rge_softc *sc = NULL; 1624198157Srrs struct driver_data *priv = 0; 1625198626Srrs struct ifnet *ifp; 1626208165Srrs int vcpu = xlr_cpu_id(); 1627208165Srrs int cpu = xlr_core_id(); 1628198157Srrs 1629198157Srrs dbg_msg("mac: bucket=%d, size=%d, code=%d, stid=%d, msg0=%llx msg1=%llx\n", 1630198626Srrs bucket, size, code, stid, msg->msg0, msg->msg1); 1631198157Srrs 1632198157Srrs phys_addr = (uint64_t) (msg->msg0 & 0xffffffffe0ULL); 1633198157Srrs length = (msg->msg0 >> 40) & 0x3fff; 1634198157Srrs if (length == 0) { 1635198157Srrs ctrl = CTRL_REG_FREE; 1636198157Srrs port = (msg->msg0 >> 54) & 0x0f; 1637198157Srrs addr = 0; 1638198157Srrs } else { 1639198157Srrs ctrl = CTRL_SNGL; 1640198157Srrs length = length - BYTE_OFFSET - MAC_CRC_LEN; 1641198157Srrs port = msg->msg0 & 0x0f; 1642198157Srrs addr = 0; 1643198157Srrs } 1644198157Srrs 1645198157Srrs if (xlr_board_info.is_xls) { 1646198157Srrs if (stid == MSGRNG_STNID_GMAC1) 1647198157Srrs port += 4; 1648198157Srrs sc = dev_mac[dev_mac_gmac0 + port]; 1649198157Srrs } else { 1650198157Srrs if (stid == MSGRNG_STNID_XGS0FR) 1651198157Srrs sc = dev_mac[dev_mac_xgs0]; 1652198157Srrs else if (stid == MSGRNG_STNID_XGS1FR) 1653198157Srrs sc = dev_mac[dev_mac_xgs0 + 1]; 1654198626Srrs else 1655198157Srrs sc = dev_mac[dev_mac_gmac0 + port]; 1656198157Srrs } 1657198157Srrs if (sc == NULL) 1658198157Srrs return; 1659198157Srrs priv = &(sc->priv); 1660198157Srrs 1661198157Srrs dbg_msg("msg0 = %llx, stid = %d, port = %d, addr=%lx, length=%d, ctrl=%d\n", 1662198626Srrs msg->msg0, stid, port, addr, length, ctrl); 1663198157Srrs 1664198157Srrs if (ctrl == CTRL_REG_FREE || ctrl == CTRL_JUMBO_FREE) { 1665198157Srrs xlr_rge_tx_ok_done[vcpu]++; 1666198157Srrs release_tx_desc(msg, 1); 1667198157Srrs ifp = sc->rge_ifp; 1668198626Srrs if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { 1669198157Srrs ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1670198157Srrs } 1671198626Srrs if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1)) 1672198626Srrs rge_tx_bkp_func(NULL, 0); 1673198157Srrs xlr_set_counter(NETIF_TX_COMPLETE_CYCLES, 1674198626Srrs (read_c0_count() - msgrng_msg_cycles)); 1675198157Srrs } else if (ctrl == CTRL_SNGL || ctrl == CTRL_START) { 1676198157Srrs /* Rx Packet */ 1677198157Srrs /* struct mbuf *m = 0; */ 1678198157Srrs /* int logical_cpu = 0; */ 1679198157Srrs 1680198157Srrs dbg_msg("Received packet, port = %d\n", port); 1681198157Srrs /* 1682198157Srrs * if num frins to be sent exceeds threshold, wake up the 1683198157Srrs * helper thread 1684198157Srrs */ 1685198157Srrs atomic_add_int(&(priv->frin_to_be_sent[cpu]), 1); 1686198157Srrs if ((priv->frin_to_be_sent[cpu]) > MAC_FRIN_TO_BE_SENT_THRESHOLD) { 1687198157Srrs mac_frin_replenish(NULL); 1688198157Srrs } 1689198157Srrs dbg_msg("gmac_%d: rx packet: phys_addr = %llx, length = %x\n", 1690198626Srrs priv->instance, phys_addr, length); 1691198157Srrs mac_stats_add(priv->stats.rx_packets, 1); 1692198157Srrs mac_stats_add(priv->stats.rx_bytes, length); 1693198157Srrs xlr_inc_counter(NETIF_RX); 1694198157Srrs xlr_set_counter(NETIF_RX_CYCLES, 1695198626Srrs (read_c0_count() - msgrng_msg_cycles)); 1696198157Srrs rge_rx(sc, phys_addr, length); 1697198157Srrs xlr_rge_rx_done[vcpu]++; 1698198157Srrs } else { 1699198157Srrs printf("[%s]: unrecognized ctrl=%d!\n", __FUNCTION__, ctrl); 1700198157Srrs } 1701198157Srrs 1702198157Srrs} 1703198157Srrs 1704198157Srrs/********************************************************************** 1705198157Srrs **********************************************************************/ 1706198157Srrsstatic int 1707198157Srrsrge_probe(dev) 1708198626Srrs device_t dev; 1709198157Srrs{ 1710208265Srpaulo device_set_desc(dev, "RMI Gigabit Ethernet"); 1711208265Srpaulo 1712198157Srrs /* Always return 0 */ 1713198157Srrs return 0; 1714198157Srrs} 1715198157Srrs 1716198157Srrsvolatile unsigned long xlr_debug_enabled; 1717198626Srrsstruct callout rge_dbg_count; 1718199139Srrsstatic void 1719198626Srrsxlr_debug_count(void *addr) 1720198157Srrs{ 1721198157Srrs struct driver_data *priv = &dev_mac[0]->priv; 1722198626Srrs 1723198626Srrs /* uint32_t crdt; */ 1724198626Srrs if (xlr_debug_enabled) { 1725198626Srrs printf("\nAvailRxIn %#x\n", xlr_read_reg(priv->mmio, 0x23e)); 1726198157Srrs } 1727198157Srrs callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL); 1728198157Srrs} 1729198157Srrs 1730198157Srrs 1731199139Srrsstatic void 1732198626Srrsxlr_tx_q_wakeup(void *addr) 1733198157Srrs{ 1734198626Srrs int i = 0; 1735198626Srrs int j = 0; 1736198626Srrs 1737198626Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 1738198157Srrs if (!dev_mac[i] || !dev_mac[i]->active) 1739198157Srrs continue; 1740198626Srrs if ((dev_mac[i]->rge_ifp->if_drv_flags) & IFF_DRV_OACTIVE) { 1741198626Srrs for (j = 0; j < XLR_MAX_CORE; j++) { 1742198626Srrs if (xlr_tot_avail_p2d[j]) { 1743198157Srrs dev_mac[i]->rge_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1744198157Srrs break; 1745198157Srrs } 1746198157Srrs } 1747198157Srrs } 1748198157Srrs } 1749203010Srrs if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1)) 1750203010Srrs rge_tx_bkp_func(NULL, 0); 1751198626Srrs callout_reset(&xlr_tx_stop_bkp, 5 * hz, xlr_tx_q_wakeup, NULL); 1752198157Srrs} 1753198157Srrs 1754198157Srrsstatic int 1755198608Srrsrge_attach(device_t dev) 1756198157Srrs{ 1757198626Srrs struct ifnet *ifp; 1758198157Srrs struct rge_softc *sc; 1759198157Srrs struct driver_data *priv = 0; 1760198626Srrs int ret = 0; 1761198157Srrs struct xlr_gmac_block_t *gmac_conf = device_get_ivars(dev); 1762198157Srrs 1763198157Srrs sc = device_get_softc(dev); 1764198157Srrs sc->rge_dev = dev; 1765198157Srrs 1766198157Srrs /* Initialize mac's */ 1767198157Srrs sc->unit = device_get_unit(dev); 1768198157Srrs 1769198157Srrs if (sc->unit > XLR_MAX_MACS) { 1770198157Srrs ret = ENXIO; 1771198157Srrs goto out; 1772198157Srrs } 1773198157Srrs RGE_LOCK_INIT(sc, device_get_nameunit(dev)); 1774198157Srrs 1775198157Srrs priv = &(sc->priv); 1776198157Srrs priv->sc = sc; 1777198157Srrs 1778198157Srrs sc->flags = 0; /* TODO : fix me up later */ 1779198157Srrs 1780198157Srrs priv->id = sc->unit; 1781198157Srrs if (gmac_conf->type == XLR_GMAC) { 1782198157Srrs priv->instance = priv->id; 1783198626Srrs priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr + 1784198626Srrs 0x1000 * (sc->unit % 4)); 1785198157Srrs if ((ret = rmi_xlr_gmac_reset(priv)) == -1) 1786198157Srrs goto out; 1787198157Srrs } else if (gmac_conf->type == XLR_XGMAC) { 1788198157Srrs priv->instance = priv->id - xlr_board_info.gmacports; 1789198157Srrs priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr); 1790198157Srrs } 1791198157Srrs if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI) { 1792198157Srrs dbg_msg("Arizona board - offset 4 \n"); 1793198626Srrs priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_4_OFFSET); 1794198157Srrs } else 1795198626Srrs priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET); 1796198157Srrs 1797198626Srrs priv->pcs_mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr); 1798198626Srrs priv->serdes_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET); 1799198157Srrs 1800198626Srrs sc->base_addr = (unsigned long)priv->mmio; 1801198626Srrs sc->mem_end = (unsigned long)priv->mmio + XLR_IO_SIZE - 1; 1802198157Srrs 1803198157Srrs sc->xmit = rge_start; 1804198157Srrs sc->stop = rge_stop; 1805198157Srrs sc->get_stats = rmi_xlr_mac_get_stats; 1806198157Srrs sc->ioctl = rge_ioctl; 1807198157Srrs 1808198157Srrs /* Initialize the device specific driver data */ 1809198157Srrs mtx_init(&priv->lock, "rge", NULL, MTX_SPIN); 1810198157Srrs 1811198157Srrs priv->type = gmac_conf->type; 1812198157Srrs 1813198157Srrs priv->mode = gmac_conf->mode; 1814198157Srrs if (xlr_board_info.is_xls == 0) { 1815198157Srrs if (xlr_board_atx_ii() && !xlr_board_atx_ii_b()) 1816198157Srrs priv->phy_addr = priv->instance - 2; 1817198157Srrs else 1818198157Srrs priv->phy_addr = priv->instance; 1819198157Srrs priv->mode = XLR_RGMII; 1820198626Srrs } else { 1821198157Srrs if (gmac_conf->mode == XLR_PORT0_RGMII && 1822198626Srrs priv->instance == 0) { 1823198626Srrs priv->mode = XLR_PORT0_RGMII; 1824198157Srrs priv->phy_addr = 0; 1825198626Srrs } else { 1826198626Srrs priv->mode = XLR_SGMII; 1827198157Srrs priv->phy_addr = priv->instance + 16; 1828198157Srrs } 1829198157Srrs } 1830198157Srrs 1831198157Srrs priv->txbucket = gmac_conf->station_txbase + priv->instance % 4; 1832198626Srrs priv->rfrbucket = gmac_conf->station_rfr; 1833198157Srrs priv->spill_configured = 0; 1834198157Srrs 1835198157Srrs dbg_msg("priv->mmio=%p\n", priv->mmio); 1836198157Srrs 1837198157Srrs /* Set up ifnet structure */ 1838198157Srrs ifp = sc->rge_ifp = if_alloc(IFT_ETHER); 1839198157Srrs if (ifp == NULL) { 1840198157Srrs device_printf(sc->rge_dev, "failed to if_alloc()\n"); 1841198157Srrs rge_release_resources(sc); 1842198157Srrs ret = ENXIO; 1843198157Srrs RGE_LOCK_DESTROY(sc); 1844198157Srrs goto out; 1845198157Srrs } 1846198157Srrs ifp->if_softc = sc; 1847198157Srrs if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1848198157Srrs ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1849198157Srrs ifp->if_ioctl = rge_ioctl; 1850198157Srrs ifp->if_start = rge_start; 1851198157Srrs ifp->if_init = rge_init; 1852198157Srrs ifp->if_mtu = ETHERMTU; 1853198157Srrs ifp->if_snd.ifq_drv_maxlen = RGE_TX_Q_SIZE; 1854198157Srrs IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 1855198157Srrs IFQ_SET_READY(&ifp->if_snd); 1856198157Srrs sc->active = 1; 1857198626Srrs ifp->if_hwassist = 0; 1858198626Srrs ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING; 1859198157Srrs ifp->if_capenable = ifp->if_capabilities; 1860198157Srrs 1861198157Srrs /* Initialize the rge_softc */ 1862198157Srrs sc->irq = gmac_conf->baseirq + priv->instance % 4; 1863198157Srrs 1864198608Srrs /* Set the IRQ into the rid field */ 1865199139Srrs /* 1866199139Srrs * note this is a hack to pass the irq to the iodi interrupt setup 1867199139Srrs * routines 1868199139Srrs */ 1869199091Srrs sc->rge_irq.__r_i = (struct resource_i *)sc->irq; 1870198608Srrs 1871198157Srrs ret = bus_setup_intr(dev, &sc->rge_irq, INTR_FAST | INTR_TYPE_NET | INTR_MPSAFE, 1872198626Srrs NULL, rge_intr, sc, &sc->rge_intrhand); 1873198157Srrs 1874198157Srrs if (ret) { 1875198157Srrs rge_detach(dev); 1876198157Srrs device_printf(sc->rge_dev, "couldn't set up irq\n"); 1877198157Srrs RGE_LOCK_DESTROY(sc); 1878198157Srrs goto out; 1879198157Srrs } 1880198157Srrs xlr_mac_get_hwaddr(sc); 1881198157Srrs xlr_mac_setup_hwaddr(priv); 1882198157Srrs 1883198157Srrs dbg_msg("MMIO %08lx, MII %08lx, PCS %08lx, base %08lx PHY %d IRQ %d\n", 1884198626Srrs (u_long)priv->mmio, (u_long)priv->mii_mmio, (u_long)priv->pcs_mmio, 1885198626Srrs (u_long)sc->base_addr, priv->phy_addr, sc->irq); 1886198626Srrs dbg_msg("HWADDR %02x:%02x tx %d rfr %d\n", (u_int)sc->dev_addr[4], 1887198626Srrs (u_int)sc->dev_addr[5], priv->txbucket, priv->rfrbucket); 1888198157Srrs 1889198157Srrs /* 1890198157Srrs * Set up ifmedia support. 1891198157Srrs */ 1892198157Srrs /* 1893198157Srrs * Initialize MII/media info. 1894198157Srrs */ 1895198157Srrs sc->rge_mii.mii_ifp = ifp; 1896198157Srrs sc->rge_mii.mii_readreg = rge_mii_read; 1897198626Srrs sc->rge_mii.mii_writereg = (mii_writereg_t) rge_mii_write; 1898198157Srrs sc->rge_mii.mii_statchg = rmi_xlr_mac_mii_statchg; 1899198157Srrs ifmedia_init(&sc->rge_mii.mii_media, 0, rmi_xlr_mac_mediachange, 1900198626Srrs rmi_xlr_mac_mediastatus); 1901198157Srrs ifmedia_add(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL); 1902198157Srrs ifmedia_set(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO); 1903198157Srrs sc->rge_mii.mii_media.ifm_media = sc->rge_mii.mii_media.ifm_cur->ifm_media; 1904198157Srrs 1905198157Srrs /* 1906198157Srrs * Call MI attach routine. 1907198157Srrs */ 1908198157Srrs ether_ifattach(ifp, sc->dev_addr); 1909198157Srrs 1910198157Srrs if (priv->type == XLR_GMAC) { 1911198157Srrs rmi_xlr_gmac_init(priv); 1912198157Srrs } else if (priv->type == XLR_XGMAC) { 1913198157Srrs rmi_xlr_xgmac_init(priv); 1914198157Srrs } 1915198157Srrs dbg_msg("rge_%d: Phoenix Mac at 0x%p (mtu=%d)\n", 1916198626Srrs sc->unit, priv->mmio, sc->mtu); 1917198157Srrs dev_mac[sc->unit] = sc; 1918198157Srrs if (priv->type == XLR_XGMAC && priv->instance == 0) 1919198157Srrs dev_mac_xgs0 = sc->unit; 1920198157Srrs if (priv->type == XLR_GMAC && priv->instance == 0) 1921198157Srrs dev_mac_gmac0 = sc->unit; 1922198157Srrs 1923198626Srrs if (!gmac_common_init_done) { 1924198157Srrs mac_common_init(); 1925198157Srrs gmac_common_init_done = 1; 1926198157Srrs callout_init(&xlr_tx_stop_bkp, CALLOUT_MPSAFE); 1927198157Srrs callout_reset(&xlr_tx_stop_bkp, hz, xlr_tx_q_wakeup, NULL); 1928198157Srrs callout_init(&rge_dbg_count, CALLOUT_MPSAFE); 1929198626Srrs //callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL); 1930198157Srrs } 1931198157Srrs if ((ret = rmi_xlr_mac_open(sc)) == -1) { 1932198157Srrs RGE_LOCK_DESTROY(sc); 1933198157Srrs goto out; 1934198157Srrs } 1935198157Srrsout: 1936198157Srrs if (ret < 0) { 1937198157Srrs device_printf(dev, "error - skipping\n"); 1938198157Srrs } 1939198157Srrs return ret; 1940198157Srrs} 1941198157Srrs 1942198626Srrsstatic void 1943198157Srrsrge_reset(struct rge_softc *sc) 1944198157Srrs{ 1945198157Srrs} 1946198157Srrs 1947198157Srrsstatic int 1948198157Srrsrge_detach(dev) 1949198626Srrs device_t dev; 1950198157Srrs{ 1951198157Srrs#ifdef FREEBSD_MAC_NOT_YET 1952198157Srrs struct rge_softc *sc; 1953198626Srrs struct ifnet *ifp; 1954198157Srrs 1955198157Srrs sc = device_get_softc(dev); 1956198157Srrs ifp = sc->rge_ifp; 1957198157Srrs 1958198157Srrs RGE_LOCK(sc); 1959198157Srrs rge_stop(sc); 1960198157Srrs rge_reset(sc); 1961198157Srrs RGE_UNLOCK(sc); 1962198157Srrs 1963198157Srrs ether_ifdetach(ifp); 1964198157Srrs 1965198157Srrs if (sc->rge_tbi) { 1966198157Srrs ifmedia_removeall(&sc->rge_ifmedia); 1967198157Srrs } else { 1968198157Srrs bus_generic_detach(dev); 1969198157Srrs device_delete_child(dev, sc->rge_miibus); 1970198157Srrs } 1971198157Srrs 1972198157Srrs rge_release_resources(sc); 1973198157Srrs 1974198157Srrs#endif /* FREEBSD_MAC_NOT_YET */ 1975198157Srrs return (0); 1976198157Srrs} 1977198626Srrsstatic int 1978198157Srrsrge_suspend(device_t dev) 1979198157Srrs{ 1980198157Srrs struct rge_softc *sc; 1981198157Srrs 1982198157Srrs sc = device_get_softc(dev); 1983198157Srrs RGE_LOCK(sc); 1984198157Srrs rge_stop(sc); 1985198157Srrs RGE_UNLOCK(sc); 1986198157Srrs 1987198157Srrs return 0; 1988198157Srrs} 1989198157Srrs 1990198626Srrsstatic int 1991198157Srrsrge_resume(device_t dev) 1992198157Srrs{ 1993198157Srrs panic("rge_resume(): unimplemented\n"); 1994198157Srrs return 0; 1995198157Srrs} 1996198157Srrs 1997198626Srrsstatic void 1998198157Srrsrge_release_resources(struct rge_softc *sc) 1999198157Srrs{ 2000198157Srrs 2001198157Srrs if (sc->rge_ifp != NULL) 2002198157Srrs if_free(sc->rge_ifp); 2003198157Srrs 2004198157Srrs if (mtx_initialized(&sc->rge_mtx)) /* XXX */ 2005198157Srrs RGE_LOCK_DESTROY(sc); 2006198157Srrs} 2007198626Srrsuint32_t gmac_rx_fail[32]; 2008198626Srrsuint32_t gmac_rx_pass[32]; 2009198157Srrs 2010198626Srrsstatic void 2011198157Srrsrge_rx(struct rge_softc *sc, vm_paddr_t paddr, int len) 2012198157Srrs{ 2013198626Srrs struct mbuf *m; 2014208165Srrs uint32_t tm, mag, sr; 2015198626Srrs struct ifnet *ifp = sc->rge_ifp; 2016198157Srrs 2017208165Srrs sr = xlr_enable_kx(); 2018208165Srrs tm = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE); 2019208165Srrs mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t)); 2020208165Srrs mips_wr_status(sr); 2021198157Srrs 2022199139Srrs m = (struct mbuf *)tm; 2023198157Srrs if (mag != 0xf00bad) { 2024198157Srrs /* somebody else packet Error - FIXME in intialization */ 2025198626Srrs printf("cpu %d: *ERROR* Not my packet paddr %p\n", xlr_cpu_id(), (void *)paddr); 2026198157Srrs return; 2027198157Srrs } 2028198157Srrs /* align the data */ 2029198157Srrs m->m_data += BYTE_OFFSET; 2030198157Srrs m->m_pkthdr.len = m->m_len = len; 2031198157Srrs m->m_pkthdr.rcvif = ifp; 2032198157Srrs 2033198157Srrs#ifdef DUMP_PACKETS 2034198157Srrs { 2035198626Srrs int i = 0; 2036198626Srrs unsigned char *buf = (char *)m->m_data; 2037198626Srrs 2038198157Srrs printf("Rx Packet: length=%d\n", len); 2039198157Srrs for (i = 0; i < 64; i++) { 2040198157Srrs if (i && (i % 16) == 0) 2041198157Srrs printf("\n"); 2042198157Srrs printf("%02x ", buf[i]); 2043198157Srrs } 2044198157Srrs printf("\n"); 2045198157Srrs } 2046198157Srrs#endif 2047198157Srrs ifp->if_ipackets++; 2048198157Srrs (*ifp->if_input) (ifp, m); 2049198157Srrs} 2050198626Srrs 2051198626Srrsstatic void 2052198157Srrsrge_intr(void *arg) 2053198157Srrs{ 2054198157Srrs struct rge_softc *sc = (struct rge_softc *)arg; 2055198157Srrs struct driver_data *priv = &(sc->priv); 2056198626Srrs xlr_reg_t *mmio = priv->mmio; 2057198626Srrs uint32_t intreg = xlr_read_reg(mmio, R_INTREG); 2058198157Srrs 2059198157Srrs if (intreg & (1 << O_INTREG__MDInt)) { 2060198626Srrs uint32_t phy_int_status = 0; 2061198626Srrs int i = 0; 2062198157Srrs 2063198157Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 2064198157Srrs struct rge_softc *phy_dev = 0; 2065198157Srrs struct driver_data *phy_priv = 0; 2066198157Srrs 2067198157Srrs phy_dev = dev_mac[i]; 2068198157Srrs if (phy_dev == NULL) 2069198157Srrs continue; 2070198157Srrs 2071198157Srrs phy_priv = &phy_dev->priv; 2072198157Srrs 2073198157Srrs if (phy_priv->type == XLR_XGMAC) 2074198157Srrs continue; 2075198157Srrs 2076198157Srrs phy_int_status = rge_mii_read_internal(phy_priv->mii_mmio, 2077198626Srrs phy_priv->phy_addr, 26); 2078198157Srrs printf("rge%d: Phy addr %d, MII MMIO %lx status %x\n", phy_priv->instance, 2079198626Srrs (int)phy_priv->phy_addr, (u_long)phy_priv->mii_mmio, phy_int_status); 2080198157Srrs rmi_xlr_gmac_config_speed(phy_priv); 2081198157Srrs } 2082198157Srrs } else { 2083198157Srrs printf("[%s]: mac type = %d, instance %d error " 2084198626Srrs "interrupt: INTREG = 0x%08x\n", 2085198626Srrs __FUNCTION__, priv->type, priv->instance, intreg); 2086198157Srrs } 2087198157Srrs 2088198157Srrs /* clear all interrupts and hope to make progress */ 2089198157Srrs xlr_write_reg(mmio, R_INTREG, 0xffffffff); 2090198157Srrs 2091198157Srrs /* on A0 and B0, xgmac interrupts are routed only to xgs_1 irq */ 2092198157Srrs if ((xlr_revision_b0()) && (priv->type == XLR_XGMAC)) { 2093198157Srrs struct rge_softc *xgs0_dev = dev_mac[dev_mac_xgs0]; 2094198157Srrs struct driver_data *xgs0_priv = &xgs0_dev->priv; 2095198626Srrs xlr_reg_t *xgs0_mmio = xgs0_priv->mmio; 2096198626Srrs uint32_t xgs0_intreg = xlr_read_reg(xgs0_mmio, R_INTREG); 2097198157Srrs 2098198157Srrs if (xgs0_intreg) { 2099198157Srrs printf("[%s]: mac type = %d, instance %d error " 2100198626Srrs "interrupt: INTREG = 0x%08x\n", 2101198626Srrs __FUNCTION__, xgs0_priv->type, xgs0_priv->instance, xgs0_intreg); 2102198157Srrs 2103198157Srrs xlr_write_reg(xgs0_mmio, R_INTREG, 0xffffffff); 2104198157Srrs } 2105198157Srrs } 2106198157Srrs} 2107198157Srrs 2108198626Srrsstatic void 2109198157Srrsrge_start_locked(struct ifnet *ifp, int threshold) 2110198157Srrs{ 2111198157Srrs struct rge_softc *sc = ifp->if_softc; 2112198626Srrs struct mbuf *m = NULL; 2113198626Srrs int prepend_pkt = 0; 2114198626Srrs int i = 0; 2115198626Srrs struct p2d_tx_desc *tx_desc = NULL; 2116208165Srrs int cpu = xlr_core_id(); 2117208165Srrs uint32_t vcpu = xlr_cpu_id(); 2118198157Srrs 2119198157Srrs if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 2120198157Srrs return; 2121198157Srrs 2122198626Srrs for (i = 0; i < xlr_tot_avail_p2d[cpu]; i++) { 2123198157Srrs if (IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 2124198157Srrs return; 2125198157Srrs tx_desc = get_p2d_desc(); 2126198626Srrs if (!tx_desc) { 2127198157Srrs xlr_rge_get_p2d_failed[vcpu]++; 2128198157Srrs return; 2129198157Srrs } 2130198157Srrs /* Grab a packet off the queue. */ 2131198157Srrs IFQ_DEQUEUE(&ifp->if_snd, m); 2132198626Srrs if (m == NULL) { 2133198157Srrs free_p2d_desc(tx_desc); 2134198157Srrs return; 2135198157Srrs } 2136198157Srrs prepend_pkt = rmi_xlr_mac_xmit(m, sc, 0, tx_desc); 2137198157Srrs 2138198157Srrs if (prepend_pkt) { 2139198157Srrs xlr_rge_tx_prepend[vcpu]++; 2140198157Srrs IF_PREPEND(&ifp->if_snd, m); 2141198157Srrs ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2142198157Srrs return; 2143198157Srrs } else { 2144198157Srrs ifp->if_opackets++; 2145198157Srrs xlr_rge_tx_done[vcpu]++; 2146198157Srrs } 2147198157Srrs } 2148198157Srrs} 2149198157Srrs 2150198626Srrsstatic void 2151198157Srrsrge_start(struct ifnet *ifp) 2152198157Srrs{ 2153198157Srrs rge_start_locked(ifp, RGE_TX_Q_SIZE); 2154198157Srrs} 2155198157Srrs 2156198626Srrsstatic int 2157198157Srrsrge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 2158198157Srrs{ 2159198157Srrs struct rge_softc *sc = ifp->if_softc; 2160198626Srrs struct ifreq *ifr = (struct ifreq *)data; 2161198626Srrs int mask, error = 0; 2162198626Srrs 2163198157Srrs /* struct mii_data *mii; */ 2164198157Srrs switch (command) { 2165198157Srrs case SIOCSIFMTU: 2166198157Srrs ifp->if_mtu = ifr->ifr_mtu; 2167198157Srrs error = rmi_xlr_mac_change_mtu(sc, ifr->ifr_mtu); 2168198157Srrs break; 2169198157Srrs case SIOCSIFFLAGS: 2170198157Srrs 2171198157Srrs RGE_LOCK(sc); 2172198157Srrs if (ifp->if_flags & IFF_UP) { 2173198157Srrs /* 2174198157Srrs * If only the state of the PROMISC flag changed, 2175198157Srrs * then just use the 'set promisc mode' command 2176198157Srrs * instead of reinitializing the entire NIC. Doing a 2177198157Srrs * full re-init means reloading the firmware and 2178198157Srrs * waiting for it to start up, which may take a 2179198157Srrs * second or two. Similarly for ALLMULTI. 2180198157Srrs */ 2181198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2182198157Srrs ifp->if_flags & IFF_PROMISC && 2183198157Srrs !(sc->flags & IFF_PROMISC)) { 2184198157Srrs sc->flags |= IFF_PROMISC; 2185198157Srrs xlr_mac_set_rx_mode(sc); 2186198157Srrs } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2187198626Srrs !(ifp->if_flags & IFF_PROMISC) && 2188198626Srrs sc->flags & IFF_PROMISC) { 2189198157Srrs sc->flags &= IFF_PROMISC; 2190198157Srrs xlr_mac_set_rx_mode(sc); 2191198157Srrs } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2192198626Srrs (ifp->if_flags ^ sc->flags) & IFF_ALLMULTI) { 2193198157Srrs rmi_xlr_mac_set_multicast_list(sc); 2194198157Srrs } else 2195198157Srrs xlr_mac_set_rx_mode(sc); 2196198157Srrs } else { 2197198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2198198157Srrs xlr_mac_set_rx_mode(sc); 2199198157Srrs } 2200198157Srrs } 2201198157Srrs sc->flags = ifp->if_flags; 2202198157Srrs RGE_UNLOCK(sc); 2203198157Srrs error = 0; 2204198157Srrs break; 2205198157Srrs case SIOCADDMULTI: 2206198157Srrs case SIOCDELMULTI: 2207198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2208198157Srrs RGE_LOCK(sc); 2209198157Srrs rmi_xlr_mac_set_multicast_list(sc); 2210198157Srrs RGE_UNLOCK(sc); 2211198157Srrs error = 0; 2212198157Srrs } 2213198157Srrs break; 2214198157Srrs case SIOCSIFMEDIA: 2215198157Srrs case SIOCGIFMEDIA: 2216198157Srrs error = ifmedia_ioctl(ifp, ifr, 2217198626Srrs &sc->rge_mii.mii_media, command); 2218198157Srrs break; 2219198157Srrs case SIOCSIFCAP: 2220198157Srrs mask = ifr->ifr_reqcap ^ ifp->if_capenable; 2221198157Srrs ifp->if_hwassist = 0; 2222198157Srrs break; 2223198157Srrs default: 2224198157Srrs error = ether_ioctl(ifp, command, data); 2225198157Srrs break; 2226198157Srrs } 2227198157Srrs 2228198157Srrs return (error); 2229198157Srrs} 2230198157Srrs 2231198626Srrsstatic void 2232198157Srrsrge_init(void *addr) 2233198157Srrs{ 2234198157Srrs struct rge_softc *sc = (struct rge_softc *)addr; 2235198626Srrs struct ifnet *ifp; 2236198157Srrs struct driver_data *priv = &(sc->priv); 2237198157Srrs 2238198157Srrs ifp = sc->rge_ifp; 2239198157Srrs 2240198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2241198157Srrs return; 2242198157Srrs ifp->if_drv_flags |= IFF_DRV_RUNNING; 2243198157Srrs ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2244198157Srrs 2245198157Srrs rmi_xlr_mac_set_enable(priv, 1); 2246198157Srrs} 2247198157Srrs 2248198626Srrsstatic void 2249198157Srrsrge_stop(struct rge_softc *sc) 2250198157Srrs{ 2251198157Srrs rmi_xlr_mac_close(sc); 2252198157Srrs} 2253198157Srrs 2254198608Srrsstatic int 2255198157Srrsrge_shutdown(device_t dev) 2256198157Srrs{ 2257198157Srrs struct rge_softc *sc; 2258198626Srrs 2259198157Srrs sc = device_get_softc(dev); 2260198157Srrs 2261198157Srrs RGE_LOCK(sc); 2262198157Srrs rge_stop(sc); 2263198157Srrs rge_reset(sc); 2264198157Srrs RGE_UNLOCK(sc); 2265198157Srrs 2266198626Srrs return (0); 2267198157Srrs} 2268198157Srrs 2269198626Srrsstatic int 2270198157Srrsrmi_xlr_mac_open(struct rge_softc *sc) 2271198157Srrs{ 2272198157Srrs struct driver_data *priv = &(sc->priv); 2273198157Srrs int i; 2274198157Srrs 2275198157Srrs dbg_msg("IN\n"); 2276198157Srrs 2277198157Srrs if (rmi_xlr_mac_fill_rxfr(sc)) { 2278198157Srrs return -1; 2279198157Srrs } 2280198157Srrs mtx_lock_spin(&priv->lock); 2281198157Srrs 2282198157Srrs xlr_mac_set_rx_mode(sc); 2283198157Srrs 2284198157Srrs if (sc->unit == xlr_board_info.gmacports - 1) { 2285198157Srrs printf("Enabling MDIO interrupts\n"); 2286198157Srrs struct rge_softc *tmp = NULL; 2287198626Srrs 2288198157Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 2289198157Srrs tmp = dev_mac[i]; 2290198157Srrs if (tmp) 2291198157Srrs xlr_write_reg(tmp->priv.mmio, R_INTMASK, 2292198626Srrs ((tmp->priv.instance == 0) << O_INTMASK__MDInt)); 2293198157Srrs } 2294198157Srrs } 2295198157Srrs /* 2296198157Srrs * Configure the speed, duplex, and flow control 2297198157Srrs */ 2298198157Srrs rmi_xlr_mac_set_speed(priv, priv->speed); 2299198157Srrs rmi_xlr_mac_set_duplex(priv, priv->duplex, priv->flow_ctrl); 2300198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2301198157Srrs 2302198157Srrs mtx_unlock_spin(&priv->lock); 2303198157Srrs 2304198157Srrs for (i = 0; i < 8; i++) { 2305198157Srrs atomic_set_int(&(priv->frin_to_be_sent[i]), 0); 2306198157Srrs } 2307198157Srrs 2308198157Srrs return 0; 2309198157Srrs} 2310198157Srrs 2311198157Srrs/********************************************************************** 2312198157Srrs **********************************************************************/ 2313198626Srrsstatic int 2314198157Srrsrmi_xlr_mac_close(struct rge_softc *sc) 2315198157Srrs{ 2316198157Srrs struct driver_data *priv = &(sc->priv); 2317198157Srrs 2318198157Srrs mtx_lock_spin(&priv->lock); 2319198157Srrs 2320198157Srrs /* 2321198157Srrs * There may have left over mbufs in the ring as well as in free in 2322198157Srrs * they will be reused next time open is called 2323198157Srrs */ 2324198157Srrs 2325198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2326198157Srrs 2327198157Srrs xlr_inc_counter(NETIF_STOP_Q); 2328198157Srrs port_inc_counter(priv->instance, PORT_STOPQ); 2329198157Srrs 2330198157Srrs mtx_unlock_spin(&priv->lock); 2331198157Srrs 2332198157Srrs return 0; 2333198157Srrs} 2334198157Srrs 2335198157Srrs/********************************************************************** 2336198157Srrs **********************************************************************/ 2337198157Srrsstatic struct rge_softc_stats * 2338198157Srrsrmi_xlr_mac_get_stats(struct rge_softc *sc) 2339198157Srrs{ 2340198157Srrs struct driver_data *priv = &(sc->priv); 2341198626Srrs 2342198157Srrs /* unsigned long flags; */ 2343198157Srrs 2344198157Srrs mtx_lock_spin(&priv->lock); 2345198157Srrs 2346198157Srrs /* XXX update other stats here */ 2347198157Srrs 2348198157Srrs mtx_unlock_spin(&priv->lock); 2349198157Srrs 2350198157Srrs return &priv->stats; 2351198157Srrs} 2352198157Srrs 2353198157Srrs/********************************************************************** 2354198157Srrs **********************************************************************/ 2355198626Srrsstatic void 2356198157Srrsrmi_xlr_mac_set_multicast_list(struct rge_softc *sc) 2357198157Srrs{ 2358198157Srrs} 2359198157Srrs 2360198157Srrs/********************************************************************** 2361198157Srrs **********************************************************************/ 2362198626Srrsstatic int 2363198157Srrsrmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu) 2364198157Srrs{ 2365198157Srrs struct driver_data *priv = &(sc->priv); 2366198157Srrs 2367198157Srrs if ((new_mtu > 9500) || (new_mtu < 64)) { 2368198157Srrs return -EINVAL; 2369198157Srrs } 2370198157Srrs mtx_lock_spin(&priv->lock); 2371198157Srrs 2372198157Srrs sc->mtu = new_mtu; 2373198157Srrs 2374198157Srrs /* Disable MAC TX/RX */ 2375198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2376198157Srrs 2377198157Srrs /* Flush RX FR IN */ 2378198157Srrs /* Flush TX IN */ 2379198157Srrs rmi_xlr_mac_set_enable(priv, 1); 2380198157Srrs 2381198157Srrs mtx_unlock_spin(&priv->lock); 2382198157Srrs return 0; 2383198157Srrs} 2384198157Srrs 2385198157Srrs/********************************************************************** 2386198157Srrs **********************************************************************/ 2387198626Srrsstatic int 2388198157Srrsrmi_xlr_mac_fill_rxfr(struct rge_softc *sc) 2389198157Srrs{ 2390198157Srrs struct driver_data *priv = &(sc->priv); 2391198626Srrs unsigned long msgrng_flags; 2392198626Srrs int i; 2393198626Srrs int ret = 0; 2394198626Srrs void *ptr; 2395198157Srrs 2396198157Srrs dbg_msg("\n"); 2397198157Srrs if (!priv->init_frin_desc) 2398198157Srrs return ret; 2399198157Srrs priv->init_frin_desc = 0; 2400198157Srrs 2401198157Srrs dbg_msg("\n"); 2402198157Srrs for (i = 0; i < MAX_NUM_DESC; i++) { 2403198157Srrs ptr = get_buf(); 2404198157Srrs if (!ptr) { 2405198157Srrs ret = -ENOMEM; 2406198157Srrs break; 2407198157Srrs } 2408198157Srrs /* Send the free Rx desc to the MAC */ 2409198157Srrs msgrng_access_enable(msgrng_flags); 2410198157Srrs xlr_mac_send_fr(priv, vtophys(ptr), MAX_FRAME_SIZE); 2411198157Srrs msgrng_access_disable(msgrng_flags); 2412198157Srrs } 2413198157Srrs 2414198157Srrs return ret; 2415198157Srrs} 2416198157Srrs 2417198157Srrs/********************************************************************** 2418198157Srrs **********************************************************************/ 2419198157Srrsstatic __inline__ void * 2420198157Srrsrmi_xlr_config_spill(xlr_reg_t * mmio, 2421198626Srrs int reg_start_0, int reg_start_1, 2422198626Srrs int reg_size, int size) 2423198157Srrs{ 2424198626Srrs uint32_t spill_size = size; 2425198626Srrs void *spill = NULL; 2426198626Srrs uint64_t phys_addr = 0; 2427198157Srrs 2428198157Srrs 2429198157Srrs spill = contigmalloc((spill_size + XLR_CACHELINE_SIZE), M_DEVBUF, 2430198626Srrs M_NOWAIT | M_ZERO, 0, 0xffffffff, XLR_CACHELINE_SIZE, 0); 2431198626Srrs if (!spill || ((vm_offset_t)spill & (XLR_CACHELINE_SIZE - 1))) { 2432198157Srrs panic("Unable to allocate memory for spill area!\n"); 2433198157Srrs } 2434198157Srrs phys_addr = vtophys(spill); 2435198157Srrs dbg_msg("Allocate spill %d bytes at %llx\n", size, phys_addr); 2436198157Srrs xlr_write_reg(mmio, reg_start_0, (phys_addr >> 5) & 0xffffffff); 2437198157Srrs xlr_write_reg(mmio, reg_start_1, (phys_addr >> 37) & 0x07); 2438198157Srrs xlr_write_reg(mmio, reg_size, spill_size); 2439198157Srrs 2440198157Srrs return spill; 2441198157Srrs} 2442198157Srrs 2443198626Srrsstatic void 2444198157Srrsrmi_xlr_config_spill_area(struct driver_data *priv) 2445198157Srrs{ 2446198157Srrs /* 2447198157Srrs * if driver initialization is done parallely on multiple cpus 2448198157Srrs * spill_configured needs synchronization 2449198157Srrs */ 2450198157Srrs if (priv->spill_configured) 2451198157Srrs return; 2452198157Srrs 2453198157Srrs if (priv->type == XLR_GMAC && priv->instance % 4 != 0) { 2454198157Srrs priv->spill_configured = 1; 2455198157Srrs return; 2456198157Srrs } 2457198157Srrs priv->spill_configured = 1; 2458198157Srrs 2459198157Srrs priv->frin_spill = 2460198626Srrs rmi_xlr_config_spill(priv->mmio, 2461198626Srrs R_REG_FRIN_SPILL_MEM_START_0, 2462198626Srrs R_REG_FRIN_SPILL_MEM_START_1, 2463198626Srrs R_REG_FRIN_SPILL_MEM_SIZE, 2464198626Srrs MAX_FRIN_SPILL * 2465198626Srrs sizeof(struct fr_desc)); 2466198157Srrs 2467198157Srrs priv->class_0_spill = 2468198626Srrs rmi_xlr_config_spill(priv->mmio, 2469198626Srrs R_CLASS0_SPILL_MEM_START_0, 2470198626Srrs R_CLASS0_SPILL_MEM_START_1, 2471198626Srrs R_CLASS0_SPILL_MEM_SIZE, 2472198626Srrs MAX_CLASS_0_SPILL * 2473198626Srrs sizeof(union rx_tx_desc)); 2474198157Srrs priv->class_1_spill = 2475198626Srrs rmi_xlr_config_spill(priv->mmio, 2476198626Srrs R_CLASS1_SPILL_MEM_START_0, 2477198626Srrs R_CLASS1_SPILL_MEM_START_1, 2478198626Srrs R_CLASS1_SPILL_MEM_SIZE, 2479198626Srrs MAX_CLASS_1_SPILL * 2480198626Srrs sizeof(union rx_tx_desc)); 2481198157Srrs 2482198157Srrs priv->frout_spill = 2483198626Srrs rmi_xlr_config_spill(priv->mmio, R_FROUT_SPILL_MEM_START_0, 2484198626Srrs R_FROUT_SPILL_MEM_START_1, 2485198626Srrs R_FROUT_SPILL_MEM_SIZE, 2486198626Srrs MAX_FROUT_SPILL * 2487198626Srrs sizeof(struct fr_desc)); 2488198157Srrs 2489198157Srrs priv->class_2_spill = 2490198626Srrs rmi_xlr_config_spill(priv->mmio, 2491198626Srrs R_CLASS2_SPILL_MEM_START_0, 2492198626Srrs R_CLASS2_SPILL_MEM_START_1, 2493198626Srrs R_CLASS2_SPILL_MEM_SIZE, 2494198626Srrs MAX_CLASS_2_SPILL * 2495198626Srrs sizeof(union rx_tx_desc)); 2496198157Srrs priv->class_3_spill = 2497198626Srrs rmi_xlr_config_spill(priv->mmio, 2498198626Srrs R_CLASS3_SPILL_MEM_START_0, 2499198626Srrs R_CLASS3_SPILL_MEM_START_1, 2500198626Srrs R_CLASS3_SPILL_MEM_SIZE, 2501198626Srrs MAX_CLASS_3_SPILL * 2502198626Srrs sizeof(union rx_tx_desc)); 2503198157Srrs priv->spill_configured = 1; 2504198157Srrs} 2505198157Srrs 2506198157Srrs/***************************************************************** 2507198157Srrs * Write the MAC address to the XLR registers 2508198157Srrs * All 4 addresses are the same for now 2509198157Srrs *****************************************************************/ 2510198626Srrsstatic void 2511198157Srrsxlr_mac_setup_hwaddr(struct driver_data *priv) 2512198157Srrs{ 2513198157Srrs struct rge_softc *sc = priv->sc; 2514198157Srrs 2515198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR0, 2516198626Srrs ((sc->dev_addr[5] << 24) | (sc->dev_addr[4] << 16) 2517198626Srrs | (sc->dev_addr[3] << 8) | (sc->dev_addr[2])) 2518198626Srrs ); 2519198157Srrs 2520198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR0 + 1, 2521198626Srrs ((sc->dev_addr[1] << 24) | (sc-> 2522198626Srrs dev_addr[0] << 16))); 2523198157Srrs 2524198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2, 0xffffffff); 2525198157Srrs 2526198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2 + 1, 0xffffffff); 2527198157Srrs 2528198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3, 0xffffffff); 2529198157Srrs 2530198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3 + 1, 0xffffffff); 2531198157Srrs 2532198157Srrs xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG, 2533198626Srrs (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) | 2534198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) | 2535198626Srrs (1 << O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID) 2536198626Srrs ); 2537198157Srrs} 2538198157Srrs 2539198157Srrs/***************************************************************** 2540198157Srrs * Read the MAC address from the XLR registers 2541198157Srrs * All 4 addresses are the same for now 2542198157Srrs *****************************************************************/ 2543198626Srrsstatic void 2544198157Srrsxlr_mac_get_hwaddr(struct rge_softc *sc) 2545198157Srrs{ 2546198157Srrs struct driver_data *priv = &(sc->priv); 2547198157Srrs 2548198157Srrs sc->dev_addr[0] = (xlr_boot1_info.mac_addr >> 40) & 0xff; 2549198157Srrs sc->dev_addr[1] = (xlr_boot1_info.mac_addr >> 32) & 0xff; 2550198157Srrs sc->dev_addr[2] = (xlr_boot1_info.mac_addr >> 24) & 0xff; 2551198157Srrs sc->dev_addr[3] = (xlr_boot1_info.mac_addr >> 16) & 0xff; 2552198157Srrs sc->dev_addr[4] = (xlr_boot1_info.mac_addr >> 8) & 0xff; 2553198157Srrs sc->dev_addr[5] = ((xlr_boot1_info.mac_addr >> 0) & 0xff) + priv->instance; 2554198157Srrs} 2555198157Srrs 2556198157Srrs/***************************************************************** 2557198157Srrs * Mac Module Initialization 2558198157Srrs *****************************************************************/ 2559198626Srrsstatic void 2560198157Srrsmac_common_init(void) 2561198157Srrs{ 2562198157Srrs init_p2d_allocation(); 2563198157Srrs init_tx_ring(); 2564198157Srrs 2565198157Srrs if (xlr_board_info.is_xls) { 2566198626Srrs if (register_msgring_handler(TX_STN_GMAC0, 2567198626Srrs rmi_xlr_mac_msgring_handler, NULL)) { 2568198157Srrs panic("Couldn't register msgring handler\n"); 2569198157Srrs } 2570198626Srrs if (register_msgring_handler(TX_STN_GMAC1, 2571198626Srrs rmi_xlr_mac_msgring_handler, NULL)) { 2572198157Srrs panic("Couldn't register msgring handler\n"); 2573198157Srrs } 2574198157Srrs } else { 2575198626Srrs if (register_msgring_handler(TX_STN_GMAC, 2576198626Srrs rmi_xlr_mac_msgring_handler, NULL)) { 2577198157Srrs panic("Couldn't register msgring handler\n"); 2578198157Srrs } 2579198157Srrs } 2580198157Srrs 2581198626Srrs /* 2582198626Srrs * Not yet if (xlr_board_atx_ii()) { if (register_msgring_handler 2583198626Srrs * (TX_STN_XGS_0, rmi_xlr_mac_msgring_handler, NULL)) { 2584198626Srrs * panic("Couldn't register msgring handler for TX_STN_XGS_0\n"); } 2585198626Srrs * if (register_msgring_handler (TX_STN_XGS_1, 2586198626Srrs * rmi_xlr_mac_msgring_handler, NULL)) { panic("Couldn't register 2587198626Srrs * msgring handler for TX_STN_XGS_1\n"); } } 2588198626Srrs */ 2589198157Srrs} 2590