xref: /illumos-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-driver.c (revision 3d393ee6c37fa10ac512ed6d36109ad616dc7c1a)
1 /*
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  * Copyright (c) 2002-2006 Neterion, Inc.
22  */
23 
24 #include "xgehal-driver.h"
25 #include "xgehal-device.h"
26 
27 static xge_hal_driver_t g_driver;
28 xge_hal_driver_t *g_xge_hal_driver = NULL;
29 char *g_xge_hal_log = NULL;
30 
31 #ifdef XGE_OS_MEMORY_CHECK
32 xge_os_malloc_t g_malloc_arr[XGE_OS_MALLOC_CNT_MAX];
33 int g_malloc_cnt = 0;
34 #endif
35 
36 /*
37  * Runtime tracing support
38  */
39 static unsigned long g_module_mask_default = 0;
40 unsigned long *g_module_mask = &g_module_mask_default;
41 static int g_level_default = 0;
42 int *g_level = &g_level_default;
43 
44 #ifdef XGE_TRACE_INTO_CIRCULAR_ARR
45 static xge_os_tracebuf_t g_tracebuf;
46 char *dmesg, *dmesg_start;
47 
48 /**
49  * xge_hal_driver_tracebuf_dump - Dump the trace buffer.
50  *
51  * Dump the trace buffer contents.
52  */
53 void
54 xge_hal_driver_tracebuf_dump(void)
55 {
56 	int i;
57 	int off = 0;
58 
59 	if (g_xge_os_tracebuf == NULL) {
60 		return;
61 	}
62 
63 	xge_os_printf("################ Trace dump Begin ###############");
64 	if (g_xge_os_tracebuf->wrapped_once) {
65 		for (i = 0; i < g_xge_os_tracebuf->size -
66 				g_xge_os_tracebuf->offset; i += off) {
67 			if (*(dmesg_start + i))
68 				xge_os_printf(dmesg_start + i);
69 			off = xge_os_strlen(dmesg_start + i) + 1;
70 		}
71 	}
72 	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
73 		if (*(dmesg + i))
74 			xge_os_printf(dmesg + i);
75 		off = xge_os_strlen(dmesg + i) + 1;
76 	}
77 	xge_os_printf("################ Trace dump End ###############");
78 }
79 
80 xge_hal_status_e
81 xge_hal_driver_tracebuf_read(int bufsize, char *retbuf, int *retsize)
82 {
83 	int i;
84 	int off = 0, retbuf_off = 0;
85 
86 	*retsize = 0;
87 	*retbuf = 0;
88 
89 	if (g_xge_os_tracebuf == NULL) {
90 		return XGE_HAL_FAIL;
91 	}
92 
93 	if (g_xge_os_tracebuf->wrapped_once) {
94 		for (i = 0; i < g_xge_os_tracebuf->size -
95 				g_xge_os_tracebuf->offset; i += off) {
96 			if (*(dmesg_start + i)) {
97 				xge_os_snprintf((retbuf + retbuf_off), (bufsize - retbuf_off),
98 				    "%s\n", dmesg_start + i);
99 				retbuf_off += xge_os_strlen(dmesg_start + i) + 1;
100 				if (retbuf_off > bufsize)
101 					return XGE_HAL_ERR_OUT_OF_MEMORY;
102 			}
103 			off = xge_os_strlen(dmesg_start + i) + 1;
104 		}
105 	}
106 	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
107 		if (*(dmesg + i)) {
108 			xge_os_snprintf((retbuf + retbuf_off), (bufsize - retbuf_off),
109 			    "%s\n", dmesg + i);
110 			retbuf_off += xge_os_strlen(dmesg + i) + 1;
111 			if (retbuf_off > bufsize)
112 				return XGE_HAL_ERR_OUT_OF_MEMORY;
113 		}
114 		off = xge_os_strlen(dmesg + i) + 1;
115 	}
116 
117 	*retsize = retbuf_off;
118 	*(retbuf + retbuf_off + 1) = 0;
119 
120 	return XGE_HAL_OK;
121 }
122 #endif
123 xge_os_tracebuf_t *g_xge_os_tracebuf = NULL;
124 
125 #ifdef XGE_HAL_DEBUG_BAR0_OFFSET
126 void
127 xge_hal_driver_bar0_offset_check(void)
128 {
129 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, adapter_status) ==
130 		   0x108);
131 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_traffic_int) ==
132 		   0x08E0);
133 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, dtx_control) ==
134 		   0x09E8);
135 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_fifo_partition_0) ==
136 		   0x1108);
137 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_enable) ==
138 		   0x1170);
139 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, prc_rxd0_n[0]) ==
140 		   0x1930);
141 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rti_command_mem) ==
142 		   0x19B8);
143 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_cfg) ==
144 		   0x2100);
145 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rmac_addr_cmd_mem) ==
146 		   0x2128);
147 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_link_util) ==
148 		   0x2170);
149 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_pause_thresh_q0q3) ==
150 		   0x2918);
151 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_err_reg) ==
152 		   0x1040);
153 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rxdma_int_status) ==
154 		   0x1800);
155 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_tmac_err_reg) ==
156 		   0x2010);
157 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_err_reg) ==
158 		   0x2810);
159 	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, xgxs_int_status) ==
160 		   0x3000);
161 }
162 #endif
163 
164 /**
165  * xge_hal_driver_initialize - Initialize HAL.
166  * @config: HAL configuration, see xge_hal_driver_config_t{}.
167  * @uld_callbacks: Upper-layer driver callbacks, e.g. link-up.
168  *
169  * HAL initialization entry point. Not to confuse with device initialization
170  * (note that HAL "contains" zero or more Xframe devices).
171  *
172  * Returns: XGE_HAL_OK - success;
173  * XGE_HAL_ERR_BAD_DRIVER_CONFIG - Driver configuration params invalid.
174  *
175  * See also: xge_hal_device_initialize(), xge_hal_status_e{},
176  * xge_hal_uld_cbs_t{}.
177  */
178 xge_hal_status_e
179 xge_hal_driver_initialize(xge_hal_driver_config_t *config,
180 			xge_hal_uld_cbs_t *uld_callbacks)
181 {
182 	xge_hal_status_e status;
183 
184 	g_xge_hal_driver = &g_driver;
185 
186 	xge_hal_driver_debug_module_mask_set(XGE_DEBUG_MODULE_MASK_DEF);
187 	xge_hal_driver_debug_level_set(XGE_DEBUG_LEVEL_DEF);
188 
189 #ifdef XGE_HAL_DEBUG_BAR0_OFFSET
190 	xge_hal_driver_bar0_offset_check();
191 #endif
192 
193 #ifdef XGE_TRACE_INTO_CIRCULAR_ARR
194 	if (config->tracebuf_size == 0)
195 		/*
196 		 * Trace buffer implementation is not lock protected.
197 		 * The only harm to expect is memcpy() to go beyond of
198 		 * allowed boundaries. To make it safe (driver-wise),
199 		 * we pre-allocate needed number of extra bytes.
200 		 */
201 		config->tracebuf_size = XGE_HAL_DEF_CIRCULAR_ARR +
202 					XGE_OS_TRACE_MSGBUF_MAX;
203 #endif
204 
205 	status = __hal_driver_config_check(config);
206 	if (status != XGE_HAL_OK)
207 		return status;
208 
209 	xge_os_memzero(g_xge_hal_driver,  sizeof(xge_hal_driver_t));
210 
211 	/* apply config */
212 	xge_os_memcpy(&g_xge_hal_driver->config, config,
213 				sizeof(xge_hal_driver_config_t));
214 
215 	/* apply ULD callbacks */
216 	xge_os_memcpy(&g_xge_hal_driver->uld_callbacks, uld_callbacks,
217 					sizeof(xge_hal_uld_cbs_t));
218 
219 	g_xge_hal_driver->is_initialized = 1;
220 
221 #ifdef XGE_TRACE_INTO_CIRCULAR_ARR
222 	g_tracebuf.size = config->tracebuf_size;
223 	g_tracebuf.data = (char *)xge_os_malloc(NULL, g_tracebuf.size);
224 	if (g_tracebuf.data == NULL) {
225 		xge_os_printf("cannot allocate trace buffer!");
226 		return XGE_HAL_ERR_OUT_OF_MEMORY;
227 	}
228 	/* timestamps disabled by default */
229 	g_tracebuf.timestamp = config->tracebuf_timestamp_en;
230 	if (g_tracebuf.timestamp) {
231 		xge_os_timestamp(g_tracebuf.msg);
232 		g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX -
233 					xge_os_strlen(g_tracebuf.msg);
234 	} else
235 		g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX;
236 	g_tracebuf.offset = 0;
237 	*g_tracebuf.msg = 0;
238 	xge_os_memzero(g_tracebuf.data, g_tracebuf.size);
239 	g_xge_os_tracebuf = &g_tracebuf;
240 	dmesg = g_tracebuf.data;
241 	*dmesg = 0;
242 #endif
243 	return XGE_HAL_OK;
244 }
245 
246 /**
247  * xge_hal_driver_terminate - Terminate HAL.
248  *
249  * HAL termination entry point.
250  *
251  * See also: xge_hal_device_terminate().
252  */
253 void
254 xge_hal_driver_terminate(void)
255 {
256 	g_xge_hal_driver->is_initialized = 0;
257 
258 #ifdef XGE_TRACE_INTO_CIRCULAR_ARR
259 	if (g_tracebuf.size) {
260 		xge_os_free(NULL, g_tracebuf.data, g_tracebuf.size);
261 	}
262 #endif
263 
264 	g_xge_hal_driver = NULL;
265 
266 #ifdef XGE_OS_MEMORY_CHECK
267 	{
268 		int i, leaks=0;
269 		xge_os_printf("OSPAL: max g_malloc_cnt %d", g_malloc_cnt);
270 		for (i=0; i<g_malloc_cnt; i++) {
271 			if (g_malloc_arr[i].ptr != NULL) {
272 				xge_os_printf("OSPAL: memory leak detected at "
273 					"%s:%d:"XGE_OS_LLXFMT":%d",
274 					g_malloc_arr[i].file,
275 					g_malloc_arr[i].line,
276 					(unsigned long long)(ulong_t)
277 						g_malloc_arr[i].ptr,
278 					g_malloc_arr[i].size);
279 				leaks++;
280 			}
281 		}
282 		if (leaks) {
283 			xge_os_printf("OSPAL: %d memory leaks detected", leaks);
284 		} else {
285 			xge_os_printf("OSPAL: no memory leaks detected");
286 		}
287 	}
288 #endif
289 }
290