xref: /onnv-gate/usr/src/uts/i86pc/io/acpi/acpidev/acpidev_memory.c (revision 12004:93f274d4a367)
110394SMichael.Corcoran@Sun.COM /*
210394SMichael.Corcoran@Sun.COM  * CDDL HEADER START
310394SMichael.Corcoran@Sun.COM  *
410394SMichael.Corcoran@Sun.COM  * The contents of this file are subject to the terms of the
510394SMichael.Corcoran@Sun.COM  * Common Development and Distribution License (the "License").
610394SMichael.Corcoran@Sun.COM  * You may not use this file except in compliance with the License.
710394SMichael.Corcoran@Sun.COM  *
810394SMichael.Corcoran@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910394SMichael.Corcoran@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010394SMichael.Corcoran@Sun.COM  * See the License for the specific language governing permissions
1110394SMichael.Corcoran@Sun.COM  * and limitations under the License.
1210394SMichael.Corcoran@Sun.COM  *
1310394SMichael.Corcoran@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410394SMichael.Corcoran@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510394SMichael.Corcoran@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610394SMichael.Corcoran@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710394SMichael.Corcoran@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810394SMichael.Corcoran@Sun.COM  *
1910394SMichael.Corcoran@Sun.COM  * CDDL HEADER END
2010394SMichael.Corcoran@Sun.COM  */
2110394SMichael.Corcoran@Sun.COM /*
22*12004Sjiang.liu@intel.com  * Copyright (c) 2009-2010, Intel Corporation.
2310394SMichael.Corcoran@Sun.COM  * All rights reserved.
2410394SMichael.Corcoran@Sun.COM  */
2510394SMichael.Corcoran@Sun.COM 
2610394SMichael.Corcoran@Sun.COM #include <sys/types.h>
2710394SMichael.Corcoran@Sun.COM #include <sys/atomic.h>
2810394SMichael.Corcoran@Sun.COM #include <sys/sunddi.h>
2910394SMichael.Corcoran@Sun.COM #include <sys/sunndi.h>
3010394SMichael.Corcoran@Sun.COM #include <sys/acpi/acpi.h>
3110394SMichael.Corcoran@Sun.COM #include <sys/acpica.h>
3210394SMichael.Corcoran@Sun.COM #include <sys/acpidev.h>
3310394SMichael.Corcoran@Sun.COM #include <sys/acpidev_rsc.h>
34*12004Sjiang.liu@intel.com #include <sys/acpidev_dr.h>
3510394SMichael.Corcoran@Sun.COM #include <sys/acpidev_impl.h>
3610394SMichael.Corcoran@Sun.COM 
3710394SMichael.Corcoran@Sun.COM static ACPI_STATUS acpidev_memory_probe(acpidev_walk_info_t *infop);
3810394SMichael.Corcoran@Sun.COM static acpidev_filter_result_t acpidev_memory_filter(
3910394SMichael.Corcoran@Sun.COM     acpidev_walk_info_t *infop, char *devname, int maxlen);
4010394SMichael.Corcoran@Sun.COM static ACPI_STATUS acpidev_memory_init(acpidev_walk_info_t *infop);
4110394SMichael.Corcoran@Sun.COM 
4210394SMichael.Corcoran@Sun.COM /*
4310394SMichael.Corcoran@Sun.COM  * Default class driver for ACPI memory objects.
4410394SMichael.Corcoran@Sun.COM  */
4510394SMichael.Corcoran@Sun.COM acpidev_class_t acpidev_class_memory = {
4610394SMichael.Corcoran@Sun.COM 	0,				/* adc_refcnt */
4710394SMichael.Corcoran@Sun.COM 	ACPIDEV_CLASS_REV1,		/* adc_version */
4810394SMichael.Corcoran@Sun.COM 	ACPIDEV_CLASS_ID_MEMORY,	/* adc_class_id */
4910394SMichael.Corcoran@Sun.COM 	"ACPI memory",			/* adc_class_name */
5010394SMichael.Corcoran@Sun.COM 	ACPIDEV_TYPE_MEMORY,		/* adc_dev_type */
5110394SMichael.Corcoran@Sun.COM 	NULL,				/* adc_private */
5210394SMichael.Corcoran@Sun.COM 	NULL,				/* adc_pre_probe */
5310394SMichael.Corcoran@Sun.COM 	NULL,				/* adc_post_probe */
5410394SMichael.Corcoran@Sun.COM 	acpidev_memory_probe,		/* adc_probe */
5510394SMichael.Corcoran@Sun.COM 	acpidev_memory_filter,		/* adc_filter */
5610394SMichael.Corcoran@Sun.COM 	acpidev_memory_init,		/* adc_init */
5710394SMichael.Corcoran@Sun.COM 	NULL,				/* adc_fini */
5810394SMichael.Corcoran@Sun.COM };
5910394SMichael.Corcoran@Sun.COM 
6010394SMichael.Corcoran@Sun.COM /*
6110394SMichael.Corcoran@Sun.COM  * List of class drivers which will be called in order when handling
6210394SMichael.Corcoran@Sun.COM  * children of ACPI memory objects.
6310394SMichael.Corcoran@Sun.COM  */
6410394SMichael.Corcoran@Sun.COM acpidev_class_list_t *acpidev_class_list_memory = NULL;
6510394SMichael.Corcoran@Sun.COM 
6610394SMichael.Corcoran@Sun.COM static char *acpidev_memory_device_ids[] = {
6710394SMichael.Corcoran@Sun.COM 	ACPIDEV_HID_MEMORY,
6810394SMichael.Corcoran@Sun.COM };
6910394SMichael.Corcoran@Sun.COM 
7010394SMichael.Corcoran@Sun.COM static char *acpidev_memory_uid_formats[] = {
7110394SMichael.Corcoran@Sun.COM 	"MEM%x-%x",
7210394SMichael.Corcoran@Sun.COM };
7310394SMichael.Corcoran@Sun.COM 
7410394SMichael.Corcoran@Sun.COM /* Filter rule table for memory objects. */
7510394SMichael.Corcoran@Sun.COM static acpidev_filter_rule_t acpidev_memory_filters[] = {
7610394SMichael.Corcoran@Sun.COM 	{	/* Ignore all memory objects under the ACPI root object */
7710394SMichael.Corcoran@Sun.COM 		NULL,
7810394SMichael.Corcoran@Sun.COM 		0,
7910394SMichael.Corcoran@Sun.COM 		ACPIDEV_FILTER_SKIP,
8010394SMichael.Corcoran@Sun.COM 		NULL,
8110394SMichael.Corcoran@Sun.COM 		1,
8210394SMichael.Corcoran@Sun.COM 		1,
8310394SMichael.Corcoran@Sun.COM 		NULL,
8410394SMichael.Corcoran@Sun.COM 		NULL,
8510394SMichael.Corcoran@Sun.COM 	},
8610394SMichael.Corcoran@Sun.COM 	{	/* Create node and scan child for all other memory objects */
8710394SMichael.Corcoran@Sun.COM 		NULL,
8810394SMichael.Corcoran@Sun.COM 		0,
8910394SMichael.Corcoran@Sun.COM 		ACPIDEV_FILTER_DEFAULT,
9010394SMichael.Corcoran@Sun.COM 		&acpidev_class_list_device,
9110394SMichael.Corcoran@Sun.COM 		2,
9210394SMichael.Corcoran@Sun.COM 		INT_MAX,
9310394SMichael.Corcoran@Sun.COM 		NULL,
9410394SMichael.Corcoran@Sun.COM 		ACPIDEV_NODE_NAME_MEMORY,
9510394SMichael.Corcoran@Sun.COM 	}
9610394SMichael.Corcoran@Sun.COM };
9710394SMichael.Corcoran@Sun.COM 
9810394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_memory_probe(acpidev_walk_info_t * infop)9910394SMichael.Corcoran@Sun.COM acpidev_memory_probe(acpidev_walk_info_t *infop)
10010394SMichael.Corcoran@Sun.COM {
101*12004Sjiang.liu@intel.com 	ACPI_STATUS rc = AE_OK;
10210394SMichael.Corcoran@Sun.COM 	int flags;
10310394SMichael.Corcoran@Sun.COM 
10410394SMichael.Corcoran@Sun.COM 	ASSERT(infop != NULL);
10510394SMichael.Corcoran@Sun.COM 	ASSERT(infop->awi_hdl != NULL);
10610394SMichael.Corcoran@Sun.COM 	ASSERT(infop->awi_info != NULL);
10710394SMichael.Corcoran@Sun.COM 	if (infop->awi_info->Type != ACPI_TYPE_DEVICE ||
10810394SMichael.Corcoran@Sun.COM 	    acpidev_match_device_id(infop->awi_info,
10910394SMichael.Corcoran@Sun.COM 	    ACPIDEV_ARRAY_PARAM(acpidev_memory_device_ids)) == 0) {
11010394SMichael.Corcoran@Sun.COM 		return (AE_OK);
11110394SMichael.Corcoran@Sun.COM 	}
11210394SMichael.Corcoran@Sun.COM 
113*12004Sjiang.liu@intel.com 	flags = ACPIDEV_PROCESS_FLAG_SCAN;
114*12004Sjiang.liu@intel.com 	switch (infop->awi_op_type) {
115*12004Sjiang.liu@intel.com 	case ACPIDEV_OP_BOOT_PROBE:
116*12004Sjiang.liu@intel.com 		if (acpica_get_devcfg_feature(ACPI_DEVCFG_MEMORY)) {
117*12004Sjiang.liu@intel.com 			flags |= ACPIDEV_PROCESS_FLAG_CREATE;
118*12004Sjiang.liu@intel.com 			acpidev_dr_check(infop);
119*12004Sjiang.liu@intel.com 		}
120*12004Sjiang.liu@intel.com 		break;
121*12004Sjiang.liu@intel.com 
122*12004Sjiang.liu@intel.com 	case ACPIDEV_OP_BOOT_REPROBE:
123*12004Sjiang.liu@intel.com 		break;
124*12004Sjiang.liu@intel.com 
125*12004Sjiang.liu@intel.com 	case ACPIDEV_OP_HOTPLUG_PROBE:
126*12004Sjiang.liu@intel.com 		if (acpica_get_devcfg_feature(ACPI_DEVCFG_MEMORY)) {
127*12004Sjiang.liu@intel.com 			flags |= ACPIDEV_PROCESS_FLAG_CREATE |
128*12004Sjiang.liu@intel.com 			    ACPIDEV_PROCESS_FLAG_SYNCSTATUS |
129*12004Sjiang.liu@intel.com 			    ACPIDEV_PROCESS_FLAG_HOLDBRANCH;
130*12004Sjiang.liu@intel.com 		}
131*12004Sjiang.liu@intel.com 		break;
132*12004Sjiang.liu@intel.com 
133*12004Sjiang.liu@intel.com 	default:
134*12004Sjiang.liu@intel.com 		ACPIDEV_DEBUG(CE_WARN, "!acpidev: unknown operation type %u "
13510394SMichael.Corcoran@Sun.COM 		    "in acpidev_memory_probe.", infop->awi_op_type);
13610394SMichael.Corcoran@Sun.COM 		rc = AE_BAD_PARAMETER;
137*12004Sjiang.liu@intel.com 		break;
138*12004Sjiang.liu@intel.com 	}
139*12004Sjiang.liu@intel.com 
140*12004Sjiang.liu@intel.com 	if (rc == AE_OK) {
141*12004Sjiang.liu@intel.com 		rc = acpidev_process_object(infop, flags);
14210394SMichael.Corcoran@Sun.COM 	}
14310394SMichael.Corcoran@Sun.COM 	if (ACPI_FAILURE(rc) && rc != AE_NOT_EXIST && rc != AE_ALREADY_EXISTS) {
14410394SMichael.Corcoran@Sun.COM 		cmn_err(CE_WARN,
14510394SMichael.Corcoran@Sun.COM 		    "!acpidev: failed to process memory object %s.",
14610394SMichael.Corcoran@Sun.COM 		    infop->awi_name);
14710394SMichael.Corcoran@Sun.COM 	} else {
14810394SMichael.Corcoran@Sun.COM 		rc = AE_OK;
14910394SMichael.Corcoran@Sun.COM 	}
15010394SMichael.Corcoran@Sun.COM 
15110394SMichael.Corcoran@Sun.COM 	return (rc);
15210394SMichael.Corcoran@Sun.COM }
15310394SMichael.Corcoran@Sun.COM 
15410394SMichael.Corcoran@Sun.COM static acpidev_filter_result_t
acpidev_memory_filter(acpidev_walk_info_t * infop,char * devname,int maxlen)15510394SMichael.Corcoran@Sun.COM acpidev_memory_filter(acpidev_walk_info_t *infop, char *devname, int maxlen)
15610394SMichael.Corcoran@Sun.COM {
15710394SMichael.Corcoran@Sun.COM 	acpidev_filter_result_t res;
15810394SMichael.Corcoran@Sun.COM 
15910394SMichael.Corcoran@Sun.COM 	ASSERT(infop != NULL);
16010394SMichael.Corcoran@Sun.COM 	if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
16110394SMichael.Corcoran@Sun.COM 	    infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE ||
16210394SMichael.Corcoran@Sun.COM 	    infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
16310394SMichael.Corcoran@Sun.COM 		res = acpidev_filter_device(infop, infop->awi_hdl,
16410394SMichael.Corcoran@Sun.COM 		    ACPIDEV_ARRAY_PARAM(acpidev_memory_filters),
16510394SMichael.Corcoran@Sun.COM 		    devname, maxlen);
16610394SMichael.Corcoran@Sun.COM 	} else {
16710394SMichael.Corcoran@Sun.COM 		res = ACPIDEV_FILTER_FAILED;
16810394SMichael.Corcoran@Sun.COM 	}
16910394SMichael.Corcoran@Sun.COM 
17010394SMichael.Corcoran@Sun.COM 	return (res);
17110394SMichael.Corcoran@Sun.COM }
17210394SMichael.Corcoran@Sun.COM 
17310394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_memory_init(acpidev_walk_info_t * infop)17410394SMichael.Corcoran@Sun.COM acpidev_memory_init(acpidev_walk_info_t *infop)
17510394SMichael.Corcoran@Sun.COM {
17610394SMichael.Corcoran@Sun.COM 	char *compatible[] = {
17710394SMichael.Corcoran@Sun.COM 		ACPIDEV_TYPE_MEMORY,
17810394SMichael.Corcoran@Sun.COM 		"mem"
17910394SMichael.Corcoran@Sun.COM 	};
18010394SMichael.Corcoran@Sun.COM 
18110394SMichael.Corcoran@Sun.COM 	ASSERT(infop != NULL);
18210394SMichael.Corcoran@Sun.COM 	ASSERT(infop->awi_hdl != NULL);
18310394SMichael.Corcoran@Sun.COM 	ASSERT(infop->awi_dip != NULL);
18410394SMichael.Corcoran@Sun.COM 	if (ACPI_FAILURE(acpidev_resource_process(infop, B_TRUE))) {
18510394SMichael.Corcoran@Sun.COM 		cmn_err(CE_WARN, "!acpidev: failed to process resources of "
18610394SMichael.Corcoran@Sun.COM 		    "memory device %s.", infop->awi_name);
18710394SMichael.Corcoran@Sun.COM 		return (AE_ERROR);
18810394SMichael.Corcoran@Sun.COM 	}
18910394SMichael.Corcoran@Sun.COM 
19010394SMichael.Corcoran@Sun.COM 	if (ACPI_FAILURE(acpidev_set_compatible(infop,
19110394SMichael.Corcoran@Sun.COM 	    ACPIDEV_ARRAY_PARAM(compatible)))) {
19210394SMichael.Corcoran@Sun.COM 		return (AE_ERROR);
19310394SMichael.Corcoran@Sun.COM 	}
19410394SMichael.Corcoran@Sun.COM 
19510394SMichael.Corcoran@Sun.COM 	if (ACPI_FAILURE(acpidev_set_unitaddr(infop,
19610394SMichael.Corcoran@Sun.COM 	    ACPIDEV_ARRAY_PARAM(acpidev_memory_uid_formats), NULL))) {
19710394SMichael.Corcoran@Sun.COM 		return (AE_ERROR);
19810394SMichael.Corcoran@Sun.COM 	}
19910394SMichael.Corcoran@Sun.COM 
20010394SMichael.Corcoran@Sun.COM 	return (AE_OK);
20110394SMichael.Corcoran@Sun.COM }
202