blob: a2ef343c767bff8fa3d9d696242f9820e9103b18 [file] [log] [blame]
girish44961712006-11-22 11:47:19 -08001/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
Santwona Behera9d587972010-05-20 10:19:34 -070022 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
Dale Ghent238d8f42016-02-03 17:58:20 -050023 * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved.
girish44961712006-11-22 11:47:19 -080024 */
25
girish44961712006-11-22 11:47:19 -080026/*
27 * SunOs MT STREAMS NIU/Neptune 10Gb Ethernet Device Driver.
28 */
29#include <sys/nxge/nxge_impl.h>
speer678453a2008-04-27 19:50:44 -070030#include <sys/nxge/nxge_hio.h>
31#include <sys/nxge/nxge_rxdma.h>
sd7746814ea4bb2006-12-22 12:42:28 -080032#include <sys/pcie.h>
girish44961712006-11-22 11:47:19 -080033
34uint32_t nxge_use_partition = 0; /* debug partition flag */
35uint32_t nxge_dma_obp_props_only = 1; /* use obp published props */
36uint32_t nxge_use_rdc_intr = 1; /* debug to assign rdc intr */
37/*
ml29623ec090652007-09-07 18:41:21 -070038 * PSARC/2007/453 MSI-X interrupt limit override
girish44961712006-11-22 11:47:19 -080039 */
ml29623ec090652007-09-07 18:41:21 -070040uint32_t nxge_msi_enable = 2;
girish44961712006-11-22 11:47:19 -080041
ml29623b4d05832008-05-12 11:51:35 -070042/*
ml296236f157ac2008-05-23 16:33:43 -070043 * Software workaround for a Neptune (PCI-E)
44 * hardware interrupt bug which the hardware
45 * may generate spurious interrupts after the
46 * device interrupt handler was removed. If this flag
47 * is enabled, the driver will reset the
48 * hardware when devices are being detached.
49 */
50uint32_t nxge_peu_reset_enable = 0;
51
52/*
ml29623b4d05832008-05-12 11:51:35 -070053 * Software workaround for the hardware
54 * checksum bugs that affect packet transmission
55 * and receive:
56 *
57 * Usage of nxge_cksum_offload:
58 *
59 * (1) nxge_cksum_offload = 0 (default):
60 * - transmits packets:
61 * TCP: uses the hardware checksum feature.
62 * UDP: driver will compute the software checksum
63 * based on the partial checksum computed
64 * by the IP layer.
65 * - receives packets
66 * TCP: marks packets checksum flags based on hardware result.
67 * UDP: will not mark checksum flags.
68 *
69 * (2) nxge_cksum_offload = 1:
70 * - transmit packets:
71 * TCP/UDP: uses the hardware checksum feature.
72 * - receives packets
73 * TCP/UDP: marks packet checksum flags based on hardware result.
74 *
75 * (3) nxge_cksum_offload = 2:
76 * - The driver will not register its checksum capability.
77 * Checksum for both TCP and UDP will be computed
78 * by the stack.
79 * - The software LSO is not allowed in this case.
80 *
81 * (4) nxge_cksum_offload > 2:
82 * - Will be treated as it is set to 2
83 * (stack will compute the checksum).
84 *
85 * (5) If the hardware bug is fixed, this workaround
86 * needs to be updated accordingly to reflect
87 * the new hardware revision.
88 */
89uint32_t nxge_cksum_offload = 0;
speer678453a2008-04-27 19:50:44 -070090
girish44961712006-11-22 11:47:19 -080091/*
92 * Globals: tunable parameters (/etc/system or adb)
93 *
94 */
95uint32_t nxge_rbr_size = NXGE_RBR_RBB_DEFAULT;
96uint32_t nxge_rbr_spare_size = 0;
97uint32_t nxge_rcr_size = NXGE_RCR_DEFAULT;
Janie Lu4df55fd2009-12-11 10:41:17 -080098uint16_t nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET;
girish44961712006-11-22 11:47:19 -080099uint32_t nxge_tx_ring_size = NXGE_TX_RING_DEFAULT;
speerb3a01052007-05-09 17:59:29 -0700100boolean_t nxge_no_msg = B_TRUE; /* control message display */
girish44961712006-11-22 11:47:19 -0800101uint32_t nxge_no_link_notify = 0; /* control DL_NOTIFY */
102uint32_t nxge_bcopy_thresh = TX_BCOPY_MAX;
103uint32_t nxge_dvma_thresh = TX_FASTDVMA_MIN;
104uint32_t nxge_dma_stream_thresh = TX_STREAM_MIN;
105uint32_t nxge_jumbo_mtu = TX_JUMBO_MTU;
ml296231f8914d2007-04-02 18:15:26 -0700106nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL;
girish44961712006-11-22 11:47:19 -0800107
ml2962330ac2e72008-01-04 11:32:17 -0800108/* MAX LSO size */
109#define NXGE_LSO_MAXLEN 65535
ml2962330ac2e72008-01-04 11:32:17 -0800110uint32_t nxge_lso_max = NXGE_LSO_MAXLEN;
111
girish44961712006-11-22 11:47:19 -0800112
113/*
114 * Add tunable to reduce the amount of time spent in the
115 * ISR doing Rx Processing.
116 */
117uint32_t nxge_max_rx_pkts = 1024;
118
119/*
120 * Tunables to manage the receive buffer blocks.
121 *
122 * nxge_rx_threshold_hi: copy all buffers.
123 * nxge_rx_bcopy_size_type: receive buffer block size type.
124 * nxge_rx_threshold_lo: copy only up to tunable block size type.
125 */
126nxge_rxbuf_threshold_t nxge_rx_threshold_hi = NXGE_RX_COPY_6;
127nxge_rxbuf_type_t nxge_rx_buf_size_type = RCR_PKTBUFSZ_0;
128nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3;
129
speer678453a2008-04-27 19:50:44 -0700130/* Use kmem_alloc() to allocate data buffers. */
Michael Speeref523512009-09-17 17:09:42 -0700131#if defined(__sparc)
speerd00f30b2008-04-28 07:24:03 -0700132uint32_t nxge_use_kmem_alloc = 1;
Michael Speeref523512009-09-17 17:09:42 -0700133#elif defined(__i386)
speerd00f30b2008-04-28 07:24:03 -0700134uint32_t nxge_use_kmem_alloc = 0;
Michael Speeref523512009-09-17 17:09:42 -0700135#else
136uint32_t nxge_use_kmem_alloc = 1;
speer678453a2008-04-27 19:50:44 -0700137#endif
138
girish44961712006-11-22 11:47:19 -0800139rtrace_t npi_rtracebuf;
140
ml29623d6d34052008-07-17 19:16:05 -0700141/*
142 * The hardware sometimes fails to allow enough time for the link partner
143 * to send an acknowledgement for packets that the hardware sent to it. The
144 * hardware resends the packets earlier than it should be in those instances.
145 * This behavior caused some switches to acknowledge the wrong packets
146 * and it triggered the fatal error.
147 * This software workaround is to set the replay timer to a value
148 * suggested by the hardware team.
149 *
150 * PCI config space replay timer register:
151 * The following replay timeout value is 0xc
152 * for bit 14:18.
153 */
154#define PCI_REPLAY_TIMEOUT_CFG_OFFSET 0xb8
155#define PCI_REPLAY_TIMEOUT_SHIFT 14
156
157uint32_t nxge_set_replay_timer = 1;
158uint32_t nxge_replay_timeout = 0xc;
159
ml29623cf020df2008-07-31 15:40:45 -0700160/*
161 * The transmit serialization sometimes causes
162 * longer sleep before calling the driver transmit
163 * function as it sleeps longer than it should.
164 * The performace group suggests that a time wait tunable
165 * can be used to set the maximum wait time when needed
166 * and the default is set to 1 tick.
167 */
168uint32_t nxge_tx_serial_maxsleep = 1;
169
girish44961712006-11-22 11:47:19 -0800170#if defined(sun4v)
171/*
172 * Hypervisor N2/NIU services information.
173 */
Janie Lu4df55fd2009-12-11 10:41:17 -0800174/*
175 * The following is the default API supported:
176 * major 1 and minor 1.
177 *
178 * Please update the MAX_NIU_MAJORS,
179 * MAX_NIU_MINORS, and minor number supported
180 * when the newer Hypervior API interfaces
181 * are added. Also, please update nxge_hsvc_register()
182 * if needed.
183 */
girish44961712006-11-22 11:47:19 -0800184static hsvc_info_t niu_hsvc = {
185 HSVC_REV_1, NULL, HSVC_GROUP_NIU, NIU_MAJOR_VER,
186 NIU_MINOR_VER, "nxge"
187};
speer678453a2008-04-27 19:50:44 -0700188
189static int nxge_hsvc_register(p_nxge_t);
girish44961712006-11-22 11:47:19 -0800190#endif
191
192/*
193 * Function Prototypes
194 */
195static int nxge_attach(dev_info_t *, ddi_attach_cmd_t);
196static int nxge_detach(dev_info_t *, ddi_detach_cmd_t);
197static void nxge_unattach(p_nxge_t);
Sherry Moore19397402008-09-22 16:30:26 -0700198static int nxge_quiesce(dev_info_t *);
girish44961712006-11-22 11:47:19 -0800199
200#if NXGE_PROPERTY
201static void nxge_remove_hard_properties(p_nxge_t);
202#endif
203
speer678453a2008-04-27 19:50:44 -0700204/*
205 * These two functions are required by nxge_hio.c
206 */
Eric Chengda14ceb2008-12-04 18:16:10 -0800207extern int nxge_m_mmac_remove(void *arg, int slot);
Michael Speer651ce692008-10-01 10:02:37 -0700208extern void nxge_grp_cleanup(p_nxge_t nxge);
speer678453a2008-04-27 19:50:44 -0700209
girish44961712006-11-22 11:47:19 -0800210static nxge_status_t nxge_setup_system_dma_pages(p_nxge_t);
211
212static nxge_status_t nxge_setup_mutexes(p_nxge_t);
213static void nxge_destroy_mutexes(p_nxge_t);
214
215static nxge_status_t nxge_map_regs(p_nxge_t nxgep);
216static void nxge_unmap_regs(p_nxge_t nxgep);
217#ifdef NXGE_DEBUG
218static void nxge_test_map_regs(p_nxge_t nxgep);
219#endif
220
221static nxge_status_t nxge_add_intrs(p_nxge_t nxgep);
girish44961712006-11-22 11:47:19 -0800222static void nxge_remove_intrs(p_nxge_t nxgep);
girish44961712006-11-22 11:47:19 -0800223
224static nxge_status_t nxge_add_intrs_adv(p_nxge_t nxgep);
225static nxge_status_t nxge_add_intrs_adv_type(p_nxge_t, uint32_t);
226static nxge_status_t nxge_add_intrs_adv_type_fix(p_nxge_t, uint32_t);
227static void nxge_intrs_enable(p_nxge_t nxgep);
228static void nxge_intrs_disable(p_nxge_t nxgep);
229
230static void nxge_suspend(p_nxge_t);
231static nxge_status_t nxge_resume(p_nxge_t);
232
233static nxge_status_t nxge_setup_dev(p_nxge_t);
234static void nxge_destroy_dev(p_nxge_t);
235
236static nxge_status_t nxge_alloc_mem_pool(p_nxge_t);
237static void nxge_free_mem_pool(p_nxge_t);
238
speer678453a2008-04-27 19:50:44 -0700239nxge_status_t nxge_alloc_rx_mem_pool(p_nxge_t);
girish44961712006-11-22 11:47:19 -0800240static void nxge_free_rx_mem_pool(p_nxge_t);
241
speer678453a2008-04-27 19:50:44 -0700242nxge_status_t nxge_alloc_tx_mem_pool(p_nxge_t);
girish44961712006-11-22 11:47:19 -0800243static void nxge_free_tx_mem_pool(p_nxge_t);
244
245static nxge_status_t nxge_dma_mem_alloc(p_nxge_t, dma_method_t,
246 struct ddi_dma_attr *,
247 size_t, ddi_device_acc_attr_t *, uint_t,
248 p_nxge_dma_common_t);
249
250static void nxge_dma_mem_free(p_nxge_dma_common_t);
speer678453a2008-04-27 19:50:44 -0700251static void nxge_dma_free_rx_data_buf(p_nxge_dma_common_t);
girish44961712006-11-22 11:47:19 -0800252
253static nxge_status_t nxge_alloc_rx_buf_dma(p_nxge_t, uint16_t,
254 p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
255static void nxge_free_rx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
256
257static nxge_status_t nxge_alloc_rx_cntl_dma(p_nxge_t, uint16_t,
258 p_nxge_dma_common_t *, size_t);
259static void nxge_free_rx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
260
speer678453a2008-04-27 19:50:44 -0700261extern nxge_status_t nxge_alloc_tx_buf_dma(p_nxge_t, uint16_t,
girish44961712006-11-22 11:47:19 -0800262 p_nxge_dma_common_t *, size_t, size_t, uint32_t *);
263static void nxge_free_tx_buf_dma(p_nxge_t, p_nxge_dma_common_t, uint32_t);
264
speer678453a2008-04-27 19:50:44 -0700265extern nxge_status_t nxge_alloc_tx_cntl_dma(p_nxge_t, uint16_t,
girish44961712006-11-22 11:47:19 -0800266 p_nxge_dma_common_t *,
267 size_t);
268static void nxge_free_tx_cntl_dma(p_nxge_t, p_nxge_dma_common_t);
269
270static int nxge_init_common_dev(p_nxge_t);
271static void nxge_uninit_common_dev(p_nxge_t);
sowmini4045d942008-04-29 11:20:32 -0700272extern int nxge_param_set_mac(p_nxge_t, queue_t *, mblk_t *,
273 char *, caddr_t);
Michael Speere759c332009-03-30 18:22:18 -0700274#if defined(sun4v)
275extern nxge_status_t nxge_hio_rdc_enable(p_nxge_t nxgep);
276extern nxge_status_t nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm);
277#endif
girish44961712006-11-22 11:47:19 -0800278
279/*
280 * The next declarations are for the GLDv3 interface.
281 */
282static int nxge_m_start(void *);
283static void nxge_m_stop(void *);
girish44961712006-11-22 11:47:19 -0800284static int nxge_m_multicst(void *, boolean_t, const uint8_t *);
285static int nxge_m_promisc(void *, boolean_t);
286static void nxge_m_ioctl(void *, queue_t *, mblk_t *);
Sriharsha Basavapatna63f531d2009-08-14 09:48:09 -0700287nxge_status_t nxge_mac_register(p_nxge_t);
Eric Chengda14ceb2008-12-04 18:16:10 -0800288static int nxge_altmac_set(p_nxge_t nxgep, uint8_t *mac_addr,
289 int slot, int rdctbl, boolean_t usetbl);
290void nxge_mmac_kstat_update(p_nxge_t nxgep, int slot,
speer58324df2007-02-22 15:55:32 -0800291 boolean_t factory);
Eric Chengda14ceb2008-12-04 18:16:10 -0800292
293static void nxge_m_getfactaddr(void *, uint_t, uint8_t *);
ml296231bd68252008-04-14 17:03:10 -0700294static boolean_t nxge_m_getcapab(void *, mac_capab_t, void *);
295static int nxge_m_setprop(void *, const char *, mac_prop_id_t,
296 uint_t, const void *);
297static int nxge_m_getprop(void *, const char *, mac_prop_id_t,
Venugopal Iyer0dc23662010-03-09 15:30:01 -0800298 uint_t, void *);
299static void nxge_m_propinfo(void *, const char *, mac_prop_id_t,
300 mac_prop_info_handle_t);
301static void nxge_priv_propinfo(const char *, mac_prop_info_handle_t);
ml296231bd68252008-04-14 17:03:10 -0700302static int nxge_set_priv_prop(nxge_t *, const char *, uint_t,
303 const void *);
Venugopal Iyer0dc23662010-03-09 15:30:01 -0800304static int nxge_get_priv_prop(nxge_t *, const char *, uint_t, void *);
Eric Chengda14ceb2008-12-04 18:16:10 -0800305static void nxge_fill_ring(void *, mac_ring_type_t, const int, const int,
306 mac_ring_info_t *, mac_ring_handle_t);
307static void nxge_group_add_ring(mac_group_driver_t, mac_ring_driver_t,
308 mac_ring_type_t);
309static void nxge_group_rem_ring(mac_group_driver_t, mac_ring_driver_t,
310 mac_ring_type_t);
sowmini4045d942008-04-29 11:20:32 -0700311
ml296236f157ac2008-05-23 16:33:43 -0700312static void nxge_niu_peu_reset(p_nxge_t nxgep);
ml29623d6d34052008-07-17 19:16:05 -0700313static void nxge_set_pci_replay_timeout(nxge_t *);
sowmini4045d942008-04-29 11:20:32 -0700314
Venugopal Iyer0dc23662010-03-09 15:30:01 -0800315char *nxge_priv_props[] = {
316 "_adv_10gfdx_cap",
317 "_adv_pause_cap",
318 "_function_number",
319 "_fw_version",
320 "_port_mode",
321 "_hot_swap_phy",
322 "_rxdma_intr_time",
323 "_rxdma_intr_pkts",
324 "_class_opt_ipv4_tcp",
325 "_class_opt_ipv4_udp",
326 "_class_opt_ipv4_ah",
327 "_class_opt_ipv4_sctp",
328 "_class_opt_ipv6_tcp",
329 "_class_opt_ipv6_udp",
330 "_class_opt_ipv6_ah",
331 "_class_opt_ipv6_sctp",
332 "_soft_lso_enable",
333 NULL
sowmini4045d942008-04-29 11:20:32 -0700334};
335
girish44961712006-11-22 11:47:19 -0800336#define NXGE_NEPTUNE_MAGIC 0x4E584745UL
337#define MAX_DUMP_SZ 256
338
ml296231bd68252008-04-14 17:03:10 -0700339#define NXGE_M_CALLBACK_FLAGS \
Venugopal Iyer0dc23662010-03-09 15:30:01 -0800340 (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
girish44961712006-11-22 11:47:19 -0800341
speer678453a2008-04-27 19:50:44 -0700342mac_callbacks_t nxge_m_callbacks = {
girish44961712006-11-22 11:47:19 -0800343 NXGE_M_CALLBACK_FLAGS,
344 nxge_m_stat,
345 nxge_m_start,
346 nxge_m_stop,
347 nxge_m_promisc,
348 nxge_m_multicst,
Eric Chengda14ceb2008-12-04 18:16:10 -0800349 NULL,
350 NULL,
Venugopal Iyer0dc23662010-03-09 15:30:01 -0800351 NULL,
girish44961712006-11-22 11:47:19 -0800352 nxge_m_ioctl,
ml296231bd68252008-04-14 17:03:10 -0700353 nxge_m_getcapab,
354 NULL,
355 NULL,
356 nxge_m_setprop,
Venugopal Iyer0dc23662010-03-09 15:30:01 -0800357 nxge_m_getprop,
358 nxge_m_propinfo
girish44961712006-11-22 11:47:19 -0800359};
360
361void
362nxge_err_inject(p_nxge_t, queue_t *, mblk_t *);
363
ml29623ec090652007-09-07 18:41:21 -0700364/* PSARC/2007/453 MSI-X interrupt limit override. */
365#define NXGE_MSIX_REQUEST_10G 8
366#define NXGE_MSIX_REQUEST_1G 2
367static int nxge_create_msi_property(p_nxge_t);
tc99174@trainef755e72008-12-24 11:19:09 -0800368/*
369 * For applications that care about the
370 * latency, it was requested by PAE and the
371 * customers that the driver has tunables that
372 * allow the user to tune it to a higher number
373 * interrupts to spread the interrupts among
374 * multiple channels. The DDI framework limits
375 * the maximum number of MSI-X resources to allocate
376 * to 8 (ddi_msix_alloc_limit). If more than 8
377 * is set, ddi_msix_alloc_limit must be set accordingly.
378 * The default number of MSI interrupts are set to
379 * 8 for 10G and 2 for 1G link.
380 */
381#define NXGE_MSIX_MAX_ALLOWED 32
382uint32_t nxge_msix_10g_intrs = NXGE_MSIX_REQUEST_10G;
383uint32_t nxge_msix_1g_intrs = NXGE_MSIX_REQUEST_1G;
ml29623ec090652007-09-07 18:41:21 -0700384
girish44961712006-11-22 11:47:19 -0800385/*
386 * These global variables control the message
387 * output.
388 */
389out_dbgmsg_t nxge_dbgmsg_out = DBG_CONSOLE | STR_LOG;
speer678453a2008-04-27 19:50:44 -0700390uint64_t nxge_debug_level;
girish44961712006-11-22 11:47:19 -0800391
392/*
393 * This list contains the instance structures for the Neptune
394 * devices present in the system. The lock exists to guarantee
395 * mutually exclusive access to the list.
396 */
397void *nxge_list = NULL;
girish44961712006-11-22 11:47:19 -0800398void *nxge_hw_list = NULL;
399nxge_os_mutex_t nxge_common_lock;
Michael Speer3b2d9862009-06-22 13:20:44 -0700400nxge_os_mutex_t nxgedebuglock;
girish44961712006-11-22 11:47:19 -0800401
girish44961712006-11-22 11:47:19 -0800402extern uint64_t npi_debug_level;
403
404extern nxge_status_t nxge_ldgv_init(p_nxge_t, int *, int *);
405extern nxge_status_t nxge_ldgv_init_n2(p_nxge_t, int *, int *);
406extern nxge_status_t nxge_ldgv_uninit(p_nxge_t);
407extern nxge_status_t nxge_intr_ldgv_init(p_nxge_t);
408extern void nxge_fm_init(p_nxge_t,
409 ddi_device_acc_attr_t *,
girish44961712006-11-22 11:47:19 -0800410 ddi_dma_attr_t *);
411extern void nxge_fm_fini(p_nxge_t);
speer58324df2007-02-22 15:55:32 -0800412extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t);
girish44961712006-11-22 11:47:19 -0800413
414/*
415 * Count used to maintain the number of buffers being used
416 * by Neptune instances and loaned up to the upper layers.
417 */
418uint32_t nxge_mblks_pending = 0;
419
420/*
421 * Device register access attributes for PIO.
422 */
423static ddi_device_acc_attr_t nxge_dev_reg_acc_attr = {
Stephen Hanson837c1ac2009-12-03 04:39:22 -0800424 DDI_DEVICE_ATTR_V1,
girish44961712006-11-22 11:47:19 -0800425 DDI_STRUCTURE_LE_ACC,
426 DDI_STRICTORDER_ACC,
Stephen Hanson837c1ac2009-12-03 04:39:22 -0800427 DDI_DEFAULT_ACC
girish44961712006-11-22 11:47:19 -0800428};
429
430/*
431 * Device descriptor access attributes for DMA.
432 */
433static ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr = {
434 DDI_DEVICE_ATTR_V0,
435 DDI_STRUCTURE_LE_ACC,
436 DDI_STRICTORDER_ACC
437};
438
439/*
440 * Device buffer access attributes for DMA.
441 */
442static ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr = {
443 DDI_DEVICE_ATTR_V0,
444 DDI_STRUCTURE_BE_ACC,
445 DDI_STRICTORDER_ACC
446};
447
448ddi_dma_attr_t nxge_desc_dma_attr = {
449 DMA_ATTR_V0, /* version number. */
450 0, /* low address */
451 0xffffffffffffffff, /* high address */
452 0xffffffffffffffff, /* address counter max */
453#ifndef NIU_PA_WORKAROUND
454 0x100000, /* alignment */
455#else
456 0x2000,
457#endif
458 0xfc00fc, /* dlim_burstsizes */
459 0x1, /* minimum transfer size */
460 0xffffffffffffffff, /* maximum transfer size */
461 0xffffffffffffffff, /* maximum segment size */
462 1, /* scatter/gather list length */
463 (unsigned int) 1, /* granularity */
464 0 /* attribute flags */
465};
466
467ddi_dma_attr_t nxge_tx_dma_attr = {
468 DMA_ATTR_V0, /* version number. */
469 0, /* low address */
470 0xffffffffffffffff, /* high address */
471 0xffffffffffffffff, /* address counter max */
472#if defined(_BIG_ENDIAN)
473 0x2000, /* alignment */
474#else
475 0x1000, /* alignment */
476#endif
477 0xfc00fc, /* dlim_burstsizes */
478 0x1, /* minimum transfer size */
479 0xffffffffffffffff, /* maximum transfer size */
480 0xffffffffffffffff, /* maximum segment size */
481 5, /* scatter/gather list length */
482 (unsigned int) 1, /* granularity */
483 0 /* attribute flags */
484};
485
486ddi_dma_attr_t nxge_rx_dma_attr = {
487 DMA_ATTR_V0, /* version number. */
488 0, /* low address */
489 0xffffffffffffffff, /* high address */
490 0xffffffffffffffff, /* address counter max */
491 0x2000, /* alignment */
492 0xfc00fc, /* dlim_burstsizes */
493 0x1, /* minimum transfer size */
494 0xffffffffffffffff, /* maximum transfer size */
495 0xffffffffffffffff, /* maximum segment size */
496 1, /* scatter/gather list length */
497 (unsigned int) 1, /* granularity */
sbehera0e2bd522007-08-02 15:19:26 -0700498 DDI_DMA_RELAXED_ORDERING /* attribute flags */
girish44961712006-11-22 11:47:19 -0800499};
500
501ddi_dma_lim_t nxge_dma_limits = {
502 (uint_t)0, /* dlim_addr_lo */
503 (uint_t)0xffffffff, /* dlim_addr_hi */
504 (uint_t)0xffffffff, /* dlim_cntr_max */
505 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */
506 0x1, /* dlim_minxfer */
507 1024 /* dlim_speed */
508};
509
510dma_method_t nxge_force_dma = DVMA;
511
512/*
513 * dma chunk sizes.
514 *
515 * Try to allocate the largest possible size
516 * so that fewer number of dma chunks would be managed
517 */
518#ifdef NIU_PA_WORKAROUND
519size_t alloc_sizes [] = {0x2000};
520#else
521size_t alloc_sizes [] = {0x1000, 0x2000, 0x4000, 0x8000,
522 0x10000, 0x20000, 0x40000, 0x80000,
ml2962330ac2e72008-01-04 11:32:17 -0800523 0x100000, 0x200000, 0x400000, 0x800000,
524 0x1000000, 0x2000000, 0x4000000};
girish44961712006-11-22 11:47:19 -0800525#endif
526
527/*
528 * Translate "dev_t" to a pointer to the associated "dev_info_t".
529 */
530
speer678453a2008-04-27 19:50:44 -0700531extern void nxge_get_environs(nxge_t *);
532
girish44961712006-11-22 11:47:19 -0800533static int
534nxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
535{
536 p_nxge_t nxgep = NULL;
537 int instance;
538 int status = DDI_SUCCESS;
girish44961712006-11-22 11:47:19 -0800539 uint8_t portn;
speer58324df2007-02-22 15:55:32 -0800540 nxge_mmac_t *mmac_info;
girish44961712006-11-22 11:47:19 -0800541
542 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_attach"));
543
544 /*
545 * Get the device instance since we'll need to setup
546 * or retrieve a soft state for this instance.
547 */
548 instance = ddi_get_instance(dip);
549
550 switch (cmd) {
551 case DDI_ATTACH:
552 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_ATTACH"));
553 break;
554
555 case DDI_RESUME:
556 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_RESUME"));
557 nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
558 if (nxgep == NULL) {
559 status = DDI_FAILURE;
560 break;
561 }
562 if (nxgep->dip != dip) {
563 status = DDI_FAILURE;
564 break;
565 }
566 if (nxgep->suspended == DDI_PM_SUSPEND) {
567 status = ddi_dev_is_needed(nxgep->dip, 0, 1);
568 } else {
speer56d930a2007-05-08 14:19:59 -0700569 status = nxge_resume(nxgep);
girish44961712006-11-22 11:47:19 -0800570 }
571 goto nxge_attach_exit;
572
573 case DDI_PM_RESUME:
574 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_RESUME"));
575 nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance);
576 if (nxgep == NULL) {
577 status = DDI_FAILURE;
578 break;
579 }
580 if (nxgep->dip != dip) {
581 status = DDI_FAILURE;
582 break;
583 }
speer56d930a2007-05-08 14:19:59 -0700584 status = nxge_resume(nxgep);
girish44961712006-11-22 11:47:19 -0800585 goto nxge_attach_exit;
586
587 default:
588 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing unknown"));
589 status = DDI_FAILURE;
590 goto nxge_attach_exit;
591 }
592
593
594 if (ddi_soft_state_zalloc(nxge_list, instance) == DDI_FAILURE) {
595 status = DDI_FAILURE;
596 goto nxge_attach_exit;
597 }
598
599 nxgep = ddi_get_soft_state(nxge_list, instance);
600 if (nxgep == NULL) {
raghus2e591292007-08-31 16:49:49 -0700601 status = NXGE_ERROR;
602 goto nxge_attach_fail2;
girish44961712006-11-22 11:47:19 -0800603 }
604
tm14400598ecde52007-07-20 13:52:33 -0700605 nxgep->nxge_magic = NXGE_MAGIC;
606
girish44961712006-11-22 11:47:19 -0800607 nxgep->drv_state = 0;
608 nxgep->dip = dip;
609 nxgep->instance = instance;
610 nxgep->p_dip = ddi_get_parent(dip);
611 nxgep->nxge_debug_level = nxge_debug_level;
612 npi_debug_level = nxge_debug_level;
613
speer678453a2008-04-27 19:50:44 -0700614 /* Are we a guest running in a Hybrid I/O environment? */
615 nxge_get_environs(nxgep);
girish44961712006-11-22 11:47:19 -0800616
617 status = nxge_map_regs(nxgep);
speer678453a2008-04-27 19:50:44 -0700618
girish44961712006-11-22 11:47:19 -0800619 if (status != NXGE_OK) {
620 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_map_regs failed"));
raghus2e591292007-08-31 16:49:49 -0700621 goto nxge_attach_fail3;
girish44961712006-11-22 11:47:19 -0800622 }
623
Stephen Hanson837c1ac2009-12-03 04:39:22 -0800624 nxge_fm_init(nxgep, &nxge_dev_reg_acc_attr, &nxge_rx_dma_attr);
speer678453a2008-04-27 19:50:44 -0700625
626 /* Create & initialize the per-Neptune data structure */
627 /* (even if we're a guest). */
girish44961712006-11-22 11:47:19 -0800628 status = nxge_init_common_dev(nxgep);
629 if (status != NXGE_OK) {
630 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -0700631 "nxge_init_common_dev failed"));
raghus2e591292007-08-31 16:49:49 -0700632 goto nxge_attach_fail4;
girish44961712006-11-22 11:47:19 -0800633 }
634
ml29623d6d34052008-07-17 19:16:05 -0700635 /*
636 * Software workaround: set the replay timer.
637 */
638 if (nxgep->niu_type != N2_NIU) {
639 nxge_set_pci_replay_timeout(nxgep);
640 }
641
speer678453a2008-04-27 19:50:44 -0700642#if defined(sun4v)
643 /* This is required by nxge_hio_init(), which follows. */
644 if ((status = nxge_hsvc_register(nxgep)) != DDI_SUCCESS)
Michael Speer9d5b8bc2008-09-13 23:17:18 -0700645 goto nxge_attach_fail4;
speer678453a2008-04-27 19:50:44 -0700646#endif
647
648 if ((status = nxge_hio_init(nxgep)) != NXGE_OK) {
649 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -0700650 "nxge_hio_init failed"));
speer678453a2008-04-27 19:50:44 -0700651 goto nxge_attach_fail4;
652 }
653
davemq59ac0c12007-07-25 18:20:14 -0700654 if (nxgep->niu_type == NEPTUNE_2_10GF) {
655 if (nxgep->function_num > 1) {
sbehera4202ea42008-02-16 07:17:20 -0800656 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Unsupported"
davemq59ac0c12007-07-25 18:20:14 -0700657 " function %d. Only functions 0 and 1 are "
658 "supported for this card.", nxgep->function_num));
659 status = NXGE_ERROR;
raghus2e591292007-08-31 16:49:49 -0700660 goto nxge_attach_fail4;
davemq59ac0c12007-07-25 18:20:14 -0700661 }
662 }
663
speer678453a2008-04-27 19:50:44 -0700664 if (isLDOMguest(nxgep)) {
665 /*
666 * Use the function number here.
667 */
668 nxgep->mac.portnum = nxgep->function_num;
669 nxgep->mac.porttype = PORT_TYPE_LOGICAL;
670
671 /* XXX We'll set the MAC address counts to 1 for now. */
672 mmac_info = &nxgep->nxge_mmac_info;
673 mmac_info->num_mmac = 1;
674 mmac_info->naddrfree = 1;
speer58324df2007-02-22 15:55:32 -0800675 } else {
speer678453a2008-04-27 19:50:44 -0700676 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
677 nxgep->mac.portnum = portn;
678 if ((portn == 0) || (portn == 1))
679 nxgep->mac.porttype = PORT_TYPE_XMAC;
680 else
681 nxgep->mac.porttype = PORT_TYPE_BMAC;
682 /*
683 * Neptune has 4 ports, the first 2 ports use XMAC (10G MAC)
684 * internally, the rest 2 ports use BMAC (1G "Big" MAC).
685 * The two types of MACs have different characterizations.
686 */
687 mmac_info = &nxgep->nxge_mmac_info;
688 if (nxgep->function_num < 2) {
689 mmac_info->num_mmac = XMAC_MAX_ALT_ADDR_ENTRY;
690 mmac_info->naddrfree = XMAC_MAX_ALT_ADDR_ENTRY;
691 } else {
692 mmac_info->num_mmac = BMAC_MAX_ALT_ADDR_ENTRY;
693 mmac_info->naddrfree = BMAC_MAX_ALT_ADDR_ENTRY;
694 }
speer58324df2007-02-22 15:55:32 -0800695 }
girish44961712006-11-22 11:47:19 -0800696 /*
697 * Setup the Ndd parameters for the this instance.
698 */
699 nxge_init_param(nxgep);
700
701 /*
702 * Setup Register Tracing Buffer.
703 */
704 npi_rtrace_buf_init((rtrace_t *)&npi_rtracebuf);
705
706 /* init stats ptr */
707 nxge_init_statsp(nxgep);
speer56d930a2007-05-08 14:19:59 -0700708
raghus2e591292007-08-31 16:49:49 -0700709 /*
speer678453a2008-04-27 19:50:44 -0700710 * Copy the vpd info from eeprom to a local data
711 * structure, and then check its validity.
raghus2e591292007-08-31 16:49:49 -0700712 */
speer678453a2008-04-27 19:50:44 -0700713 if (!isLDOMguest(nxgep)) {
714 int *regp;
715 uint_t reglen;
716 int rv;
speer56d930a2007-05-08 14:19:59 -0700717
speer678453a2008-04-27 19:50:44 -0700718 nxge_vpd_info_get(nxgep);
girish44961712006-11-22 11:47:19 -0800719
speer678453a2008-04-27 19:50:44 -0700720 /* Find the NIU config handle. */
721 rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
722 ddi_get_parent(nxgep->dip), DDI_PROP_DONTPASS,
723 "reg", &regp, &reglen);
724
725 if (rv != DDI_PROP_SUCCESS) {
726 goto nxge_attach_fail5;
727 }
728 /*
729 * The address_hi, that is the first int, in the reg
730 * property consists of config handle, but need to remove
731 * the bits 28-31 which are OBP specific info.
732 */
733 nxgep->niu_cfg_hdl = (*regp) & 0xFFFFFFF;
734 ddi_prop_free(regp);
girish44961712006-11-22 11:47:19 -0800735 }
736
Michael Speer48056c52009-05-26 19:21:24 -0700737 /*
738 * Set the defaults for the MTU size.
739 */
740 nxge_hw_id_init(nxgep);
741
speer678453a2008-04-27 19:50:44 -0700742 if (isLDOMguest(nxgep)) {
743 uchar_t *prop_val;
744 uint_t prop_len;
Sriharsha Basavapatna7b1f6842008-09-09 14:55:21 -0700745 uint32_t max_frame_size;
girish44961712006-11-22 11:47:19 -0800746
speer678453a2008-04-27 19:50:44 -0700747 extern void nxge_get_logical_props(p_nxge_t);
748
749 nxgep->statsp->mac_stats.xcvr_inuse = LOGICAL_XCVR;
750 nxgep->mac.portmode = PORT_LOGICAL;
751 (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
752 "phy-type", "virtual transceiver");
753
754 nxgep->nports = 1;
755 nxgep->board_ver = 0; /* XXX What? */
756
757 /*
758 * local-mac-address property gives us info on which
759 * specific MAC address the Hybrid resource is associated
760 * with.
761 */
762 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0,
763 "local-mac-address", &prop_val,
764 &prop_len) != DDI_PROP_SUCCESS) {
765 goto nxge_attach_fail5;
766 }
767 if (prop_len != ETHERADDRL) {
768 ddi_prop_free(prop_val);
769 goto nxge_attach_fail5;
770 }
771 ether_copy(prop_val, nxgep->hio_mac_addr);
772 ddi_prop_free(prop_val);
773 nxge_get_logical_props(nxgep);
774
Sriharsha Basavapatna7b1f6842008-09-09 14:55:21 -0700775 /*
776 * Enable Jumbo property based on the "max-frame-size"
777 * property value.
778 */
779 max_frame_size = ddi_prop_get_int(DDI_DEV_T_ANY,
780 nxgep->dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
781 "max-frame-size", NXGE_MTU_DEFAULT_MAX);
782 if ((max_frame_size > NXGE_MTU_DEFAULT_MAX) &&
783 (max_frame_size <= TX_JUMBO_MTU)) {
Sriharsha Basavapatna7b1f6842008-09-09 14:55:21 -0700784 nxgep->mac.is_jumbo = B_TRUE;
785 nxgep->mac.maxframesize = (uint16_t)max_frame_size;
786 nxgep->mac.default_mtu = nxgep->mac.maxframesize -
787 NXGE_EHEADER_VLAN_CRC;
788 }
speer678453a2008-04-27 19:50:44 -0700789 } else {
790 status = nxge_xcvr_find(nxgep);
791
792 if (status != NXGE_OK) {
793 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_attach: "
sowmini4045d942008-04-29 11:20:32 -0700794 " Couldn't determine card type"
795 " .... exit "));
speer678453a2008-04-27 19:50:44 -0700796 goto nxge_attach_fail5;
797 }
798
799 status = nxge_get_config_properties(nxgep);
800
801 if (status != NXGE_OK) {
802 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -0700803 "get_hw create failed"));
speer678453a2008-04-27 19:50:44 -0700804 goto nxge_attach_fail;
805 }
girish44961712006-11-22 11:47:19 -0800806 }
807
girish44961712006-11-22 11:47:19 -0800808 /*
809 * Setup the Kstats for the driver.
810 */
811 nxge_setup_kstats(nxgep);
812
speer678453a2008-04-27 19:50:44 -0700813 if (!isLDOMguest(nxgep))
814 nxge_setup_param(nxgep);
girish44961712006-11-22 11:47:19 -0800815
816 status = nxge_setup_system_dma_pages(nxgep);
817 if (status != NXGE_OK) {
818 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "set dma page failed"));
819 goto nxge_attach_fail;
820 }
821
speer678453a2008-04-27 19:50:44 -0700822
823 if (!isLDOMguest(nxgep))
824 nxge_hw_init_niu_common(nxgep);
girish44961712006-11-22 11:47:19 -0800825
826 status = nxge_setup_mutexes(nxgep);
827 if (status != NXGE_OK) {
828 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set mutex failed"));
829 goto nxge_attach_fail;
830 }
831
speer678453a2008-04-27 19:50:44 -0700832#if defined(sun4v)
833 if (isLDOMguest(nxgep)) {
834 /* Find our VR & channel sets. */
835 status = nxge_hio_vr_add(nxgep);
Michael Speeref523512009-09-17 17:09:42 -0700836 if (status != DDI_SUCCESS) {
837 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
Michael Speer330cd342008-10-11 18:43:57 -0700838 "nxge_hio_vr_add failed"));
839 (void) hsvc_unregister(&nxgep->niu_hsvc);
840 nxgep->niu_hsvc_available = B_FALSE;
Michael Speeref523512009-09-17 17:09:42 -0700841 goto nxge_attach_fail;
Michael Speer330cd342008-10-11 18:43:57 -0700842 }
speer678453a2008-04-27 19:50:44 -0700843 goto nxge_attach_exit;
844 }
845#endif
846
girish44961712006-11-22 11:47:19 -0800847 status = nxge_setup_dev(nxgep);
848 if (status != DDI_SUCCESS) {
849 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "set dev failed"));
850 goto nxge_attach_fail;
851 }
852
853 status = nxge_add_intrs(nxgep);
854 if (status != DDI_SUCCESS) {
855 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "add_intr failed"));
856 goto nxge_attach_fail;
857 }
Michael Speer330cd342008-10-11 18:43:57 -0700858
yc14809700161852008-06-09 20:15:04 -0700859 /* If a guest, register with vio_net instead. */
raghus2e591292007-08-31 16:49:49 -0700860 if ((status = nxge_mac_register(nxgep)) != NXGE_OK) {
girish44961712006-11-22 11:47:19 -0800861 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
speer678453a2008-04-27 19:50:44 -0700862 "unable to register to mac layer (%d)", status));
girish44961712006-11-22 11:47:19 -0800863 goto nxge_attach_fail;
864 }
865
866 mac_link_update(nxgep->mach, LINK_STATE_UNKNOWN);
867
speer678453a2008-04-27 19:50:44 -0700868 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
869 "registered to mac (instance %d)", instance));
girish44961712006-11-22 11:47:19 -0800870
yc14809700161852008-06-09 20:15:04 -0700871 /* nxge_link_monitor calls xcvr.check_link recursively */
girish44961712006-11-22 11:47:19 -0800872 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
873
874 goto nxge_attach_exit;
875
876nxge_attach_fail:
877 nxge_unattach(nxgep);
raghus2e591292007-08-31 16:49:49 -0700878 goto nxge_attach_fail1;
879
880nxge_attach_fail5:
881 /*
882 * Tear down the ndd parameters setup.
883 */
884 nxge_destroy_param(nxgep);
885
886 /*
887 * Tear down the kstat setup.
888 */
889 nxge_destroy_kstats(nxgep);
890
891nxge_attach_fail4:
892 if (nxgep->nxge_hw_p) {
893 nxge_uninit_common_dev(nxgep);
894 nxgep->nxge_hw_p = NULL;
895 }
896
897nxge_attach_fail3:
898 /*
899 * Unmap the register setup.
900 */
901 nxge_unmap_regs(nxgep);
902
903 nxge_fm_fini(nxgep);
904
905nxge_attach_fail2:
906 ddi_soft_state_free(nxge_list, nxgep->instance);
907
908nxge_attach_fail1:
speer56d930a2007-05-08 14:19:59 -0700909 if (status != NXGE_OK)
910 status = (NXGE_ERROR | NXGE_DDI_FAILED);
girish44961712006-11-22 11:47:19 -0800911 nxgep = NULL;
912
913nxge_attach_exit:
914 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_attach status = 0x%08x",
sowmini4045d942008-04-29 11:20:32 -0700915 status));
girish44961712006-11-22 11:47:19 -0800916
917 return (status);
918}
919
920static int
921nxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
922{
923 int status = DDI_SUCCESS;
924 int instance;
925 p_nxge_t nxgep = NULL;
926
927 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_detach"));
928 instance = ddi_get_instance(dip);
929 nxgep = ddi_get_soft_state(nxge_list, instance);
930 if (nxgep == NULL) {
931 status = DDI_FAILURE;
932 goto nxge_detach_exit;
933 }
934
935 switch (cmd) {
936 case DDI_DETACH:
937 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_DETACH"));
938 break;
939
940 case DDI_PM_SUSPEND:
941 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_PM_SUSPEND"));
942 nxgep->suspended = DDI_PM_SUSPEND;
943 nxge_suspend(nxgep);
944 break;
945
946 case DDI_SUSPEND:
947 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "doing DDI_SUSPEND"));
948 if (nxgep->suspended != DDI_PM_SUSPEND) {
949 nxgep->suspended = DDI_SUSPEND;
950 nxge_suspend(nxgep);
951 }
952 break;
953
954 default:
955 status = DDI_FAILURE;
956 }
957
958 if (cmd != DDI_DETACH)
959 goto nxge_detach_exit;
960
961 /*
962 * Stop the xcvr polling.
963 */
964 nxgep->suspended = cmd;
965
966 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
967
Sriharsha Basavapatna63f531d2009-08-14 09:48:09 -0700968 if (nxgep->mach && (status = mac_unregister(nxgep->mach)) != 0) {
girish44961712006-11-22 11:47:19 -0800969 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -0700970 "<== nxge_detach status = 0x%08X", status));
girish44961712006-11-22 11:47:19 -0800971 return (DDI_FAILURE);
972 }
973
974 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -0700975 "<== nxge_detach (mac_unregister) status = 0x%08X", status));
girish44961712006-11-22 11:47:19 -0800976
977 nxge_unattach(nxgep);
978 nxgep = NULL;
979
980nxge_detach_exit:
981 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_detach status = 0x%08X",
sowmini4045d942008-04-29 11:20:32 -0700982 status));
girish44961712006-11-22 11:47:19 -0800983
984 return (status);
985}
986
987static void
988nxge_unattach(p_nxge_t nxgep)
989{
990 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unattach"));
991
992 if (nxgep == NULL || nxgep->dev_regs == NULL) {
993 return;
994 }
995
tm14400598ecde52007-07-20 13:52:33 -0700996 nxgep->nxge_magic = 0;
997
girish44961712006-11-22 11:47:19 -0800998 if (nxgep->nxge_timerid) {
999 nxge_stop_timer(nxgep, nxgep->nxge_timerid);
1000 nxgep->nxge_timerid = 0;
1001 }
1002
ml296236f157ac2008-05-23 16:33:43 -07001003 /*
1004 * If this flag is set, it will affect the Neptune
1005 * only.
1006 */
1007 if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) {
1008 nxge_niu_peu_reset(nxgep);
1009 }
1010
speer678453a2008-04-27 19:50:44 -07001011#if defined(sun4v)
1012 if (isLDOMguest(nxgep)) {
speerd00f30b2008-04-28 07:24:03 -07001013 (void) nxge_hio_vr_release(nxgep);
speer678453a2008-04-27 19:50:44 -07001014 }
1015#endif
1016
sbehera53560812008-01-07 15:28:09 -08001017 if (nxgep->nxge_hw_p) {
1018 nxge_uninit_common_dev(nxgep);
1019 nxgep->nxge_hw_p = NULL;
1020 }
1021
girish44961712006-11-22 11:47:19 -08001022#if defined(sun4v)
1023 if (nxgep->niu_type == N2_NIU && nxgep->niu_hsvc_available == B_TRUE) {
1024 (void) hsvc_unregister(&nxgep->niu_hsvc);
1025 nxgep->niu_hsvc_available = B_FALSE;
1026 }
1027#endif
1028 /*
1029 * Stop any further interrupts.
1030 */
1031 nxge_remove_intrs(nxgep);
1032
girish44961712006-11-22 11:47:19 -08001033 /*
1034 * Stop the device and free resources.
1035 */
speer678453a2008-04-27 19:50:44 -07001036 if (!isLDOMguest(nxgep)) {
1037 nxge_destroy_dev(nxgep);
1038 }
girish44961712006-11-22 11:47:19 -08001039
1040 /*
1041 * Tear down the ndd parameters setup.
1042 */
1043 nxge_destroy_param(nxgep);
1044
1045 /*
1046 * Tear down the kstat setup.
1047 */
1048 nxge_destroy_kstats(nxgep);
1049
1050 /*
Santwona Behera9d587972010-05-20 10:19:34 -07001051 * Free any memory allocated for PHY properties
1052 */
1053 if (nxgep->phy_prop.cnt > 0) {
1054 KMEM_FREE(nxgep->phy_prop.arr,
1055 sizeof (nxge_phy_mdio_val_t) * nxgep->phy_prop.cnt);
1056 nxgep->phy_prop.cnt = 0;
1057 }
1058
1059 /*
girish44961712006-11-22 11:47:19 -08001060 * Destroy all mutexes.
1061 */
1062 nxge_destroy_mutexes(nxgep);
1063
1064 /*
1065 * Remove the list of ndd parameters which
1066 * were setup during attach.
1067 */
1068 if (nxgep->dip) {
1069 NXGE_DEBUG_MSG((nxgep, OBP_CTL,
sowmini4045d942008-04-29 11:20:32 -07001070 " nxge_unattach: remove all properties"));
girish44961712006-11-22 11:47:19 -08001071
1072 (void) ddi_prop_remove_all(nxgep->dip);
1073 }
1074
1075#if NXGE_PROPERTY
1076 nxge_remove_hard_properties(nxgep);
1077#endif
1078
1079 /*
1080 * Unmap the register setup.
1081 */
1082 nxge_unmap_regs(nxgep);
1083
1084 nxge_fm_fini(nxgep);
1085
1086 ddi_soft_state_free(nxge_list, nxgep->instance);
1087
1088 NXGE_DEBUG_MSG((NULL, DDI_CTL, "<== nxge_unattach"));
1089}
1090
speer678453a2008-04-27 19:50:44 -07001091#if defined(sun4v)
1092int
Michael Speer9d5b8bc2008-09-13 23:17:18 -07001093nxge_hsvc_register(nxge_t *nxgep)
speer678453a2008-04-27 19:50:44 -07001094{
1095 nxge_status_t status;
Janie Lu4df55fd2009-12-11 10:41:17 -08001096 int i, j;
speer678453a2008-04-27 19:50:44 -07001097
Janie Lu4df55fd2009-12-11 10:41:17 -08001098 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hsvc_register"));
1099 if (nxgep->niu_type != N2_NIU) {
1100 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hsvc_register"));
1101 return (DDI_SUCCESS);
speer678453a2008-04-27 19:50:44 -07001102 }
1103
Janie Lu4df55fd2009-12-11 10:41:17 -08001104 /*
1105 * Currently, the NIU Hypervisor API supports two major versions:
1106 * version 1 and 2.
1107 * If Hypervisor introduces a higher major or minor version,
1108 * please update NIU_MAJOR_HI and NIU_MINOR_HI accordingly.
1109 */
1110 nxgep->niu_hsvc_available = B_FALSE;
1111 bcopy(&niu_hsvc, &nxgep->niu_hsvc,
1112 sizeof (hsvc_info_t));
1113
1114 for (i = NIU_MAJOR_HI; i > 0; i--) {
1115 nxgep->niu_hsvc.hsvc_major = i;
1116 for (j = NIU_MINOR_HI; j >= 0; j--) {
1117 nxgep->niu_hsvc.hsvc_minor = j;
1118 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1119 "nxge_hsvc_register: %s: negotiating "
1120 "hypervisor services revision %d "
1121 "group: 0x%lx major: 0x%lx "
1122 "minor: 0x%lx",
1123 nxgep->niu_hsvc.hsvc_modname,
1124 nxgep->niu_hsvc.hsvc_rev,
1125 nxgep->niu_hsvc.hsvc_group,
1126 nxgep->niu_hsvc.hsvc_major,
1127 nxgep->niu_hsvc.hsvc_minor,
1128 nxgep->niu_min_ver));
1129
1130 if ((status = hsvc_register(&nxgep->niu_hsvc,
1131 &nxgep->niu_min_ver)) == 0) {
1132 /* Use the supported minor */
1133 nxgep->niu_hsvc.hsvc_minor = nxgep->niu_min_ver;
1134 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1135 "nxge_hsvc_register: %s: negotiated "
1136 "hypervisor services revision %d "
1137 "group: 0x%lx major: 0x%lx "
1138 "minor: 0x%lx (niu_min_ver 0x%lx)",
1139 nxgep->niu_hsvc.hsvc_modname,
1140 nxgep->niu_hsvc.hsvc_rev,
1141 nxgep->niu_hsvc.hsvc_group,
1142 nxgep->niu_hsvc.hsvc_major,
1143 nxgep->niu_hsvc.hsvc_minor,
1144 nxgep->niu_min_ver));
1145
1146 nxgep->niu_hsvc_available = B_TRUE;
1147 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1148 "<== nxge_hsvc_register: "
1149 "NIU Hypervisor service enabled"));
1150 return (DDI_SUCCESS);
1151 }
1152
1153 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1154 "nxge_hsvc_register: %s: negotiated failed - "
1155 "try lower major number "
1156 "hypervisor services revision %d "
1157 "group: 0x%lx major: 0x%lx minor: 0x%lx "
1158 "errno: %d",
1159 nxgep->niu_hsvc.hsvc_modname,
1160 nxgep->niu_hsvc.hsvc_rev,
1161 nxgep->niu_hsvc.hsvc_group,
1162 nxgep->niu_hsvc.hsvc_major,
1163 nxgep->niu_hsvc.hsvc_minor, status));
1164 }
1165 }
1166
1167 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1168 "nxge_hsvc_register: %s: cannot negotiate "
1169 "hypervisor services revision %d group: 0x%lx "
1170 "major: 0x%lx minor: 0x%lx errno: %d",
1171 niu_hsvc.hsvc_modname, niu_hsvc.hsvc_rev,
1172 niu_hsvc.hsvc_group, niu_hsvc.hsvc_major,
1173 niu_hsvc.hsvc_minor, status));
1174
1175 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1176 "<== nxge_hsvc_register: Register to NIU Hypervisor failed"));
1177
1178 return (DDI_FAILURE);
speer678453a2008-04-27 19:50:44 -07001179}
1180#endif
1181
girish44961712006-11-22 11:47:19 -08001182static char n2_siu_name[] = "niu";
1183
1184static nxge_status_t
1185nxge_map_regs(p_nxge_t nxgep)
1186{
1187 int ddi_status = DDI_SUCCESS;
1188 p_dev_regs_t dev_regs;
1189 char buf[MAXPATHLEN + 1];
1190 char *devname;
1191#ifdef NXGE_DEBUG
1192 char *sysname;
1193#endif
1194 off_t regsize;
1195 nxge_status_t status = NXGE_OK;
sd7746814ea4bb2006-12-22 12:42:28 -08001196#if !defined(_BIG_ENDIAN)
1197 off_t pci_offset;
1198 uint16_t pcie_devctl;
1199#endif
girish44961712006-11-22 11:47:19 -08001200
speer678453a2008-04-27 19:50:44 -07001201 if (isLDOMguest(nxgep)) {
1202 return (nxge_guest_regs_map(nxgep));
1203 }
1204
girish44961712006-11-22 11:47:19 -08001205 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_map_regs"));
1206 nxgep->dev_regs = NULL;
1207 dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
1208 dev_regs->nxge_regh = NULL;
1209 dev_regs->nxge_pciregh = NULL;
1210 dev_regs->nxge_msix_regh = NULL;
1211 dev_regs->nxge_vir_regh = NULL;
1212 dev_regs->nxge_vir2_regh = NULL;
davemq59ac0c12007-07-25 18:20:14 -07001213 nxgep->niu_type = NIU_TYPE_NONE;
girish44961712006-11-22 11:47:19 -08001214
1215 devname = ddi_pathname(nxgep->dip, buf);
1216 ASSERT(strlen(devname) > 0);
1217 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001218 "nxge_map_regs: pathname devname %s", devname));
girish44961712006-11-22 11:47:19 -08001219
yc14809700161852008-06-09 20:15:04 -07001220 /*
1221 * The driver is running on a N2-NIU system if devname is something
1222 * like "/niu@80/network@0"
1223 */
girish44961712006-11-22 11:47:19 -08001224 if (strstr(devname, n2_siu_name)) {
1225 /* N2/NIU */
1226 nxgep->niu_type = N2_NIU;
1227 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001228 "nxge_map_regs: N2/NIU devname %s", devname));
Janie Lu4df55fd2009-12-11 10:41:17 -08001229 /*
1230 * Get function number:
1231 * - N2/NIU: "/niu@80/network@0" and "/niu@80/network@1"
1232 */
girish44961712006-11-22 11:47:19 -08001233 nxgep->function_num =
sowmini4045d942008-04-29 11:20:32 -07001234 (devname[strlen(devname) -1] == '1' ? 1 : 0);
girish44961712006-11-22 11:47:19 -08001235 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001236 "nxge_map_regs: N2/NIU function number %d",
1237 nxgep->function_num));
girish44961712006-11-22 11:47:19 -08001238 } else {
1239 int *prop_val;
1240 uint_t prop_len;
1241 uint8_t func_num;
1242
1243 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip,
sowmini4045d942008-04-29 11:20:32 -07001244 0, "reg",
1245 &prop_val, &prop_len) != DDI_PROP_SUCCESS) {
girish44961712006-11-22 11:47:19 -08001246 NXGE_DEBUG_MSG((nxgep, VPD_CTL,
sowmini4045d942008-04-29 11:20:32 -07001247 "Reg property not found"));
girish44961712006-11-22 11:47:19 -08001248 ddi_status = DDI_FAILURE;
1249 goto nxge_map_regs_fail0;
1250
1251 } else {
1252 func_num = (prop_val[0] >> 8) & 0x7;
1253 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001254 "Reg property found: fun # %d",
1255 func_num));
girish44961712006-11-22 11:47:19 -08001256 nxgep->function_num = func_num;
speer678453a2008-04-27 19:50:44 -07001257 if (isLDOMguest(nxgep)) {
1258 nxgep->function_num /= 2;
1259 return (NXGE_OK);
1260 }
girish44961712006-11-22 11:47:19 -08001261 ddi_prop_free(prop_val);
1262 }
1263 }
1264
1265 switch (nxgep->niu_type) {
girish44961712006-11-22 11:47:19 -08001266 default:
1267 (void) ddi_dev_regsize(nxgep->dip, 0, &regsize);
1268 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001269 "nxge_map_regs: pci config size 0x%x", regsize));
girish44961712006-11-22 11:47:19 -08001270
1271 ddi_status = ddi_regs_map_setup(nxgep->dip, 0,
sowmini4045d942008-04-29 11:20:32 -07001272 (caddr_t *)&(dev_regs->nxge_pciregp), 0, 0,
1273 &nxge_dev_reg_acc_attr, &dev_regs->nxge_pciregh);
girish44961712006-11-22 11:47:19 -08001274 if (ddi_status != DDI_SUCCESS) {
1275 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001276 "ddi_map_regs, nxge bus config regs failed"));
girish44961712006-11-22 11:47:19 -08001277 goto nxge_map_regs_fail0;
1278 }
1279 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001280 "nxge_map_reg: PCI config addr 0x%0llx "
1281 " handle 0x%0llx", dev_regs->nxge_pciregp,
1282 dev_regs->nxge_pciregh));
girish44961712006-11-22 11:47:19 -08001283 /*
1284 * IMP IMP
1285 * workaround for bit swapping bug in HW
1286 * which ends up in no-snoop = yes
1287 * resulting, in DMA not synched properly
1288 */
1289#if !defined(_BIG_ENDIAN)
sd7746814ea4bb2006-12-22 12:42:28 -08001290 /* workarounds for x86 systems */
1291 pci_offset = 0x80 + PCIE_DEVCTL;
Michael Speer48056c52009-05-26 19:21:24 -07001292 pcie_devctl = pci_config_get16(dev_regs->nxge_pciregh,
1293 pci_offset);
1294 pcie_devctl &= ~PCIE_DEVCTL_ENABLE_NO_SNOOP;
sd7746814ea4bb2006-12-22 12:42:28 -08001295 pcie_devctl |= PCIE_DEVCTL_RO_EN;
1296 pci_config_put16(dev_regs->nxge_pciregh, pci_offset,
sowmini4045d942008-04-29 11:20:32 -07001297 pcie_devctl);
girish44961712006-11-22 11:47:19 -08001298#endif
sd7746814ea4bb2006-12-22 12:42:28 -08001299
girish44961712006-11-22 11:47:19 -08001300 (void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
1301 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001302 "nxge_map_regs: pio size 0x%x", regsize));
girish44961712006-11-22 11:47:19 -08001303 /* set up the device mapped register */
1304 ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
sowmini4045d942008-04-29 11:20:32 -07001305 (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
1306 &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
girish44961712006-11-22 11:47:19 -08001307 if (ddi_status != DDI_SUCCESS) {
1308 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001309 "ddi_map_regs for Neptune global reg failed"));
girish44961712006-11-22 11:47:19 -08001310 goto nxge_map_regs_fail1;
1311 }
1312
1313 /* set up the msi/msi-x mapped register */
1314 (void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
1315 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001316 "nxge_map_regs: msix size 0x%x", regsize));
girish44961712006-11-22 11:47:19 -08001317 ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
sowmini4045d942008-04-29 11:20:32 -07001318 (caddr_t *)&(dev_regs->nxge_msix_regp), 0, 0,
1319 &nxge_dev_reg_acc_attr, &dev_regs->nxge_msix_regh);
girish44961712006-11-22 11:47:19 -08001320 if (ddi_status != DDI_SUCCESS) {
1321 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001322 "ddi_map_regs for msi reg failed"));
girish44961712006-11-22 11:47:19 -08001323 goto nxge_map_regs_fail2;
1324 }
1325
1326 /* set up the vio region mapped register */
1327 (void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
1328 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001329 "nxge_map_regs: vio size 0x%x", regsize));
girish44961712006-11-22 11:47:19 -08001330 ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
sowmini4045d942008-04-29 11:20:32 -07001331 (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
1332 &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
girish44961712006-11-22 11:47:19 -08001333
1334 if (ddi_status != DDI_SUCCESS) {
1335 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001336 "ddi_map_regs for nxge vio reg failed"));
girish44961712006-11-22 11:47:19 -08001337 goto nxge_map_regs_fail3;
1338 }
1339 nxgep->dev_regs = dev_regs;
1340
1341 NPI_PCI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_pciregh);
1342 NPI_PCI_ADD_HANDLE_SET(nxgep,
sowmini4045d942008-04-29 11:20:32 -07001343 (npi_reg_ptr_t)dev_regs->nxge_pciregp);
girish44961712006-11-22 11:47:19 -08001344 NPI_MSI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_msix_regh);
1345 NPI_MSI_ADD_HANDLE_SET(nxgep,
sowmini4045d942008-04-29 11:20:32 -07001346 (npi_reg_ptr_t)dev_regs->nxge_msix_regp);
girish44961712006-11-22 11:47:19 -08001347
1348 NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1349 NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
1350
1351 NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1352 NPI_REG_ADD_HANDLE_SET(nxgep,
sowmini4045d942008-04-29 11:20:32 -07001353 (npi_reg_ptr_t)dev_regs->nxge_regp);
girish44961712006-11-22 11:47:19 -08001354
1355 NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
1356 NPI_VREG_ADD_HANDLE_SET(nxgep,
sowmini4045d942008-04-29 11:20:32 -07001357 (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
girish44961712006-11-22 11:47:19 -08001358
1359 break;
1360
1361 case N2_NIU:
1362 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "ddi_map_regs, NIU"));
1363 /*
1364 * Set up the device mapped register (FWARC 2006/556)
1365 * (changed back to 1: reg starts at 1!)
1366 */
1367 (void) ddi_dev_regsize(nxgep->dip, 1, &regsize);
1368 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001369 "nxge_map_regs: dev size 0x%x", regsize));
girish44961712006-11-22 11:47:19 -08001370 ddi_status = ddi_regs_map_setup(nxgep->dip, 1,
sowmini4045d942008-04-29 11:20:32 -07001371 (caddr_t *)&(dev_regs->nxge_regp), 0, 0,
1372 &nxge_dev_reg_acc_attr, &dev_regs->nxge_regh);
girish44961712006-11-22 11:47:19 -08001373
1374 if (ddi_status != DDI_SUCCESS) {
1375 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001376 "ddi_map_regs for N2/NIU, global reg failed "));
girish44961712006-11-22 11:47:19 -08001377 goto nxge_map_regs_fail1;
1378 }
1379
speer678453a2008-04-27 19:50:44 -07001380 /* set up the first vio region mapped register */
girish44961712006-11-22 11:47:19 -08001381 (void) ddi_dev_regsize(nxgep->dip, 2, &regsize);
1382 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001383 "nxge_map_regs: vio (1) size 0x%x", regsize));
girish44961712006-11-22 11:47:19 -08001384 ddi_status = ddi_regs_map_setup(nxgep->dip, 2,
sowmini4045d942008-04-29 11:20:32 -07001385 (caddr_t *)&(dev_regs->nxge_vir_regp), 0, 0,
1386 &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir_regh);
girish44961712006-11-22 11:47:19 -08001387
1388 if (ddi_status != DDI_SUCCESS) {
1389 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001390 "ddi_map_regs for nxge vio reg failed"));
girish44961712006-11-22 11:47:19 -08001391 goto nxge_map_regs_fail2;
1392 }
speer678453a2008-04-27 19:50:44 -07001393 /* set up the second vio region mapped register */
girish44961712006-11-22 11:47:19 -08001394 (void) ddi_dev_regsize(nxgep->dip, 3, &regsize);
1395 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001396 "nxge_map_regs: vio (3) size 0x%x", regsize));
girish44961712006-11-22 11:47:19 -08001397 ddi_status = ddi_regs_map_setup(nxgep->dip, 3,
sowmini4045d942008-04-29 11:20:32 -07001398 (caddr_t *)&(dev_regs->nxge_vir2_regp), 0, 0,
1399 &nxge_dev_reg_acc_attr, &dev_regs->nxge_vir2_regh);
girish44961712006-11-22 11:47:19 -08001400
1401 if (ddi_status != DDI_SUCCESS) {
1402 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001403 "ddi_map_regs for nxge vio2 reg failed"));
girish44961712006-11-22 11:47:19 -08001404 goto nxge_map_regs_fail3;
1405 }
1406 nxgep->dev_regs = dev_regs;
1407
1408 NPI_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1409 NPI_ADD_HANDLE_SET(nxgep, (npi_reg_ptr_t)dev_regs->nxge_regp);
1410
1411 NPI_REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_regh);
1412 NPI_REG_ADD_HANDLE_SET(nxgep,
sowmini4045d942008-04-29 11:20:32 -07001413 (npi_reg_ptr_t)dev_regs->nxge_regp);
girish44961712006-11-22 11:47:19 -08001414
1415 NPI_VREG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir_regh);
1416 NPI_VREG_ADD_HANDLE_SET(nxgep,
sowmini4045d942008-04-29 11:20:32 -07001417 (npi_reg_ptr_t)dev_regs->nxge_vir_regp);
girish44961712006-11-22 11:47:19 -08001418
1419 NPI_V2REG_ACC_HANDLE_SET(nxgep, dev_regs->nxge_vir2_regh);
1420 NPI_V2REG_ADD_HANDLE_SET(nxgep,
sowmini4045d942008-04-29 11:20:32 -07001421 (npi_reg_ptr_t)dev_regs->nxge_vir2_regp);
girish44961712006-11-22 11:47:19 -08001422
1423 break;
1424 }
1425
1426 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "nxge_map_reg: hardware addr 0x%0llx "
sowmini4045d942008-04-29 11:20:32 -07001427 " handle 0x%0llx", dev_regs->nxge_regp, dev_regs->nxge_regh));
girish44961712006-11-22 11:47:19 -08001428
1429 goto nxge_map_regs_exit;
1430nxge_map_regs_fail3:
1431 if (dev_regs->nxge_msix_regh) {
1432 ddi_regs_map_free(&dev_regs->nxge_msix_regh);
1433 }
1434 if (dev_regs->nxge_vir_regh) {
1435 ddi_regs_map_free(&dev_regs->nxge_regh);
1436 }
1437nxge_map_regs_fail2:
1438 if (dev_regs->nxge_regh) {
1439 ddi_regs_map_free(&dev_regs->nxge_regh);
1440 }
1441nxge_map_regs_fail1:
1442 if (dev_regs->nxge_pciregh) {
1443 ddi_regs_map_free(&dev_regs->nxge_pciregh);
1444 }
1445nxge_map_regs_fail0:
1446 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "Freeing register set memory"));
1447 kmem_free(dev_regs, sizeof (dev_regs_t));
1448
1449nxge_map_regs_exit:
1450 if (ddi_status != DDI_SUCCESS)
1451 status |= (NXGE_ERROR | NXGE_DDI_FAILED);
1452 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_map_regs"));
1453 return (status);
1454}
1455
1456static void
1457nxge_unmap_regs(p_nxge_t nxgep)
1458{
1459 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_unmap_regs"));
speer678453a2008-04-27 19:50:44 -07001460
1461 if (isLDOMguest(nxgep)) {
1462 nxge_guest_regs_map_free(nxgep);
1463 return;
1464 }
1465
girish44961712006-11-22 11:47:19 -08001466 if (nxgep->dev_regs) {
1467 if (nxgep->dev_regs->nxge_pciregh) {
1468 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001469 "==> nxge_unmap_regs: bus"));
girish44961712006-11-22 11:47:19 -08001470 ddi_regs_map_free(&nxgep->dev_regs->nxge_pciregh);
1471 nxgep->dev_regs->nxge_pciregh = NULL;
1472 }
1473 if (nxgep->dev_regs->nxge_regh) {
1474 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001475 "==> nxge_unmap_regs: device registers"));
girish44961712006-11-22 11:47:19 -08001476 ddi_regs_map_free(&nxgep->dev_regs->nxge_regh);
1477 nxgep->dev_regs->nxge_regh = NULL;
1478 }
1479 if (nxgep->dev_regs->nxge_msix_regh) {
1480 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001481 "==> nxge_unmap_regs: device interrupts"));
girish44961712006-11-22 11:47:19 -08001482 ddi_regs_map_free(&nxgep->dev_regs->nxge_msix_regh);
1483 nxgep->dev_regs->nxge_msix_regh = NULL;
1484 }
1485 if (nxgep->dev_regs->nxge_vir_regh) {
1486 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001487 "==> nxge_unmap_regs: vio region"));
girish44961712006-11-22 11:47:19 -08001488 ddi_regs_map_free(&nxgep->dev_regs->nxge_vir_regh);
1489 nxgep->dev_regs->nxge_vir_regh = NULL;
1490 }
1491 if (nxgep->dev_regs->nxge_vir2_regh) {
1492 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001493 "==> nxge_unmap_regs: vio2 region"));
girish44961712006-11-22 11:47:19 -08001494 ddi_regs_map_free(&nxgep->dev_regs->nxge_vir2_regh);
1495 nxgep->dev_regs->nxge_vir2_regh = NULL;
1496 }
1497
1498 kmem_free(nxgep->dev_regs, sizeof (dev_regs_t));
1499 nxgep->dev_regs = NULL;
1500 }
1501
1502 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_unmap_regs"));
1503}
1504
1505static nxge_status_t
1506nxge_setup_mutexes(p_nxge_t nxgep)
1507{
1508 int ddi_status = DDI_SUCCESS;
1509 nxge_status_t status = NXGE_OK;
1510 nxge_classify_t *classify_ptr;
1511 int partition;
1512
1513 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_mutexes"));
1514
1515 /*
1516 * Get the interrupt cookie so the mutexes can be
speer58324df2007-02-22 15:55:32 -08001517 * Initialized.
girish44961712006-11-22 11:47:19 -08001518 */
speer678453a2008-04-27 19:50:44 -07001519 if (isLDOMguest(nxgep)) {
1520 nxgep->interrupt_cookie = 0;
1521 } else {
1522 ddi_status = ddi_get_iblock_cookie(nxgep->dip, 0,
1523 &nxgep->interrupt_cookie);
1524
1525 if (ddi_status != DDI_SUCCESS) {
1526 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1527 "<== nxge_setup_mutexes: failed 0x%x",
1528 ddi_status));
1529 goto nxge_setup_mutexes_exit;
1530 }
girish44961712006-11-22 11:47:19 -08001531 }
1532
tm14400598ecde52007-07-20 13:52:33 -07001533 cv_init(&nxgep->poll_cv, NULL, CV_DRIVER, NULL);
1534 MUTEX_INIT(&nxgep->poll_lock, NULL,
1535 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1536
girish44961712006-11-22 11:47:19 -08001537 /*
tm14400598ecde52007-07-20 13:52:33 -07001538 * Initialize mutexes for this device.
girish44961712006-11-22 11:47:19 -08001539 */
1540 MUTEX_INIT(nxgep->genlock, NULL,
sowmini4045d942008-04-29 11:20:32 -07001541 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
girish44961712006-11-22 11:47:19 -08001542 MUTEX_INIT(&nxgep->ouraddr_lock, NULL,
sowmini4045d942008-04-29 11:20:32 -07001543 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
girish44961712006-11-22 11:47:19 -08001544 MUTEX_INIT(&nxgep->mif_lock, NULL,
sowmini4045d942008-04-29 11:20:32 -07001545 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
speer678453a2008-04-27 19:50:44 -07001546 MUTEX_INIT(&nxgep->group_lock, NULL,
1547 MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
girish44961712006-11-22 11:47:19 -08001548 RW_INIT(&nxgep->filter_lock, NULL,
sowmini4045d942008-04-29 11:20:32 -07001549 RW_DRIVER, (void *)nxgep->interrupt_cookie);
girish44961712006-11-22 11:47:19 -08001550
1551 classify_ptr = &nxgep->classifier;
1552 /*
1553 * FFLP Mutexes are never used in interrupt context
1554 * as fflp operation can take very long time to
1555 * complete and hence not suitable to invoke from interrupt
1556 * handlers.
1557 */
1558 MUTEX_INIT(&classify_ptr->tcam_lock, NULL,
davemq59ac0c12007-07-25 18:20:14 -07001559 NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
raghus2e591292007-08-31 16:49:49 -07001560 if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
girish44961712006-11-22 11:47:19 -08001561 MUTEX_INIT(&classify_ptr->fcram_lock, NULL,
davemq59ac0c12007-07-25 18:20:14 -07001562 NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
girish44961712006-11-22 11:47:19 -08001563 for (partition = 0; partition < MAX_PARTITION; partition++) {
1564 MUTEX_INIT(&classify_ptr->hash_lock[partition], NULL,
1565 NXGE_MUTEX_DRIVER, (void *)nxgep->interrupt_cookie);
1566 }
1567 }
1568
1569nxge_setup_mutexes_exit:
1570 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07001571 "<== nxge_setup_mutexes status = %x", status));
girish44961712006-11-22 11:47:19 -08001572
1573 if (ddi_status != DDI_SUCCESS)
1574 status |= (NXGE_ERROR | NXGE_DDI_FAILED);
1575
1576 return (status);
1577}
1578
1579static void
1580nxge_destroy_mutexes(p_nxge_t nxgep)
1581{
1582 int partition;
1583 nxge_classify_t *classify_ptr;
1584
1585 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_mutexes"));
1586 RW_DESTROY(&nxgep->filter_lock);
speer678453a2008-04-27 19:50:44 -07001587 MUTEX_DESTROY(&nxgep->group_lock);
girish44961712006-11-22 11:47:19 -08001588 MUTEX_DESTROY(&nxgep->mif_lock);
1589 MUTEX_DESTROY(&nxgep->ouraddr_lock);
1590 MUTEX_DESTROY(nxgep->genlock);
1591
1592 classify_ptr = &nxgep->classifier;
1593 MUTEX_DESTROY(&classify_ptr->tcam_lock);
1594
tm14400598ecde52007-07-20 13:52:33 -07001595 /* Destroy all polling resources. */
1596 MUTEX_DESTROY(&nxgep->poll_lock);
1597 cv_destroy(&nxgep->poll_cv);
1598
1599 /* free data structures, based on HW type */
raghus2e591292007-08-31 16:49:49 -07001600 if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
girish44961712006-11-22 11:47:19 -08001601 MUTEX_DESTROY(&classify_ptr->fcram_lock);
1602 for (partition = 0; partition < MAX_PARTITION; partition++) {
1603 MUTEX_DESTROY(&classify_ptr->hash_lock[partition]);
1604 }
1605 }
girish44961712006-11-22 11:47:19 -08001606
1607 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_mutexes"));
1608}
1609
1610nxge_status_t
1611nxge_init(p_nxge_t nxgep)
1612{
speer678453a2008-04-27 19:50:44 -07001613 nxge_status_t status = NXGE_OK;
girish44961712006-11-22 11:47:19 -08001614
1615 NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_init"));
1616
sd7746814ea4bb2006-12-22 12:42:28 -08001617 if (nxgep->drv_state & STATE_HW_INITIALIZED) {
1618 return (status);
1619 }
1620
girish44961712006-11-22 11:47:19 -08001621 /*
1622 * Allocate system memory for the receive/transmit buffer blocks
1623 * and receive/transmit descriptor rings.
1624 */
1625 status = nxge_alloc_mem_pool(nxgep);
1626 if (status != NXGE_OK) {
1627 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "alloc mem failed\n"));
1628 goto nxge_init_fail1;
1629 }
1630
speer678453a2008-04-27 19:50:44 -07001631 if (!isLDOMguest(nxgep)) {
1632 /*
1633 * Initialize and enable the TXC registers.
1634 * (Globally enable the Tx controller,
1635 * enable the port, configure the dma channel bitmap,
1636 * configure the max burst size).
1637 */
1638 status = nxge_txc_init(nxgep);
1639 if (status != NXGE_OK) {
1640 NXGE_ERROR_MSG((nxgep,
1641 NXGE_ERR_CTL, "init txc failed\n"));
1642 goto nxge_init_fail2;
1643 }
girish44961712006-11-22 11:47:19 -08001644 }
1645
1646 /*
1647 * Initialize and enable TXDMA channels.
1648 */
1649 status = nxge_init_txdma_channels(nxgep);
1650 if (status != NXGE_OK) {
1651 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init txdma failed\n"));
1652 goto nxge_init_fail3;
1653 }
1654
1655 /*
1656 * Initialize and enable RXDMA channels.
1657 */
1658 status = nxge_init_rxdma_channels(nxgep);
1659 if (status != NXGE_OK) {
1660 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init rxdma failed\n"));
1661 goto nxge_init_fail4;
1662 }
1663
1664 /*
speer678453a2008-04-27 19:50:44 -07001665 * The guest domain is now done.
1666 */
1667 if (isLDOMguest(nxgep)) {
1668 nxgep->drv_state |= STATE_HW_INITIALIZED;
1669 goto nxge_init_exit;
1670 }
1671
1672 /*
girish44961712006-11-22 11:47:19 -08001673 * Initialize TCAM and FCRAM (Neptune).
1674 */
1675 status = nxge_classify_init(nxgep);
1676 if (status != NXGE_OK) {
1677 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init classify failed\n"));
1678 goto nxge_init_fail5;
1679 }
1680
1681 /*
1682 * Initialize ZCP
1683 */
1684 status = nxge_zcp_init(nxgep);
1685 if (status != NXGE_OK) {
1686 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init ZCP failed\n"));
1687 goto nxge_init_fail5;
1688 }
1689
1690 /*
1691 * Initialize IPP.
1692 */
1693 status = nxge_ipp_init(nxgep);
1694 if (status != NXGE_OK) {
1695 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init IPP failed\n"));
1696 goto nxge_init_fail5;
1697 }
1698
1699 /*
1700 * Initialize the MAC block.
1701 */
1702 status = nxge_mac_init(nxgep);
1703 if (status != NXGE_OK) {
1704 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "init MAC failed\n"));
1705 goto nxge_init_fail5;
1706 }
1707
girish44961712006-11-22 11:47:19 -08001708 /*
Michael Speere759c332009-03-30 18:22:18 -07001709 * Enable the interrrupts for DDI.
girish44961712006-11-22 11:47:19 -08001710 */
Michael Speere759c332009-03-30 18:22:18 -07001711 nxge_intrs_enable(nxgep);
1712
girish44961712006-11-22 11:47:19 -08001713 nxgep->drv_state |= STATE_HW_INITIALIZED;
1714
1715 goto nxge_init_exit;
1716
1717nxge_init_fail5:
1718 nxge_uninit_rxdma_channels(nxgep);
1719nxge_init_fail4:
1720 nxge_uninit_txdma_channels(nxgep);
1721nxge_init_fail3:
speer678453a2008-04-27 19:50:44 -07001722 if (!isLDOMguest(nxgep)) {
1723 (void) nxge_txc_uninit(nxgep);
1724 }
girish44961712006-11-22 11:47:19 -08001725nxge_init_fail2:
1726 nxge_free_mem_pool(nxgep);
1727nxge_init_fail1:
1728 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07001729 "<== nxge_init status (failed) = 0x%08x", status));
girish44961712006-11-22 11:47:19 -08001730 return (status);
1731
1732nxge_init_exit:
girish44961712006-11-22 11:47:19 -08001733 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_init status = 0x%08x",
sowmini4045d942008-04-29 11:20:32 -07001734 status));
girish44961712006-11-22 11:47:19 -08001735 return (status);
1736}
1737
1738
1739timeout_id_t
1740nxge_start_timer(p_nxge_t nxgep, fptrv_t func, int msec)
1741{
sowmini4045d942008-04-29 11:20:32 -07001742 if ((nxgep->suspended == 0) || (nxgep->suspended == DDI_RESUME)) {
girish44961712006-11-22 11:47:19 -08001743 return (timeout(func, (caddr_t)nxgep,
sowmini4045d942008-04-29 11:20:32 -07001744 drv_usectohz(1000 * msec)));
girish44961712006-11-22 11:47:19 -08001745 }
1746 return (NULL);
1747}
1748
1749/*ARGSUSED*/
1750void
1751nxge_stop_timer(p_nxge_t nxgep, timeout_id_t timerid)
1752{
1753 if (timerid) {
1754 (void) untimeout(timerid);
1755 }
1756}
1757
1758void
1759nxge_uninit(p_nxge_t nxgep)
1760{
1761 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_uninit"));
1762
1763 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
1764 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001765 "==> nxge_uninit: not initialized"));
girish44961712006-11-22 11:47:19 -08001766 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07001767 "<== nxge_uninit"));
girish44961712006-11-22 11:47:19 -08001768 return;
1769 }
1770
Michael Speere759c332009-03-30 18:22:18 -07001771 if (!isLDOMguest(nxgep)) {
1772 /*
1773 * Reset the receive MAC side.
1774 */
1775 (void) nxge_rx_mac_disable(nxgep);
1776
1777 /*
1778 * Drain the IPP.
1779 */
1780 (void) nxge_ipp_drain(nxgep);
1781 }
1782
girish44961712006-11-22 11:47:19 -08001783 /* stop timer */
1784 if (nxgep->nxge_timerid) {
1785 nxge_stop_timer(nxgep, nxgep->nxge_timerid);
1786 nxgep->nxge_timerid = 0;
1787 }
1788
1789 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
1790 (void) nxge_intr_hw_disable(nxgep);
1791
girish44961712006-11-22 11:47:19 -08001792
1793 /* Disable and soft reset the IPP */
speer678453a2008-04-27 19:50:44 -07001794 if (!isLDOMguest(nxgep))
1795 (void) nxge_ipp_disable(nxgep);
girish44961712006-11-22 11:47:19 -08001796
speera3c5bd62007-01-30 11:29:19 -08001797 /* Free classification resources */
1798 (void) nxge_classify_uninit(nxgep);
1799
girish44961712006-11-22 11:47:19 -08001800 /*
1801 * Reset the transmit/receive DMA side.
1802 */
1803 (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
1804 (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
1805
1806 nxge_uninit_txdma_channels(nxgep);
1807 nxge_uninit_rxdma_channels(nxgep);
1808
1809 /*
1810 * Reset the transmit MAC side.
1811 */
1812 (void) nxge_tx_mac_disable(nxgep);
1813
1814 nxge_free_mem_pool(nxgep);
1815
ml296236f157ac2008-05-23 16:33:43 -07001816 /*
1817 * Start the timer if the reset flag is not set.
1818 * If this reset flag is set, the link monitor
1819 * will not be started in order to stop furthur bus
1820 * activities coming from this interface.
1821 * The driver will start the monitor function
1822 * if the interface was initialized again later.
1823 */
1824 if (!nxge_peu_reset_enable) {
1825 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
1826 }
girish44961712006-11-22 11:47:19 -08001827
1828 nxgep->drv_state &= ~STATE_HW_INITIALIZED;
1829
1830 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_uninit: "
sowmini4045d942008-04-29 11:20:32 -07001831 "nxge_mblks_pending %d", nxge_mblks_pending));
girish44961712006-11-22 11:47:19 -08001832}
1833
1834void
1835nxge_get64(p_nxge_t nxgep, p_mblk_t mp)
1836{
1837 uint64_t reg;
1838 uint64_t regdata;
1839 int i, retry;
1840
1841 bcopy((char *)mp->b_rptr, (char *)&reg, sizeof (uint64_t));
1842 regdata = 0;
1843 retry = 1;
1844
1845 for (i = 0; i < retry; i++) {
1846 NXGE_REG_RD64(nxgep->npi_handle, reg, &regdata);
1847 }
1848 bcopy((char *)&regdata, (char *)mp->b_rptr, sizeof (uint64_t));
1849}
1850
1851void
1852nxge_put64(p_nxge_t nxgep, p_mblk_t mp)
1853{
1854 uint64_t reg;
1855 uint64_t buf[2];
1856
1857 bcopy((char *)mp->b_rptr, (char *)&buf[0], 2 * sizeof (uint64_t));
1858 reg = buf[0];
1859
1860 NXGE_NPI_PIO_WRITE64(nxgep->npi_handle, reg, buf[1]);
1861}
1862
girish44961712006-11-22 11:47:19 -08001863/*ARGSUSED*/
1864/*VARARGS*/
1865void
1866nxge_debug_msg(p_nxge_t nxgep, uint64_t level, char *fmt, ...)
1867{
1868 char msg_buffer[1048];
1869 char prefix_buffer[32];
1870 int instance;
1871 uint64_t debug_level;
1872 int cmn_level = CE_CONT;
1873 va_list ap;
1874
speer678453a2008-04-27 19:50:44 -07001875 if (nxgep && nxgep->nxge_debug_level != nxge_debug_level) {
1876 /* In case a developer has changed nxge_debug_level. */
1877 if (nxgep->nxge_debug_level != nxge_debug_level)
1878 nxgep->nxge_debug_level = nxge_debug_level;
1879 }
1880
girish44961712006-11-22 11:47:19 -08001881 debug_level = (nxgep == NULL) ? nxge_debug_level :
sowmini4045d942008-04-29 11:20:32 -07001882 nxgep->nxge_debug_level;
girish44961712006-11-22 11:47:19 -08001883
1884 if ((level & debug_level) ||
sowmini4045d942008-04-29 11:20:32 -07001885 (level == NXGE_NOTE) ||
1886 (level == NXGE_ERR_CTL)) {
girish44961712006-11-22 11:47:19 -08001887 /* do the msg processing */
girish44961712006-11-22 11:47:19 -08001888 MUTEX_ENTER(&nxgedebuglock);
1889
1890 if ((level & NXGE_NOTE)) {
1891 cmn_level = CE_NOTE;
1892 }
1893
1894 if (level & NXGE_ERR_CTL) {
1895 cmn_level = CE_WARN;
1896 }
1897
1898 va_start(ap, fmt);
1899 (void) vsprintf(msg_buffer, fmt, ap);
1900 va_end(ap);
1901 if (nxgep == NULL) {
1902 instance = -1;
1903 (void) sprintf(prefix_buffer, "%s :", "nxge");
1904 } else {
1905 instance = nxgep->instance;
1906 (void) sprintf(prefix_buffer,
sowmini4045d942008-04-29 11:20:32 -07001907 "%s%d :", "nxge", instance);
girish44961712006-11-22 11:47:19 -08001908 }
1909
1910 MUTEX_EXIT(&nxgedebuglock);
1911 cmn_err(cmn_level, "!%s %s\n",
sowmini4045d942008-04-29 11:20:32 -07001912 prefix_buffer, msg_buffer);
girish44961712006-11-22 11:47:19 -08001913
1914 }
1915}
1916
1917char *
1918nxge_dump_packet(char *addr, int size)
1919{
1920 uchar_t *ap = (uchar_t *)addr;
1921 int i;
1922 static char etherbuf[1024];
1923 char *cp = etherbuf;
1924 char digits[] = "0123456789abcdef";
1925
1926 if (!size)
1927 size = 60;
1928
1929 if (size > MAX_DUMP_SZ) {
1930 /* Dump the leading bytes */
1931 for (i = 0; i < MAX_DUMP_SZ/2; i++) {
1932 if (*ap > 0x0f)
1933 *cp++ = digits[*ap >> 4];
1934 *cp++ = digits[*ap++ & 0xf];
1935 *cp++ = ':';
1936 }
1937 for (i = 0; i < 20; i++)
1938 *cp++ = '.';
1939 /* Dump the last MAX_DUMP_SZ/2 bytes */
1940 ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ/2));
1941 for (i = 0; i < MAX_DUMP_SZ/2; i++) {
1942 if (*ap > 0x0f)
1943 *cp++ = digits[*ap >> 4];
1944 *cp++ = digits[*ap++ & 0xf];
1945 *cp++ = ':';
1946 }
1947 } else {
1948 for (i = 0; i < size; i++) {
1949 if (*ap > 0x0f)
1950 *cp++ = digits[*ap >> 4];
1951 *cp++ = digits[*ap++ & 0xf];
1952 *cp++ = ':';
1953 }
1954 }
1955 *--cp = 0;
1956 return (etherbuf);
1957}
1958
1959#ifdef NXGE_DEBUG
1960static void
1961nxge_test_map_regs(p_nxge_t nxgep)
1962{
1963 ddi_acc_handle_t cfg_handle;
1964 p_pci_cfg_t cfg_ptr;
1965 ddi_acc_handle_t dev_handle;
1966 char *dev_ptr;
1967 ddi_acc_handle_t pci_config_handle;
1968 uint32_t regval;
1969 int i;
1970
1971 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_test_map_regs"));
1972
1973 dev_handle = nxgep->dev_regs->nxge_regh;
1974 dev_ptr = (char *)nxgep->dev_regs->nxge_regp;
1975
raghus2e591292007-08-31 16:49:49 -07001976 if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
girish44961712006-11-22 11:47:19 -08001977 cfg_handle = nxgep->dev_regs->nxge_pciregh;
1978 cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
1979
1980 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07001981 "Neptune PCI regp cfg_ptr 0x%llx", (char *)cfg_ptr));
girish44961712006-11-22 11:47:19 -08001982 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07001983 "Neptune PCI cfg_ptr vendor id ptr 0x%llx",
1984 &cfg_ptr->vendorid));
girish44961712006-11-22 11:47:19 -08001985 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07001986 "\tvendorid 0x%x devid 0x%x",
1987 NXGE_PIO_READ16(cfg_handle, &cfg_ptr->vendorid, 0),
1988 NXGE_PIO_READ16(cfg_handle, &cfg_ptr->devid, 0)));
girish44961712006-11-22 11:47:19 -08001989 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07001990 "PCI BAR: base 0x%x base14 0x%x base 18 0x%x "
1991 "bar1c 0x%x",
1992 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base, 0),
1993 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base14, 0),
1994 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base18, 0),
1995 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base1c, 0)));
girish44961712006-11-22 11:47:19 -08001996 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07001997 "\nNeptune PCI BAR: base20 0x%x base24 0x%x "
1998 "base 28 0x%x bar2c 0x%x\n",
1999 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base20, 0),
2000 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base24, 0),
2001 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base28, 0),
2002 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base2c, 0)));
girish44961712006-11-22 11:47:19 -08002003 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07002004 "\nNeptune PCI BAR: base30 0x%x\n",
2005 NXGE_PIO_READ32(cfg_handle, &cfg_ptr->base30, 0)));
girish44961712006-11-22 11:47:19 -08002006
2007 cfg_handle = nxgep->dev_regs->nxge_pciregh;
2008 cfg_ptr = (void *)nxgep->dev_regs->nxge_pciregp;
2009 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
davemq59ac0c12007-07-25 18:20:14 -07002010 "first 0x%llx second 0x%llx third 0x%llx "
2011 "last 0x%llx ",
2012 NXGE_PIO_READ64(dev_handle,
2013 (uint64_t *)(dev_ptr + 0), 0),
2014 NXGE_PIO_READ64(dev_handle,
2015 (uint64_t *)(dev_ptr + 8), 0),
2016 NXGE_PIO_READ64(dev_handle,
2017 (uint64_t *)(dev_ptr + 16), 0),
2018 NXGE_PIO_READ64(cfg_handle,
2019 (uint64_t *)(dev_ptr + 24), 0)));
girish44961712006-11-22 11:47:19 -08002020 }
2021}
2022
2023#endif
2024
2025static void
2026nxge_suspend(p_nxge_t nxgep)
2027{
2028 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_suspend"));
2029
2030 nxge_intrs_disable(nxgep);
2031 nxge_destroy_dev(nxgep);
2032
2033 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_suspend"));
2034}
2035
2036static nxge_status_t
2037nxge_resume(p_nxge_t nxgep)
2038{
2039 nxge_status_t status = NXGE_OK;
2040
2041 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_resume"));
girish44961712006-11-22 11:47:19 -08002042
joycey91c98b32007-07-03 15:49:58 -07002043 nxgep->suspended = DDI_RESUME;
2044 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
2045 (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_START);
2046 (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START);
2047 (void) nxge_rx_mac_enable(nxgep);
2048 (void) nxge_tx_mac_enable(nxgep);
2049 nxge_intrs_enable(nxgep);
girish44961712006-11-22 11:47:19 -08002050 nxgep->suspended = 0;
2051
2052 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07002053 "<== nxge_resume status = 0x%x", status));
girish44961712006-11-22 11:47:19 -08002054 return (status);
2055}
2056
2057static nxge_status_t
2058nxge_setup_dev(p_nxge_t nxgep)
2059{
2060 nxge_status_t status = NXGE_OK;
2061
2062 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_setup_dev port %d",
davemq59ac0c12007-07-25 18:20:14 -07002063 nxgep->mac.portnum));
girish44961712006-11-22 11:47:19 -08002064
2065 status = nxge_link_init(nxgep);
sd7746814ea4bb2006-12-22 12:42:28 -08002066
2067 if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) {
2068 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07002069 "port%d Bad register acc handle", nxgep->mac.portnum));
sd7746814ea4bb2006-12-22 12:42:28 -08002070 status = NXGE_ERROR;
2071 }
2072
girish44961712006-11-22 11:47:19 -08002073 if (status != NXGE_OK) {
2074 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07002075 " nxge_setup_dev status "
2076 "(xcvr init 0x%08x)", status));
girish44961712006-11-22 11:47:19 -08002077 goto nxge_setup_dev_exit;
2078 }
2079
2080nxge_setup_dev_exit:
2081 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07002082 "<== nxge_setup_dev port %d status = 0x%08x",
2083 nxgep->mac.portnum, status));
girish44961712006-11-22 11:47:19 -08002084
2085 return (status);
2086}
2087
2088static void
2089nxge_destroy_dev(p_nxge_t nxgep)
2090{
2091 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_destroy_dev"));
2092
2093 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP);
2094
2095 (void) nxge_hw_stop(nxgep);
2096
2097 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_destroy_dev"));
2098}
2099
2100static nxge_status_t
2101nxge_setup_system_dma_pages(p_nxge_t nxgep)
2102{
2103 int ddi_status = DDI_SUCCESS;
2104 uint_t count;
2105 ddi_dma_cookie_t cookie;
2106 uint_t iommu_pagesize;
2107 nxge_status_t status = NXGE_OK;
2108
speer678453a2008-04-27 19:50:44 -07002109 NXGE_ERROR_MSG((nxgep, DDI_CTL, "==> nxge_setup_system_dma_pages"));
girish44961712006-11-22 11:47:19 -08002110 nxgep->sys_page_sz = ddi_ptob(nxgep->dip, (ulong_t)1);
2111 if (nxgep->niu_type != N2_NIU) {
2112 iommu_pagesize = dvma_pagesize(nxgep->dip);
2113 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07002114 " nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
2115 " default_block_size %d iommu_pagesize %d",
2116 nxgep->sys_page_sz,
2117 ddi_ptob(nxgep->dip, (ulong_t)1),
2118 nxgep->rx_default_block_size,
2119 iommu_pagesize));
girish44961712006-11-22 11:47:19 -08002120
2121 if (iommu_pagesize != 0) {
2122 if (nxgep->sys_page_sz == iommu_pagesize) {
2123 if (iommu_pagesize > 0x4000)
2124 nxgep->sys_page_sz = 0x4000;
2125 } else {
2126 if (nxgep->sys_page_sz > iommu_pagesize)
2127 nxgep->sys_page_sz = iommu_pagesize;
2128 }
2129 }
2130 }
2131 nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
2132 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07002133 "==> nxge_setup_system_dma_pages: page %d (ddi_ptob %d) "
2134 "default_block_size %d page mask %d",
2135 nxgep->sys_page_sz,
2136 ddi_ptob(nxgep->dip, (ulong_t)1),
2137 nxgep->rx_default_block_size,
2138 nxgep->sys_page_mask));
girish44961712006-11-22 11:47:19 -08002139
2140
2141 switch (nxgep->sys_page_sz) {
2142 default:
2143 nxgep->sys_page_sz = 0x1000;
2144 nxgep->sys_page_mask = ~(nxgep->sys_page_sz - 1);
2145 nxgep->rx_default_block_size = 0x1000;
2146 nxgep->rx_bksize_code = RBR_BKSIZE_4K;
2147 break;
2148 case 0x1000:
2149 nxgep->rx_default_block_size = 0x1000;
2150 nxgep->rx_bksize_code = RBR_BKSIZE_4K;
2151 break;
2152 case 0x2000:
2153 nxgep->rx_default_block_size = 0x2000;
2154 nxgep->rx_bksize_code = RBR_BKSIZE_8K;
2155 break;
2156 case 0x4000:
2157 nxgep->rx_default_block_size = 0x4000;
2158 nxgep->rx_bksize_code = RBR_BKSIZE_16K;
2159 break;
2160 case 0x8000:
2161 nxgep->rx_default_block_size = 0x8000;
2162 nxgep->rx_bksize_code = RBR_BKSIZE_32K;
2163 break;
2164 }
2165
2166#ifndef USE_RX_BIG_BUF
2167 nxge_rx_dma_attr.dma_attr_align = nxgep->sys_page_sz;
2168#else
2169 nxgep->rx_default_block_size = 0x2000;
2170 nxgep->rx_bksize_code = RBR_BKSIZE_8K;
2171#endif
2172 /*
2173 * Get the system DMA burst size.
2174 */
2175 ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr,
sowmini4045d942008-04-29 11:20:32 -07002176 DDI_DMA_DONTWAIT, 0,
2177 &nxgep->dmasparehandle);
girish44961712006-11-22 11:47:19 -08002178 if (ddi_status != DDI_SUCCESS) {
2179 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07002180 "ddi_dma_alloc_handle: failed "
2181 " status 0x%x", ddi_status));
girish44961712006-11-22 11:47:19 -08002182 goto nxge_get_soft_properties_exit;
2183 }
2184
2185 ddi_status = ddi_dma_addr_bind_handle(nxgep->dmasparehandle, NULL,
sowmini4045d942008-04-29 11:20:32 -07002186 (caddr_t)nxgep->dmasparehandle,
2187 sizeof (nxgep->dmasparehandle),
2188 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2189 DDI_DMA_DONTWAIT, 0,
2190 &cookie, &count);
girish44961712006-11-22 11:47:19 -08002191 if (ddi_status != DDI_DMA_MAPPED) {
2192 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
sowmini4045d942008-04-29 11:20:32 -07002193 "Binding spare handle to find system"
2194 " burstsize failed."));
girish44961712006-11-22 11:47:19 -08002195 ddi_status = DDI_FAILURE;
2196 goto nxge_get_soft_properties_fail1;
2197 }
2198
2199 nxgep->sys_burst_sz = ddi_dma_burstsizes(nxgep->dmasparehandle);
2200 (void) ddi_dma_unbind_handle(nxgep->dmasparehandle);
2201
2202nxge_get_soft_properties_fail1:
2203 ddi_dma_free_handle(&nxgep->dmasparehandle);
2204
2205nxge_get_soft_properties_exit:
2206
2207 if (ddi_status != DDI_SUCCESS)
2208 status |= (NXGE_ERROR | NXGE_DDI_FAILED);
2209
2210 NXGE_DEBUG_MSG((nxgep, DDI_CTL,
sowmini4045d942008-04-29 11:20:32 -07002211 "<== nxge_setup_system_dma_pages status = 0x%08x", status));
girish44961712006-11-22 11:47:19 -08002212 return (status);
2213}
2214
2215static nxge_status_t
2216nxge_alloc_mem_pool(p_nxge_t nxgep)
2217{
2218 nxge_status_t status = NXGE_OK;
2219
2220 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_alloc_mem_pool"));
2221
2222 status = nxge_alloc_rx_mem_pool(nxgep);
2223 if (status != NXGE_OK) {
2224 return (NXGE_ERROR);