144961713Sgirish /*
244961713Sgirish * CDDL HEADER START
344961713Sgirish *
444961713Sgirish * The contents of this file are subject to the terms of the
544961713Sgirish * Common Development and Distribution License (the "License").
644961713Sgirish * You may not use this file except in compliance with the License.
744961713Sgirish *
844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish * See the License for the specific language governing permissions
1144961713Sgirish * and limitations under the License.
1244961713Sgirish *
1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish *
1944961713Sgirish * CDDL HEADER END
2044961713Sgirish */
2144961713Sgirish /*
229d587972SSantwona Behera * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23238d8f47SDale Ghent * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved.
2444961713Sgirish */
2544961713Sgirish
2644961713Sgirish /*
2744961713Sgirish * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver.
2844961713Sgirish */
2944961713Sgirish #include <sys/nxge/nxge_impl.h>
30678453a8Sspeer #include <sys/nxge/nxge_hio.h>
31678453a8Sspeer #include <sys/nxge/nxge_rxdma.h>
3214ea4bb7Ssd #include <sys/pcie.h>
3344961713Sgirish
34*86ef0a63SRichard Lowe uint32_t nxge_use_partition = 0; /* debug partition flag */
35*86ef0a63SRichard Lowe uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */
36*86ef0a63SRichard Lowe uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */
3744961713Sgirish /*
38ec090658Sml * PSARC/2007/453 MSI-X interrupt limit override
3944961713Sgirish */
40ec090658Sml uint32_t nxge_msi_enable = 2;
4144961713Sgirish
426f157acbSml /*
436f157acbSml * Software workaround for a Neptune (PCI-E)
446f157acbSml * hardware interrupt bug which the hardware
456f157acbSml * may generate spurious interrupts after the
466f157acbSml * device interrupt handler was removed. If this flag
476f157acbSml * is enabled, the driver will reset the
486f157acbSml * hardware when devices are being detached.
496f157acbSml */
506f157acbSml uint32_t nxge_peu_reset_enable = 0;
516f157acbSml
52b4d05839Sml /*
53b4d05839Sml * Software workaround for the hardware
54b4d05839Sml * checksum bugs that affect packet transmission
55b4d05839Sml * and receive:
56b4d05839Sml *
57b4d05839Sml * Usage of nxge_cksum_offload:
58b4d05839Sml *
59b4d05839Sml * (1) nxge_cksum_offload = 0 (default):
60b4d05839Sml * - transmits packets:
61b4d05839Sml * TCP: uses the hardware checksum feature.
62b4d05839Sml * UDP: driver will compute the software checksum
63b4d05839Sml * based on the partial checksum computed
64b4d05839Sml * by the IP layer.
65b4d05839Sml * - receives packets
66b4d05839Sml * TCP: marks packets checksum flags based on hardware result.
67b4d05839Sml * UDP: will not mark checksum flags.
68b4d05839Sml *
69b4d05839Sml * (2) nxge_cksum_offload = 1:
70b4d05839Sml * - transmit packets:
71b4d05839Sml * TCP/UDP: uses the hardware checksum feature.
72b4d05839Sml * - receives packets
73b4d05839Sml * TCP/UDP: marks packet checksum flags based on hardware result.
74b4d05839Sml *
75b4d05839Sml * (3) nxge_cksum_offload = 2:
76b4d05839Sml * - The driver will not register its checksum capability.
77b4d05839Sml * Checksum for both TCP and UDP will be computed
78b4d05839Sml * by the stack.
79b4d05839Sml * - The software LSO is not allowed in this case.
80b4d05839Sml *
81b4d05839Sml * (4) nxge_cksum_offload > 2:
82b4d05839Sml * - Will be treated as it is set to 2
83b4d05839Sml * (stack will compute the checksum).
84b4d05839Sml *
85b4d05839Sml * (5) If the hardware bug is fixed, this workaround
86b4d05839Sml * needs to be updated accordingly to reflect
87b4d05839Sml * the new hardware revision.
88b4d05839Sml */
89b4d05839Sml uint32_t nxge_cksum_offload = 0;
90678453a8Sspeer
9144961713Sgirish /*
9244961713Sgirish * Globals: tunable parameters (/etc/system or adb)
9344961713Sgirish *
9444961713Sgirish */
95*86ef0a63SRichard Lowe uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT;
96*86ef0a63SRichard Lowe uint32_t nxge_rbr_spare_size = 0;
97*86ef0a63SRichard Lowe uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT;
984df55fdeSJanie Lu uint16_t nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET;
99*86ef0a63SRichard Lowe uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT;
100*86ef0a63SRichard Lowe boolean_t nxge_no_msg = B_TRUE; /* control message display */
101*86ef0a63SRichard Lowe uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */
102*86ef0a63SRichard Lowe uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX;
103*86ef0a63SRichard Lowe uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN;
104*86ef0a63SRichard Lowe uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN;
10544961713Sgirish uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU;
1061f8914d5Sml nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL;
10744961713Sgirish
10830ac2e7bSml /* MAX LSO size */
10930ac2e7bSml #define NXGE_LSO_MAXLEN 65535
11030ac2e7bSml uint32_t nxge_lso_max = NXGE_LSO_MAXLEN;
11130ac2e7bSml
11244961713Sgirish
11344961713Sgirish /*
11444961713Sgirish * Add tunable to reduce the amount of time spent in the
11544961713Sgirish * ISR doing Rx Processing.
11644961713Sgirish */
11744961713Sgirish uint32_t nxge_max_rx_pkts = 1024;
11844961713Sgirish
11944961713Sgirish /*
12044961713Sgirish * Tunables to manage the receive buffer blocks.
12144961713Sgirish *
12244961713Sgirish * nxge_rx_threshold_hi: copy all buffers.
12344961713Sgirish * nxge_rx_bcopy_size_type: receive buffer block size type.
12444961713Sgirish * nxge_rx_threshold_lo: copy only up to tunable block size type.
12544961713Sgirish */
12644961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6;
12744961713Sgirish nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
12844961713Sgirish nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3;
12944961713Sgirish
130d00f30bbSspeer uint32_t nxge_use_kmem_alloc = 1;
131678453a8Sspeer
13244961713Sgirish rtrace_t npi_rtracebuf;
13344961713Sgirish
134d6d3405fSml /*
135d6d3405fSml * The hardware sometimes fails to allow enough time for the link partner
136d6d3405fSml * to send an acknowledgement for packets that the hardware sent to it. The
137d6d3405fSml * hardware resends the packets earlier than it should be in those instances.
138d6d3405fSml * This behavior caused some switches to acknowledge the wrong packets
139d6d3405fSml * and it triggered the fatal error.
140d6d3405fSml * This software workaround is to set the replay timer to a value
141d6d3405fSml * suggested by the hardware team.
142d6d3405fSml *
143d6d3405fSml * PCI config space replay timer register:
144d6d3405fSml * The following replay timeout value is 0xc
145d6d3405fSml * for bit 14:18.
146d6d3405fSml */
147d6d3405fSml #define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8
148d6d3405fSml #define PCI_REPLAY_TIMEOUT_SHIFT 14
149d6d3405fSml
150d6d3405fSml uint32_t nxge_set_replay_timer = 1;
151d6d3405fSml uint32_t nxge_replay_timeout = 0xc;
152d6d3405fSml
153cf020df9Sml /*
154cf020df9Sml * The transmit serialization sometimes causes
155cf020df9Sml * longer sleep before calling the driver transmit
156cf020df9Sml * function as it sleeps longer than it should.
157cf020df9Sml * The performace group suggests that a time wait tunable
158cf020df9Sml * can be used to set the maximum wait time when needed
159cf020df9Sml * and the default is set to 1 tick.
160cf020df9Sml */
161cf020df9Sml uint32_t nxge_tx_serial_maxsleep = 1;
162cf020df9Sml
16344961713Sgirish #if defined(sun4v)
16444961713Sgirish /*
16544961713Sgirish * Hypervisor N2/NIU services information.
16644961713Sgirish */
1674df55fdeSJanie Lu /*
1684df55fdeSJanie Lu * The following is the default API supported:
1694df55fdeSJanie Lu * major 1 and minor 1.
1704df55fdeSJanie Lu *
1714df55fdeSJanie Lu * Please update the MAX_NIU_MAJORS,
1724df55fdeSJanie Lu * MAX_NIU_MINORS, and minor number supported
1734df55fdeSJanie Lu * when the newer Hypervior API interfaces
1744df55fdeSJanie Lu * are added. Also, please update nxge_hsvc_register()
1754df55fdeSJanie Lu * if needed.
1764df55fdeSJanie Lu */
17744961713Sgirish static hsvc_info_t niu_hsvc = {
17844961713Sgirish HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER,
17944961713Sgirish NIU_MINOR_VER, "nxge"
18044961713Sgirish };
181678453a8Sspeer
182678453a8Sspeer static int nxge_hsvc_register(p_nxge_t);
18344961713Sgirish #endif
18444961713Sgirish
18544961713Sgirish /*
18644961713Sgirish * Function Prototypes
18744961713Sgirish */
18844961713Sgirish static int nxge_attach(dev_info_t *, ddi_attach_cmd_t);
18944961713Sgirish static int nxge_detach(dev_info_t *, ddi_detach_cmd_t);
19044961713Sgirish static void nxge_unattach(p_nxge_t);
19119397407SSherry Moore static int nxge_quiesce(dev_info_t *);
19244961713Sgirish
19344961713Sgirish #if NXGE_PROPERTY
19444961713Sgirish static void nxge_remove_hard_properties(p_nxge_t);
19544961713Sgirish #endif
19644961713Sgirish
197678453a8Sspeer /*
198678453a8Sspeer * These two functions are required by nxge_hio.c
199678453a8Sspeer */
200da14cebeSEric Cheng extern int nxge_m_mmac_remove(void *arg, int slot);
201651ce697SMichael Speer extern void nxge_grp_cleanup(p_nxge_t nxge);
202678453a8Sspeer
20344961713Sgirish static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t);
20444961713Sgirish
20544961713Sgirish static nxge_status_t nxge_setup_mutexes(p_nxge_t);
20644961713Sgirish static void nxge_destroy_mutexes(p_nxge_t);
20744961713Sgirish
20844961713Sgirish static nxge_status_t nxge_map_regs(p_nxge_t nxgep);
20944961713Sgirish static void nxge_unmap_regs(p_nxge_t nxgep);
21044961713Sgirish #ifdef NXGE_DEBUG
21144961713Sgirish static void nxge_test_map_regs(p_nxge_t nxgep);
21244961713Sgirish #endif
21344961713Sgirish
21444961713Sgirish static nxge_status_t nxge_add_intrs(p_nxge_t nxgep);
21544961713Sgirish static void nxge_remove_intrs(p_nxge_t nxgep);
21644961713Sgirish
21744961713Sgirish static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep);
21844961713Sgirish static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t);
21944961713Sgirish static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t);
22044961713Sgirish static void nxge_intrs_enable(p_nxge_t nxgep);
22144961713Sgirish static void nxge_intrs_disable(p_nxge_t nxgep);
22244961713Sgirish
22344961713Sgirish static void nxge_suspend(p_nxge_t);
22444961713Sgirish static nxge_status_t nxge_resume(p_nxge_t);
22544961713Sgirish
22644961713Sgirish static nxge_status_t nxge_setup_dev(p_nxge_t);
22744961713Sgirish static void nxge_destroy_dev(p_nxge_t);
22844961713Sgirish
22944961713Sgirish static nxge_status_t nxge_alloc_mem_pool(p_nxge_t);
23044961713Sgirish static void nxge_free_mem_pool(p_nxge_t);
23144961713Sgirish
232678453a8Sspeer nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t);
23344961713Sgirish static void nxge_free_rx_mem_pool(p_nxge_t);
23444961713Sgirish
235678453a8Sspeer nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t);
23644961713Sgirish static void nxge_free_tx_mem_pool(p_nxge_t);
23744961713Sgirish
23844961713Sgirish static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t,
23944961713Sgirish struct ddi_dma_attr *,
24044961713Sgirish size_t, ddi_device_acc_attr_t *, uint_t,
24144961713Sgirish p_nxge_dma_common_t);
24244961713Sgirish
24344961713Sgirish static void nxge_dma_mem_free(p_nxge_dma_common_t);
244678453a8Sspeer static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t);
24544961713Sgirish
24644961713Sgirish static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t,
24744961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
24844961713Sgirish static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
24944961713Sgirish
25044961713Sgirish static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t,
25144961713Sgirish p_nxge_dma_common_t *, size_t);
25244961713Sgirish static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
25344961713Sgirish
254678453a8Sspeer extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t,
25544961713Sgirish p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
25644961713Sgirish static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
25744961713Sgirish
258678453a8Sspeer extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t,
25944961713Sgirish p_nxge_dma_common_t *,
26044961713Sgirish size_t);
26144961713Sgirish static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
26244961713Sgirish
26344961713Sgirish static int nxge_init_common_dev(p_nxge_t);
26444961713Sgirish static void nxge_uninit_common_dev(p_nxge_t);
2654045d941Ssowmini extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *,
2664045d941Ssowmini char *, caddr_t);
267e759c33aSMichael Speer #if defined(sun4v)
268e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep);
269e759c33aSMichael Speer extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm);
270e759c33aSMichael Speer #endif
27144961713Sgirish
27244961713Sgirish /*
27344961713Sgirish * The next declarations are for the GLDv3 interface.
27444961713Sgirish */
27544961713Sgirish static int nxge_m_start(void *);
27644961713Sgirish static void nxge_m_stop(void *);
27744961713Sgirish static int nxge_m_multicst(void *, boolean_t, const uint8_t *);
27844961713Sgirish static int nxge_m_promisc(void *, boolean_t);
27944961713Sgirish static void nxge_m_ioctl(void *, queue_t *, mblk_t *);
28063f531d1SSriharsha Basavapatna nxge_status_t nxge_mac_register(p_nxge_t);
281da14cebeSEric Cheng static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr,
282da14cebeSEric Cheng int slot, int rdctbl, boolean_t usetbl);
283da14cebeSEric Cheng void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot,
28458324dfcSspeer boolean_t factory);
285da14cebeSEric Cheng
286da14cebeSEric Cheng static void nxge_m_getfactaddr(void *, uint_t, uint8_t *);
2871bd6825cSml static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *);
2881bd6825cSml static int nxge_m_setprop(void *, const char *, mac_prop_id_t,
2891bd6825cSml uint_t, const void *);
2901bd6825cSml static int nxge_m_getprop(void *, const char *, mac_prop_id_t,
2910dc2366fSVenugopal Iyer uint_t, void *);
2920dc2366fSVenugopal Iyer static void nxge_m_propinfo(void *, const char *, mac_prop_id_t,
2930dc2366fSVenugopal Iyer mac_prop_info_handle_t);
2940dc2366fSVenugopal Iyer static void nxge_priv_propinfo(const char *, mac_prop_info_handle_t);
2951bd6825cSml static int nxge_set_priv_prop(nxge_t *, const char *, uint_t,
2961bd6825cSml const void *);
2970dc2366fSVenugopal Iyer static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, void *);
298da14cebeSEric Cheng static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int,
299da14cebeSEric Cheng mac_ring_info_t *, mac_ring_handle_t);
300da14cebeSEric Cheng static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t,
301da14cebeSEric Cheng mac_ring_type_t);
302da14cebeSEric Cheng static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t,
303da14cebeSEric Cheng mac_ring_type_t);
3044045d941Ssowmini
3056f157acbSml static void nxge_niu_peu_reset(p_nxge_t nxgep);
306d6d3405fSml static void nxge_set_pci_replay_timeout(nxge_t *);
3074045d941Ssowmini
3080dc2366fSVenugopal Iyer char *nxge_priv_props[] = {
3090dc2366fSVenugopal Iyer "_adv_10gfdx_cap",
3100dc2366fSVenugopal Iyer "_adv_pause_cap",
3110dc2366fSVenugopal Iyer "_function_number",
3120dc2366fSVenugopal Iyer "_fw_version",
3130dc2366fSVenugopal Iyer "_port_mode",
3140dc2366fSVenugopal Iyer "_hot_swap_phy",
3150dc2366fSVenugopal Iyer "_rxdma_intr_time",
3160dc2366fSVenugopal Iyer "_rxdma_intr_pkts",
3170dc2366fSVenugopal Iyer "_class_opt_ipv4_tcp",
3180dc2366fSVenugopal Iyer "_class_opt_ipv4_udp",
3190dc2366fSVenugopal Iyer "_class_opt_ipv4_ah",
3200dc2366fSVenugopal Iyer "_class_opt_ipv4_sctp",
3210dc2366fSVenugopal Iyer "_class_opt_ipv6_tcp",
3220dc2366fSVenugopal Iyer "_class_opt_ipv6_udp",
3230dc2366fSVenugopal Iyer "_class_opt_ipv6_ah",
3240dc2366fSVenugopal Iyer "_class_opt_ipv6_sctp",
3250dc2366fSVenugopal Iyer "_soft_lso_enable",
3260dc2366fSVenugopal Iyer NULL
3274045d941Ssowmini };
3284045d941Ssowmini
32944961713Sgirish #define NXGE_NEPTUNE_MAGIC 0x4E584745UL
33044961713Sgirish #define MAX_DUMP_SZ 256
33144961713Sgirish
3321bd6825cSml #define NXGE_M_CALLBACK_FLAGS \
3330dc2366fSVenugopal Iyer (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
33444961713Sgirish
335678453a8Sspeer mac_callbacks_t nxge_m_callbacks = {
33644961713Sgirish NXGE_M_CALLBACK_FLAGS,
33744961713Sgirish nxge_m_stat,
33844961713Sgirish nxge_m_start,
33944961713Sgirish nxge_m_stop,
34044961713Sgirish nxge_m_promisc,
34144961713Sgirish nxge_m_multicst,
342da14cebeSEric Cheng NULL,
343da14cebeSEric Cheng NULL,
3440dc2366fSVenugopal Iyer NULL,
34544961713Sgirish nxge_m_ioctl,
3461bd6825cSml nxge_m_getcapab,
3471bd6825cSml NULL,
3481bd6825cSml NULL,
3491bd6825cSml nxge_m_setprop,
3500dc2366fSVenugopal Iyer nxge_m_getprop,
3510dc2366fSVenugopal Iyer nxge_m_propinfo
35244961713Sgirish };
35344961713Sgirish
35444961713Sgirish void
35544961713Sgirish nxge_err_inject(p_nxge_t, queue_t *, mblk_t *);
35644961713Sgirish
357ec090658Sml /* PSARC/2007/453 MSI-X interrupt limit override. */
358ec090658Sml #define NXGE_MSIX_REQUEST_10G 8
359ec090658Sml #define NXGE_MSIX_REQUEST_1G 2
360ec090658Sml static int nxge_create_msi_property(p_nxge_t);
361ef755e7aStc /*
362ef755e7aStc * For applications that care about the
363ef755e7aStc * latency, it was requested by PAE and the
364ef755e7aStc * customers that the driver has tunables that
365ef755e7aStc * allow the user to tune it to a higher number
366ef755e7aStc * interrupts to spread the interrupts among
367ef755e7aStc * multiple channels. The DDI framework limits
368ef755e7aStc * the maximum number of MSI-X resources to allocate
369ef755e7aStc * to 8 (ddi_msix_alloc_limit). If more than 8
370ef755e7aStc * is set, ddi_msix_alloc_limit must be set accordingly.
371ef755e7aStc * The default number of MSI interrupts are set to
372ef755e7aStc * 8 for 10G and 2 for 1G link.
373ef755e7aStc */
374ef755e7aStc #define NXGE_MSIX_MAX_ALLOWED 32
375ef755e7aStc uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G;
376ef755e7aStc uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G;
377ec090658Sml
37844961713Sgirish /*
37944961713Sgirish * These global variables control the message
38044961713Sgirish * output.
38144961713Sgirish */
38244961713Sgirish out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG;
383678453a8Sspeer uint64_t nxge_debug_level;
38444961713Sgirish
38544961713Sgirish /*
38644961713Sgirish * This list contains the instance structures for the Neptune
38744961713Sgirish * devices present in the system. The lock exists to guarantee
38844961713Sgirish * mutually exclusive access to the list.
38944961713Sgirish */
390*86ef0a63SRichard Lowe void *nxge_list = NULL;
39144961713Sgirish void *nxge_hw_list = NULL;
392*86ef0a63SRichard Lowe nxge_os_mutex_t nxge_common_lock;
393*86ef0a63SRichard Lowe nxge_os_mutex_t nxgedebuglock;
39444961713Sgirish
395*86ef0a63SRichard Lowe extern uint64_t npi_debug_level;
39644961713Sgirish
39744961713Sgirish extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *);
39844961713Sgirish extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *);
39944961713Sgirish extern nxge_status_t nxge_ldgv_uninit(p_nxge_t);
40044961713Sgirish extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t);
40144961713Sgirish extern void nxge_fm_init(p_nxge_t,
40244961713Sgirish ddi_device_acc_attr_t *,
40344961713Sgirish ddi_dma_attr_t *);
40444961713Sgirish extern void nxge_fm_fini(p_nxge_t);
40558324dfcSspeer extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t);
40644961713Sgirish
40744961713Sgirish /*
40844961713Sgirish * Count used to maintain the number of buffers being used
40944961713Sgirish * by Neptune instances and loaned up to the upper layers.
41044961713Sgirish */
41144961713Sgirish uint32_t nxge_mblks_pending = 0;
41244961713Sgirish
41344961713Sgirish /*
41444961713Sgirish * Device register access attributes for PIO.
41544961713Sgirish */
41644961713Sgirish static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = {
417837c1ac4SStephen Hanson DDI_DEVICE_ATTR_V1,
41844961713Sgirish DDI_STRUCTURE_LE_ACC,
41944961713Sgirish DDI_STRICTORDER_ACC,
420837c1ac4SStephen Hanson DDI_DEFAULT_ACC
42144961713Sgirish };
42244961713Sgirish
42344961713Sgirish /*
42444961713Sgirish * Device descriptor access attributes for DMA.
42544961713Sgirish */
42644961713Sgirish static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = {
42744961713Sgirish DDI_DEVICE_ATTR_V0,
42844961713Sgirish DDI_STRUCTURE_LE_ACC,
42944961713Sgirish DDI_STRICTORDER_ACC
43044961713Sgirish };
43144961713Sgirish
43244961713Sgirish /*
43344961713Sgirish * Device buffer access attributes for DMA.
43444961713Sgirish */
43544961713Sgirish static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = {
43644961713Sgirish DDI_DEVICE_ATTR_V0,
43744961713Sgirish DDI_STRUCTURE_BE_ACC,
43844961713Sgirish DDI_STRICTORDER_ACC
43944961713Sgirish };
44044961713Sgirish
44144961713Sgirish ddi_dma_attr_t nxge_desc_dma_attr = {
44244961713Sgirish DMA_ATTR_V0, /* version number. */
44344961713Sgirish 0, /* low address */
44444961713Sgirish 0xffffffffffffffff, /* high address */
44544961713Sgirish 0xffffffffffffffff, /* address counter max */
44644961713Sgirish #ifndef NIU_PA_WORKAROUND
44744961713Sgirish 0x100000, /* alignment */
44844961713Sgirish #else
44944961713Sgirish 0x2000,
45044961713Sgirish #endif
45144961713Sgirish 0xfc00fc, /* dlim_burstsizes */
45244961713Sgirish 0x1, /* minimum transfer size */
45344961713Sgirish 0xffffffffffffffff, /* maximum transfer size */
45444961713Sgirish 0xffffffffffffffff, /* maximum segment size */
45544961713Sgirish 1, /* scatter/gather list length */
45644961713Sgirish (unsigned int) 1, /* granularity */
45744961713Sgirish 0 /* attribute flags */
45844961713Sgirish };
45944961713Sgirish
46044961713Sgirish ddi_dma_attr_t nxge_tx_dma_attr = {
46144961713Sgirish DMA_ATTR_V0, /* version number. */
46244961713Sgirish 0, /* low address */
46344961713Sgirish 0xffffffffffffffff, /* high address */
46444961713Sgirish 0xffffffffffffffff, /* address counter max */
46544961713Sgirish #if defined(_BIG_ENDIAN)
46644961713Sgirish 0x2000, /* alignment */
46744961713Sgirish #else
46844961713Sgirish 0x1000, /* alignment */
46944961713Sgirish #endif
47044961713Sgirish 0xfc00fc, /* dlim_burstsizes */
47144961713Sgirish 0x1, /* minimum transfer size */
47244961713Sgirish 0xffffffffffffffff, /* maximum transfer size */
47344961713Sgirish 0xffffffffffffffff, /* maximum segment size */
47444961713Sgirish 5, /* scatter/gather list length */
47544961713Sgirish (unsigned int) 1, /* granularity */
47644961713Sgirish 0 /* attribute flags */
47744961713Sgirish };
47844961713Sgirish
47944961713Sgirish ddi_dma_attr_t nxge_rx_dma_attr = {
48044961713Sgirish DMA_ATTR_V0, /* version number. */
48144961713Sgirish 0, /* low address */
48244961713Sgirish 0xffffffffffffffff, /* high address */
48344961713Sgirish 0xffffffffffffffff, /* address counter max */
48444961713Sgirish 0x2000, /* alignment */
48544961713Sgirish 0xfc00fc, /* dlim_burstsizes */
48644961713Sgirish 0x1, /* minimum transfer size */
48744961713Sgirish 0xffffffffffffffff, /* maximum transfer size */
48844961713Sgirish 0xffffffffffffffff, /* maximum segment size */
48944961713Sgirish 1, /* scatter/gather list length */
49044961713Sgirish (unsigned int) 1, /* granularity */
4910e2bd521Ssbehera DDI_DMA_RELAXED_ORDERING /* attribute flags */
49244961713Sgirish };
49344961713Sgirish
49444961713Sgirish ddi_dma_lim_t nxge_dma_limits = {
49544961713Sgirish (uint_t)0, /* dlim_addr_lo */
49644961713Sgirish (uint_t)0xffffffff, /* dlim_addr_hi */
49744961713Sgirish (uint_t)0xffffffff, /* dlim_cntr_max */
49844961713Sgirish (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */
49944961713Sgirish 0x1, /* dlim_minxfer */
50044961713Sgirish 1024 /* dlim_speed */
50144961713Sgirish };
50244961713Sgirish
50344961713Sgirish dma_method_t nxge_force_dma = DVMA;
50444961713Sgirish
50544961713Sgirish /*
50644961713Sgirish * dma chunk sizes.
50744961713Sgirish *
50844961713Sgirish * Try to allocate the largest possible size
50944961713Sgirish * so that fewer number of dma chunks would be managed
51044961713Sgirish */
51144961713Sgirish #ifdef NIU_PA_WORKAROUND
51244961713Sgirish size_t alloc_sizes [] = {0x2000};
51344961713Sgirish #else
51444961713Sgirish size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000,
51544961713Sgirish 0x10000, 0x20000, 0x40000, 0x80000,
51630ac2e7bSml 0x100000, 0x200000, 0x400000, 0x800000,
51730ac2e7bSml 0x1000000, 0x2000000, 0x4000000};
51844961713Sgirish #endif
51944961713Sgirish
52044961713Sgirish /*
52144961713Sgirish * Translate "dev_t" to a pointer to the associated "dev_info_t".
52244961713Sgirish */
52344961713Sgirish
524678453a8Sspeer extern void nxge_get_environs(nxge_t *);
525678453a8Sspeer
52644961713Sgirish static int
nxge_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)52744961713Sgirish nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
52844961713Sgirish {
52944961713Sgirish p_nxge_t nxgep = NULL;
53044961713Sgirish int instance;
53144961713Sgirish int status = DDI_SUCCESS;
53244961713Sgirish uint8_t portn;
53358324dfcSspeer nxge_mmac_t *mmac_info;
53444961713Sgirish
53544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach"));
53644961713Sgirish
53744961713Sgirish /*
53844961713Sgirish * Get the device instance since we'll need to setup
53944961713Sgirish * or retrieve a soft state for this instance.
54044961713Sgirish */
54144961713Sgirish instance = ddi_get_instance(dip);
54244961713Sgirish
54344961713Sgirish switch (cmd) {
54444961713Sgirish case DDI_ATTACH:
54544961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH"));
54644961713Sgirish break;
54744961713Sgirish
54844961713Sgirish case DDI_RESUME:
54944961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME"));
55044961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
55144961713Sgirish if (nxgep == NULL) {
55244961713Sgirish status = DDI_FAILURE;
55344961713Sgirish break;
55444961713Sgirish }
55544961713Sgirish if (nxgep->dip != dip) {
55644961713Sgirish status = DDI_FAILURE;
55744961713Sgirish break;
55844961713Sgirish }
55944961713Sgirish if (nxgep->suspended == DDI_PM_SUSPEND) {
56044961713Sgirish status = ddi_dev_is_needed(nxgep->dip, 0, 1);
56144961713Sgirish } else {
56256d930aeSspeer status = nxge_resume(nxgep);
56344961713Sgirish }
56444961713Sgirish goto nxge_attach_exit;
56544961713Sgirish
56644961713Sgirish case DDI_PM_RESUME:
56744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME"));
56844961713Sgirish nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
56944961713Sgirish if (nxgep == NULL) {
57044961713Sgirish status = DDI_FAILURE;
57144961713Sgirish break;
57244961713Sgirish }
57344961713Sgirish if (nxgep->dip != dip) {
57444961713Sgirish status = DDI_FAILURE;
57544961713Sgirish break;
57644961713Sgirish }
57756d930aeSspeer status = nxge_resume(nxgep);
57844961713Sgirish goto nxge_attach_exit;
57944961713Sgirish
58044961713Sgirish default:
58144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown"));
58244961713Sgirish status = DDI_FAILURE;
58344961713Sgirish goto nxge_attach_exit;
58444961713Sgirish }
58544961713Sgirish
58644961713Sgirish
58744961713Sgirish if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) {
58844961713Sgirish status = DDI_FAILURE;
58944961713Sgirish goto nxge_attach_exit;
59044961713Sgirish }
59144961713Sgirish
59244961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance);
59344961713Sgirish if (nxgep == NULL) {
5942e59129aSraghus status = NXGE_ERROR;
5952e59129aSraghus goto nxge_attach_fail2;
59644961713Sgirish }
59744961713Sgirish
59898ecde52Stm nxgep->nxge_magic = NXGE_MAGIC;
59998ecde52Stm
60044961713Sgirish nxgep->drv_state = 0;
60144961713Sgirish nxgep->dip = dip;
60244961713Sgirish nxgep->instance = instance;
60344961713Sgirish nxgep->p_dip = ddi_get_parent(dip);
60444961713Sgirish nxgep->nxge_debug_level = nxge_debug_level;
60544961713Sgirish npi_debug_level = nxge_debug_level;
60644961713Sgirish
607678453a8Sspeer /* Are we a guest running in a Hybrid I/O environment? */
608678453a8Sspeer nxge_get_environs(nxgep);
60944961713Sgirish
61044961713Sgirish status = nxge_map_regs(nxgep);
611678453a8Sspeer
61244961713Sgirish if (status != NXGE_OK) {
61344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed"));
6142e59129aSraghus goto nxge_attach_fail3;
61544961713Sgirish }
61644961713Sgirish
617837c1ac4SStephen Hanson nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_rx_dma_attr);
618678453a8Sspeer
619678453a8Sspeer /* Create & initialize the per-Neptune data structure */
620678453a8Sspeer /* (even if we're a guest). */
62144961713Sgirish status = nxge_init_common_dev(nxgep);
62244961713Sgirish if (status != NXGE_OK) {
62344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6244045d941Ssowmini "nxge_init_common_dev failed"));
6252e59129aSraghus goto nxge_attach_fail4;
62644961713Sgirish }
62744961713Sgirish
628d6d3405fSml /*
629d6d3405fSml * Software workaround: set the replay timer.
630d6d3405fSml */
631d6d3405fSml if (nxgep->niu_type != N2_NIU) {
632d6d3405fSml nxge_set_pci_replay_timeout(nxgep);
633d6d3405fSml }
634d6d3405fSml
635678453a8Sspeer #if defined(sun4v)
636678453a8Sspeer /* This is required by nxge_hio_init(), which follows. */
637678453a8Sspeer if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS)
6389d5b8bc5SMichael Speer goto nxge_attach_fail4;
639678453a8Sspeer #endif
640678453a8Sspeer
641678453a8Sspeer if ((status = nxge_hio_init(nxgep)) != NXGE_OK) {
642678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6434045d941Ssowmini "nxge_hio_init failed"));
644678453a8Sspeer goto nxge_attach_fail4;
645678453a8Sspeer }
646678453a8Sspeer
64759ac0c16Sdavemq if (nxgep->niu_type == NEPTUNE_2_10GF) {
64859ac0c16Sdavemq if (nxgep->function_num > 1) {
6494202ea4bSsbehera NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported"
65059ac0c16Sdavemq " function %d. Only functions 0 and 1 are "
65159ac0c16Sdavemq "supported for this card.", nxgep->function_num));
65259ac0c16Sdavemq status = NXGE_ERROR;
6532e59129aSraghus goto nxge_attach_fail4;
65459ac0c16Sdavemq }
65559ac0c16Sdavemq }
65659ac0c16Sdavemq
657678453a8Sspeer if (isLDOMguest(nxgep)) {
658678453a8Sspeer /*
659678453a8Sspeer * Use the function number here.
660678453a8Sspeer */
661678453a8Sspeer nxgep->mac.portnum = nxgep->function_num;
662678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_LOGICAL;
663678453a8Sspeer
664678453a8Sspeer /* XXX We'll set the MAC address counts to 1 for now. */
665678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info;
666678453a8Sspeer mmac_info->num_mmac = 1;
667678453a8Sspeer mmac_info->naddrfree = 1;
66858324dfcSspeer } else {
669678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num);
670678453a8Sspeer nxgep->mac.portnum = portn;
671678453a8Sspeer if ((portn == 0) || (portn == 1))
672678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_XMAC;
673678453a8Sspeer else
674678453a8Sspeer nxgep->mac.porttype = PORT_TYPE_BMAC;
675678453a8Sspeer /*
676678453a8Sspeer * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC)
677678453a8Sspeer * internally, the rest 2 ports use BMAC (1G "Big" MAC).
678678453a8Sspeer * The two types of MACs have different characterizations.
679678453a8Sspeer */
680678453a8Sspeer mmac_info = &nxgep->nxge_mmac_info;
681678453a8Sspeer if (nxgep->function_num < 2) {
682678453a8Sspeer mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY;
683678453a8Sspeer mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY;
684678453a8Sspeer } else {
685678453a8Sspeer mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY;
686678453a8Sspeer mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY;
687678453a8Sspeer }
68858324dfcSspeer }
68944961713Sgirish /*
69044961713Sgirish * Setup the Ndd parameters for the this instance.
69144961713Sgirish */
69244961713Sgirish nxge_init_param(nxgep);
69344961713Sgirish
69444961713Sgirish /*
69544961713Sgirish * Setup Register Tracing Buffer.
69644961713Sgirish */
69744961713Sgirish npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf);
69844961713Sgirish
69944961713Sgirish /* init stats ptr */
70044961713Sgirish nxge_init_statsp(nxgep);
70156d930aeSspeer
7022e59129aSraghus /*
703678453a8Sspeer * Copy the vpd info from eeprom to a local data
704678453a8Sspeer * structure, and then check its validity.
7052e59129aSraghus */
706678453a8Sspeer if (!isLDOMguest(nxgep)) {
707678453a8Sspeer int *regp;
708678453a8Sspeer uint_t reglen;
709678453a8Sspeer int rv;
71056d930aeSspeer
711678453a8Sspeer nxge_vpd_info_get(nxgep);
71244961713Sgirish
713678453a8Sspeer /* Find the NIU config handle. */
714678453a8Sspeer rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
715678453a8Sspeer ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS,
716678453a8Sspeer "reg", ®p, ®len);
717678453a8Sspeer
718678453a8Sspeer if (rv != DDI_PROP_SUCCESS) {
719678453a8Sspeer goto nxge_attach_fail5;
720678453a8Sspeer }
721678453a8Sspeer /*
722678453a8Sspeer * The address_hi, that is the first int, in the reg
723678453a8Sspeer * property consists of config handle, but need to remove
724678453a8Sspeer * the bits 28-31 which are OBP specific info.
725678453a8Sspeer */
726678453a8Sspeer nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF;
727678453a8Sspeer ddi_prop_free(regp);
72844961713Sgirish }
72944961713Sgirish
73048056c53SMichael Speer /*
73148056c53SMichael Speer * Set the defaults for the MTU size.
73248056c53SMichael Speer */
73348056c53SMichael Speer nxge_hw_id_init(nxgep);
73448056c53SMichael Speer
735678453a8Sspeer if (isLDOMguest(nxgep)) {
736678453a8Sspeer uchar_t *prop_val;
737678453a8Sspeer uint_t prop_len;
7387b1f684aSSriharsha Basavapatna uint32_t max_frame_size;
73944961713Sgirish
740678453a8Sspeer extern void nxge_get_logical_props(p_nxge_t);
741678453a8Sspeer
742678453a8Sspeer nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR;
743678453a8Sspeer nxgep->mac.portmode = PORT_LOGICAL;
744678453a8Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
745678453a8Sspeer "phy-type", "virtual transceiver");
746678453a8Sspeer
747678453a8Sspeer nxgep->nports = 1;
748678453a8Sspeer nxgep->board_ver = 0; /* XXX What? */
749678453a8Sspeer
750678453a8Sspeer /*
751678453a8Sspeer * local-mac-address property gives us info on which
752678453a8Sspeer * specific MAC address the Hybrid resource is associated
753678453a8Sspeer * with.
754678453a8Sspeer */
755678453a8Sspeer if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
756678453a8Sspeer "local-mac-address", &prop_val,
757678453a8Sspeer &prop_len) != DDI_PROP_SUCCESS) {
758678453a8Sspeer goto nxge_attach_fail5;
759678453a8Sspeer }
760*86ef0a63SRichard Lowe if (prop_len != ETHERADDRL) {
761678453a8Sspeer ddi_prop_free(prop_val);
762678453a8Sspeer goto nxge_attach_fail5;
763678453a8Sspeer }
764678453a8Sspeer ether_copy(prop_val, nxgep->hio_mac_addr);
765678453a8Sspeer ddi_prop_free(prop_val);
766678453a8Sspeer nxge_get_logical_props(nxgep);
767678453a8Sspeer
7687b1f684aSSriharsha Basavapatna /*
7697b1f684aSSriharsha Basavapatna * Enable Jumbo property based on the "max-frame-size"
7707b1f684aSSriharsha Basavapatna * property value.
7717b1f684aSSriharsha Basavapatna */
7727b1f684aSSriharsha Basavapatna max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY,
7737b1f684aSSriharsha Basavapatna nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
7747b1f684aSSriharsha Basavapatna "max-frame-size", NXGE_MTU_DEFAULT_MAX);
7757b1f684aSSriharsha Basavapatna if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) &&
7767b1f684aSSriharsha Basavapatna (max_frame_size <= TX_JUMBO_MTU)) {
7777b1f684aSSriharsha Basavapatna nxgep->mac.is_jumbo = B_TRUE;
7787b1f684aSSriharsha Basavapatna nxgep->mac.maxframesize = (uint16_t)max_frame_size;
7797b1f684aSSriharsha Basavapatna nxgep->mac.default_mtu = nxgep->mac.maxframesize -
7807b1f684aSSriharsha Basavapatna NXGE_EHEADER_VLAN_CRC;
7817b1f684aSSriharsha Basavapatna }
782678453a8Sspeer } else {
783678453a8Sspeer status = nxge_xcvr_find(nxgep);
784678453a8Sspeer
785678453a8Sspeer if (status != NXGE_OK) {
786678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: "
7874045d941Ssowmini " Couldn't determine card type"
7884045d941Ssowmini " .... exit "));
789678453a8Sspeer goto nxge_attach_fail5;
790678453a8Sspeer }
791678453a8Sspeer
792678453a8Sspeer status = nxge_get_config_properties(nxgep);
793678453a8Sspeer
794678453a8Sspeer if (status != NXGE_OK) {
795678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7964045d941Ssowmini "get_hw create failed"));
797678453a8Sspeer goto nxge_attach_fail;
798678453a8Sspeer }
79944961713Sgirish }
80044961713Sgirish
80144961713Sgirish /*
80244961713Sgirish * Setup the Kstats for the driver.
80344961713Sgirish */
80444961713Sgirish nxge_setup_kstats(nxgep);
80544961713Sgirish
806678453a8Sspeer if (!isLDOMguest(nxgep))
807678453a8Sspeer nxge_setup_param(nxgep);
80844961713Sgirish
80944961713Sgirish status = nxge_setup_system_dma_pages(nxgep);
81044961713Sgirish if (status != NXGE_OK) {
81144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed"));
81244961713Sgirish goto nxge_attach_fail;
81344961713Sgirish }
81444961713Sgirish
815678453a8Sspeer
816678453a8Sspeer if (!isLDOMguest(nxgep))
817678453a8Sspeer nxge_hw_init_niu_common(nxgep);
81844961713Sgirish
81944961713Sgirish status = nxge_setup_mutexes(nxgep);
82044961713Sgirish if (status != NXGE_OK) {
82144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed"));
82244961713Sgirish goto nxge_attach_fail;
82344961713Sgirish }
82444961713Sgirish
825678453a8Sspeer #if defined(sun4v)
826678453a8Sspeer if (isLDOMguest(nxgep)) {
827678453a8Sspeer /* Find our VR & channel sets. */
828678453a8Sspeer status = nxge_hio_vr_add(nxgep);
829ef523517SMichael Speer if (status != DDI_SUCCESS) {
830ef523517SMichael Speer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
831330cd344SMichael Speer "nxge_hio_vr_add failed"));
832330cd344SMichael Speer (void) hsvc_unregister(&nxgep->niu_hsvc);
833330cd344SMichael Speer nxgep->niu_hsvc_available = B_FALSE;
834ef523517SMichael Speer goto nxge_attach_fail;
835330cd344SMichael Speer }
836678453a8Sspeer goto nxge_attach_exit;
837678453a8Sspeer }
838678453a8Sspeer #endif
839678453a8Sspeer
84044961713Sgirish status = nxge_setup_dev(nxgep);
84144961713Sgirish if (status != DDI_SUCCESS) {
84244961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed"));
84344961713Sgirish goto nxge_attach_fail;
84444961713Sgirish }
84544961713Sgirish
84644961713Sgirish status = nxge_add_intrs(nxgep);
84744961713Sgirish if (status != DDI_SUCCESS) {
84844961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed"));
84944961713Sgirish goto nxge_attach_fail;
85044961713Sgirish }
851330cd344SMichael Speer
85200161856Syc /* If a guest, register with vio_net instead. */
8532e59129aSraghus if ((status = nxge_mac_register(nxgep)) != NXGE_OK) {
85444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL,
855678453a8Sspeer "unable to register to mac layer (%d)", status));
85644961713Sgirish goto nxge_attach_fail;
85744961713Sgirish }
85844961713Sgirish
85944961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN);
86044961713Sgirish
861678453a8Sspeer NXGE_DEBUG_MSG((nxgep, DDI_CTL,
862678453a8Sspeer "registered to mac (instance %d)", instance));
86344961713Sgirish
86400161856Syc /* nxge_link_monitor calls xcvr.check_link recursively */
86544961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
86644961713Sgirish
86744961713Sgirish goto nxge_attach_exit;
86844961713Sgirish
86944961713Sgirish nxge_attach_fail:
87044961713Sgirish nxge_unattach(nxgep);
8712e59129aSraghus goto nxge_attach_fail1;
8722e59129aSraghus
8732e59129aSraghus nxge_attach_fail5:
8742e59129aSraghus /*
8752e59129aSraghus * Tear down the ndd parameters setup.
8762e59129aSraghus */
8772e59129aSraghus nxge_destroy_param(nxgep);
8782e59129aSraghus
8792e59129aSraghus /*
8802e59129aSraghus * Tear down the kstat setup.
8812e59129aSraghus */
8822e59129aSraghus nxge_destroy_kstats(nxgep);
8832e59129aSraghus
8842e59129aSraghus nxge_attach_fail4:
8852e59129aSraghus if (nxgep->nxge_hw_p) {
8862e59129aSraghus nxge_uninit_common_dev(nxgep);
8872e59129aSraghus nxgep->nxge_hw_p = NULL;
8882e59129aSraghus }
8892e59129aSraghus
8902e59129aSraghus nxge_attach_fail3:
8912e59129aSraghus /*
8922e59129aSraghus * Unmap the register setup.
8932e59129aSraghus */
8942e59129aSraghus nxge_unmap_regs(nxgep);
8952e59129aSraghus
8962e59129aSraghus nxge_fm_fini(nxgep);
8972e59129aSraghus
8982e59129aSraghus nxge_attach_fail2:
8992e59129aSraghus ddi_soft_state_free(nxge_list, nxgep->instance);
9002e59129aSraghus
9012e59129aSraghus nxge_attach_fail1:
90256d930aeSspeer if (status != NXGE_OK)
90356d930aeSspeer status = (NXGE_ERROR | NXGE_DDI_FAILED);
90444961713Sgirish nxgep = NULL;
90544961713Sgirish
90644961713Sgirish nxge_attach_exit:
90744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x",
9084045d941Ssowmini status));
90944961713Sgirish
91044961713Sgirish return (status);
91144961713Sgirish }
91244961713Sgirish
91344961713Sgirish static int
nxge_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)91444961713Sgirish nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
91544961713Sgirish {
916*86ef0a63SRichard Lowe int status = DDI_SUCCESS;
917*86ef0a63SRichard Lowe int instance;
918*86ef0a63SRichard Lowe p_nxge_t nxgep = NULL;
91944961713Sgirish
92044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach"));
92144961713Sgirish instance = ddi_get_instance(dip);
92244961713Sgirish nxgep = ddi_get_soft_state(nxge_list, instance);
92344961713Sgirish if (nxgep == NULL) {
92444961713Sgirish status = DDI_FAILURE;
92544961713Sgirish goto nxge_detach_exit;
92644961713Sgirish }
92744961713Sgirish
92844961713Sgirish switch (cmd) {
92944961713Sgirish case DDI_DETACH:
93044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH"));
93144961713Sgirish break;
93244961713Sgirish
93344961713Sgirish case DDI_PM_SUSPEND:
93444961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
93544961713Sgirish nxgep->suspended = DDI_PM_SUSPEND;
93644961713Sgirish nxge_suspend(nxgep);
93744961713Sgirish break;
93844961713Sgirish
93944961713Sgirish case DDI_SUSPEND:
94044961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND"));
94144961713Sgirish if (nxgep->suspended != DDI_PM_SUSPEND) {
94244961713Sgirish nxgep->suspended = DDI_SUSPEND;
94344961713Sgirish nxge_suspend(nxgep);
94444961713Sgirish }
94544961713Sgirish break;
94644961713Sgirish
94744961713Sgirish default:
94844961713Sgirish status = DDI_FAILURE;
94944961713Sgirish }
95044961713Sgirish
95144961713Sgirish if (cmd != DDI_DETACH)
95244961713Sgirish goto nxge_detach_exit;
95344961713Sgirish
95444961713Sgirish /*
95544961713Sgirish * Stop the xcvr polling.
95644961713Sgirish */
95744961713Sgirish nxgep->suspended = cmd;
95844961713Sgirish
95944961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
96044961713Sgirish
96163f531d1SSriharsha Basavapatna if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) {
96244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
9634045d941Ssowmini "<== nxge_detach status = 0x%08X", status));
96444961713Sgirish return (DDI_FAILURE);
96544961713Sgirish }
96644961713Sgirish
96744961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL,
9684045d941Ssowmini "<== nxge_detach (mac_unregister) status = 0x%08X", status));
969