rge.c revision 212553
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 212553 2010-09-13 13:11:50Z jchandra $"); 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> 58211994Sjchandra#include <sys/sysctl.h> 59198157Srrs 60198157Srrs#include <net/if.h> 61198157Srrs#include <net/if_arp.h> 62198157Srrs#include <net/ethernet.h> 63198157Srrs#include <net/if_dl.h> 64198157Srrs#include <net/if_media.h> 65198157Srrs 66198157Srrs#include <net/bpf.h> 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> 90211994Sjchandra 91211994Sjchandra#include <dev/mii/mii.h> 92211994Sjchandra#include <dev/mii/miivar.h> 93211994Sjchandra#include <dev/mii/brgphyreg.h> 94211994Sjchandra 95198608Srrs#include <mips/rmi/interrupt.h> 96198608Srrs#include <mips/rmi/msgring.h> 97198608Srrs#include <mips/rmi/iomap.h> 98198608Srrs#include <mips/rmi/pic.h> 99211994Sjchandra#include <mips/rmi/rmi_mips_exts.h> 100211994Sjchandra#include <mips/rmi/rmi_boot_info.h> 101198608Srrs#include <mips/rmi/board.h> 102211996Sjchandra 103211996Sjchandra#include <mips/rmi/dev/xlr/debug.h> 104202066Simp#include <mips/rmi/dev/xlr/atx_cpld.h> 105202066Simp#include <mips/rmi/dev/xlr/xgmac_mdio.h> 106202092Simp#include <mips/rmi/dev/xlr/rge.h> 107198157Srrs 108198608Srrs#include "miibus_if.h" 109198608Srrs 110198157SrrsMODULE_DEPEND(rge, ether, 1, 1, 1); 111198157SrrsMODULE_DEPEND(rge, miibus, 1, 1, 1); 112198157Srrs 113198157Srrs/* #define DEBUG */ 114198157Srrs 115198157Srrs#define RGE_TX_THRESHOLD 1024 116198157Srrs#define RGE_TX_Q_SIZE 1024 117198157Srrs 118198157Srrs#ifdef DEBUG 119198157Srrs#undef dbg_msg 120198626Srrsint mac_debug = 1; 121198626Srrs 122198157Srrs#define dbg_msg(fmt, args...) \ 123198157Srrs do {\ 124198157Srrs if (mac_debug) {\ 125198157Srrs printf("[%s@%d|%s]: cpu_%d: " fmt, \ 126208369Sjchandra __FILE__, __LINE__, __FUNCTION__, xlr_cpu_id(), ##args);\ 127198157Srrs }\ 128198157Srrs } while(0); 129198157Srrs 130198157Srrs#define DUMP_PACKETS 131198157Srrs#else 132198157Srrs#undef dbg_msg 133198157Srrs#define dbg_msg(fmt, args...) 134198626Srrsint mac_debug = 0; 135198626Srrs 136198157Srrs#endif 137198157Srrs 138198157Srrs#define MAC_B2B_IPG 88 139198157Srrs 140198157Srrs/* frame sizes need to be cacheline aligned */ 141198157Srrs#define MAX_FRAME_SIZE 1536 142198157Srrs#define MAX_FRAME_SIZE_JUMBO 9216 143198157Srrs 144198157Srrs#define MAC_SKB_BACK_PTR_SIZE SMP_CACHE_BYTES 145198157Srrs#define MAC_PREPAD 0 146198157Srrs#define BYTE_OFFSET 2 147198157Srrs#define XLR_RX_BUF_SIZE (MAX_FRAME_SIZE+BYTE_OFFSET+MAC_PREPAD+MAC_SKB_BACK_PTR_SIZE+SMP_CACHE_BYTES) 148198157Srrs#define MAC_CRC_LEN 4 149198157Srrs#define MAX_NUM_MSGRNG_STN_CC 128 150198157Srrs 151198157Srrs#define MAX_NUM_DESC 1024 152198157Srrs#define MAX_SPILL_SIZE (MAX_NUM_DESC + 128) 153198157Srrs 154198157Srrs#define MAC_FRIN_TO_BE_SENT_THRESHOLD 16 155198157Srrs 156198157Srrs#define MAX_FRIN_SPILL (MAX_SPILL_SIZE << 2) 157198157Srrs#define MAX_FROUT_SPILL (MAX_SPILL_SIZE << 2) 158198157Srrs#define MAX_CLASS_0_SPILL (MAX_SPILL_SIZE << 2) 159198157Srrs#define MAX_CLASS_1_SPILL (MAX_SPILL_SIZE << 2) 160198157Srrs#define MAX_CLASS_2_SPILL (MAX_SPILL_SIZE << 2) 161198157Srrs#define MAX_CLASS_3_SPILL (MAX_SPILL_SIZE << 2) 162198157Srrs 163198157Srrs/***************************************************************** 164198157Srrs * Phoenix Generic Mac driver 165198157Srrs *****************************************************************/ 166198157Srrs 167198157Srrsextern uint32_t cpu_ltop_map[32]; 168198157Srrs 169198157Srrs#ifdef ENABLED_DEBUG 170198626Srrsstatic int port_counters[4][8] __aligned(XLR_CACHELINE_SIZE); 171198626Srrs 172198157Srrs#define port_inc_counter(port, counter) atomic_add_int(&port_counters[port][(counter)], 1) 173198157Srrs#define port_set_counter(port, counter, value) atomic_set_int(&port_counters[port][(counter)], (value)) 174198157Srrs#else 175198626Srrs#define port_inc_counter(port, counter) /* Nothing */ 176198626Srrs#define port_set_counter(port, counter, value) /* Nothing */ 177198157Srrs#endif 178198157Srrs 179198157Srrsint xlr_rge_tx_prepend[MAXCPU]; 180198157Srrsint xlr_rge_tx_done[MAXCPU]; 181198157Srrsint xlr_rge_get_p2d_failed[MAXCPU]; 182198157Srrsint xlr_rge_msg_snd_failed[MAXCPU]; 183198157Srrsint xlr_rge_tx_ok_done[MAXCPU]; 184198157Srrsint xlr_rge_rx_done[MAXCPU]; 185198157Srrsint xlr_rge_repl_done[MAXCPU]; 186198157Srrs 187198626Srrsstatic __inline__ unsigned int 188198157Srrsldadd_wu(unsigned int value, unsigned long *addr) 189198157Srrs{ 190198626Srrs __asm__ __volatile__(".set push\n" 191198626Srrs ".set noreorder\n" 192198626Srrs "move $8, %2\n" 193198626Srrs "move $9, %3\n" 194198626Srrs /* "ldaddwu $8, $9\n" */ 195198626Srrs ".word 0x71280011\n" 196198626Srrs "move %0, $8\n" 197198626Srrs ".set pop\n" 198198626Srrs : "=&r"(value), "+m"(*addr) 199198626Srrs : "0"(value), "r"((unsigned long)addr) 200198626Srrs : "$8", "$9"); 201198626Srrs 202198157Srrs return value; 203198157Srrs} 204198157Srrs 205208165Srrsstatic __inline__ uint32_t 206208165Srrsxlr_enable_kx(void) 207208165Srrs{ 208208165Srrs uint32_t sr = mips_rd_status(); 209208165Srrs 210208165Srrs mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX); 211208165Srrs return sr; 212208165Srrs} 213208165Srrs 214198157Srrs/* #define mac_stats_add(x, val) ({(x) += (val);}) */ 215198157Srrs#define mac_stats_add(x, val) ldadd_wu(val, &x) 216198157Srrs 217198157Srrs#define XLR_MAX_CORE 8 218198157Srrs#define RGE_LOCK_INIT(_sc, _name) \ 219198157Srrs mtx_init(&(_sc)->rge_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) 220198157Srrs#define RGE_LOCK(_sc) mtx_lock(&(_sc)->rge_mtx) 221198157Srrs#define RGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rge_mtx, MA_OWNED) 222198157Srrs#define RGE_UNLOCK(_sc) mtx_unlock(&(_sc)->rge_mtx) 223198157Srrs#define RGE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rge_mtx) 224198157Srrs 225198157Srrs#define XLR_MAX_MACS 8 226198157Srrs#define XLR_MAX_TX_FRAGS 14 227198626Srrs#define MAX_P2D_DESC_PER_PORT 512 228198157Srrsstruct p2d_tx_desc { 229198626Srrs uint64_t frag[XLR_MAX_TX_FRAGS + 2]; 230198157Srrs}; 231198626Srrs 232198157Srrs#define MAX_TX_RING_SIZE (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT * sizeof(struct p2d_tx_desc)) 233198157Srrs 234198157Srrsstruct rge_softc *dev_mac[XLR_MAX_MACS]; 235198626Srrsstatic int dev_mac_xgs0; 236198626Srrsstatic int dev_mac_gmac0; 237198157Srrs 238198626Srrsstatic int gmac_common_init_done; 239198157Srrs 240198157Srrs 241198626Srrsstatic int rge_probe(device_t); 242198626Srrsstatic int rge_attach(device_t); 243198626Srrsstatic int rge_detach(device_t); 244198626Srrsstatic int rge_suspend(device_t); 245198626Srrsstatic int rge_resume(device_t); 246198626Srrsstatic void rge_release_resources(struct rge_softc *); 247198626Srrsstatic void rge_rx(struct rge_softc *, vm_paddr_t paddr, int); 248198626Srrsstatic void rge_intr(void *); 249198626Srrsstatic void rge_start_locked(struct ifnet *, int); 250198626Srrsstatic void rge_start(struct ifnet *); 251198626Srrsstatic int rge_ioctl(struct ifnet *, u_long, caddr_t); 252198626Srrsstatic void rge_init(void *); 253198626Srrsstatic void rge_stop(struct rge_softc *); 254198626Srrsstatic int rge_shutdown(device_t); 255198626Srrsstatic void rge_reset(struct rge_softc *); 256198157Srrs 257198157Srrsstatic struct mbuf *get_mbuf(void); 258198626Srrsstatic void free_buf(vm_paddr_t paddr); 259198626Srrsstatic void *get_buf(void); 260198157Srrs 261198626Srrsstatic void xlr_mac_get_hwaddr(struct rge_softc *); 262198626Srrsstatic void xlr_mac_setup_hwaddr(struct driver_data *); 263198626Srrsstatic void rmi_xlr_mac_set_enable(struct driver_data *priv, int flag); 264198626Srrsstatic void rmi_xlr_xgmac_init(struct driver_data *priv); 265198626Srrsstatic void rmi_xlr_gmac_init(struct driver_data *priv); 266198626Srrsstatic void mac_common_init(void); 267198626Srrsstatic int rge_mii_write(device_t, int, int, int); 268198626Srrsstatic int rge_mii_read(device_t, int, int); 269198626Srrsstatic void rmi_xlr_mac_mii_statchg(device_t); 270198626Srrsstatic int rmi_xlr_mac_mediachange(struct ifnet *); 271198626Srrsstatic void rmi_xlr_mac_mediastatus(struct ifnet *, struct ifmediareq *); 272198626Srrsstatic void xlr_mac_set_rx_mode(struct rge_softc *sc); 273198626Srrsvoid 274198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code, 275198626Srrs int stid, struct msgrng_msg *msg, 276198626Srrs void *data); 277198626Srrsstatic void mac_frin_replenish(void *); 278198626Srrsstatic int rmi_xlr_mac_open(struct rge_softc *); 279198626Srrsstatic int rmi_xlr_mac_close(struct rge_softc *); 280198626Srrsstatic int 281198157Srrsmac_xmit(struct mbuf *, struct rge_softc *, 282198626Srrs struct driver_data *, int, struct p2d_tx_desc *); 283198626Srrsstatic int rmi_xlr_mac_xmit(struct mbuf *, struct rge_softc *, int, struct p2d_tx_desc *); 284198157Srrsstatic struct rge_softc_stats *rmi_xlr_mac_get_stats(struct rge_softc *sc); 285198626Srrsstatic void rmi_xlr_mac_set_multicast_list(struct rge_softc *sc); 286198626Srrsstatic int rmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu); 287198626Srrsstatic int rmi_xlr_mac_fill_rxfr(struct rge_softc *sc); 288198626Srrsstatic void rmi_xlr_config_spill_area(struct driver_data *priv); 289198626Srrsstatic int rmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed); 290198626Srrsstatic int 291198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s, 292198626Srrs xlr_mac_duplex_t duplex, xlr_mac_fc_t fc); 293198157Srrsstatic void serdes_regs_init(struct driver_data *priv); 294198157Srrsstatic int rmi_xlr_gmac_reset(struct driver_data *priv); 295198157Srrs 296198157Srrs/*Statistics...*/ 297198157Srrsstatic int get_p2d_desc_failed = 0; 298198626Srrsstatic int msg_snd_failed = 0; 299198157Srrs 300198157SrrsSYSCTL_INT(_hw, OID_AUTO, get_p2d_failed, CTLFLAG_RW, 301198626Srrs &get_p2d_desc_failed, 0, "p2d desc failed"); 302198157SrrsSYSCTL_INT(_hw, OID_AUTO, msg_snd_failed, CTLFLAG_RW, 303198626Srrs &msg_snd_failed, 0, "msg snd failed"); 304198157Srrs 305198626Srrsstruct callout xlr_tx_stop_bkp; 306198157Srrs 307198157Srrsstatic device_method_t rge_methods[] = { 308198157Srrs /* Device interface */ 309198157Srrs DEVMETHOD(device_probe, rge_probe), 310198157Srrs DEVMETHOD(device_attach, rge_attach), 311198157Srrs DEVMETHOD(device_detach, rge_detach), 312198157Srrs DEVMETHOD(device_shutdown, rge_shutdown), 313198157Srrs DEVMETHOD(device_suspend, rge_suspend), 314198157Srrs DEVMETHOD(device_resume, rge_resume), 315198157Srrs 316198157Srrs /* MII interface */ 317198157Srrs DEVMETHOD(miibus_readreg, rge_mii_read), 318198608Srrs DEVMETHOD(miibus_statchg, rmi_xlr_mac_mii_statchg), 319198157Srrs DEVMETHOD(miibus_writereg, rge_mii_write), 320198157Srrs {0, 0} 321198157Srrs}; 322198157Srrs 323198626Srrsstatic driver_t rge_driver = { 324198157Srrs "rge", 325198157Srrs rge_methods, 326198157Srrs sizeof(struct rge_softc) 327198157Srrs}; 328198157Srrs 329198157Srrsstatic devclass_t rge_devclass; 330198157Srrs 331198157SrrsDRIVER_MODULE(rge, iodi, rge_driver, rge_devclass, 0, 0); 332198157SrrsDRIVER_MODULE(miibus, rge, miibus_driver, miibus_devclass, 0, 0); 333198157Srrs 334198157Srrs#ifndef __STR 335198157Srrs#define __STR(x) #x 336198157Srrs#endif 337198157Srrs#ifndef STR 338198157Srrs#define STR(x) __STR(x) 339198157Srrs#endif 340198157Srrs 341198626Srrsvoid *xlr_tx_ring_mem; 342198157Srrs 343198157Srrsstruct tx_desc_node { 344198157Srrs struct p2d_tx_desc *ptr; 345198626Srrs TAILQ_ENTRY(tx_desc_node) list; 346198157Srrs}; 347198626Srrs 348198157Srrs#define XLR_MAX_TX_DESC_NODES (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT) 349198157Srrsstruct tx_desc_node tx_desc_nodes[XLR_MAX_TX_DESC_NODES]; 350198157Srrsstatic volatile int xlr_tot_avail_p2d[XLR_MAX_CORE]; 351198157Srrsstatic int xlr_total_active_core = 0; 352198157Srrs 353198157Srrs/* 354198157Srrs * This should contain the list of all free tx frag desc nodes pointing to tx 355198157Srrs * p2d arrays 356198157Srrs */ 357198626Srrsstatic 358198157SrrsTAILQ_HEAD(, tx_desc_node) tx_frag_desc[XLR_MAX_CORE] = 359198626Srrs{ 360198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[0]), 361198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[1]), 362198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[2]), 363198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[3]), 364198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[4]), 365198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[5]), 366198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[6]), 367198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[7]), 368198626Srrs}; 369198157Srrs 370198157Srrs/* This contains a list of free tx frag node descriptors */ 371199139Srrsstatic 372198626SrrsTAILQ_HEAD(, tx_desc_node) free_tx_frag_desc[XLR_MAX_CORE] = 373198626Srrs{ 374198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[0]), 375198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[1]), 376198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[2]), 377198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[3]), 378198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[4]), 379198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[5]), 380198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[6]), 381198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[7]), 382198626Srrs}; 383198157Srrs 384198157Srrsstatic struct mtx tx_desc_lock[XLR_MAX_CORE]; 385198157Srrs 386198157Srrsstatic inline void 387198626Srrsmac_make_desc_rfr(struct msgrng_msg *msg, 388198626Srrs vm_paddr_t addr) 389198157Srrs{ 390198157Srrs msg->msg0 = (uint64_t) addr & 0xffffffffe0ULL; 391198157Srrs msg->msg1 = msg->msg2 = msg->msg3 = 0; 392198157Srrs} 393198157Srrs 394198157Srrs#define MAC_TX_DESC_ALIGNMENT (XLR_CACHELINE_SIZE - 1) 395198157Srrs 396198157Srrsstatic void 397198157Srrsinit_p2d_allocation(void) 398198157Srrs{ 399198626Srrs int active_core[8] = {0}; 400198626Srrs int i = 0; 401198157Srrs uint32_t cpumask; 402198157Srrs int cpu; 403198157Srrs 404208369Sjchandra cpumask = xlr_hw_thread_mask; 405198157Srrs 406198157Srrs for (i = 0; i < 32; i++) { 407198157Srrs if (cpumask & (1 << i)) { 408208165Srrs cpu = i; 409198626Srrs if (!active_core[cpu / 4]) { 410198626Srrs active_core[cpu / 4] = 1; 411198157Srrs xlr_total_active_core++; 412198157Srrs } 413198157Srrs } 414198157Srrs } 415198626Srrs for (i = 0; i < XLR_MAX_CORE; i++) { 416198626Srrs if (active_core[i]) 417198626Srrs xlr_tot_avail_p2d[i] = XLR_MAX_TX_DESC_NODES / xlr_total_active_core; 418198157Srrs } 419198626Srrs printf("Total Active Core %d\n", xlr_total_active_core); 420198157Srrs} 421198157Srrs 422198157Srrs 423198157Srrsstatic void 424198157Srrsinit_tx_ring(void) 425198157Srrs{ 426198626Srrs int i; 427198626Srrs int j = 0; 428198157Srrs struct tx_desc_node *start, *node; 429198157Srrs struct p2d_tx_desc *tx_desc; 430198626Srrs vm_paddr_t paddr; 431198626Srrs vm_offset_t unmapped_addr; 432198157Srrs 433198626Srrs for (i = 0; i < XLR_MAX_CORE; i++) 434198157Srrs mtx_init(&tx_desc_lock[i], "xlr tx_desc", NULL, MTX_SPIN); 435198157Srrs 436198157Srrs start = &tx_desc_nodes[0]; 437198157Srrs /* TODO: try to get this from KSEG0 */ 438198157Srrs xlr_tx_ring_mem = contigmalloc((MAX_TX_RING_SIZE + XLR_CACHELINE_SIZE), 439198626Srrs M_DEVBUF, M_NOWAIT | M_ZERO, 0, 440198626Srrs 0x10000000, XLR_CACHELINE_SIZE, 0); 441198157Srrs 442198157Srrs if (xlr_tx_ring_mem == NULL) { 443198157Srrs panic("TX ring memory allocation failed"); 444198157Srrs } 445198626Srrs paddr = vtophys((vm_offset_t)xlr_tx_ring_mem); 446198157Srrs 447198157Srrs unmapped_addr = MIPS_PHYS_TO_KSEG0(paddr); 448198157Srrs 449198157Srrs 450198157Srrs tx_desc = (struct p2d_tx_desc *)unmapped_addr; 451198157Srrs 452198157Srrs for (i = 0; i < XLR_MAX_TX_DESC_NODES; i++) { 453198157Srrs node = start + i; 454198157Srrs node->ptr = tx_desc; 455198157Srrs tx_desc++; 456198157Srrs TAILQ_INSERT_HEAD(&tx_frag_desc[j], node, list); 457198626Srrs j = (i / (XLR_MAX_TX_DESC_NODES / xlr_total_active_core)); 458198157Srrs } 459198157Srrs} 460198157Srrs 461198157Srrsstatic inline struct p2d_tx_desc * 462198157Srrsget_p2d_desc(void) 463198157Srrs{ 464198157Srrs struct tx_desc_node *node; 465198157Srrs struct p2d_tx_desc *tx_desc = NULL; 466208165Srrs int cpu = xlr_core_id(); 467198157Srrs 468198157Srrs mtx_lock_spin(&tx_desc_lock[cpu]); 469198157Srrs node = TAILQ_FIRST(&tx_frag_desc[cpu]); 470198157Srrs if (node) { 471198157Srrs xlr_tot_avail_p2d[cpu]--; 472198157Srrs TAILQ_REMOVE(&tx_frag_desc[cpu], node, list); 473198157Srrs tx_desc = node->ptr; 474198157Srrs TAILQ_INSERT_HEAD(&free_tx_frag_desc[cpu], node, list); 475198626Srrs } else { 476198626Srrs /* Increment p2d desc fail count */ 477198157Srrs get_p2d_desc_failed++; 478198157Srrs } 479198157Srrs mtx_unlock_spin(&tx_desc_lock[cpu]); 480198157Srrs return tx_desc; 481198157Srrs} 482198626Srrsstatic void 483198157Srrsfree_p2d_desc(struct p2d_tx_desc *tx_desc) 484198157Srrs{ 485198157Srrs struct tx_desc_node *node; 486208165Srrs int cpu = xlr_core_id(); 487198157Srrs 488198157Srrs mtx_lock_spin(&tx_desc_lock[cpu]); 489198157Srrs node = TAILQ_FIRST(&free_tx_frag_desc[cpu]); 490198157Srrs KASSERT((node != NULL), ("Free TX frag node list is empty\n")); 491198157Srrs 492198157Srrs TAILQ_REMOVE(&free_tx_frag_desc[cpu], node, list); 493198157Srrs node->ptr = tx_desc; 494198157Srrs TAILQ_INSERT_HEAD(&tx_frag_desc[cpu], node, list); 495198157Srrs xlr_tot_avail_p2d[cpu]++; 496198157Srrs mtx_unlock_spin(&tx_desc_lock[cpu]); 497198157Srrs 498198157Srrs} 499198157Srrs 500198626Srrsstatic int 501198157Srrsbuild_frag_list(struct mbuf *m_head, struct msgrng_msg *p2p_msg, struct p2d_tx_desc *tx_desc) 502198157Srrs{ 503198626Srrs struct mbuf *m; 504198626Srrs vm_paddr_t paddr; 505198626Srrs uint64_t p2d_len; 506198626Srrs int nfrag; 507198626Srrs vm_paddr_t p1, p2; 508198626Srrs uint32_t len1, len2; 509198626Srrs vm_offset_t taddr; 510198626Srrs uint64_t fr_stid; 511198626Srrs 512208165Srrs fr_stid = (xlr_core_id() << 3) + xlr_thr_id() + 4; 513198157Srrs 514198157Srrs if (tx_desc == NULL) 515198157Srrs return 1; 516198157Srrs 517198157Srrs nfrag = 0; 518198157Srrs for (m = m_head; m != NULL; m = m->m_next) { 519198157Srrs if ((nfrag + 1) >= XLR_MAX_TX_FRAGS) { 520198157Srrs free_p2d_desc(tx_desc); 521198157Srrs return 1; 522198157Srrs } 523198157Srrs if (m->m_len != 0) { 524198157Srrs paddr = vtophys(mtod(m, vm_offset_t)); 525198157Srrs p1 = paddr + m->m_len; 526198626Srrs p2 = vtophys(((vm_offset_t)m->m_data + m->m_len)); 527198157Srrs if (p1 != p2) { 528198157Srrs len1 = (uint32_t) 529198626Srrs (PAGE_SIZE - (paddr & PAGE_MASK)); 530198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 531198626Srrs ((uint64_t) len1 << 40) | paddr; 532198157Srrs nfrag++; 533198626Srrs taddr = (vm_offset_t)m->m_data + len1; 534198157Srrs p2 = vtophys(taddr); 535198157Srrs len2 = m->m_len - len1; 536203754Srrs if (len2 == 0) 537203754Srrs continue; 538198157Srrs if (nfrag >= XLR_MAX_TX_FRAGS) 539198157Srrs panic("TX frags exceeded"); 540198157Srrs 541198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 542198626Srrs ((uint64_t) len2 << 40) | p2; 543198157Srrs 544198157Srrs taddr += len2; 545198157Srrs p1 = vtophys(taddr); 546198157Srrs 547198157Srrs if ((p2 + len2) != p1) { 548198608Srrs printf("p1 = %p p2 = %p\n", (void *)p1, (void *)p2); 549198157Srrs printf("len1 = %x len2 = %x\n", len1, 550198626Srrs len2); 551198157Srrs printf("m_data %p\n", m->m_data); 552198157Srrs DELAY(1000000); 553198157Srrs panic("Multiple Mbuf segment discontiguous\n"); 554198157Srrs } 555198157Srrs } else { 556198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 557198626Srrs ((uint64_t) m->m_len << 40) | paddr; 558198157Srrs } 559198157Srrs nfrag++; 560198157Srrs } 561198157Srrs } 562198157Srrs /* set eop in the last tx p2d desc */ 563198157Srrs tx_desc->frag[nfrag - 1] |= (1ULL << 63); 564198626Srrs paddr = vtophys((vm_offset_t)tx_desc); 565198157Srrs tx_desc->frag[nfrag] = (1ULL << 63) | (fr_stid << 54) | paddr; 566198157Srrs nfrag++; 567210630Sjchandra tx_desc->frag[XLR_MAX_TX_FRAGS] = (uint64_t)(intptr_t)tx_desc; 568210630Sjchandra tx_desc->frag[XLR_MAX_TX_FRAGS + 1] = (uint64_t)(intptr_t)m_head; 569198157Srrs 570198157Srrs p2d_len = (nfrag * 8); 571198157Srrs p2p_msg->msg0 = (1ULL << 63) | (1ULL << 62) | (127ULL << 54) | 572198626Srrs (p2d_len << 40) | paddr; 573198157Srrs 574198157Srrs return 0; 575198157Srrs} 576198626Srrsstatic void 577198157Srrsrelease_tx_desc(struct msgrng_msg *msg, int rel_buf) 578198157Srrs{ 579199139Srrs struct p2d_tx_desc *tx_desc, *chk_addr; 580198626Srrs struct mbuf *m; 581198157Srrs 582199139Srrs tx_desc = (struct p2d_tx_desc *)MIPS_PHYS_TO_KSEG0(msg->msg0); 583209808Sjchandra chk_addr = (struct p2d_tx_desc *)(intptr_t)tx_desc->frag[XLR_MAX_TX_FRAGS]; 584199139Srrs if (tx_desc != chk_addr) { 585199139Srrs printf("Address %p does not match with stored addr %p - we leaked a descriptor\n", 586199139Srrs tx_desc, chk_addr); 587199139Srrs return; 588199139Srrs } 589198157Srrs if (rel_buf) { 590209808Sjchandra m = (struct mbuf *)(intptr_t)tx_desc->frag[XLR_MAX_TX_FRAGS + 1]; 591198157Srrs m_freem(m); 592198157Srrs } 593198157Srrs free_p2d_desc(tx_desc); 594198157Srrs} 595198157Srrs 596198157Srrs 597198626Srrsstatic struct mbuf * 598198157Srrsget_mbuf(void) 599198157Srrs{ 600198626Srrs struct mbuf *m_new = NULL; 601198157Srrs 602198157Srrs if ((m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR)) == NULL) 603198157Srrs return NULL; 604198157Srrs 605198157Srrs m_new->m_len = MCLBYTES; 606198157Srrs m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 607198157Srrs return m_new; 608198157Srrs} 609198157Srrs 610198626Srrsstatic void 611198157Srrsfree_buf(vm_paddr_t paddr) 612198157Srrs{ 613198626Srrs struct mbuf *m; 614210630Sjchandra uint32_t mag; 615210630Sjchandra#ifdef __mips_n64 616210630Sjchandra uint64_t *vaddr; 617198157Srrs 618210630Sjchandra vaddr = (uint64_t *)MIPS_PHYS_TO_XKPHYS_CACHED(paddr); 619210630Sjchandra m = (struct mbuf *)vaddr[0]; 620210630Sjchandra mag = (uint32_t)vaddr[1]; 621210630Sjchandra#else 622210630Sjchandra uint32_t sr; 623210630Sjchandra 624208165Srrs sr = xlr_enable_kx(); 625210630Sjchandra m = (struct mbuf *)(intptr_t)xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t)); 626210630Sjchandra mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + 3 * sizeof(uint32_t)); 627208165Srrs mips_wr_status(sr); 628210630Sjchandra#endif 629208165Srrs 630199139Srrs if (mag != 0xf00bad) { 631208165Srrs printf("Something is wrong kseg:%lx found mag:%x not 0xf00bad\n", 632208165Srrs (u_long)paddr, mag); 633199139Srrs return; 634199139Srrs } 635198157Srrs if (m != NULL) 636198157Srrs m_freem(m); 637198157Srrs} 638198157Srrs 639198157Srrsstatic void * 640198157Srrsget_buf(void) 641198157Srrs{ 642198626Srrs struct mbuf *m_new = NULL; 643210630Sjchandra uint64_t *md; 644198157Srrs#ifdef INVARIANTS 645198626Srrs vm_paddr_t temp1, temp2; 646198157Srrs#endif 647198157Srrs 648198157Srrs m_new = get_mbuf(); 649198157Srrs if (m_new == NULL) 650198157Srrs return NULL; 651198157Srrs 652209808Sjchandra m_adj(m_new, XLR_CACHELINE_SIZE - ((uintptr_t)m_new->m_data & 0x1f)); 653210630Sjchandra md = (uint64_t *)m_new->m_data; 654209808Sjchandra md[0] = (uintptr_t)m_new; /* Back Ptr */ 655198157Srrs md[1] = 0xf00bad; 656198157Srrs m_adj(m_new, XLR_CACHELINE_SIZE); 657198157Srrs 658198157Srrs#ifdef INVARIANTS 659198626Srrs temp1 = vtophys((vm_offset_t)m_new->m_data); 660198626Srrs temp2 = vtophys((vm_offset_t)m_new->m_data + 1536); 661198157Srrs if ((temp1 + 1536) != temp2) 662198157Srrs panic("ALLOCED BUFFER IS NOT CONTIGUOUS\n"); 663198157Srrs#endif 664198157Srrs return (void *)m_new->m_data; 665198157Srrs} 666198157Srrs 667198157Srrs/********************************************************************** 668198157Srrs **********************************************************************/ 669198626Srrsstatic void 670198157Srrsrmi_xlr_mac_set_enable(struct driver_data *priv, int flag) 671198157Srrs{ 672198626Srrs uint32_t regval; 673198626Srrs int tx_threshold = 1518; 674198157Srrs 675198157Srrs if (flag) { 676198157Srrs regval = xlr_read_reg(priv->mmio, R_TX_CONTROL); 677198157Srrs regval |= (1 << O_TX_CONTROL__TxEnable) | 678198626Srrs (tx_threshold << O_TX_CONTROL__TxThreshold); 679198157Srrs 680198157Srrs xlr_write_reg(priv->mmio, R_TX_CONTROL, regval); 681198157Srrs 682198157Srrs regval = xlr_read_reg(priv->mmio, R_RX_CONTROL); 683198157Srrs regval |= 1 << O_RX_CONTROL__RxEnable; 684198157Srrs if (priv->mode == XLR_PORT0_RGMII) 685198157Srrs regval |= 1 << O_RX_CONTROL__RGMII; 686198157Srrs xlr_write_reg(priv->mmio, R_RX_CONTROL, regval); 687198157Srrs 688198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1); 689198157Srrs regval |= (O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen); 690198157Srrs xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval); 691198157Srrs } else { 692198157Srrs regval = xlr_read_reg(priv->mmio, R_TX_CONTROL); 693198157Srrs regval &= ~((1 << O_TX_CONTROL__TxEnable) | 694198626Srrs (tx_threshold << O_TX_CONTROL__TxThreshold)); 695198157Srrs 696198157Srrs xlr_write_reg(priv->mmio, R_TX_CONTROL, regval); 697198157Srrs 698198157Srrs regval = xlr_read_reg(priv->mmio, R_RX_CONTROL); 699198157Srrs regval &= ~(1 << O_RX_CONTROL__RxEnable); 700198157Srrs xlr_write_reg(priv->mmio, R_RX_CONTROL, regval); 701198157Srrs 702198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1); 703198157Srrs regval &= ~(O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen); 704198157Srrs xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval); 705198157Srrs } 706198157Srrs} 707198157Srrs 708198157Srrs/********************************************************************** 709198157Srrs **********************************************************************/ 710198626Srrsstatic __inline__ int 711198157Srrsxlr_mac_send_fr(struct driver_data *priv, 712198626Srrs vm_paddr_t addr, int len) 713198157Srrs{ 714212321Sjchandra struct msgrng_msg msg; 715198626Srrs int stid = priv->rfrbucket; 716212409Sjchandra int code, ret; 717212321Sjchandra uint32_t msgrng_flags; 718212409Sjchandra#ifdef INVARIANTS 719212409Sjchandra int i = 0; 720212409Sjchandra#endif 721198157Srrs 722198626Srrs mac_make_desc_rfr(&msg, addr); 723198157Srrs 724198157Srrs /* Send the packet to MAC */ 725208165Srrs dbg_msg("mac_%d: Sending free packet %lx to stid %d\n", 726208165Srrs priv->instance, (u_long)addr, stid); 727212321Sjchandra if (priv->type == XLR_XGMAC) 728212321Sjchandra code = MSGRNG_CODE_XGMAC; /* WHY? */ 729212321Sjchandra else 730212321Sjchandra code = MSGRNG_CODE_MAC; 731198157Srrs 732212321Sjchandra do { 733212321Sjchandra msgrng_flags = msgrng_access_enable(); 734212553Sjchandra ret = message_send(1, code, stid, &msg); 735212321Sjchandra msgrng_restore(msgrng_flags); 736212321Sjchandra KASSERT(i++ < 100000, ("Too many credit fails\n")); 737212321Sjchandra } while (ret != 0); 738212321Sjchandra 739198157Srrs return 0; 740198157Srrs} 741198157Srrs 742198157Srrs/**************************************************************/ 743198157Srrs 744198626Srrsstatic void 745198157Srrsxgmac_mdio_setup(volatile unsigned int *_mmio) 746198157Srrs{ 747198626Srrs int i; 748198626Srrs uint32_t rd_data; 749198626Srrs 750198157Srrs for (i = 0; i < 4; i++) { 751198157Srrs rd_data = xmdio_read(_mmio, 1, 0x8000 + i); 752198157Srrs rd_data = rd_data & 0xffffdfff; /* clear isolate bit */ 753198157Srrs xmdio_write(_mmio, 1, 0x8000 + i, rd_data); 754198157Srrs } 755198157Srrs} 756198157Srrs 757198157Srrs/********************************************************************** 758198157Srrs * Init MII interface 759198157Srrs * 760198157Srrs * Input parameters: 761198157Srrs * s - priv structure 762198157Srrs ********************************************************************* */ 763198157Srrs#define PHY_STATUS_RETRIES 25000 764198157Srrs 765198626Srrsstatic void 766198157Srrsrmi_xlr_mac_mii_init(struct driver_data *priv) 767198157Srrs{ 768198626Srrs xlr_reg_t *mii_mmio = priv->mii_mmio; 769198157Srrs 770198157Srrs /* use the lowest clock divisor - divisor 28 */ 771198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_CONFIG, 0x07); 772198157Srrs} 773198157Srrs 774198157Srrs/********************************************************************** 775198157Srrs * Read a PHY register. 776198157Srrs * 777198157Srrs * Input parameters: 778198157Srrs * s - priv structure 779198157Srrs * phyaddr - PHY's address 780198157Srrs * regidx = index of register to read 781198157Srrs * 782198157Srrs * Return value: 783198157Srrs * value read, or 0 if an error occurred. 784198157Srrs ********************************************************************* */ 785198157Srrs 786198626Srrsstatic int 787198626Srrsrge_mii_read_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx) 788198157Srrs{ 789198626Srrs int i = 0; 790198157Srrs 791198157Srrs /* setup the phy reg to be used */ 792198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS, 793198626Srrs (phyaddr << 8) | (regidx << 0)); 794198157Srrs /* Issue the read command */ 795198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND, 796198626Srrs (1 << O_MII_MGMT_COMMAND__rstat)); 797198157Srrs 798198157Srrs /* poll for the read cycle to complete */ 799198157Srrs for (i = 0; i < PHY_STATUS_RETRIES; i++) { 800198157Srrs if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0) 801198157Srrs break; 802198157Srrs } 803198157Srrs 804198157Srrs /* clear the read cycle */ 805198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND, 0); 806198157Srrs 807198157Srrs if (i == PHY_STATUS_RETRIES) { 808198157Srrs return 0xffffffff; 809198157Srrs } 810198157Srrs /* Read the data back */ 811198157Srrs return xlr_read_reg(mii_mmio, R_MII_MGMT_STATUS); 812198157Srrs} 813198157Srrs 814198626Srrsstatic int 815198608Srrsrge_mii_read(device_t dev, int phyaddr, int regidx) 816198157Srrs{ 817198157Srrs struct rge_softc *sc = device_get_softc(dev); 818198626Srrs 819198157Srrs return rge_mii_read_internal(sc->priv.mii_mmio, phyaddr, regidx); 820198157Srrs} 821198157Srrs 822198157Srrs/********************************************************************** 823198157Srrs * Set MII hooks to newly selected media 824198157Srrs * 825198157Srrs * Input parameters: 826198157Srrs * ifp - Interface Pointer 827198157Srrs * 828198157Srrs * Return value: 829198157Srrs * nothing 830198157Srrs ********************************************************************* */ 831198626Srrsstatic int 832198157Srrsrmi_xlr_mac_mediachange(struct ifnet *ifp) 833198157Srrs{ 834198157Srrs struct rge_softc *sc = ifp->if_softc; 835198157Srrs 836198157Srrs if (ifp->if_flags & IFF_UP) 837198157Srrs mii_mediachg(&sc->rge_mii); 838198157Srrs 839198157Srrs return 0; 840198157Srrs} 841198157Srrs 842198157Srrs/********************************************************************** 843198157Srrs * Get the current interface media status 844198157Srrs * 845198157Srrs * Input parameters: 846198157Srrs * ifp - Interface Pointer 847198157Srrs * ifmr - Interface media request ptr 848198157Srrs * 849198157Srrs * Return value: 850198157Srrs * nothing 851198157Srrs ********************************************************************* */ 852198157Srrsstatic void 853198157Srrsrmi_xlr_mac_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 854198157Srrs{ 855198157Srrs struct rge_softc *sc = ifp->if_softc; 856198157Srrs 857198626Srrs /* Check whether this is interface is active or not. */ 858198157Srrs ifmr->ifm_status = IFM_AVALID; 859198626Srrs if (sc->link_up) { 860198157Srrs ifmr->ifm_status |= IFM_ACTIVE; 861198626Srrs } else { 862198157Srrs ifmr->ifm_active = IFM_ETHER; 863198157Srrs } 864198157Srrs} 865198157Srrs 866198157Srrs/********************************************************************** 867198157Srrs * Write a value to a PHY register. 868198157Srrs * 869198157Srrs * Input parameters: 870198157Srrs * s - priv structure 871198157Srrs * phyaddr - PHY to use 872198157Srrs * regidx - register within the PHY 873198157Srrs * regval - data to write to register 874198157Srrs * 875198157Srrs * Return value: 876198157Srrs * nothing 877198157Srrs ********************************************************************* */ 878198608Srrsstatic void 879198626Srrsrge_mii_write_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx, int regval) 880198157Srrs{ 881198626Srrs int i = 0; 882198157Srrs 883198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS, 884198626Srrs (phyaddr << 8) | (regidx << 0)); 885198157Srrs 886198157Srrs /* Write the data which starts the write cycle */ 887198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_WRITE_DATA, regval); 888198157Srrs 889198157Srrs /* poll for the write cycle to complete */ 890198157Srrs for (i = 0; i < PHY_STATUS_RETRIES; i++) { 891198157Srrs if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0) 892198157Srrs break; 893198157Srrs } 894198157Srrs 895198157Srrs return; 896198157Srrs} 897198157Srrs 898198608Srrsstatic int 899198608Srrsrge_mii_write(device_t dev, int phyaddr, int regidx, int regval) 900198157Srrs{ 901198157Srrs struct rge_softc *sc = device_get_softc(dev); 902198157Srrs 903198157Srrs rge_mii_write_internal(sc->priv.mii_mmio, phyaddr, regidx, regval); 904198608Srrs return (0); 905198157Srrs} 906198157Srrs 907198626Srrsstatic void 908198608Srrsrmi_xlr_mac_mii_statchg(struct device *dev) 909198157Srrs{ 910198157Srrs} 911198157Srrs 912198157Srrsstatic void 913198157Srrsserdes_regs_init(struct driver_data *priv) 914198157Srrs{ 915198626Srrs xlr_reg_t *mmio_gpio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GPIO_OFFSET); 916198157Srrs 917198157Srrs /* Initialize SERDES CONTROL Registers */ 918198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 0, 0x6DB0); 919198626Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 1, 0xFFFF); 920198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 2, 0xB6D0); 921198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 3, 0x00FF); 922198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 4, 0x0000); 923198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 5, 0x0000); 924198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 6, 0x0005); 925198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 7, 0x0001); 926198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 8, 0x0000); 927198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 9, 0x0000); 928198626Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 10, 0x0000); 929198157Srrs 930198626Srrs /* 931209318Sjchandra * GPIO setting which affect the serdes - needs figuring out 932198157Srrs */ 933209318Sjchandra DELAY(100); 934209318Sjchandra xlr_write_reg(mmio_gpio, 0x20, 0x7e6802); 935209318Sjchandra xlr_write_reg(mmio_gpio, 0x10, 0x7104); 936209318Sjchandra DELAY(100); 937209318Sjchandra 938209318Sjchandra /* 939209318Sjchandra * This kludge is needed to setup serdes (?) clock correctly on some 940209318Sjchandra * XLS boards 941209318Sjchandra */ 942209318Sjchandra if ((xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI || 943209318Sjchandra xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XII) && 944209318Sjchandra xlr_boot1_info.board_minor_version == 4) { 945209318Sjchandra /* use 125 Mhz instead of 156.25Mhz ref clock */ 946209318Sjchandra DELAY(100); 947209318Sjchandra xlr_write_reg(mmio_gpio, 0x10, 0x7103); 948209318Sjchandra xlr_write_reg(mmio_gpio, 0x21, 0x7103); 949209318Sjchandra DELAY(100); 950198626Srrs } 951209318Sjchandra 952198157Srrs return; 953198626Srrs} 954198157Srrs 955199139Srrsstatic void 956198626Srrsserdes_autoconfig(struct driver_data *priv) 957198157Srrs{ 958198626Srrs int delay = 100000; 959198157Srrs 960198626Srrs /* Enable Auto negotiation in the PCS Layer */ 961198626Srrs rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x1000); 962198626Srrs DELAY(delay); 963198626Srrs rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x0200); 964198626Srrs DELAY(delay); 965198157Srrs 966198626Srrs rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x1000); 967198626Srrs DELAY(delay); 968198626Srrs rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x0200); 969198626Srrs DELAY(delay); 970198157Srrs 971198626Srrs rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x1000); 972198626Srrs DELAY(delay); 973198626Srrs rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x0200); 974198626Srrs DELAY(delay); 975198157Srrs 976198626Srrs rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x1000); 977198626Srrs DELAY(delay); 978198626Srrs rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x0200); 979198626Srrs DELAY(delay); 980198157Srrs 981198157Srrs} 982198157Srrs 983198157Srrs/***************************************************************** 984198157Srrs * Initialize GMAC 985198157Srrs *****************************************************************/ 986198626Srrsstatic void 987198157Srrsrmi_xlr_config_pde(struct driver_data *priv) 988198157Srrs{ 989198626Srrs int i = 0, cpu = 0, bucket = 0; 990198626Srrs uint64_t bucket_map = 0; 991198626Srrs 992198157Srrs /* uint32_t desc_pack_ctrl = 0; */ 993198626Srrs uint32_t cpumask; 994198157Srrs 995208369Sjchandra cpumask = 0x1; 996208165Srrs#ifdef SMP 997208165Srrs /* 998208165Srrs * rge may be called before SMP start in a BOOTP/NFSROOT 999208165Srrs * setup. we will distribute packets to other cpus only when 1000208165Srrs * the SMP is started. 1001208165Srrs */ 1002208165Srrs if (smp_started) 1003208369Sjchandra cpumask = xlr_hw_thread_mask; 1004208165Srrs#endif 1005198157Srrs 1006208165Srrs for (i = 0; i < MAXCPU; i++) { 1007198157Srrs if (cpumask & (1 << i)) { 1008208165Srrs cpu = i; 1009198626Srrs bucket = ((cpu >> 2) << 3); 1010198157Srrs bucket_map |= (1ULL << bucket); 1011198157Srrs } 1012198157Srrs } 1013209808Sjchandra printf("rmi_xlr_config_pde: bucket_map=%jx\n", (uintmax_t)bucket_map); 1014198157Srrs 1015198157Srrs /* bucket_map = 0x1; */ 1016198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_0, (bucket_map & 0xffffffff)); 1017198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_0 + 1, 1018198626Srrs ((bucket_map >> 32) & 0xffffffff)); 1019198157Srrs 1020198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_1, (bucket_map & 0xffffffff)); 1021198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_1 + 1, 1022198626Srrs ((bucket_map >> 32) & 0xffffffff)); 1023198157Srrs 1024198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_2, (bucket_map & 0xffffffff)); 1025198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_2 + 1, 1026198626Srrs ((bucket_map >> 32) & 0xffffffff)); 1027198157Srrs 1028198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_3, (bucket_map & 0xffffffff)); 1029198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_3 + 1, 1030198626Srrs ((bucket_map >> 32) & 0xffffffff)); 1031198157Srrs} 1032198157Srrs 1033198626Srrsstatic void 1034208165Srrsrge_smp_update_pde(void *dummy __unused) 1035208165Srrs{ 1036208165Srrs int i; 1037208165Srrs struct driver_data *priv; 1038208165Srrs struct rge_softc *sc; 1039208165Srrs 1040208165Srrs printf("Updating packet distribution for SMP\n"); 1041208165Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 1042208165Srrs sc = dev_mac[i]; 1043208165Srrs if (!sc) 1044208165Srrs continue; 1045208165Srrs priv = &(sc->priv); 1046208165Srrs rmi_xlr_mac_set_enable(priv, 0); 1047208165Srrs rmi_xlr_config_pde(priv); 1048208165Srrs rmi_xlr_mac_set_enable(priv, 1); 1049208165Srrs } 1050208165Srrs} 1051208165Srrs 1052208165SrrsSYSINIT(rge_smp_update_pde, SI_SUB_SMP, SI_ORDER_ANY, rge_smp_update_pde, NULL); 1053208165Srrs 1054208165Srrs 1055208165Srrsstatic void 1056198157Srrsrmi_xlr_config_parser(struct driver_data *priv) 1057198157Srrs{ 1058198157Srrs /* 1059198157Srrs * Mark it as no classification The parser extract is gauranteed to 1060198157Srrs * be zero with no classfication 1061198157Srrs */ 1062198157Srrs xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x00); 1063198157Srrs 1064198157Srrs xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x01); 1065198157Srrs 1066198157Srrs /* configure the parser : L2 Type is configured in the bootloader */ 1067198157Srrs /* extract IP: src, dest protocol */ 1068198157Srrs xlr_write_reg(priv->mmio, R_L3CTABLE, 1069198626Srrs (9 << 20) | (1 << 19) | (1 << 18) | (0x01 << 16) | 1070198626Srrs (0x0800 << 0)); 1071198157Srrs xlr_write_reg(priv->mmio, R_L3CTABLE + 1, 1072198626Srrs (12 << 25) | (4 << 21) | (16 << 14) | (4 << 10)); 1073198157Srrs 1074198157Srrs} 1075198157Srrs 1076198626Srrsstatic void 1077198157Srrsrmi_xlr_config_classifier(struct driver_data *priv) 1078198157Srrs{ 1079198626Srrs int i = 0; 1080198157Srrs 1081198157Srrs if (priv->type == XLR_XGMAC) { 1082198157Srrs /* xgmac translation table doesn't have sane values on reset */ 1083198157Srrs for (i = 0; i < 64; i++) 1084198157Srrs xlr_write_reg(priv->mmio, R_TRANSLATETABLE + i, 0x0); 1085198157Srrs 1086198157Srrs /* 1087198157Srrs * use upper 7 bits of the parser extract to index the 1088198157Srrs * translate table 1089198157Srrs */ 1090198157Srrs xlr_write_reg(priv->mmio, R_PARSERCONFIGREG, 0x0); 1091198157Srrs } 1092198157Srrs} 1093198157Srrs 1094198157Srrsenum { 1095198626Srrs SGMII_SPEED_10 = 0x00000000, 1096198626Srrs SGMII_SPEED_100 = 0x02000000, 1097198626Srrs SGMII_SPEED_1000 = 0x04000000, 1098198157Srrs}; 1099198157Srrs 1100198626Srrsstatic void 1101198157Srrsrmi_xlr_gmac_config_speed(struct driver_data *priv) 1102198157Srrs{ 1103198157Srrs int phy_addr = priv->phy_addr; 1104198626Srrs xlr_reg_t *mmio = priv->mmio; 1105198157Srrs struct rge_softc *sc = priv->sc; 1106198157Srrs 1107198157Srrs priv->speed = rge_mii_read_internal(priv->mii_mmio, phy_addr, 28); 1108198157Srrs priv->link = rge_mii_read_internal(priv->mii_mmio, phy_addr, 1) & 0x4; 1109198157Srrs priv->speed = (priv->speed >> 3) & 0x03; 1110198157Srrs 1111198157Srrs if (priv->speed == xlr_mac_speed_10) { 1112198157Srrs if (priv->mode != XLR_RGMII) 1113198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_10); 1114209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117); 1115198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x02); 1116198157Srrs printf("%s: [10Mbps]\n", device_get_nameunit(sc->rge_dev)); 1117198626Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1118198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1119198626Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1120198157Srrs } else if (priv->speed == xlr_mac_speed_100) { 1121198157Srrs if (priv->mode != XLR_RGMII) 1122198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100); 1123209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117); 1124198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x01); 1125198157Srrs printf("%s: [100Mbps]\n", device_get_nameunit(sc->rge_dev)); 1126198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1127198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1128198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1129198157Srrs } else { 1130198157Srrs if (priv->speed != xlr_mac_speed_1000) { 1131198157Srrs if (priv->mode != XLR_RGMII) 1132198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100); 1133198157Srrs printf("PHY reported unknown MAC speed, defaulting to 100Mbps\n"); 1134209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117); 1135198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x01); 1136198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1137198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1138198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1139198157Srrs } else { 1140198157Srrs if (priv->mode != XLR_RGMII) 1141198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_1000); 1142209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7217); 1143198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x00); 1144198157Srrs printf("%s: [1000Mbps]\n", device_get_nameunit(sc->rge_dev)); 1145198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1146198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1147198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1148198157Srrs } 1149198157Srrs } 1150198626Srrs 1151198157Srrs if (!priv->link) { 1152198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER; 1153198157Srrs sc->link_up = 0; 1154198157Srrs } else { 1155198157Srrs sc->link_up = 1; 1156198157Srrs } 1157198157Srrs} 1158198157Srrs 1159198157Srrs/***************************************************************** 1160198157Srrs * Initialize XGMAC 1161198157Srrs *****************************************************************/ 1162198626Srrsstatic void 1163198157Srrsrmi_xlr_xgmac_init(struct driver_data *priv) 1164198157Srrs{ 1165198626Srrs int i = 0; 1166198626Srrs xlr_reg_t *mmio = priv->mmio; 1167198626Srrs int id = priv->instance; 1168198157Srrs struct rge_softc *sc = priv->sc; 1169198157Srrs volatile unsigned short *cpld; 1170198157Srrs 1171198157Srrs cpld = (volatile unsigned short *)0xBD840000; 1172198157Srrs 1173198157Srrs xlr_write_reg(priv->mmio, R_DESC_PACK_CTRL, 1174198626Srrs (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize) | (4 << 20)); 1175198157Srrs xlr_write_reg(priv->mmio, R_BYTEOFFSET0, BYTE_OFFSET); 1176198157Srrs rmi_xlr_config_pde(priv); 1177198157Srrs rmi_xlr_config_parser(priv); 1178198157Srrs rmi_xlr_config_classifier(priv); 1179198157Srrs 1180198157Srrs xlr_write_reg(priv->mmio, R_MSG_TX_THRESHOLD, 1); 1181198157Srrs 1182198157Srrs /* configure the XGMAC Registers */ 1183198157Srrs xlr_write_reg(mmio, R_XGMAC_CONFIG_1, 0x50000026); 1184198157Srrs 1185198157Srrs /* configure the XGMAC_GLUE Registers */ 1186198157Srrs xlr_write_reg(mmio, R_DMACR0, 0xffffffff); 1187198157Srrs xlr_write_reg(mmio, R_DMACR1, 0xffffffff); 1188198157Srrs xlr_write_reg(mmio, R_DMACR2, 0xffffffff); 1189198157Srrs xlr_write_reg(mmio, R_DMACR3, 0xffffffff); 1190198157Srrs xlr_write_reg(mmio, R_STATCTRL, 0x04); 1191198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1192198157Srrs 1193198157Srrs xlr_write_reg(mmio, R_XGMACPADCALIBRATION, 0x030); 1194198157Srrs xlr_write_reg(mmio, R_EGRESSFIFOCARVINGSLOTS, 0x0f); 1195198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1196198157Srrs xlr_write_reg(mmio, R_XGMAC_MIIM_CONFIG, 0x3e); 1197198157Srrs 1198198157Srrs /* 1199198157Srrs * take XGMII phy out of reset 1200198157Srrs */ 1201198157Srrs /* 1202198157Srrs * we are pulling everything out of reset because writing a 0 would 1203198157Srrs * reset other devices on the chip 1204198157Srrs */ 1205198157Srrs cpld[ATX_CPLD_RESET_1] = 0xffff; 1206198157Srrs cpld[ATX_CPLD_MISC_CTRL] = 0xffff; 1207198157Srrs cpld[ATX_CPLD_RESET_2] = 0xffff; 1208198157Srrs 1209198157Srrs xgmac_mdio_setup(mmio); 1210198157Srrs 1211198157Srrs rmi_xlr_config_spill_area(priv); 1212198157Srrs 1213198157Srrs if (id == 0) { 1214198157Srrs for (i = 0; i < 16; i++) { 1215198157Srrs xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i, 1216198626Srrs bucket_sizes. 1217198626Srrs bucket[MSGRNG_STNID_XGS0_TX + i]); 1218198157Srrs } 1219198157Srrs 1220198157Srrs xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE, 1221198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC0JFR]); 1222198157Srrs xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE, 1223198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC0RFR]); 1224198157Srrs 1225198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1226198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1227198626Srrs cc_table_xgs_0. 1228198626Srrs counters[i >> 3][i & 0x07]); 1229198157Srrs } 1230198157Srrs } else if (id == 1) { 1231198157Srrs for (i = 0; i < 16; i++) { 1232198157Srrs xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i, 1233198626Srrs bucket_sizes. 1234198626Srrs bucket[MSGRNG_STNID_XGS1_TX + i]); 1235198157Srrs } 1236198157Srrs 1237198157Srrs xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE, 1238198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC1JFR]); 1239198157Srrs xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE, 1240198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC1RFR]); 1241198157Srrs 1242198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1243198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1244198626Srrs cc_table_xgs_1. 1245198626Srrs counters[i >> 3][i & 0x07]); 1246198157Srrs } 1247198157Srrs } 1248198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1249198157Srrs sc->rge_mii.mii_media.ifm_media |= (IFM_AVALID | IFM_ACTIVE); 1250198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1251198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1252198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media |= (IFM_AVALID | IFM_ACTIVE); 1253198157Srrs 1254198157Srrs priv->init_frin_desc = 1; 1255198157Srrs} 1256198157Srrs 1257198157Srrs/******************************************************* 1258198157Srrs * Initialization gmac 1259198157Srrs *******************************************************/ 1260198157Srrsstatic int 1261198157Srrsrmi_xlr_gmac_reset(struct driver_data *priv) 1262198157Srrs{ 1263198157Srrs volatile uint32_t val; 1264198157Srrs xlr_reg_t *mmio = priv->mmio; 1265198157Srrs int i, maxloops = 100; 1266198157Srrs 1267198626Srrs /* Disable MAC RX */ 1268198626Srrs val = xlr_read_reg(mmio, R_MAC_CONFIG_1); 1269198626Srrs val &= ~0x4; 1270198626Srrs xlr_write_reg(mmio, R_MAC_CONFIG_1, val); 1271198157Srrs 1272198626Srrs /* Disable Core RX */ 1273198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1274198626Srrs val &= ~0x1; 1275198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1276198157Srrs 1277198626Srrs /* wait for rx to halt */ 1278198626Srrs for (i = 0; i < maxloops; i++) { 1279198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1280198626Srrs if (val & 0x2) 1281198626Srrs break; 1282198626Srrs DELAY(1000); 1283198626Srrs } 1284198157Srrs if (i == maxloops) 1285198157Srrs return -1; 1286198157Srrs 1287198626Srrs /* Issue a soft reset */ 1288198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1289198626Srrs val |= 0x4; 1290198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1291198626Srrs 1292198626Srrs /* wait for reset to complete */ 1293198626Srrs for (i = 0; i < maxloops; i++) { 1294198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1295198626Srrs if (val & 0x8) 1296198626Srrs break; 1297198626Srrs DELAY(1000); 1298198626Srrs } 1299198157Srrs if (i == maxloops) 1300198157Srrs return -1; 1301198157Srrs 1302198626Srrs /* Clear the soft reset bit */ 1303198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1304198626Srrs val &= ~0x4; 1305198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1306198157Srrs return 0; 1307198157Srrs} 1308198157Srrs 1309198626Srrsstatic void 1310198157Srrsrmi_xlr_gmac_init(struct driver_data *priv) 1311198157Srrs{ 1312198626Srrs int i = 0; 1313198626Srrs xlr_reg_t *mmio = priv->mmio; 1314198626Srrs int id = priv->instance; 1315198157Srrs struct stn_cc *gmac_cc_config; 1316198626Srrs uint32_t value = 0; 1317198626Srrs int blk = id / 4, port = id % 4; 1318198157Srrs 1319198157Srrs rmi_xlr_mac_set_enable(priv, 0); 1320198157Srrs 1321198157Srrs rmi_xlr_config_spill_area(priv); 1322198157Srrs 1323198157Srrs xlr_write_reg(mmio, R_DESC_PACK_CTRL, 1324198626Srrs (BYTE_OFFSET << O_DESC_PACK_CTRL__ByteOffset) | 1325198626Srrs (1 << O_DESC_PACK_CTRL__MaxEntry) | 1326198626Srrs (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize)); 1327198157Srrs 1328198157Srrs rmi_xlr_config_pde(priv); 1329198157Srrs rmi_xlr_config_parser(priv); 1330198157Srrs rmi_xlr_config_classifier(priv); 1331198157Srrs 1332198157Srrs xlr_write_reg(mmio, R_MSG_TX_THRESHOLD, 3); 1333198157Srrs xlr_write_reg(mmio, R_MAC_CONFIG_1, 0x35); 1334198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, (0x7 << 6)); 1335198157Srrs 1336198626Srrs if (priv->mode == XLR_PORT0_RGMII) { 1337198157Srrs printf("Port 0 set in RGMII mode\n"); 1338198157Srrs value = xlr_read_reg(mmio, R_RX_CONTROL); 1339198157Srrs value |= 1 << O_RX_CONTROL__RGMII; 1340198157Srrs xlr_write_reg(mmio, R_RX_CONTROL, value); 1341198157Srrs } 1342198157Srrs rmi_xlr_mac_mii_init(priv); 1343198157Srrs 1344198626Srrs 1345198157Srrs#if 0 1346198157Srrs priv->advertising = ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half | 1347198626Srrs ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half | 1348198626Srrs ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | 1349198626Srrs ADVERTISED_MII; 1350198157Srrs#endif 1351198157Srrs 1352198157Srrs /* 1353198157Srrs * Enable all MDIO interrupts in the phy RX_ER bit seems to be get 1354198157Srrs * set about every 1 sec in GigE mode, ignore it for now... 1355198157Srrs */ 1356198157Srrs rge_mii_write_internal(priv->mii_mmio, priv->phy_addr, 25, 0xfffffffe); 1357198157Srrs 1358198626Srrs if (priv->mode != XLR_RGMII) { 1359198157Srrs serdes_regs_init(priv); 1360198157Srrs serdes_autoconfig(priv); 1361198157Srrs } 1362198626Srrs rmi_xlr_gmac_config_speed(priv); 1363198157Srrs 1364198157Srrs value = xlr_read_reg(mmio, R_IPG_IFG); 1365198157Srrs xlr_write_reg(mmio, R_IPG_IFG, ((value & ~0x7f) | MAC_B2B_IPG)); 1366198157Srrs xlr_write_reg(mmio, R_DMACR0, 0xffffffff); 1367198157Srrs xlr_write_reg(mmio, R_DMACR1, 0xffffffff); 1368198157Srrs xlr_write_reg(mmio, R_DMACR2, 0xffffffff); 1369198157Srrs xlr_write_reg(mmio, R_DMACR3, 0xffffffff); 1370198157Srrs xlr_write_reg(mmio, R_STATCTRL, 0x04); 1371198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1372198157Srrs xlr_write_reg(mmio, R_INTMASK, 0); 1373198157Srrs xlr_write_reg(mmio, R_FREEQCARVE, 0); 1374198157Srrs 1375198157Srrs xlr_write_reg(mmio, R_GMAC_TX0_BUCKET_SIZE + port, 1376198626Srrs xlr_board_info.bucket_sizes->bucket[priv->txbucket]); 1377198157Srrs xlr_write_reg(mmio, R_GMAC_JFR0_BUCKET_SIZE, 1378198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_0]); 1379198157Srrs xlr_write_reg(mmio, R_GMAC_RFR0_BUCKET_SIZE, 1380198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_0]); 1381198157Srrs xlr_write_reg(mmio, R_GMAC_JFR1_BUCKET_SIZE, 1382198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_1]); 1383198157Srrs xlr_write_reg(mmio, R_GMAC_RFR1_BUCKET_SIZE, 1384198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_1]); 1385198157Srrs 1386198157Srrs dbg_msg("Programming credit counter %d : %d -> %d\n", blk, R_GMAC_TX0_BUCKET_SIZE + port, 1387198626Srrs xlr_board_info.bucket_sizes->bucket[priv->txbucket]); 1388198157Srrs 1389198157Srrs gmac_cc_config = xlr_board_info.gmac_block[blk].credit_config; 1390198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1391198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1392198626Srrs gmac_cc_config->counters[i >> 3][i & 0x07]); 1393198157Srrs dbg_msg("%d: %d -> %d\n", priv->instance, 1394198626Srrs R_CC_CPU0_0 + i, gmac_cc_config->counters[i >> 3][i & 0x07]); 1395198157Srrs } 1396198157Srrs priv->init_frin_desc = 1; 1397198157Srrs} 1398198157Srrs 1399198157Srrs/********************************************************************** 1400198157Srrs * Set promiscuous mode 1401198157Srrs **********************************************************************/ 1402198626Srrsstatic void 1403198157Srrsxlr_mac_set_rx_mode(struct rge_softc *sc) 1404198157Srrs{ 1405198157Srrs struct driver_data *priv = &(sc->priv); 1406198626Srrs uint32_t regval; 1407198157Srrs 1408198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_FILTER_CONFIG); 1409198626Srrs 1410198157Srrs if (sc->flags & IFF_PROMISC) { 1411198157Srrs regval |= (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) | 1412198626Srrs (1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) | 1413198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) | 1414198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN); 1415198157Srrs } else { 1416198157Srrs regval &= ~((1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) | 1417198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN)); 1418198157Srrs } 1419198157Srrs 1420198157Srrs xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG, regval); 1421198157Srrs} 1422198157Srrs 1423198157Srrs/********************************************************************** 1424198157Srrs * Configure LAN speed for the specified MAC. 1425198157Srrs ********************************************************************* */ 1426198626Srrsstatic int 1427198157Srrsrmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed) 1428198157Srrs{ 1429198157Srrs return 0; 1430198157Srrs} 1431198157Srrs 1432198157Srrs/********************************************************************** 1433198157Srrs * Set Ethernet duplex and flow control options for this MAC 1434198157Srrs ********************************************************************* */ 1435198626Srrsstatic int 1436198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s, 1437198626Srrs xlr_mac_duplex_t duplex, xlr_mac_fc_t fc) 1438198157Srrs{ 1439198157Srrs return 0; 1440198157Srrs} 1441198157Srrs 1442198157Srrs/***************************************************************** 1443198157Srrs * Kernel Net Stack <-> MAC Driver Interface 1444198157Srrs *****************************************************************/ 1445198157Srrs/********************************************************************** 1446198157Srrs **********************************************************************/ 1447198157Srrs#define MAC_TX_FAIL 2 1448198157Srrs#define MAC_TX_PASS 0 1449198157Srrs#define MAC_TX_RETRY 1 1450198157Srrs 1451198626Srrsint xlr_dev_queue_xmit_hack = 0; 1452198157Srrs 1453198626Srrsstatic int 1454198157Srrsmac_xmit(struct mbuf *m, struct rge_softc *sc, 1455198626Srrs struct driver_data *priv, int len, struct p2d_tx_desc *tx_desc) 1456198157Srrs{ 1457212321Sjchandra struct msgrng_msg msg = {0,0,0,0}; 1458198626Srrs int stid = priv->txbucket; 1459198626Srrs uint32_t tx_cycles = 0; 1460212321Sjchandra uint32_t mflags; 1461208369Sjchandra int vcpu = xlr_cpu_id(); 1462198157Srrs int rv; 1463198157Srrs 1464198157Srrs tx_cycles = mips_rd_count(); 1465198157Srrs 1466198157Srrs if (build_frag_list(m, &msg, tx_desc) != 0) 1467198157Srrs return MAC_TX_FAIL; 1468198157Srrs 1469198157Srrs else { 1470212321Sjchandra mflags = msgrng_access_enable(); 1471212553Sjchandra if ((rv = message_send(1, MSGRNG_CODE_MAC, stid, &msg)) != 0) { 1472198157Srrs msg_snd_failed++; 1473212321Sjchandra msgrng_restore(mflags); 1474198157Srrs release_tx_desc(&msg, 0); 1475198157Srrs xlr_rge_msg_snd_failed[vcpu]++; 1476209808Sjchandra dbg_msg("Failed packet to cpu %d, rv = %d, stid %d, msg0=%jx\n", 1477209808Sjchandra vcpu, rv, stid, (uintmax_t)msg.msg0); 1478198157Srrs return MAC_TX_FAIL; 1479198157Srrs } 1480212321Sjchandra msgrng_restore(mflags); 1481198157Srrs port_inc_counter(priv->instance, PORT_TX); 1482198157Srrs } 1483198157Srrs 1484198157Srrs /* Send the packet to MAC */ 1485209808Sjchandra dbg_msg("Sent tx packet to stid %d, msg0=%jx, msg1=%jx \n", stid, 1486209808Sjchandra (uintmax_t)msg.msg0, (uintmax_t)msg.msg1); 1487198157Srrs#ifdef DUMP_PACKETS 1488198157Srrs { 1489198626Srrs int i = 0; 1490198626Srrs unsigned char *buf = (char *)m->m_data; 1491198626Srrs 1492198157Srrs printf("Tx Packet: length=%d\n", len); 1493198157Srrs for (i = 0; i < 64; i++) { 1494198157Srrs if (i && (i % 16) == 0) 1495198157Srrs printf("\n"); 1496198157Srrs printf("%02x ", buf[i]); 1497198157Srrs } 1498198157Srrs printf("\n"); 1499198157Srrs } 1500198157Srrs#endif 1501198157Srrs xlr_inc_counter(NETIF_TX); 1502198157Srrs return MAC_TX_PASS; 1503198157Srrs} 1504198157Srrs 1505198626Srrsstatic int 1506198157Srrsrmi_xlr_mac_xmit(struct mbuf *m, struct rge_softc *sc, int len, struct p2d_tx_desc *tx_desc) 1507198157Srrs{ 1508198157Srrs struct driver_data *priv = &(sc->priv); 1509198626Srrs int ret = -ENOSPC; 1510198157Srrs 1511198157Srrs dbg_msg("IN\n"); 1512198157Srrs 1513198157Srrs xlr_inc_counter(NETIF_STACK_TX); 1514198157Srrs 1515198157Srrsretry: 1516198157Srrs ret = mac_xmit(m, sc, priv, len, tx_desc); 1517198157Srrs 1518198157Srrs if (ret == MAC_TX_RETRY) 1519198157Srrs goto retry; 1520198157Srrs 1521198157Srrs dbg_msg("OUT, ret = %d\n", ret); 1522198157Srrs if (ret == MAC_TX_FAIL) { 1523198157Srrs /* FULL */ 1524198157Srrs dbg_msg("Msg Ring Full. Stopping upper layer Q\n"); 1525198157Srrs port_inc_counter(priv->instance, PORT_STOPQ); 1526198157Srrs } 1527198157Srrs return ret; 1528198157Srrs} 1529198157Srrs 1530198626Srrsstatic void 1531198157Srrsmac_frin_replenish(void *args /* ignored */ ) 1532198157Srrs{ 1533208165Srrs int cpu = xlr_core_id(); 1534198626Srrs int done = 0; 1535198626Srrs int i = 0; 1536198157Srrs 1537198157Srrs xlr_inc_counter(REPLENISH_ENTER); 1538198157Srrs /* 1539198157Srrs * xlr_set_counter(REPLENISH_ENTER_COUNT, 1540198157Srrs * atomic_read(frin_to_be_sent)); 1541198157Srrs */ 1542198157Srrs xlr_set_counter(REPLENISH_CPU, PCPU_GET(cpuid)); 1543198157Srrs 1544198157Srrs for (;;) { 1545198157Srrs 1546198157Srrs done = 0; 1547198157Srrs 1548198157Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 1549198157Srrs /* int offset = 0; */ 1550198626Srrs void *m; 1551198626Srrs uint32_t cycles; 1552198157Srrs struct rge_softc *sc; 1553198157Srrs struct driver_data *priv; 1554198626Srrs int frin_to_be_sent; 1555198157Srrs 1556198157Srrs sc = dev_mac[i]; 1557198157Srrs if (!sc) 1558198157Srrs goto skip; 1559198157Srrs 1560198157Srrs priv = &(sc->priv); 1561198157Srrs frin_to_be_sent = priv->frin_to_be_sent[cpu]; 1562198157Srrs 1563198157Srrs /* if (atomic_read(frin_to_be_sent) < 0) */ 1564198157Srrs if (frin_to_be_sent < 0) { 1565198626Srrs panic("BUG?: [%s]: gmac_%d illegal value for frin_to_be_sent=%d\n", 1566198626Srrs __FUNCTION__, i, 1567198626Srrs frin_to_be_sent); 1568198157Srrs } 1569198157Srrs /* if (!atomic_read(frin_to_be_sent)) */ 1570198157Srrs if (!frin_to_be_sent) 1571198157Srrs goto skip; 1572198157Srrs 1573198157Srrs cycles = mips_rd_count(); 1574198157Srrs { 1575198157Srrs m = get_buf(); 1576198157Srrs if (!m) { 1577198157Srrs device_printf(sc->rge_dev, "No buffer\n"); 1578198157Srrs goto skip; 1579198157Srrs } 1580198157Srrs } 1581198157Srrs xlr_inc_counter(REPLENISH_FRIN); 1582198157Srrs if (xlr_mac_send_fr(priv, vtophys(m), MAX_FRAME_SIZE)) { 1583198157Srrs free_buf(vtophys(m)); 1584198157Srrs printf("[%s]: rx free message_send failed!\n", __FUNCTION__); 1585198157Srrs break; 1586198157Srrs } 1587198157Srrs xlr_set_counter(REPLENISH_CYCLES, 1588198626Srrs (read_c0_count() - cycles)); 1589198157Srrs atomic_subtract_int((&priv->frin_to_be_sent[cpu]), 1); 1590198157Srrs 1591198157Srrs continue; 1592198157Srrs skip: 1593198157Srrs done++; 1594198157Srrs } 1595198157Srrs if (done == XLR_MAX_MACS) 1596198157Srrs break; 1597198157Srrs } 1598198157Srrs} 1599198157Srrs 1600203010Srrsstatic volatile uint32_t g_tx_frm_tx_ok=0; 1601198157Srrs 1602198626Srrsstatic void 1603198157Srrsrge_tx_bkp_func(void *arg, int npending) 1604198157Srrs{ 1605198626Srrs int i = 0; 1606198626Srrs 1607198626Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 1608198157Srrs if (!dev_mac[i] || !dev_mac[i]->active) 1609198157Srrs continue; 1610198157Srrs rge_start_locked(dev_mac[i]->rge_ifp, RGE_TX_THRESHOLD); 1611198157Srrs } 1612198157Srrs atomic_subtract_int(&g_tx_frm_tx_ok, 1); 1613198157Srrs} 1614198157Srrs 1615198157Srrs/* This function is called from an interrupt handler */ 1616198626Srrsvoid 1617198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code, 1618198626Srrs int stid, struct msgrng_msg *msg, 1619198626Srrs void *data /* ignored */ ) 1620198157Srrs{ 1621198626Srrs uint64_t phys_addr = 0; 1622198626Srrs unsigned long addr = 0; 1623198626Srrs uint32_t length = 0; 1624198626Srrs int ctrl = 0, port = 0; 1625198157Srrs struct rge_softc *sc = NULL; 1626198157Srrs struct driver_data *priv = 0; 1627198626Srrs struct ifnet *ifp; 1628208165Srrs int vcpu = xlr_cpu_id(); 1629208165Srrs int cpu = xlr_core_id(); 1630198157Srrs 1631209808Sjchandra dbg_msg("mac: bucket=%d, size=%d, code=%d, stid=%d, msg0=%jx msg1=%jx\n", 1632209808Sjchandra bucket, size, code, stid, (uintmax_t)msg->msg0, (uintmax_t)msg->msg1); 1633198157Srrs 1634198157Srrs phys_addr = (uint64_t) (msg->msg0 & 0xffffffffe0ULL); 1635198157Srrs length = (msg->msg0 >> 40) & 0x3fff; 1636198157Srrs if (length == 0) { 1637198157Srrs ctrl = CTRL_REG_FREE; 1638198157Srrs port = (msg->msg0 >> 54) & 0x0f; 1639198157Srrs addr = 0; 1640198157Srrs } else { 1641198157Srrs ctrl = CTRL_SNGL; 1642198157Srrs length = length - BYTE_OFFSET - MAC_CRC_LEN; 1643198157Srrs port = msg->msg0 & 0x0f; 1644198157Srrs addr = 0; 1645198157Srrs } 1646198157Srrs 1647198157Srrs if (xlr_board_info.is_xls) { 1648198157Srrs if (stid == MSGRNG_STNID_GMAC1) 1649198157Srrs port += 4; 1650198157Srrs sc = dev_mac[dev_mac_gmac0 + port]; 1651198157Srrs } else { 1652198157Srrs if (stid == MSGRNG_STNID_XGS0FR) 1653198157Srrs sc = dev_mac[dev_mac_xgs0]; 1654198157Srrs else if (stid == MSGRNG_STNID_XGS1FR) 1655198157Srrs sc = dev_mac[dev_mac_xgs0 + 1]; 1656198626Srrs else 1657198157Srrs sc = dev_mac[dev_mac_gmac0 + port]; 1658198157Srrs } 1659198157Srrs if (sc == NULL) 1660198157Srrs return; 1661198157Srrs priv = &(sc->priv); 1662198157Srrs 1663209808Sjchandra dbg_msg("msg0 = %jx, stid = %d, port = %d, addr=%lx, length=%d, ctrl=%d\n", 1664209808Sjchandra (uintmax_t)msg->msg0, stid, port, addr, length, ctrl); 1665198157Srrs 1666198157Srrs if (ctrl == CTRL_REG_FREE || ctrl == CTRL_JUMBO_FREE) { 1667198157Srrs xlr_rge_tx_ok_done[vcpu]++; 1668198157Srrs release_tx_desc(msg, 1); 1669198157Srrs ifp = sc->rge_ifp; 1670198626Srrs if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { 1671198157Srrs ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1672198157Srrs } 1673198626Srrs if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1)) 1674198626Srrs rge_tx_bkp_func(NULL, 0); 1675198157Srrs xlr_set_counter(NETIF_TX_COMPLETE_CYCLES, 1676198626Srrs (read_c0_count() - msgrng_msg_cycles)); 1677198157Srrs } else if (ctrl == CTRL_SNGL || ctrl == CTRL_START) { 1678198157Srrs /* Rx Packet */ 1679198157Srrs /* struct mbuf *m = 0; */ 1680198157Srrs /* int logical_cpu = 0; */ 1681198157Srrs 1682198157Srrs dbg_msg("Received packet, port = %d\n", port); 1683198157Srrs /* 1684198157Srrs * if num frins to be sent exceeds threshold, wake up the 1685198157Srrs * helper thread 1686198157Srrs */ 1687198157Srrs atomic_add_int(&(priv->frin_to_be_sent[cpu]), 1); 1688198157Srrs if ((priv->frin_to_be_sent[cpu]) > MAC_FRIN_TO_BE_SENT_THRESHOLD) { 1689198157Srrs mac_frin_replenish(NULL); 1690198157Srrs } 1691209808Sjchandra dbg_msg("gmac_%d: rx packet: phys_addr = %jx, length = %x\n", 1692209808Sjchandra priv->instance, (uintmax_t)phys_addr, length); 1693198157Srrs mac_stats_add(priv->stats.rx_packets, 1); 1694198157Srrs mac_stats_add(priv->stats.rx_bytes, length); 1695198157Srrs xlr_inc_counter(NETIF_RX); 1696198157Srrs xlr_set_counter(NETIF_RX_CYCLES, 1697198626Srrs (read_c0_count() - msgrng_msg_cycles)); 1698198157Srrs rge_rx(sc, phys_addr, length); 1699198157Srrs xlr_rge_rx_done[vcpu]++; 1700198157Srrs } else { 1701198157Srrs printf("[%s]: unrecognized ctrl=%d!\n", __FUNCTION__, ctrl); 1702198157Srrs } 1703198157Srrs 1704198157Srrs} 1705198157Srrs 1706198157Srrs/********************************************************************** 1707198157Srrs **********************************************************************/ 1708198157Srrsstatic int 1709198157Srrsrge_probe(dev) 1710198626Srrs device_t dev; 1711198157Srrs{ 1712208265Srpaulo device_set_desc(dev, "RMI Gigabit Ethernet"); 1713208265Srpaulo 1714198157Srrs /* Always return 0 */ 1715198157Srrs return 0; 1716198157Srrs} 1717198157Srrs 1718198157Srrsvolatile unsigned long xlr_debug_enabled; 1719198626Srrsstruct callout rge_dbg_count; 1720199139Srrsstatic void 1721198626Srrsxlr_debug_count(void *addr) 1722198157Srrs{ 1723198157Srrs struct driver_data *priv = &dev_mac[0]->priv; 1724198626Srrs 1725198626Srrs /* uint32_t crdt; */ 1726198626Srrs if (xlr_debug_enabled) { 1727198626Srrs printf("\nAvailRxIn %#x\n", xlr_read_reg(priv->mmio, 0x23e)); 1728198157Srrs } 1729198157Srrs callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL); 1730198157Srrs} 1731198157Srrs 1732198157Srrs 1733199139Srrsstatic void 1734198626Srrsxlr_tx_q_wakeup(void *addr) 1735198157Srrs{ 1736198626Srrs int i = 0; 1737198626Srrs int j = 0; 1738198626Srrs 1739198626Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 1740198157Srrs if (!dev_mac[i] || !dev_mac[i]->active) 1741198157Srrs continue; 1742198626Srrs if ((dev_mac[i]->rge_ifp->if_drv_flags) & IFF_DRV_OACTIVE) { 1743198626Srrs for (j = 0; j < XLR_MAX_CORE; j++) { 1744198626Srrs if (xlr_tot_avail_p2d[j]) { 1745198157Srrs dev_mac[i]->rge_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1746198157Srrs break; 1747198157Srrs } 1748198157Srrs } 1749198157Srrs } 1750198157Srrs } 1751203010Srrs if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1)) 1752203010Srrs rge_tx_bkp_func(NULL, 0); 1753198626Srrs callout_reset(&xlr_tx_stop_bkp, 5 * hz, xlr_tx_q_wakeup, NULL); 1754198157Srrs} 1755198157Srrs 1756198157Srrsstatic int 1757198608Srrsrge_attach(device_t dev) 1758198157Srrs{ 1759198626Srrs struct ifnet *ifp; 1760198157Srrs struct rge_softc *sc; 1761198157Srrs struct driver_data *priv = 0; 1762198626Srrs int ret = 0; 1763198157Srrs struct xlr_gmac_block_t *gmac_conf = device_get_ivars(dev); 1764198157Srrs 1765198157Srrs sc = device_get_softc(dev); 1766198157Srrs sc->rge_dev = dev; 1767198157Srrs 1768198157Srrs /* Initialize mac's */ 1769198157Srrs sc->unit = device_get_unit(dev); 1770198157Srrs 1771198157Srrs if (sc->unit > XLR_MAX_MACS) { 1772198157Srrs ret = ENXIO; 1773198157Srrs goto out; 1774198157Srrs } 1775198157Srrs RGE_LOCK_INIT(sc, device_get_nameunit(dev)); 1776198157Srrs 1777198157Srrs priv = &(sc->priv); 1778198157Srrs priv->sc = sc; 1779198157Srrs 1780198157Srrs sc->flags = 0; /* TODO : fix me up later */ 1781198157Srrs 1782198157Srrs priv->id = sc->unit; 1783198157Srrs if (gmac_conf->type == XLR_GMAC) { 1784198157Srrs priv->instance = priv->id; 1785198626Srrs priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr + 1786198626Srrs 0x1000 * (sc->unit % 4)); 1787198157Srrs if ((ret = rmi_xlr_gmac_reset(priv)) == -1) 1788198157Srrs goto out; 1789198157Srrs } else if (gmac_conf->type == XLR_XGMAC) { 1790198157Srrs priv->instance = priv->id - xlr_board_info.gmacports; 1791198157Srrs priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr); 1792198157Srrs } 1793209318Sjchandra if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI || 1794209318Sjchandra (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI && 1795209318Sjchandra priv->instance >=4)) { 1796198157Srrs dbg_msg("Arizona board - offset 4 \n"); 1797198626Srrs priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_4_OFFSET); 1798198157Srrs } else 1799198626Srrs priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET); 1800198157Srrs 1801198626Srrs priv->pcs_mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr); 1802198626Srrs priv->serdes_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET); 1803198157Srrs 1804198626Srrs sc->base_addr = (unsigned long)priv->mmio; 1805198626Srrs sc->mem_end = (unsigned long)priv->mmio + XLR_IO_SIZE - 1; 1806198157Srrs 1807198157Srrs sc->xmit = rge_start; 1808198157Srrs sc->stop = rge_stop; 1809198157Srrs sc->get_stats = rmi_xlr_mac_get_stats; 1810198157Srrs sc->ioctl = rge_ioctl; 1811198157Srrs 1812198157Srrs /* Initialize the device specific driver data */ 1813198157Srrs mtx_init(&priv->lock, "rge", NULL, MTX_SPIN); 1814198157Srrs 1815198157Srrs priv->type = gmac_conf->type; 1816198157Srrs 1817198157Srrs priv->mode = gmac_conf->mode; 1818198157Srrs if (xlr_board_info.is_xls == 0) { 1819209318Sjchandra /* TODO - check II and IIB boards */ 1820209318Sjchandra if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_II && 1821209318Sjchandra xlr_boot1_info.board_minor_version != 1) 1822198157Srrs priv->phy_addr = priv->instance - 2; 1823198157Srrs else 1824198157Srrs priv->phy_addr = priv->instance; 1825198157Srrs priv->mode = XLR_RGMII; 1826198626Srrs } else { 1827198157Srrs if (gmac_conf->mode == XLR_PORT0_RGMII && 1828198626Srrs priv->instance == 0) { 1829198626Srrs priv->mode = XLR_PORT0_RGMII; 1830198157Srrs priv->phy_addr = 0; 1831198626Srrs } else { 1832198626Srrs priv->mode = XLR_SGMII; 1833209318Sjchandra /* Board 11 has SGMII daughter cards with the XLS chips, in this case 1834209318Sjchandra the phy number is 0-3 for both GMAC blocks */ 1835209318Sjchandra if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI) 1836209318Sjchandra priv->phy_addr = priv->instance % 4 + 16; 1837209318Sjchandra else 1838209318Sjchandra priv->phy_addr = priv->instance + 16; 1839198157Srrs } 1840198157Srrs } 1841198157Srrs 1842198157Srrs priv->txbucket = gmac_conf->station_txbase + priv->instance % 4; 1843198626Srrs priv->rfrbucket = gmac_conf->station_rfr; 1844198157Srrs priv->spill_configured = 0; 1845198157Srrs 1846198157Srrs dbg_msg("priv->mmio=%p\n", priv->mmio); 1847198157Srrs 1848198157Srrs /* Set up ifnet structure */ 1849198157Srrs ifp = sc->rge_ifp = if_alloc(IFT_ETHER); 1850198157Srrs if (ifp == NULL) { 1851198157Srrs device_printf(sc->rge_dev, "failed to if_alloc()\n"); 1852198157Srrs rge_release_resources(sc); 1853198157Srrs ret = ENXIO; 1854198157Srrs RGE_LOCK_DESTROY(sc); 1855198157Srrs goto out; 1856198157Srrs } 1857198157Srrs ifp->if_softc = sc; 1858198157Srrs if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1859198157Srrs ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1860198157Srrs ifp->if_ioctl = rge_ioctl; 1861198157Srrs ifp->if_start = rge_start; 1862198157Srrs ifp->if_init = rge_init; 1863198157Srrs ifp->if_mtu = ETHERMTU; 1864198157Srrs ifp->if_snd.ifq_drv_maxlen = RGE_TX_Q_SIZE; 1865198157Srrs IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 1866198157Srrs IFQ_SET_READY(&ifp->if_snd); 1867198157Srrs sc->active = 1; 1868198626Srrs ifp->if_hwassist = 0; 1869198626Srrs ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING; 1870198157Srrs ifp->if_capenable = ifp->if_capabilities; 1871198157Srrs 1872198157Srrs /* Initialize the rge_softc */ 1873198157Srrs sc->irq = gmac_conf->baseirq + priv->instance % 4; 1874198157Srrs 1875198608Srrs /* Set the IRQ into the rid field */ 1876199139Srrs /* 1877199139Srrs * note this is a hack to pass the irq to the iodi interrupt setup 1878199139Srrs * routines 1879199139Srrs */ 1880209808Sjchandra sc->rge_irq.__r_i = (struct resource_i *)(intptr_t)sc->irq; 1881198608Srrs 1882198157Srrs ret = bus_setup_intr(dev, &sc->rge_irq, INTR_FAST | INTR_TYPE_NET | INTR_MPSAFE, 1883198626Srrs NULL, rge_intr, sc, &sc->rge_intrhand); 1884198157Srrs 1885198157Srrs if (ret) { 1886198157Srrs rge_detach(dev); 1887198157Srrs device_printf(sc->rge_dev, "couldn't set up irq\n"); 1888198157Srrs RGE_LOCK_DESTROY(sc); 1889198157Srrs goto out; 1890198157Srrs } 1891198157Srrs xlr_mac_get_hwaddr(sc); 1892198157Srrs xlr_mac_setup_hwaddr(priv); 1893198157Srrs 1894198157Srrs dbg_msg("MMIO %08lx, MII %08lx, PCS %08lx, base %08lx PHY %d IRQ %d\n", 1895198626Srrs (u_long)priv->mmio, (u_long)priv->mii_mmio, (u_long)priv->pcs_mmio, 1896198626Srrs (u_long)sc->base_addr, priv->phy_addr, sc->irq); 1897198626Srrs dbg_msg("HWADDR %02x:%02x tx %d rfr %d\n", (u_int)sc->dev_addr[4], 1898198626Srrs (u_int)sc->dev_addr[5], priv->txbucket, priv->rfrbucket); 1899198157Srrs 1900198157Srrs /* 1901198157Srrs * Set up ifmedia support. 1902198157Srrs */ 1903198157Srrs /* 1904198157Srrs * Initialize MII/media info. 1905198157Srrs */ 1906198157Srrs sc->rge_mii.mii_ifp = ifp; 1907198157Srrs sc->rge_mii.mii_readreg = rge_mii_read; 1908198626Srrs sc->rge_mii.mii_writereg = (mii_writereg_t) rge_mii_write; 1909198157Srrs sc->rge_mii.mii_statchg = rmi_xlr_mac_mii_statchg; 1910198157Srrs ifmedia_init(&sc->rge_mii.mii_media, 0, rmi_xlr_mac_mediachange, 1911198626Srrs rmi_xlr_mac_mediastatus); 1912198157Srrs ifmedia_add(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL); 1913198157Srrs ifmedia_set(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO); 1914198157Srrs sc->rge_mii.mii_media.ifm_media = sc->rge_mii.mii_media.ifm_cur->ifm_media; 1915198157Srrs 1916198157Srrs /* 1917198157Srrs * Call MI attach routine. 1918198157Srrs */ 1919198157Srrs ether_ifattach(ifp, sc->dev_addr); 1920198157Srrs 1921198157Srrs if (priv->type == XLR_GMAC) { 1922198157Srrs rmi_xlr_gmac_init(priv); 1923198157Srrs } else if (priv->type == XLR_XGMAC) { 1924198157Srrs rmi_xlr_xgmac_init(priv); 1925198157Srrs } 1926198157Srrs dbg_msg("rge_%d: Phoenix Mac at 0x%p (mtu=%d)\n", 1927198626Srrs sc->unit, priv->mmio, sc->mtu); 1928198157Srrs dev_mac[sc->unit] = sc; 1929198157Srrs if (priv->type == XLR_XGMAC && priv->instance == 0) 1930198157Srrs dev_mac_xgs0 = sc->unit; 1931198157Srrs if (priv->type == XLR_GMAC && priv->instance == 0) 1932198157Srrs dev_mac_gmac0 = sc->unit; 1933198157Srrs 1934198626Srrs if (!gmac_common_init_done) { 1935198157Srrs mac_common_init(); 1936198157Srrs gmac_common_init_done = 1; 1937198157Srrs callout_init(&xlr_tx_stop_bkp, CALLOUT_MPSAFE); 1938198157Srrs callout_reset(&xlr_tx_stop_bkp, hz, xlr_tx_q_wakeup, NULL); 1939198157Srrs callout_init(&rge_dbg_count, CALLOUT_MPSAFE); 1940198626Srrs //callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL); 1941198157Srrs } 1942198157Srrs if ((ret = rmi_xlr_mac_open(sc)) == -1) { 1943198157Srrs RGE_LOCK_DESTROY(sc); 1944198157Srrs goto out; 1945198157Srrs } 1946198157Srrsout: 1947198157Srrs if (ret < 0) { 1948198157Srrs device_printf(dev, "error - skipping\n"); 1949198157Srrs } 1950198157Srrs return ret; 1951198157Srrs} 1952198157Srrs 1953198626Srrsstatic void 1954198157Srrsrge_reset(struct rge_softc *sc) 1955198157Srrs{ 1956198157Srrs} 1957198157Srrs 1958198157Srrsstatic int 1959198157Srrsrge_detach(dev) 1960198626Srrs device_t dev; 1961198157Srrs{ 1962198157Srrs#ifdef FREEBSD_MAC_NOT_YET 1963198157Srrs struct rge_softc *sc; 1964198626Srrs struct ifnet *ifp; 1965198157Srrs 1966198157Srrs sc = device_get_softc(dev); 1967198157Srrs ifp = sc->rge_ifp; 1968198157Srrs 1969198157Srrs RGE_LOCK(sc); 1970198157Srrs rge_stop(sc); 1971198157Srrs rge_reset(sc); 1972198157Srrs RGE_UNLOCK(sc); 1973198157Srrs 1974198157Srrs ether_ifdetach(ifp); 1975198157Srrs 1976198157Srrs if (sc->rge_tbi) { 1977198157Srrs ifmedia_removeall(&sc->rge_ifmedia); 1978198157Srrs } else { 1979198157Srrs bus_generic_detach(dev); 1980198157Srrs device_delete_child(dev, sc->rge_miibus); 1981198157Srrs } 1982198157Srrs 1983198157Srrs rge_release_resources(sc); 1984198157Srrs 1985198157Srrs#endif /* FREEBSD_MAC_NOT_YET */ 1986198157Srrs return (0); 1987198157Srrs} 1988198626Srrsstatic int 1989198157Srrsrge_suspend(device_t dev) 1990198157Srrs{ 1991198157Srrs struct rge_softc *sc; 1992198157Srrs 1993198157Srrs sc = device_get_softc(dev); 1994198157Srrs RGE_LOCK(sc); 1995198157Srrs rge_stop(sc); 1996198157Srrs RGE_UNLOCK(sc); 1997198157Srrs 1998198157Srrs return 0; 1999198157Srrs} 2000198157Srrs 2001198626Srrsstatic int 2002198157Srrsrge_resume(device_t dev) 2003198157Srrs{ 2004198157Srrs panic("rge_resume(): unimplemented\n"); 2005198157Srrs return 0; 2006198157Srrs} 2007198157Srrs 2008198626Srrsstatic void 2009198157Srrsrge_release_resources(struct rge_softc *sc) 2010198157Srrs{ 2011198157Srrs 2012198157Srrs if (sc->rge_ifp != NULL) 2013198157Srrs if_free(sc->rge_ifp); 2014198157Srrs 2015198157Srrs if (mtx_initialized(&sc->rge_mtx)) /* XXX */ 2016198157Srrs RGE_LOCK_DESTROY(sc); 2017198157Srrs} 2018198626Srrsuint32_t gmac_rx_fail[32]; 2019198626Srrsuint32_t gmac_rx_pass[32]; 2020198157Srrs 2021198626Srrsstatic void 2022198157Srrsrge_rx(struct rge_softc *sc, vm_paddr_t paddr, int len) 2023198157Srrs{ 2024198626Srrs struct mbuf *m; 2025210630Sjchandra uint32_t mag; 2026198626Srrs struct ifnet *ifp = sc->rge_ifp; 2027210630Sjchandra#ifdef __mips_n64 2028210630Sjchandra uint64_t *vaddr; 2029198157Srrs 2030210630Sjchandra vaddr =(uint64_t *)MIPS_PHYS_TO_XKPHYS_CACHED(paddr - XLR_CACHELINE_SIZE); 2031210630Sjchandra m = (struct mbuf *)vaddr[0]; 2032210630Sjchandra mag = (uint32_t)vaddr[1]; 2033210630Sjchandra#else 2034210630Sjchandra uint32_t sr; 2035210630Sjchandra /* 2036210630Sjchandra * On 32 bit machines we use XKPHYS to get the values stores with 2037210630Sjchandra * the mbuf, need to explicitly enable KX. Disable interrupts while 2038210630Sjchandra * KX is enabled to prevent this setting leaking to other code. 2039210630Sjchandra */ 2040208165Srrs sr = xlr_enable_kx(); 2041210630Sjchandra m = (struct mbuf *)(intptr_t)xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t)); 2042210630Sjchandra mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + 3 * sizeof(uint32_t)); 2043208165Srrs mips_wr_status(sr); 2044210630Sjchandra#endif 2045198157Srrs if (mag != 0xf00bad) { 2046198157Srrs /* somebody else packet Error - FIXME in intialization */ 2047210630Sjchandra printf("cpu %d: *ERROR* Not my packet paddr %p\n", 2048210630Sjchandra xlr_cpu_id(), (void *)paddr); 2049198157Srrs return; 2050198157Srrs } 2051198157Srrs /* align the data */ 2052198157Srrs m->m_data += BYTE_OFFSET; 2053198157Srrs m->m_pkthdr.len = m->m_len = len; 2054198157Srrs m->m_pkthdr.rcvif = ifp; 2055198157Srrs 2056198157Srrs#ifdef DUMP_PACKETS 2057198157Srrs { 2058198626Srrs int i = 0; 2059198626Srrs unsigned char *buf = (char *)m->m_data; 2060198626Srrs 2061198157Srrs printf("Rx Packet: length=%d\n", len); 2062198157Srrs for (i = 0; i < 64; i++) { 2063198157Srrs if (i && (i % 16) == 0) 2064198157Srrs printf("\n"); 2065198157Srrs printf("%02x ", buf[i]); 2066198157Srrs } 2067198157Srrs printf("\n"); 2068198157Srrs } 2069198157Srrs#endif 2070198157Srrs ifp->if_ipackets++; 2071198157Srrs (*ifp->if_input) (ifp, m); 2072198157Srrs} 2073198626Srrs 2074198626Srrsstatic void 2075198157Srrsrge_intr(void *arg) 2076198157Srrs{ 2077198157Srrs struct rge_softc *sc = (struct rge_softc *)arg; 2078198157Srrs struct driver_data *priv = &(sc->priv); 2079198626Srrs xlr_reg_t *mmio = priv->mmio; 2080198626Srrs uint32_t intreg = xlr_read_reg(mmio, R_INTREG); 2081198157Srrs 2082198157Srrs if (intreg & (1 << O_INTREG__MDInt)) { 2083198626Srrs uint32_t phy_int_status = 0; 2084198626Srrs int i = 0; 2085198157Srrs 2086198157Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 2087198157Srrs struct rge_softc *phy_dev = 0; 2088198157Srrs struct driver_data *phy_priv = 0; 2089198157Srrs 2090198157Srrs phy_dev = dev_mac[i]; 2091198157Srrs if (phy_dev == NULL) 2092198157Srrs continue; 2093198157Srrs 2094198157Srrs phy_priv = &phy_dev->priv; 2095198157Srrs 2096198157Srrs if (phy_priv->type == XLR_XGMAC) 2097198157Srrs continue; 2098198157Srrs 2099198157Srrs phy_int_status = rge_mii_read_internal(phy_priv->mii_mmio, 2100198626Srrs phy_priv->phy_addr, 26); 2101198157Srrs printf("rge%d: Phy addr %d, MII MMIO %lx status %x\n", phy_priv->instance, 2102198626Srrs (int)phy_priv->phy_addr, (u_long)phy_priv->mii_mmio, phy_int_status); 2103198157Srrs rmi_xlr_gmac_config_speed(phy_priv); 2104198157Srrs } 2105198157Srrs } else { 2106198157Srrs printf("[%s]: mac type = %d, instance %d error " 2107198626Srrs "interrupt: INTREG = 0x%08x\n", 2108198626Srrs __FUNCTION__, priv->type, priv->instance, intreg); 2109198157Srrs } 2110198157Srrs 2111198157Srrs /* clear all interrupts and hope to make progress */ 2112198157Srrs xlr_write_reg(mmio, R_INTREG, 0xffffffff); 2113198157Srrs 2114209318Sjchandra /* (not yet) on A0 and B0, xgmac interrupts are routed only to xgs_1 irq */ 2115209318Sjchandra if ((xlr_revision() < 2) && (priv->type == XLR_XGMAC)) { 2116198157Srrs struct rge_softc *xgs0_dev = dev_mac[dev_mac_xgs0]; 2117198157Srrs struct driver_data *xgs0_priv = &xgs0_dev->priv; 2118198626Srrs xlr_reg_t *xgs0_mmio = xgs0_priv->mmio; 2119198626Srrs uint32_t xgs0_intreg = xlr_read_reg(xgs0_mmio, R_INTREG); 2120198157Srrs 2121198157Srrs if (xgs0_intreg) { 2122198157Srrs printf("[%s]: mac type = %d, instance %d error " 2123198626Srrs "interrupt: INTREG = 0x%08x\n", 2124198626Srrs __FUNCTION__, xgs0_priv->type, xgs0_priv->instance, xgs0_intreg); 2125198157Srrs 2126198157Srrs xlr_write_reg(xgs0_mmio, R_INTREG, 0xffffffff); 2127198157Srrs } 2128198157Srrs } 2129198157Srrs} 2130198157Srrs 2131198626Srrsstatic void 2132198157Srrsrge_start_locked(struct ifnet *ifp, int threshold) 2133198157Srrs{ 2134198157Srrs struct rge_softc *sc = ifp->if_softc; 2135198626Srrs struct mbuf *m = NULL; 2136198626Srrs int prepend_pkt = 0; 2137198626Srrs int i = 0; 2138198626Srrs struct p2d_tx_desc *tx_desc = NULL; 2139208165Srrs int cpu = xlr_core_id(); 2140208165Srrs uint32_t vcpu = xlr_cpu_id(); 2141198157Srrs 2142198157Srrs if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 2143198157Srrs return; 2144198157Srrs 2145198626Srrs for (i = 0; i < xlr_tot_avail_p2d[cpu]; i++) { 2146198157Srrs if (IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 2147198157Srrs return; 2148198157Srrs tx_desc = get_p2d_desc(); 2149198626Srrs if (!tx_desc) { 2150198157Srrs xlr_rge_get_p2d_failed[vcpu]++; 2151198157Srrs return; 2152198157Srrs } 2153198157Srrs /* Grab a packet off the queue. */ 2154198157Srrs IFQ_DEQUEUE(&ifp->if_snd, m); 2155198626Srrs if (m == NULL) { 2156198157Srrs free_p2d_desc(tx_desc); 2157198157Srrs return; 2158198157Srrs } 2159198157Srrs prepend_pkt = rmi_xlr_mac_xmit(m, sc, 0, tx_desc); 2160198157Srrs 2161198157Srrs if (prepend_pkt) { 2162198157Srrs xlr_rge_tx_prepend[vcpu]++; 2163198157Srrs IF_PREPEND(&ifp->if_snd, m); 2164198157Srrs ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2165198157Srrs return; 2166198157Srrs } else { 2167198157Srrs ifp->if_opackets++; 2168198157Srrs xlr_rge_tx_done[vcpu]++; 2169198157Srrs } 2170198157Srrs } 2171198157Srrs} 2172198157Srrs 2173198626Srrsstatic void 2174198157Srrsrge_start(struct ifnet *ifp) 2175198157Srrs{ 2176198157Srrs rge_start_locked(ifp, RGE_TX_Q_SIZE); 2177198157Srrs} 2178198157Srrs 2179198626Srrsstatic int 2180198157Srrsrge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 2181198157Srrs{ 2182198157Srrs struct rge_softc *sc = ifp->if_softc; 2183198626Srrs struct ifreq *ifr = (struct ifreq *)data; 2184198626Srrs int mask, error = 0; 2185198626Srrs 2186198157Srrs /* struct mii_data *mii; */ 2187198157Srrs switch (command) { 2188198157Srrs case SIOCSIFMTU: 2189198157Srrs ifp->if_mtu = ifr->ifr_mtu; 2190198157Srrs error = rmi_xlr_mac_change_mtu(sc, ifr->ifr_mtu); 2191198157Srrs break; 2192198157Srrs case SIOCSIFFLAGS: 2193198157Srrs 2194198157Srrs RGE_LOCK(sc); 2195198157Srrs if (ifp->if_flags & IFF_UP) { 2196198157Srrs /* 2197198157Srrs * If only the state of the PROMISC flag changed, 2198198157Srrs * then just use the 'set promisc mode' command 2199198157Srrs * instead of reinitializing the entire NIC. Doing a 2200198157Srrs * full re-init means reloading the firmware and 2201198157Srrs * waiting for it to start up, which may take a 2202198157Srrs * second or two. Similarly for ALLMULTI. 2203198157Srrs */ 2204198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2205198157Srrs ifp->if_flags & IFF_PROMISC && 2206198157Srrs !(sc->flags & IFF_PROMISC)) { 2207198157Srrs sc->flags |= IFF_PROMISC; 2208198157Srrs xlr_mac_set_rx_mode(sc); 2209198157Srrs } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2210198626Srrs !(ifp->if_flags & IFF_PROMISC) && 2211198626Srrs sc->flags & IFF_PROMISC) { 2212198157Srrs sc->flags &= IFF_PROMISC; 2213198157Srrs xlr_mac_set_rx_mode(sc); 2214198157Srrs } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2215198626Srrs (ifp->if_flags ^ sc->flags) & IFF_ALLMULTI) { 2216198157Srrs rmi_xlr_mac_set_multicast_list(sc); 2217198157Srrs } else 2218198157Srrs xlr_mac_set_rx_mode(sc); 2219198157Srrs } else { 2220198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2221198157Srrs xlr_mac_set_rx_mode(sc); 2222198157Srrs } 2223198157Srrs } 2224198157Srrs sc->flags = ifp->if_flags; 2225198157Srrs RGE_UNLOCK(sc); 2226198157Srrs error = 0; 2227198157Srrs break; 2228198157Srrs case SIOCADDMULTI: 2229198157Srrs case SIOCDELMULTI: 2230198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2231198157Srrs RGE_LOCK(sc); 2232198157Srrs rmi_xlr_mac_set_multicast_list(sc); 2233198157Srrs RGE_UNLOCK(sc); 2234198157Srrs error = 0; 2235198157Srrs } 2236198157Srrs break; 2237198157Srrs case SIOCSIFMEDIA: 2238198157Srrs case SIOCGIFMEDIA: 2239198157Srrs error = ifmedia_ioctl(ifp, ifr, 2240198626Srrs &sc->rge_mii.mii_media, command); 2241198157Srrs break; 2242198157Srrs case SIOCSIFCAP: 2243198157Srrs mask = ifr->ifr_reqcap ^ ifp->if_capenable; 2244198157Srrs ifp->if_hwassist = 0; 2245198157Srrs break; 2246198157Srrs default: 2247198157Srrs error = ether_ioctl(ifp, command, data); 2248198157Srrs break; 2249198157Srrs } 2250198157Srrs 2251198157Srrs return (error); 2252198157Srrs} 2253198157Srrs 2254198626Srrsstatic void 2255198157Srrsrge_init(void *addr) 2256198157Srrs{ 2257198157Srrs struct rge_softc *sc = (struct rge_softc *)addr; 2258198626Srrs struct ifnet *ifp; 2259198157Srrs struct driver_data *priv = &(sc->priv); 2260198157Srrs 2261198157Srrs ifp = sc->rge_ifp; 2262198157Srrs 2263198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2264198157Srrs return; 2265198157Srrs ifp->if_drv_flags |= IFF_DRV_RUNNING; 2266198157Srrs ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2267198157Srrs 2268198157Srrs rmi_xlr_mac_set_enable(priv, 1); 2269198157Srrs} 2270198157Srrs 2271198626Srrsstatic void 2272198157Srrsrge_stop(struct rge_softc *sc) 2273198157Srrs{ 2274198157Srrs rmi_xlr_mac_close(sc); 2275198157Srrs} 2276198157Srrs 2277198608Srrsstatic int 2278198157Srrsrge_shutdown(device_t dev) 2279198157Srrs{ 2280198157Srrs struct rge_softc *sc; 2281198626Srrs 2282198157Srrs sc = device_get_softc(dev); 2283198157Srrs 2284198157Srrs RGE_LOCK(sc); 2285198157Srrs rge_stop(sc); 2286198157Srrs rge_reset(sc); 2287198157Srrs RGE_UNLOCK(sc); 2288198157Srrs 2289198626Srrs return (0); 2290198157Srrs} 2291198157Srrs 2292198626Srrsstatic int 2293198157Srrsrmi_xlr_mac_open(struct rge_softc *sc) 2294198157Srrs{ 2295198157Srrs struct driver_data *priv = &(sc->priv); 2296198157Srrs int i; 2297198157Srrs 2298198157Srrs dbg_msg("IN\n"); 2299198157Srrs 2300198157Srrs if (rmi_xlr_mac_fill_rxfr(sc)) { 2301198157Srrs return -1; 2302198157Srrs } 2303198157Srrs mtx_lock_spin(&priv->lock); 2304198157Srrs 2305198157Srrs xlr_mac_set_rx_mode(sc); 2306198157Srrs 2307198157Srrs if (sc->unit == xlr_board_info.gmacports - 1) { 2308198157Srrs printf("Enabling MDIO interrupts\n"); 2309198157Srrs struct rge_softc *tmp = NULL; 2310198626Srrs 2311198157Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 2312198157Srrs tmp = dev_mac[i]; 2313198157Srrs if (tmp) 2314198157Srrs xlr_write_reg(tmp->priv.mmio, R_INTMASK, 2315198626Srrs ((tmp->priv.instance == 0) << O_INTMASK__MDInt)); 2316198157Srrs } 2317198157Srrs } 2318198157Srrs /* 2319198157Srrs * Configure the speed, duplex, and flow control 2320198157Srrs */ 2321198157Srrs rmi_xlr_mac_set_speed(priv, priv->speed); 2322198157Srrs rmi_xlr_mac_set_duplex(priv, priv->duplex, priv->flow_ctrl); 2323198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2324198157Srrs 2325198157Srrs mtx_unlock_spin(&priv->lock); 2326198157Srrs 2327198157Srrs for (i = 0; i < 8; i++) { 2328198157Srrs atomic_set_int(&(priv->frin_to_be_sent[i]), 0); 2329198157Srrs } 2330198157Srrs 2331198157Srrs return 0; 2332198157Srrs} 2333198157Srrs 2334198157Srrs/********************************************************************** 2335198157Srrs **********************************************************************/ 2336198626Srrsstatic int 2337198157Srrsrmi_xlr_mac_close(struct rge_softc *sc) 2338198157Srrs{ 2339198157Srrs struct driver_data *priv = &(sc->priv); 2340198157Srrs 2341198157Srrs mtx_lock_spin(&priv->lock); 2342198157Srrs 2343198157Srrs /* 2344198157Srrs * There may have left over mbufs in the ring as well as in free in 2345198157Srrs * they will be reused next time open is called 2346198157Srrs */ 2347198157Srrs 2348198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2349198157Srrs 2350198157Srrs xlr_inc_counter(NETIF_STOP_Q); 2351198157Srrs port_inc_counter(priv->instance, PORT_STOPQ); 2352198157Srrs 2353198157Srrs mtx_unlock_spin(&priv->lock); 2354198157Srrs 2355198157Srrs return 0; 2356198157Srrs} 2357198157Srrs 2358198157Srrs/********************************************************************** 2359198157Srrs **********************************************************************/ 2360198157Srrsstatic struct rge_softc_stats * 2361198157Srrsrmi_xlr_mac_get_stats(struct rge_softc *sc) 2362198157Srrs{ 2363198157Srrs struct driver_data *priv = &(sc->priv); 2364198626Srrs 2365198157Srrs /* unsigned long flags; */ 2366198157Srrs 2367198157Srrs mtx_lock_spin(&priv->lock); 2368198157Srrs 2369198157Srrs /* XXX update other stats here */ 2370198157Srrs 2371198157Srrs mtx_unlock_spin(&priv->lock); 2372198157Srrs 2373198157Srrs return &priv->stats; 2374198157Srrs} 2375198157Srrs 2376198157Srrs/********************************************************************** 2377198157Srrs **********************************************************************/ 2378198626Srrsstatic void 2379198157Srrsrmi_xlr_mac_set_multicast_list(struct rge_softc *sc) 2380198157Srrs{ 2381198157Srrs} 2382198157Srrs 2383198157Srrs/********************************************************************** 2384198157Srrs **********************************************************************/ 2385198626Srrsstatic int 2386198157Srrsrmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu) 2387198157Srrs{ 2388198157Srrs struct driver_data *priv = &(sc->priv); 2389198157Srrs 2390198157Srrs if ((new_mtu > 9500) || (new_mtu < 64)) { 2391198157Srrs return -EINVAL; 2392198157Srrs } 2393198157Srrs mtx_lock_spin(&priv->lock); 2394198157Srrs 2395198157Srrs sc->mtu = new_mtu; 2396198157Srrs 2397198157Srrs /* Disable MAC TX/RX */ 2398198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2399198157Srrs 2400198157Srrs /* Flush RX FR IN */ 2401198157Srrs /* Flush TX IN */ 2402198157Srrs rmi_xlr_mac_set_enable(priv, 1); 2403198157Srrs 2404198157Srrs mtx_unlock_spin(&priv->lock); 2405198157Srrs return 0; 2406198157Srrs} 2407198157Srrs 2408198157Srrs/********************************************************************** 2409198157Srrs **********************************************************************/ 2410198626Srrsstatic int 2411198157Srrsrmi_xlr_mac_fill_rxfr(struct rge_softc *sc) 2412198157Srrs{ 2413198157Srrs struct driver_data *priv = &(sc->priv); 2414198626Srrs int i; 2415198626Srrs int ret = 0; 2416198626Srrs void *ptr; 2417198157Srrs 2418198157Srrs dbg_msg("\n"); 2419198157Srrs if (!priv->init_frin_desc) 2420198157Srrs return ret; 2421198157Srrs priv->init_frin_desc = 0; 2422198157Srrs 2423198157Srrs dbg_msg("\n"); 2424198157Srrs for (i = 0; i < MAX_NUM_DESC; i++) { 2425198157Srrs ptr = get_buf(); 2426198157Srrs if (!ptr) { 2427198157Srrs ret = -ENOMEM; 2428198157Srrs break; 2429198157Srrs } 2430198157Srrs /* Send the free Rx desc to the MAC */ 2431198157Srrs xlr_mac_send_fr(priv, vtophys(ptr), MAX_FRAME_SIZE); 2432198157Srrs } 2433198157Srrs 2434198157Srrs return ret; 2435198157Srrs} 2436198157Srrs 2437198157Srrs/********************************************************************** 2438198157Srrs **********************************************************************/ 2439198157Srrsstatic __inline__ void * 2440198157Srrsrmi_xlr_config_spill(xlr_reg_t * mmio, 2441198626Srrs int reg_start_0, int reg_start_1, 2442198626Srrs int reg_size, int size) 2443198157Srrs{ 2444198626Srrs uint32_t spill_size = size; 2445198626Srrs void *spill = NULL; 2446198626Srrs uint64_t phys_addr = 0; 2447198157Srrs 2448198157Srrs 2449198157Srrs spill = contigmalloc((spill_size + XLR_CACHELINE_SIZE), M_DEVBUF, 2450198626Srrs M_NOWAIT | M_ZERO, 0, 0xffffffff, XLR_CACHELINE_SIZE, 0); 2451198626Srrs if (!spill || ((vm_offset_t)spill & (XLR_CACHELINE_SIZE - 1))) { 2452198157Srrs panic("Unable to allocate memory for spill area!\n"); 2453198157Srrs } 2454198157Srrs phys_addr = vtophys(spill); 2455209808Sjchandra dbg_msg("Allocate spill %d bytes at %jx\n", size, (uintmax_t)phys_addr); 2456198157Srrs xlr_write_reg(mmio, reg_start_0, (phys_addr >> 5) & 0xffffffff); 2457198157Srrs xlr_write_reg(mmio, reg_start_1, (phys_addr >> 37) & 0x07); 2458198157Srrs xlr_write_reg(mmio, reg_size, spill_size); 2459198157Srrs 2460198157Srrs return spill; 2461198157Srrs} 2462198157Srrs 2463198626Srrsstatic void 2464198157Srrsrmi_xlr_config_spill_area(struct driver_data *priv) 2465198157Srrs{ 2466198157Srrs /* 2467198157Srrs * if driver initialization is done parallely on multiple cpus 2468198157Srrs * spill_configured needs synchronization 2469198157Srrs */ 2470198157Srrs if (priv->spill_configured) 2471198157Srrs return; 2472198157Srrs 2473198157Srrs if (priv->type == XLR_GMAC && priv->instance % 4 != 0) { 2474198157Srrs priv->spill_configured = 1; 2475198157Srrs return; 2476198157Srrs } 2477198157Srrs priv->spill_configured = 1; 2478198157Srrs 2479198157Srrs priv->frin_spill = 2480198626Srrs rmi_xlr_config_spill(priv->mmio, 2481198626Srrs R_REG_FRIN_SPILL_MEM_START_0, 2482198626Srrs R_REG_FRIN_SPILL_MEM_START_1, 2483198626Srrs R_REG_FRIN_SPILL_MEM_SIZE, 2484198626Srrs MAX_FRIN_SPILL * 2485198626Srrs sizeof(struct fr_desc)); 2486198157Srrs 2487198157Srrs priv->class_0_spill = 2488198626Srrs rmi_xlr_config_spill(priv->mmio, 2489198626Srrs R_CLASS0_SPILL_MEM_START_0, 2490198626Srrs R_CLASS0_SPILL_MEM_START_1, 2491198626Srrs R_CLASS0_SPILL_MEM_SIZE, 2492198626Srrs MAX_CLASS_0_SPILL * 2493198626Srrs sizeof(union rx_tx_desc)); 2494198157Srrs priv->class_1_spill = 2495198626Srrs rmi_xlr_config_spill(priv->mmio, 2496198626Srrs R_CLASS1_SPILL_MEM_START_0, 2497198626Srrs R_CLASS1_SPILL_MEM_START_1, 2498198626Srrs R_CLASS1_SPILL_MEM_SIZE, 2499198626Srrs MAX_CLASS_1_SPILL * 2500198626Srrs sizeof(union rx_tx_desc)); 2501198157Srrs 2502198157Srrs priv->frout_spill = 2503198626Srrs rmi_xlr_config_spill(priv->mmio, R_FROUT_SPILL_MEM_START_0, 2504198626Srrs R_FROUT_SPILL_MEM_START_1, 2505198626Srrs R_FROUT_SPILL_MEM_SIZE, 2506198626Srrs MAX_FROUT_SPILL * 2507198626Srrs sizeof(struct fr_desc)); 2508198157Srrs 2509198157Srrs priv->class_2_spill = 2510198626Srrs rmi_xlr_config_spill(priv->mmio, 2511198626Srrs R_CLASS2_SPILL_MEM_START_0, 2512198626Srrs R_CLASS2_SPILL_MEM_START_1, 2513198626Srrs R_CLASS2_SPILL_MEM_SIZE, 2514198626Srrs MAX_CLASS_2_SPILL * 2515198626Srrs sizeof(union rx_tx_desc)); 2516198157Srrs priv->class_3_spill = 2517198626Srrs rmi_xlr_config_spill(priv->mmio, 2518198626Srrs R_CLASS3_SPILL_MEM_START_0, 2519198626Srrs R_CLASS3_SPILL_MEM_START_1, 2520198626Srrs R_CLASS3_SPILL_MEM_SIZE, 2521198626Srrs MAX_CLASS_3_SPILL * 2522198626Srrs sizeof(union rx_tx_desc)); 2523198157Srrs priv->spill_configured = 1; 2524198157Srrs} 2525198157Srrs 2526198157Srrs/***************************************************************** 2527198157Srrs * Write the MAC address to the XLR registers 2528198157Srrs * All 4 addresses are the same for now 2529198157Srrs *****************************************************************/ 2530198626Srrsstatic void 2531198157Srrsxlr_mac_setup_hwaddr(struct driver_data *priv) 2532198157Srrs{ 2533198157Srrs struct rge_softc *sc = priv->sc; 2534198157Srrs 2535198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR0, 2536198626Srrs ((sc->dev_addr[5] << 24) | (sc->dev_addr[4] << 16) 2537198626Srrs | (sc->dev_addr[3] << 8) | (sc->dev_addr[2])) 2538198626Srrs ); 2539198157Srrs 2540198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR0 + 1, 2541198626Srrs ((sc->dev_addr[1] << 24) | (sc-> 2542198626Srrs dev_addr[0] << 16))); 2543198157Srrs 2544198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2, 0xffffffff); 2545198157Srrs 2546198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2 + 1, 0xffffffff); 2547198157Srrs 2548198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3, 0xffffffff); 2549198157Srrs 2550198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3 + 1, 0xffffffff); 2551198157Srrs 2552198157Srrs xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG, 2553198626Srrs (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) | 2554198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) | 2555198626Srrs (1 << O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID) 2556198626Srrs ); 2557198157Srrs} 2558198157Srrs 2559198157Srrs/***************************************************************** 2560198157Srrs * Read the MAC address from the XLR registers 2561198157Srrs * All 4 addresses are the same for now 2562198157Srrs *****************************************************************/ 2563198626Srrsstatic void 2564198157Srrsxlr_mac_get_hwaddr(struct rge_softc *sc) 2565198157Srrs{ 2566198157Srrs struct driver_data *priv = &(sc->priv); 2567198157Srrs 2568198157Srrs sc->dev_addr[0] = (xlr_boot1_info.mac_addr >> 40) & 0xff; 2569198157Srrs sc->dev_addr[1] = (xlr_boot1_info.mac_addr >> 32) & 0xff; 2570198157Srrs sc->dev_addr[2] = (xlr_boot1_info.mac_addr >> 24) & 0xff; 2571198157Srrs sc->dev_addr[3] = (xlr_boot1_info.mac_addr >> 16) & 0xff; 2572198157Srrs sc->dev_addr[4] = (xlr_boot1_info.mac_addr >> 8) & 0xff; 2573198157Srrs sc->dev_addr[5] = ((xlr_boot1_info.mac_addr >> 0) & 0xff) + priv->instance; 2574198157Srrs} 2575198157Srrs 2576198157Srrs/***************************************************************** 2577198157Srrs * Mac Module Initialization 2578198157Srrs *****************************************************************/ 2579198626Srrsstatic void 2580198157Srrsmac_common_init(void) 2581198157Srrs{ 2582198157Srrs init_p2d_allocation(); 2583198157Srrs init_tx_ring(); 2584198157Srrs 2585198157Srrs if (xlr_board_info.is_xls) { 2586198626Srrs if (register_msgring_handler(TX_STN_GMAC0, 2587198626Srrs rmi_xlr_mac_msgring_handler, NULL)) { 2588198157Srrs panic("Couldn't register msgring handler\n"); 2589198157Srrs } 2590198626Srrs if (register_msgring_handler(TX_STN_GMAC1, 2591198626Srrs rmi_xlr_mac_msgring_handler, NULL)) { 2592198157Srrs panic("Couldn't register msgring handler\n"); 2593198157Srrs } 2594198157Srrs } else { 2595198626Srrs if (register_msgring_handler(TX_STN_GMAC, 2596198626Srrs rmi_xlr_mac_msgring_handler, NULL)) { 2597198157Srrs panic("Couldn't register msgring handler\n"); 2598198157Srrs } 2599198157Srrs } 2600198157Srrs 2601198626Srrs /* 2602198626Srrs * Not yet if (xlr_board_atx_ii()) { if (register_msgring_handler 2603198626Srrs * (TX_STN_XGS_0, rmi_xlr_mac_msgring_handler, NULL)) { 2604198626Srrs * panic("Couldn't register msgring handler for TX_STN_XGS_0\n"); } 2605198626Srrs * if (register_msgring_handler (TX_STN_XGS_1, 2606198626Srrs * rmi_xlr_mac_msgring_handler, NULL)) { panic("Couldn't register 2607198626Srrs * msgring handler for TX_STN_XGS_1\n"); } } 2608198626Srrs */ 2609198157Srrs} 2610