chicago.c revision 124:fbe238b68a52
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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/sysmacros.h>
32#include <sys/sunddi.h>
33#include <sys/esunddi.h>
34#include <sys/platform_module.h>
35#include <sys/errno.h>
36#include <sys/lgrp.h>
37#include <sys/memnode.h>
38#include <sys/promif.h>
39
40#define	SHARED_MI2CV_PATH "/i2c@1f,520000"
41static dev_info_t *shared_mi2cv_dip;
42static kmutex_t chicago_mi2cv_mutex;
43
44int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
45
46void
47startup_platform(void)
48{
49	mutex_init(&chicago_mi2cv_mutex, NULL, NULL, NULL);
50}
51
52int
53set_platform_tsb_spares()
54{
55	return (0);
56}
57
58void
59set_platform_defaults(void)
60{
61	extern char *tod_module_name;
62	/* Set appropriate tod module for Chicago */
63	if (tod_module_name == NULL)
64		tod_module_name = "todds1337";
65}
66
67/*
68 * Definitions for accessing the pci config space of the isa node
69 * of Southbridge.
70 */
71static ddi_acc_handle_t isa_handle = NULL;	/* handle for isa pci space */
72
73
74void
75load_platform_drivers(void)
76{
77	/*
78	 * Install power driver which handles the power button.
79	 */
80	if (i_ddi_attach_hw_nodes("power") != DDI_SUCCESS)
81		cmn_err(CE_WARN, "Failed to install \"power\" driver.");
82	(void) ddi_hold_driver(ddi_name_to_major("power"));
83
84	/*
85	 * It is OK to return error because 'us' driver is not available
86	 * in all clusters (e.g. missing in Core cluster).
87	 */
88	(void) i_ddi_attach_hw_nodes("us");
89
90	if (i_ddi_attach_hw_nodes("grbeep") != DDI_SUCCESS)
91		cmn_err(CE_WARN, "Failed to install \"beep\" driver.");
92
93
94	/*
95	 * mc-us3i must stay loaded for plat_get_mem_unum()
96	 */
97	if (i_ddi_attach_hw_nodes("mc-us3i") != DDI_SUCCESS)
98		cmn_err(CE_WARN, "mc-us3i driver failed to install");
99	(void) ddi_hold_driver(ddi_name_to_major("mc-us3i"));
100
101	/*
102	 * Figure out which mi2cv dip is shared with OBP for the nvram
103	 * device, so the lock can be acquired.
104	 */
105	shared_mi2cv_dip = e_ddi_hold_devi_by_path(SHARED_MI2CV_PATH, 0);
106
107	/*
108	 * todds1337 needs early attach
109	 */
110	if (i_ddi_attach_hw_nodes("todds1337") != DDI_SUCCESS)
111		cmn_err(CE_WARN, "todds1337 driver failed to install");
112}
113
114/*ARGSUSED*/
115int
116plat_cpu_poweron(struct cpu *cp)
117{
118	return (ENOTSUP);	/* not supported on this platform */
119}
120
121/*ARGSUSED*/
122int
123plat_cpu_poweroff(struct cpu *cp)
124{
125	return (ENOTSUP);	/* not supported on this platform */
126}
127
128/*ARGSUSED*/
129void
130plat_freelist_process(int mnode)
131{
132}
133
134char *platform_module_list[] = {
135	"mi2cv",
136	"jbusppm",
137	"pca9556",
138	"ppm",
139	(char *)0
140};
141
142/*ARGSUSED*/
143void
144plat_tod_fault(enum tod_fault_type tod_bad)
145{
146}
147
148/*ARGSUSED*/
149int
150plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
151    int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
152{
153	if (flt_in_memory && (p2get_mem_unum != NULL))
154		return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
155		    buf, buflen, lenp));
156	else
157		return (ENOTSUP);
158}
159
160/*ARGSUSED*/
161int
162plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
163{
164	if (snprintf(buf, buflen, "MB") >= buflen) {
165		return (ENOSPC);
166	} else {
167		*lenp = strlen(buf);
168		return (0);
169	}
170}
171
172/*
173 * Fiesta support for lgroups.
174 *
175 * On fiesta platform, an lgroup platform handle == CPU id
176 */
177
178/*
179 * Macro for extracting the CPU number from the CPU id
180 */
181#define	CPUID_TO_LGRP(id)	((id) & 0x7)
182#define	CHICAGO_MC_SHIFT	36
183
184/*
185 * Return the platform handle for the lgroup containing the given CPU
186 */
187void *
188plat_lgrp_cpu_to_hand(processorid_t id)
189{
190	return ((void *) CPUID_TO_LGRP(id));
191}
192
193/*
194 * Platform specific lgroup initialization
195 */
196void
197plat_lgrp_init(void)
198{
199	dnode_t		curnode;
200	char		tmp_name[MAXSYSNAME];
201	int		portid;
202	int		cpucnt = 0;
203	int		max_portid = -1;
204	extern uint32_t lgrp_expand_proc_thresh;
205	extern uint32_t lgrp_expand_proc_diff;
206	extern pgcnt_t	lgrp_mem_free_thresh;
207	extern uint32_t lgrp_loadavg_tolerance;
208	extern uint32_t lgrp_loadavg_max_effect;
209	extern uint32_t lgrp_load_thresh;
210	extern lgrp_mem_policy_t  lgrp_mem_policy_root;
211
212	/*
213	 * Count the number of CPUs installed to determine if
214	 * NUMA optimization should be enabled or not.
215	 *
216	 * All CPU nodes reside in the root node and have a
217	 * device type "cpu".
218	 */
219	curnode = prom_rootnode();
220	for (curnode = prom_childnode(curnode); curnode;
221	    curnode = prom_nextnode(curnode)) {
222		bzero(tmp_name, MAXSYSNAME);
223		if (prom_getproplen(curnode, OBP_NAME) < MAXSYSNAME) {
224			if (prom_getprop(curnode, OBP_NAME,
225			    (caddr_t)tmp_name) == -1 || prom_getprop(curnode,
226			    OBP_DEVICETYPE, tmp_name) == -1 || strcmp(tmp_name,
227			    "cpu") != 0)
228			continue;
229
230			cpucnt++;
231			if (prom_getprop(curnode, "portid", (caddr_t)&portid) !=
232			    -1 && portid > max_portid)
233				max_portid = portid;
234		}
235	}
236	if (cpucnt <= 1)
237		max_mem_nodes = 1;
238	else if (max_portid >= 0 && max_portid < MAX_MEM_NODES)
239		max_mem_nodes = max_portid + 1;
240
241	/*
242	 * Set tuneables for fiesta architecture
243	 *
244	 * lgrp_expand_proc_thresh is the minimum load on the lgroups
245	 * this process is currently running on before considering
246	 * expanding threads to another lgroup.
247	 *
248	 * lgrp_expand_proc_diff determines how much less the remote lgroup
249	 * must be loaded before expanding to it.
250	 *
251	 * Optimize for memory bandwidth by spreading multi-threaded
252	 * program to different lgroups.
253	 */
254	lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1;
255	lgrp_expand_proc_diff = lgrp_loadavg_max_effect / 2;
256	lgrp_loadavg_tolerance = lgrp_loadavg_max_effect / 2;
257	lgrp_mem_free_thresh = 1;	/* home lgrp must have some memory */
258	lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1;
259	lgrp_mem_policy_root = LGRP_MEM_POLICY_NEXT;
260	lgrp_load_thresh = 0;
261
262	mem_node_pfn_shift = CHICAGO_MC_SHIFT - MMU_PAGESHIFT;
263}
264
265/*
266 * Return latency between "from" and "to" lgroups
267 *
268 * This latency number can only be used for relative comparison
269 * between lgroups on the running system, cannot be used across platforms,
270 * and may not reflect the actual latency.  It is platform and implementation
271 * specific, so platform gets to decide its value.  It would be nice if the
272 * number was at least proportional to make comparisons more meaningful though.
273 * NOTE: The numbers below are supposed to be load latencies for uncached
274 * memory divided by 10.
275 */
276int
277plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to)
278{
279	/*
280	 * Return remote latency when there are more than two lgroups
281	 * (root and child) and getting latency between two different
282	 * lgroups or root is involved
283	 */
284	if (lgrp_optimizations() && (from != to ||
285	    from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE))
286		return (17);
287	else
288		return (12);
289}
290
291int
292plat_pfn_to_mem_node(pfn_t pfn)
293{
294	ASSERT(max_mem_nodes > 1);
295	return (pfn >> mem_node_pfn_shift);
296}
297
298/*
299 * Assign memnode to lgroups
300 */
301void
302plat_fill_mc(dnode_t nodeid)
303{
304	int		portid;
305
306	/*
307	 * Chicago memory controller portid == global CPU id
308	 */
309	if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) == -1) ||
310	    (portid < 0))
311		return;
312
313	if (portid < max_mem_nodes)
314		plat_assign_lgrphand_to_mem_node((lgrp_handle_t)portid, portid);
315}
316
317/* ARGSUSED */
318void
319plat_build_mem_nodes(u_longlong_t *list, size_t nelems)
320{
321	size_t	elem;
322	pfn_t	basepfn;
323	pgcnt_t	npgs;
324
325	/*
326	 * Boot install lists are arranged <addr, len>, <addr, len>, ...
327	 */
328	for (elem = 0; elem < nelems; elem += 2) {
329		basepfn = btop(list[elem]);
330		npgs = btop(list[elem+1]);
331		mem_node_add_slice(basepfn, basepfn + npgs - 1);
332	}
333}
334
335/*
336 * Common locking enter code
337 */
338void
339plat_setprop_enter(void)
340{
341	mutex_enter(&chicago_mi2cv_mutex);
342}
343
344/*
345 * Common locking exit code
346 */
347void
348plat_setprop_exit(void)
349{
350	mutex_exit(&chicago_mi2cv_mutex);
351}
352
353/*
354 * Called by mi2cv driver
355 */
356void
357plat_shared_i2c_enter(dev_info_t *i2cnexus_dip)
358{
359	if (i2cnexus_dip == shared_mi2cv_dip) {
360		plat_setprop_enter();
361	}
362}
363
364/*
365 * Called by mi2cv driver
366 */
367void
368plat_shared_i2c_exit(dev_info_t *i2cnexus_dip)
369{
370	if (i2cnexus_dip == shared_mi2cv_dip) {
371		plat_setprop_exit();
372	}
373}
374