diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 17:45:52 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 17:45:52 -0500 |
commit | fbb9c10d40f88011ac72f855c97e3bdd981026a9 (patch) | |
tree | 255b3c21fd859004310bfad0a829ea4392d4851b | |
parent | 3e7cc142c1e040fd4629ad34a54b1c5b46dc3dd3 (diff) | |
parent | 7ede9f8a1805b26b3141730c9deaea8bc95a64bc (diff) |
Merge branch 'acpi-dsm'
* acpi-dsm:
ACPI / extlog: replace open-coded _DSM code with helper functions
ACPI / nouveau: replace open-coded _DSM code with helper functions
nouveau / ACPI: fix memory leak in ACPI _DSM related code
ACPI / i915: replace open-coded _DSM code with helper functions
ACPI / i2c-hid: replace open-coded _DSM code with helper functions
ACPI / TPM: detect PPI features by checking availability of _DSM functions
ACPI / TPM: replace open-coded _DSM code with helper functions
ACPI / TPM: match node name instead of full path when searching for TPM device
PCI / pci-label: treat PCI label with index 0 as valid label
ACPI / PCI: replace open-coded _DSM code with helper functions
PCI / pci-label: release allocated ACPI object on error recovery path
ACPI: introduce helper interfaces for _DSM method
-rw-r--r-- | drivers/acpi/acpi_extlog.c | 61 | ||||
-rw-r--r-- | drivers/acpi/utils.c | 97 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_ppi.c | 405 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_acpi.c | 144 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 131 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 26 | ||||
-rw-r--r-- | drivers/pci/pci-label.c | 129 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 26 |
9 files changed, 403 insertions, 664 deletions
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index 2635a01c5b3e..94166680b3a3 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c | |||
@@ -19,11 +19,9 @@ | |||
19 | #define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */ | 19 | #define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */ |
20 | 20 | ||
21 | #define EXTLOG_DSM_REV 0x0 | 21 | #define EXTLOG_DSM_REV 0x0 |
22 | #define EXTLOG_FN_QUERY 0x0 | ||
23 | #define EXTLOG_FN_ADDR 0x1 | 22 | #define EXTLOG_FN_ADDR 0x1 |
24 | 23 | ||
25 | #define FLAG_OS_OPTIN BIT(0) | 24 | #define FLAG_OS_OPTIN BIT(0) |
26 | #define EXTLOG_QUERY_L1_EXIST BIT(1) | ||
27 | #define ELOG_ENTRY_VALID (1ULL<<63) | 25 | #define ELOG_ENTRY_VALID (1ULL<<63) |
28 | #define ELOG_ENTRY_LEN 0x1000 | 26 | #define ELOG_ENTRY_LEN 0x1000 |
29 | 27 | ||
@@ -42,7 +40,7 @@ struct extlog_l1_head { | |||
42 | u8 rev1[12]; | 40 | u8 rev1[12]; |
43 | }; | 41 | }; |
44 | 42 | ||
45 | static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295"; | 43 | static u8 extlog_dsm_uuid[] __initdata = "663E35AF-CC10-41A4-88EA-5470AF055295"; |
46 | 44 | ||
47 | /* L1 table related physical address */ | 45 | /* L1 table related physical address */ |
48 | static u64 elog_base; | 46 | static u64 elog_base; |
@@ -152,62 +150,27 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, | |||
152 | return NOTIFY_DONE; | 150 | return NOTIFY_DONE; |
153 | } | 151 | } |
154 | 152 | ||
155 | static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret) | 153 | static bool __init extlog_get_l1addr(void) |
156 | { | 154 | { |
157 | struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
158 | struct acpi_object_list input; | ||
159 | union acpi_object params[4], *obj; | ||
160 | u8 uuid[16]; | 155 | u8 uuid[16]; |
161 | int i; | 156 | acpi_handle handle; |
157 | union acpi_object *obj; | ||
162 | 158 | ||
163 | acpi_str_to_uuid(extlog_dsm_uuid, uuid); | 159 | acpi_str_to_uuid(extlog_dsm_uuid, uuid); |
164 | input.count = 4; | ||
165 | input.pointer = params; | ||
166 | params[0].type = ACPI_TYPE_BUFFER; | ||
167 | params[0].buffer.length = 16; | ||
168 | params[0].buffer.pointer = uuid; | ||
169 | params[1].type = ACPI_TYPE_INTEGER; | ||
170 | params[1].integer.value = rev; | ||
171 | params[2].type = ACPI_TYPE_INTEGER; | ||
172 | params[2].integer.value = func; | ||
173 | params[3].type = ACPI_TYPE_PACKAGE; | ||
174 | params[3].package.count = 0; | ||
175 | params[3].package.elements = NULL; | ||
176 | |||
177 | if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) | ||
178 | return -1; | ||
179 | |||
180 | *ret = 0; | ||
181 | obj = (union acpi_object *)buf.pointer; | ||
182 | if (obj->type == ACPI_TYPE_INTEGER) { | ||
183 | *ret = obj->integer.value; | ||
184 | } else if (obj->type == ACPI_TYPE_BUFFER) { | ||
185 | if (obj->buffer.length <= 8) { | ||
186 | for (i = 0; i < obj->buffer.length; i++) | ||
187 | *ret |= (obj->buffer.pointer[i] << (i * 8)); | ||
188 | } | ||
189 | } | ||
190 | kfree(buf.pointer); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static bool extlog_get_l1addr(void) | ||
196 | { | ||
197 | acpi_handle handle; | ||
198 | u64 ret; | ||
199 | 160 | ||
200 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) | 161 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) |
201 | return false; | 162 | return false; |
202 | 163 | if (!acpi_check_dsm(handle, uuid, EXTLOG_DSM_REV, 1 << EXTLOG_FN_ADDR)) | |
203 | if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_QUERY, &ret) || | ||
204 | !(ret & EXTLOG_QUERY_L1_EXIST)) | ||
205 | return false; | 164 | return false; |
206 | 165 | obj = acpi_evaluate_dsm_typed(handle, uuid, EXTLOG_DSM_REV, | |
207 | if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_ADDR, &ret)) | 166 | EXTLOG_FN_ADDR, NULL, ACPI_TYPE_INTEGER); |
167 | if (!obj) { | ||
208 | return false; | 168 | return false; |
169 | } else { | ||
170 | l1_dirbase = obj->integer.value; | ||
171 | ACPI_FREE(obj); | ||
172 | } | ||
209 | 173 | ||
210 | l1_dirbase = ret; | ||
211 | /* Spec says L1 directory must be 4K aligned, bail out if it isn't */ | 174 | /* Spec says L1 directory must be 4K aligned, bail out if it isn't */ |
212 | if (l1_dirbase & ((1 << 12) - 1)) { | 175 | if (l1_dirbase & ((1 << 12) - 1)) { |
213 | pr_warn(FW_BUG "L1 Directory is invalid at physical %llx\n", | 176 | pr_warn(FW_BUG "L1 Directory is invalid at physical %llx\n", |
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 1336b9151479..0347a37eb438 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
@@ -572,3 +572,100 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) | |||
572 | 572 | ||
573 | return status; | 573 | return status; |
574 | } | 574 | } |
575 | |||
576 | /** | ||
577 | * acpi_evaluate_dsm - evaluate device's _DSM method | ||
578 | * @handle: ACPI device handle | ||
579 | * @uuid: UUID of requested functions, should be 16 bytes | ||
580 | * @rev: revision number of requested function | ||
581 | * @func: requested function number | ||
582 | * @argv4: the function specific parameter | ||
583 | * | ||
584 | * Evaluate device's _DSM method with specified UUID, revision id and | ||
585 | * function number. Caller needs to free the returned object. | ||
586 | * | ||
587 | * Though ACPI defines the fourth parameter for _DSM should be a package, | ||
588 | * some old BIOSes do expect a buffer or an integer etc. | ||
589 | */ | ||
590 | union acpi_object * | ||
591 | acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func, | ||
592 | union acpi_object *argv4) | ||
593 | { | ||
594 | acpi_status ret; | ||
595 | struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
596 | union acpi_object params[4]; | ||
597 | struct acpi_object_list input = { | ||
598 | .count = 4, | ||
599 | .pointer = params, | ||
600 | }; | ||
601 | |||
602 | params[0].type = ACPI_TYPE_BUFFER; | ||
603 | params[0].buffer.length = 16; | ||
604 | params[0].buffer.pointer = (char *)uuid; | ||
605 | params[1].type = ACPI_TYPE_INTEGER; | ||
606 | params[1].integer.value = rev; | ||
607 | params[2].type = ACPI_TYPE_INTEGER; | ||
608 | params[2].integer.value = func; | ||
609 | if (argv4) { | ||
610 | params[3] = *argv4; | ||
611 | } else { | ||
612 | params[3].type = ACPI_TYPE_PACKAGE; | ||
613 | params[3].package.count = 0; | ||
614 | params[3].package.elements = NULL; | ||
615 | } | ||
616 | |||
617 | ret = acpi_evaluate_object(handle, "_DSM", &input, &buf); | ||
618 | if (ACPI_SUCCESS(ret)) | ||
619 | return (union acpi_object *)buf.pointer; | ||
620 | |||
621 | if (ret != AE_NOT_FOUND) | ||
622 | acpi_handle_warn(handle, | ||
623 | "failed to evaluate _DSM (0x%x)\n", ret); | ||
624 | |||
625 | return NULL; | ||
626 | } | ||
627 | EXPORT_SYMBOL(acpi_evaluate_dsm); | ||
628 | |||
629 | /** | ||
630 | * acpi_check_dsm - check if _DSM method supports requested functions. | ||
631 | * @handle: ACPI device handle | ||
632 | * @uuid: UUID of requested functions, should be 16 bytes at least | ||
633 | * @rev: revision number of requested functions | ||
634 | * @funcs: bitmap of requested functions | ||
635 | * @exclude: excluding special value, used to support i915 and nouveau | ||
636 | * | ||
637 | * Evaluate device's _DSM method to check whether it supports requested | ||
638 | * functions. Currently only support 64 functions at maximum, should be | ||
639 | * enough for now. | ||
640 | */ | ||
641 | bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) | ||
642 | { | ||
643 | int i; | ||
644 | u64 mask = 0; | ||
645 | union acpi_object *obj; | ||
646 | |||
647 | if (funcs == 0) | ||
648 | return false; | ||
649 | |||
650 | obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL); | ||
651 | if (!obj) | ||
652 | return false; | ||
653 | |||
654 | /* For compatibility, old BIOSes may return an integer */ | ||
655 | if (obj->type == ACPI_TYPE_INTEGER) | ||
656 | mask = obj->integer.value; | ||
657 | else if (obj->type == ACPI_TYPE_BUFFER) | ||
658 | for (i = 0; i < obj->buffer.length && i < 8; i++) | ||
659 | mask |= (((u8)obj->buffer.pointer[i]) << (i * 8)); | ||
660 | ACPI_FREE(obj); | ||
661 | |||
662 | /* | ||
663 | * Bit 0 indicates whether there's support for any functions other than | ||
664 | * function 0 for the specified UUID and revision. | ||
665 | */ | ||
666 | if ((mask & 0x1) && (mask & funcs) == funcs) | ||
667 | return true; | ||
668 | |||
669 | return false; | ||
670 | } | ||
671 | EXPORT_SYMBOL(acpi_check_dsm); | ||
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 70dbee4b50e9..b3ea223585bd 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c | |||
@@ -1,15 +1,6 @@ | |||
1 | #include <linux/acpi.h> | 1 | #include <linux/acpi.h> |
2 | #include "tpm.h" | 2 | #include "tpm.h" |
3 | 3 | ||
4 | static const u8 tpm_ppi_uuid[] = { | ||
5 | 0xA6, 0xFA, 0xDD, 0x3D, | ||
6 | 0x1B, 0x36, | ||
7 | 0xB4, 0x4E, | ||
8 | 0xA4, 0x24, | ||
9 | 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53 | ||
10 | }; | ||
11 | static char *tpm_device_name = "TPM"; | ||
12 | |||
13 | #define TPM_PPI_REVISION_ID 1 | 4 | #define TPM_PPI_REVISION_ID 1 |
14 | #define TPM_PPI_FN_VERSION 1 | 5 | #define TPM_PPI_FN_VERSION 1 |
15 | #define TPM_PPI_FN_SUBREQ 2 | 6 | #define TPM_PPI_FN_SUBREQ 2 |
@@ -23,250 +14,178 @@ static char *tpm_device_name = "TPM"; | |||
23 | #define PPI_VS_REQ_END 255 | 14 | #define PPI_VS_REQ_END 255 |
24 | #define PPI_VERSION_LEN 3 | 15 | #define PPI_VERSION_LEN 3 |
25 | 16 | ||
17 | static const u8 tpm_ppi_uuid[] = { | ||
18 | 0xA6, 0xFA, 0xDD, 0x3D, | ||
19 | 0x1B, 0x36, | ||
20 | 0xB4, 0x4E, | ||
21 | 0xA4, 0x24, | ||
22 | 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53 | ||
23 | }; | ||
24 | |||
25 | static char tpm_ppi_version[PPI_VERSION_LEN + 1]; | ||
26 | static acpi_handle tpm_ppi_handle; | ||
27 | |||
26 | static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context, | 28 | static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context, |
27 | void **return_value) | 29 | void **return_value) |
28 | { | 30 | { |
29 | acpi_status status = AE_OK; | 31 | union acpi_object *obj; |
30 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
31 | 32 | ||
32 | if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) { | 33 | if (!acpi_check_dsm(handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, |
33 | if (strstr(buffer.pointer, context) != NULL) { | 34 | 1 << TPM_PPI_FN_VERSION)) |
34 | *return_value = handle; | 35 | return AE_OK; |
35 | status = AE_CTRL_TERMINATE; | 36 | |
36 | } | 37 | /* Cache version string */ |
37 | kfree(buffer.pointer); | 38 | obj = acpi_evaluate_dsm_typed(handle, tpm_ppi_uuid, |
39 | TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION, | ||
40 | NULL, ACPI_TYPE_STRING); | ||
41 | if (obj) { | ||
42 | strlcpy(tpm_ppi_version, obj->string.pointer, | ||
43 | PPI_VERSION_LEN + 1); | ||
44 | ACPI_FREE(obj); | ||
38 | } | 45 | } |
39 | 46 | ||
40 | return status; | 47 | *return_value = handle; |
48 | |||
49 | return AE_CTRL_TERMINATE; | ||
41 | } | 50 | } |
42 | 51 | ||
43 | static inline void ppi_assign_params(union acpi_object params[4], | 52 | static inline union acpi_object * |
44 | u64 function_num) | 53 | tpm_eval_dsm(int func, acpi_object_type type, union acpi_object *argv4) |
45 | { | 54 | { |
46 | params[0].type = ACPI_TYPE_BUFFER; | 55 | BUG_ON(!tpm_ppi_handle); |
47 | params[0].buffer.length = sizeof(tpm_ppi_uuid); | 56 | return acpi_evaluate_dsm_typed(tpm_ppi_handle, tpm_ppi_uuid, |
48 | params[0].buffer.pointer = (char *)tpm_ppi_uuid; | 57 | TPM_PPI_REVISION_ID, func, argv4, type); |
49 | params[1].type = ACPI_TYPE_INTEGER; | ||
50 | params[1].integer.value = TPM_PPI_REVISION_ID; | ||
51 | params[2].type = ACPI_TYPE_INTEGER; | ||
52 | params[2].integer.value = function_num; | ||
53 | params[3].type = ACPI_TYPE_PACKAGE; | ||
54 | params[3].package.count = 0; | ||
55 | params[3].package.elements = NULL; | ||
56 | } | 58 | } |
57 | 59 | ||
58 | static ssize_t tpm_show_ppi_version(struct device *dev, | 60 | static ssize_t tpm_show_ppi_version(struct device *dev, |
59 | struct device_attribute *attr, char *buf) | 61 | struct device_attribute *attr, char *buf) |
60 | { | 62 | { |
61 | acpi_handle handle; | 63 | return scnprintf(buf, PAGE_SIZE, "%s\n", tpm_ppi_version); |
62 | acpi_status status; | ||
63 | struct acpi_object_list input; | ||
64 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
65 | union acpi_object params[4]; | ||
66 | union acpi_object *obj; | ||
67 | |||
68 | input.count = 4; | ||
69 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
70 | input.pointer = params; | ||
71 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
72 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
73 | tpm_device_name, &handle); | ||
74 | if (ACPI_FAILURE(status)) | ||
75 | return -ENXIO; | ||
76 | |||
77 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
78 | ACPI_TYPE_STRING); | ||
79 | if (ACPI_FAILURE(status)) | ||
80 | return -ENOMEM; | ||
81 | obj = (union acpi_object *)output.pointer; | ||
82 | status = scnprintf(buf, PAGE_SIZE, "%s\n", obj->string.pointer); | ||
83 | kfree(output.pointer); | ||
84 | return status; | ||
85 | } | 64 | } |
86 | 65 | ||
87 | static ssize_t tpm_show_ppi_request(struct device *dev, | 66 | static ssize_t tpm_show_ppi_request(struct device *dev, |
88 | struct device_attribute *attr, char *buf) | 67 | struct device_attribute *attr, char *buf) |
89 | { | 68 | { |
90 | acpi_handle handle; | 69 | ssize_t size = -EINVAL; |
91 | acpi_status status; | 70 | union acpi_object *obj; |
92 | struct acpi_object_list input; | 71 | |
93 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 72 | obj = tpm_eval_dsm(TPM_PPI_FN_GETREQ, ACPI_TYPE_PACKAGE, NULL); |
94 | union acpi_object params[4]; | 73 | if (!obj) |
95 | union acpi_object *ret_obj; | ||
96 | |||
97 | input.count = 4; | ||
98 | ppi_assign_params(params, TPM_PPI_FN_GETREQ); | ||
99 | input.pointer = params; | ||
100 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
101 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
102 | tpm_device_name, &handle); | ||
103 | if (ACPI_FAILURE(status)) | ||
104 | return -ENXIO; | 74 | return -ENXIO; |
105 | 75 | ||
106 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
107 | ACPI_TYPE_PACKAGE); | ||
108 | if (ACPI_FAILURE(status)) | ||
109 | return -ENOMEM; | ||
110 | /* | 76 | /* |
111 | * output.pointer should be of package type, including two integers. | 77 | * output.pointer should be of package type, including two integers. |
112 | * The first is function return code, 0 means success and 1 means | 78 | * The first is function return code, 0 means success and 1 means |
113 | * error. The second is pending TPM operation requested by the OS, 0 | 79 | * error. The second is pending TPM operation requested by the OS, 0 |
114 | * means none and >0 means operation value. | 80 | * means none and >0 means operation value. |
115 | */ | 81 | */ |
116 | ret_obj = ((union acpi_object *)output.pointer)->package.elements; | 82 | if (obj->package.count == 2 && |
117 | if (ret_obj->type == ACPI_TYPE_INTEGER) { | 83 | obj->package.elements[0].type == ACPI_TYPE_INTEGER && |
118 | if (ret_obj->integer.value) { | 84 | obj->package.elements[1].type == ACPI_TYPE_INTEGER) { |
119 | status = -EFAULT; | 85 | if (obj->package.elements[0].integer.value) |
120 | goto cleanup; | 86 | size = -EFAULT; |
121 | } | ||
122 | ret_obj++; | ||
123 | if (ret_obj->type == ACPI_TYPE_INTEGER) | ||
124 | status = scnprintf(buf, PAGE_SIZE, "%llu\n", | ||
125 | ret_obj->integer.value); | ||
126 | else | 87 | else |
127 | status = -EINVAL; | 88 | size = scnprintf(buf, PAGE_SIZE, "%llu\n", |
128 | } else { | 89 | obj->package.elements[1].integer.value); |
129 | status = -EINVAL; | ||
130 | } | 90 | } |
131 | cleanup: | 91 | |
132 | kfree(output.pointer); | 92 | ACPI_FREE(obj); |
133 | return status; | 93 | |
94 | return size; | ||
134 | } | 95 | } |
135 | 96 | ||
136 | static ssize_t tpm_store_ppi_request(struct device *dev, | 97 | static ssize_t tpm_store_ppi_request(struct device *dev, |
137 | struct device_attribute *attr, | 98 | struct device_attribute *attr, |
138 | const char *buf, size_t count) | 99 | const char *buf, size_t count) |
139 | { | 100 | { |
140 | char version[PPI_VERSION_LEN + 1]; | ||
141 | acpi_handle handle; | ||
142 | acpi_status status; | ||
143 | struct acpi_object_list input; | ||
144 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
145 | union acpi_object params[4]; | ||
146 | union acpi_object obj; | ||
147 | u32 req; | 101 | u32 req; |
148 | u64 ret; | 102 | u64 ret; |
103 | int func = TPM_PPI_FN_SUBREQ; | ||
104 | union acpi_object *obj, tmp; | ||
105 | union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); | ||
149 | 106 | ||
150 | input.count = 4; | ||
151 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
152 | input.pointer = params; | ||
153 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
154 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
155 | tpm_device_name, &handle); | ||
156 | if (ACPI_FAILURE(status)) | ||
157 | return -ENXIO; | ||
158 | |||
159 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
160 | ACPI_TYPE_STRING); | ||
161 | if (ACPI_FAILURE(status)) | ||
162 | return -ENOMEM; | ||
163 | strlcpy(version, | ||
164 | ((union acpi_object *)output.pointer)->string.pointer, | ||
165 | PPI_VERSION_LEN + 1); | ||
166 | kfree(output.pointer); | ||
167 | output.length = ACPI_ALLOCATE_BUFFER; | ||
168 | output.pointer = NULL; | ||
169 | /* | 107 | /* |
170 | * the function to submit TPM operation request to pre-os environment | 108 | * the function to submit TPM operation request to pre-os environment |
171 | * is updated with function index from SUBREQ to SUBREQ2 since PPI | 109 | * is updated with function index from SUBREQ to SUBREQ2 since PPI |
172 | * version 1.1 | 110 | * version 1.1 |
173 | */ | 111 | */ |
174 | if (strcmp(version, "1.1") == -1) | 112 | if (acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, |
175 | params[2].integer.value = TPM_PPI_FN_SUBREQ; | 113 | 1 << TPM_PPI_FN_SUBREQ2)) |
176 | else | 114 | func = TPM_PPI_FN_SUBREQ2; |
177 | params[2].integer.value = TPM_PPI_FN_SUBREQ2; | 115 | |
178 | /* | 116 | /* |
179 | * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS | 117 | * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS |
180 | * accept buffer/string/integer type, but some BIOS accept buffer/ | 118 | * accept buffer/string/integer type, but some BIOS accept buffer/ |
181 | * string/package type. For PPI version 1.0 and 1.1, use buffer type | 119 | * string/package type. For PPI version 1.0 and 1.1, use buffer type |
182 | * for compatibility, and use package type since 1.2 according to spec. | 120 | * for compatibility, and use package type since 1.2 according to spec. |
183 | */ | 121 | */ |
184 | if (strcmp(version, "1.2") == -1) { | 122 | if (strcmp(tpm_ppi_version, "1.2") < 0) { |
185 | params[3].type = ACPI_TYPE_BUFFER; | 123 | if (sscanf(buf, "%d", &req) != 1) |
186 | params[3].buffer.length = sizeof(req); | 124 | return -EINVAL; |
187 | sscanf(buf, "%d", &req); | 125 | argv4.type = ACPI_TYPE_BUFFER; |
188 | params[3].buffer.pointer = (char *)&req; | 126 | argv4.buffer.length = sizeof(req); |
127 | argv4.buffer.pointer = (u8 *)&req; | ||
128 | } else { | ||
129 | tmp.type = ACPI_TYPE_INTEGER; | ||
130 | if (sscanf(buf, "%llu", &tmp.integer.value) != 1) | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | obj = tpm_eval_dsm(func, ACPI_TYPE_INTEGER, &argv4); | ||
135 | if (!obj) { | ||
136 | return -ENXIO; | ||
189 | } else { | 137 | } else { |
190 | params[3].package.count = 1; | 138 | ret = obj->integer.value; |
191 | obj.type = ACPI_TYPE_INTEGER; | 139 | ACPI_FREE(obj); |
192 | sscanf(buf, "%llu", &obj.integer.value); | ||
193 | params[3].package.elements = &obj; | ||
194 | } | 140 | } |
195 | 141 | ||
196 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
197 | ACPI_TYPE_INTEGER); | ||
198 | if (ACPI_FAILURE(status)) | ||
199 | return -ENOMEM; | ||
200 | ret = ((union acpi_object *)output.pointer)->integer.value; | ||
201 | if (ret == 0) | 142 | if (ret == 0) |
202 | status = (acpi_status)count; | 143 | return (acpi_status)count; |
203 | else if (ret == 1) | 144 | |
204 | status = -EPERM; | 145 | return (ret == 1) ? -EPERM : -EFAULT; |
205 | else | ||
206 | status = -EFAULT; | ||
207 | kfree(output.pointer); | ||
208 | return status; | ||
209 | } | 146 | } |
210 | 147 | ||
211 | static ssize_t tpm_show_ppi_transition_action(struct device *dev, | 148 | static ssize_t tpm_show_ppi_transition_action(struct device *dev, |
212 | struct device_attribute *attr, | 149 | struct device_attribute *attr, |
213 | char *buf) | 150 | char *buf) |
214 | { | 151 | { |
215 | char version[PPI_VERSION_LEN + 1]; | ||
216 | acpi_handle handle; | ||
217 | acpi_status status; | ||
218 | struct acpi_object_list input; | ||
219 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
220 | union acpi_object params[4]; | ||
221 | u32 ret; | 152 | u32 ret; |
222 | char *info[] = { | 153 | acpi_status status; |
154 | union acpi_object *obj = NULL; | ||
155 | union acpi_object tmp = { | ||
156 | .buffer.type = ACPI_TYPE_BUFFER, | ||
157 | .buffer.length = 0, | ||
158 | .buffer.pointer = NULL | ||
159 | }; | ||
160 | |||
161 | static char *info[] = { | ||
223 | "None", | 162 | "None", |
224 | "Shutdown", | 163 | "Shutdown", |
225 | "Reboot", | 164 | "Reboot", |
226 | "OS Vendor-specific", | 165 | "OS Vendor-specific", |
227 | "Error", | 166 | "Error", |
228 | }; | 167 | }; |
229 | input.count = 4; | ||
230 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
231 | input.pointer = params; | ||
232 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
233 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
234 | tpm_device_name, &handle); | ||
235 | if (ACPI_FAILURE(status)) | ||
236 | return -ENXIO; | ||
237 | 168 | ||
238 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
239 | ACPI_TYPE_STRING); | ||
240 | if (ACPI_FAILURE(status)) | ||
241 | return -ENOMEM; | ||
242 | strlcpy(version, | ||
243 | ((union acpi_object *)output.pointer)->string.pointer, | ||
244 | PPI_VERSION_LEN + 1); | ||
245 | /* | 169 | /* |
246 | * PPI spec defines params[3].type as empty package, but some platforms | 170 | * PPI spec defines params[3].type as empty package, but some platforms |
247 | * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for | 171 | * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for |
248 | * compatibility, define params[3].type as buffer, if PPI version < 1.2 | 172 | * compatibility, define params[3].type as buffer, if PPI version < 1.2 |
249 | */ | 173 | */ |
250 | if (strcmp(version, "1.2") == -1) { | 174 | if (strcmp(tpm_ppi_version, "1.2") < 0) |
251 | params[3].type = ACPI_TYPE_BUFFER; | 175 | obj = &tmp; |
252 | params[3].buffer.length = 0; | 176 | obj = tpm_eval_dsm(TPM_PPI_FN_GETACT, ACPI_TYPE_INTEGER, obj); |
253 | params[3].buffer.pointer = NULL; | 177 | if (!obj) { |
178 | return -ENXIO; | ||
179 | } else { | ||
180 | ret = obj->integer.value; | ||
181 | ACPI_FREE(obj); | ||
254 | } | 182 | } |
255 | params[2].integer.value = TPM_PPI_FN_GETACT; | 183 | |
256 | kfree(output.pointer); | ||
257 | output.length = ACPI_ALLOCATE_BUFFER; | ||
258 | output.pointer = NULL; | ||
259 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
260 | ACPI_TYPE_INTEGER); | ||
261 | if (ACPI_FAILURE(status)) | ||
262 | return -ENOMEM; | ||
263 | ret = ((union acpi_object *)output.pointer)->integer.value; | ||
264 | if (ret < ARRAY_SIZE(info) - 1) | 184 | if (ret < ARRAY_SIZE(info) - 1) |
265 | status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]); | 185 | status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]); |
266 | else | 186 | else |
267 | status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, | 187 | status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, |
268 | info[ARRAY_SIZE(info)-1]); | 188 | info[ARRAY_SIZE(info)-1]); |
269 | kfree(output.pointer); | ||
270 | return status; | 189 | return status; |
271 | } | 190 | } |
272 | 191 | ||
@@ -274,27 +193,14 @@ static ssize_t tpm_show_ppi_response(struct device *dev, | |||
274 | struct device_attribute *attr, | 193 | struct device_attribute *attr, |
275 | char *buf) | 194 | char *buf) |
276 | { | 195 | { |
277 | acpi_handle handle; | 196 | acpi_status status = -EINVAL; |
278 | acpi_status status; | 197 | union acpi_object *obj, *ret_obj; |
279 | struct acpi_object_list input; | 198 | u64 req, res; |
280 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 199 | |
281 | union acpi_object params[4]; | 200 | obj = tpm_eval_dsm(TPM_PPI_FN_GETRSP, ACPI_TYPE_PACKAGE, NULL); |
282 | union acpi_object *ret_obj; | 201 | if (!obj) |
283 | u64 req; | ||
284 | |||
285 | input.count = 4; | ||
286 | ppi_assign_params(params, TPM_PPI_FN_GETRSP); | ||
287 | input.pointer = params; | ||
288 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
289 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
290 | tpm_device_name, &handle); | ||
291 | if (ACPI_FAILURE(status)) | ||
292 | return -ENXIO; | 202 | return -ENXIO; |
293 | 203 | ||
294 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
295 | ACPI_TYPE_PACKAGE); | ||
296 | if (ACPI_FAILURE(status)) | ||
297 | return -ENOMEM; | ||
298 | /* | 204 | /* |
299 | * parameter output.pointer should be of package type, including | 205 | * parameter output.pointer should be of package type, including |
300 | * 3 integers. The first means function return code, the second means | 206 | * 3 integers. The first means function return code, the second means |
@@ -302,115 +208,82 @@ static ssize_t tpm_show_ppi_response(struct device *dev, | |||
302 | * the most recent TPM operation request. Only if the first is 0, and | 208 | * the most recent TPM operation request. Only if the first is 0, and |
303 | * the second integer is not 0, the response makes sense. | 209 | * the second integer is not 0, the response makes sense. |
304 | */ | 210 | */ |
305 | ret_obj = ((union acpi_object *)output.pointer)->package.elements; | 211 | ret_obj = obj->package.elements; |
306 | if (ret_obj->type != ACPI_TYPE_INTEGER) { | 212 | if (obj->package.count < 3 || |
307 | status = -EINVAL; | 213 | ret_obj[0].type != ACPI_TYPE_INTEGER || |
214 | ret_obj[1].type != ACPI_TYPE_INTEGER || | ||
215 | ret_obj[2].type != ACPI_TYPE_INTEGER) | ||
308 | goto cleanup; | 216 | goto cleanup; |
309 | } | 217 | |
310 | if (ret_obj->integer.value) { | 218 | if (ret_obj[0].integer.value) { |
311 | status = -EFAULT; | 219 | status = -EFAULT; |
312 | goto cleanup; | 220 | goto cleanup; |
313 | } | 221 | } |
314 | ret_obj++; | 222 | |
315 | if (ret_obj->type != ACPI_TYPE_INTEGER) { | 223 | req = ret_obj[1].integer.value; |
316 | status = -EINVAL; | 224 | res = ret_obj[2].integer.value; |
317 | goto cleanup; | 225 | if (req) { |
318 | } | 226 | if (res == 0) |
319 | if (ret_obj->integer.value) { | ||
320 | req = ret_obj->integer.value; | ||
321 | ret_obj++; | ||
322 | if (ret_obj->type != ACPI_TYPE_INTEGER) { | ||
323 | status = -EINVAL; | ||
324 | goto cleanup; | ||
325 | } | ||
326 | if (ret_obj->integer.value == 0) | ||
327 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, | 227 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, |
328 | "0: Success"); | 228 | "0: Success"); |
329 | else if (ret_obj->integer.value == 0xFFFFFFF0) | 229 | else if (res == 0xFFFFFFF0) |
330 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, | 230 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, |
331 | "0xFFFFFFF0: User Abort"); | 231 | "0xFFFFFFF0: User Abort"); |
332 | else if (ret_obj->integer.value == 0xFFFFFFF1) | 232 | else if (res == 0xFFFFFFF1) |
333 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, | 233 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, |
334 | "0xFFFFFFF1: BIOS Failure"); | 234 | "0xFFFFFFF1: BIOS Failure"); |
335 | else if (ret_obj->integer.value >= 1 && | 235 | else if (res >= 1 && res <= 0x00000FFF) |
336 | ret_obj->integer.value <= 0x00000FFF) | ||
337 | status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n", | 236 | status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n", |
338 | req, ret_obj->integer.value, | 237 | req, res, "Corresponding TPM error"); |
339 | "Corresponding TPM error"); | ||
340 | else | 238 | else |
341 | status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n", | 239 | status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n", |
342 | req, ret_obj->integer.value, | 240 | req, res, "Error"); |
343 | "Error"); | ||
344 | } else { | 241 | } else { |
345 | status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n", | 242 | status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n", |
346 | ret_obj->integer.value, "No Recent Request"); | 243 | req, "No Recent Request"); |
347 | } | 244 | } |
245 | |||
348 | cleanup: | 246 | cleanup: |
349 | kfree(output.pointer); | 247 | ACPI_FREE(obj); |
350 | return status; | 248 | return status; |
351 | } | 249 | } |
352 | 250 | ||
353 | static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) | 251 | static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) |
354 | { | 252 | { |
355 | char *str = buf; | ||
356 | char version[PPI_VERSION_LEN + 1]; | ||
357 | acpi_handle handle; | ||
358 | acpi_status status; | ||
359 | struct acpi_object_list input; | ||
360 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
361 | union acpi_object params[4]; | ||
362 | union acpi_object obj; | ||
363 | int i; | 253 | int i; |
364 | u32 ret; | 254 | u32 ret; |
365 | char *info[] = { | 255 | char *str = buf; |
256 | union acpi_object *obj, tmp; | ||
257 | union acpi_object argv = ACPI_INIT_DSM_ARGV4(1, &tmp); | ||
258 | |||
259 | static char *info[] = { | ||
366 | "Not implemented", | 260 | "Not implemented", |
367 | "BIOS only", | 261 | "BIOS only", |
368 | "Blocked for OS by BIOS", | 262 | "Blocked for OS by BIOS", |
369 | "User required", | 263 | "User required", |
370 | "User not required", | 264 | "User not required", |
371 | }; | 265 | }; |
372 | input.count = 4; | ||
373 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
374 | input.pointer = params; | ||
375 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
376 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
377 | tpm_device_name, &handle); | ||
378 | if (ACPI_FAILURE(status)) | ||
379 | return -ENXIO; | ||
380 | 266 | ||
381 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | 267 | if (!acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, |
382 | ACPI_TYPE_STRING); | 268 | 1 << TPM_PPI_FN_GETOPR)) |
383 | if (ACPI_FAILURE(status)) | ||
384 | return -ENOMEM; | ||
385 | |||
386 | strlcpy(version, | ||
387 | ((union acpi_object *)output.pointer)->string.pointer, | ||
388 | PPI_VERSION_LEN + 1); | ||
389 | kfree(output.pointer); | ||
390 | output.length = ACPI_ALLOCATE_BUFFER; | ||
391 | output.pointer = NULL; | ||
392 | if (strcmp(version, "1.2") == -1) | ||
393 | return -EPERM; | 269 | return -EPERM; |
394 | 270 | ||
395 | params[2].integer.value = TPM_PPI_FN_GETOPR; | 271 | tmp.integer.type = ACPI_TYPE_INTEGER; |
396 | params[3].package.count = 1; | ||
397 | obj.type = ACPI_TYPE_INTEGER; | ||
398 | params[3].package.elements = &obj; | ||
399 | for (i = start; i <= end; i++) { | 272 | for (i = start; i <= end; i++) { |
400 | obj.integer.value = i; | 273 | tmp.integer.value = i; |
401 | status = acpi_evaluate_object_typed(handle, "_DSM", | 274 | obj = tpm_eval_dsm(TPM_PPI_FN_GETOPR, ACPI_TYPE_INTEGER, &argv); |
402 | &input, &output, ACPI_TYPE_INTEGER); | 275 | if (!obj) { |
403 | if (ACPI_FAILURE(status)) | ||
404 | return -ENOMEM; | 276 | return -ENOMEM; |
277 | } else { | ||
278 | ret = obj->integer.value; | ||
279 | ACPI_FREE(obj); | ||
280 | } | ||
405 | 281 | ||
406 | ret = ((union acpi_object *)output.pointer)->integer.value; | ||
407 | if (ret > 0 && ret < ARRAY_SIZE(info)) | 282 | if (ret > 0 && ret < ARRAY_SIZE(info)) |
408 | str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n", | 283 | str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n", |
409 | i, ret, info[ret]); | 284 | i, ret, info[ret]); |
410 | kfree(output.pointer); | ||
411 | output.length = ACPI_ALLOCATE_BUFFER; | ||
412 | output.pointer = NULL; | ||
413 | } | 285 | } |
286 | |||
414 | return str - buf; | 287 | return str - buf; |
415 | } | 288 | } |
416 | 289 | ||
@@ -452,6 +325,12 @@ static struct attribute_group ppi_attr_grp = { | |||
452 | 325 | ||
453 | int tpm_add_ppi(struct kobject *parent) | 326 | int tpm_add_ppi(struct kobject *parent) |
454 | { | 327 | { |
328 | /* Cache TPM ACPI handle and version string */ | ||
329 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, | ||
330 | ppi_callback, NULL, NULL, &tpm_ppi_handle); | ||
331 | if (tpm_ppi_handle == NULL) | ||
332 | return -ENODEV; | ||
333 | |||
455 | return sysfs_create_group(parent, &ppi_attr_grp); | 334 | return sysfs_create_group(parent, &ppi_attr_grp); |
456 | } | 335 | } |
457 | 336 | ||
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index 5325b25ccbb4..d96eee1ae9c5 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c | |||
@@ -10,8 +10,6 @@ | |||
10 | #include "i915_drv.h" | 10 | #include "i915_drv.h" |
11 | 11 | ||
12 | #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */ | 12 | #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */ |
13 | |||
14 | #define INTEL_DSM_FN_SUPPORTED_FUNCTIONS 0 /* No args */ | ||
15 | #define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */ | 13 | #define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */ |
16 | 14 | ||
17 | static struct intel_dsm_priv { | 15 | static struct intel_dsm_priv { |
@@ -26,61 +24,6 @@ static const u8 intel_dsm_guid[] = { | |||
26 | 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c | 24 | 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c |
27 | }; | 25 | }; |
28 | 26 | ||
29 | static int intel_dsm(acpi_handle handle, int func) | ||
30 | { | ||
31 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
32 | struct acpi_object_list input; | ||
33 | union acpi_object params[4]; | ||
34 | union acpi_object *obj; | ||
35 | u32 result; | ||
36 | int ret = 0; | ||
37 | |||
38 | input.count = 4; | ||
39 | input.pointer = params; | ||
40 | params[0].type = ACPI_TYPE_BUFFER; | ||
41 | params[0].buffer.length = sizeof(intel_dsm_guid); | ||
42 | params[0].buffer.pointer = (char *)intel_dsm_guid; | ||
43 | params[1].type = ACPI_TYPE_INTEGER; | ||
44 | params[1].integer.value = INTEL_DSM_REVISION_ID; | ||
45 | params[2].type = ACPI_TYPE_INTEGER; | ||
46 | params[2].integer.value = func; | ||
47 | params[3].type = ACPI_TYPE_PACKAGE; | ||
48 | params[3].package.count = 0; | ||
49 | params[3].package.elements = NULL; | ||
50 | |||
51 | ret = acpi_evaluate_object(handle, "_DSM", &input, &output); | ||
52 | if (ret) { | ||
53 | DRM_DEBUG_DRIVER("failed to evaluate _DSM: %d\n", ret); | ||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | obj = (union acpi_object *)output.pointer; | ||
58 | |||
59 | result = 0; | ||
60 | switch (obj->type) { | ||
61 | case ACPI_TYPE_INTEGER: | ||
62 | result = obj->integer.value; | ||
63 | break; | ||
64 | |||
65 | case ACPI_TYPE_BUFFER: | ||
66 | if (obj->buffer.length == 4) { | ||
67 | result = (obj->buffer.pointer[0] | | ||
68 | (obj->buffer.pointer[1] << 8) | | ||
69 | (obj->buffer.pointer[2] << 16) | | ||
70 | (obj->buffer.pointer[3] << 24)); | ||
71 | break; | ||
72 | } | ||
73 | default: | ||
74 | ret = -EINVAL; | ||
75 | break; | ||
76 | } | ||
77 | if (result == 0x80000002) | ||
78 | ret = -ENODEV; | ||
79 | |||
80 | kfree(output.pointer); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static char *intel_dsm_port_name(u8 id) | 27 | static char *intel_dsm_port_name(u8 id) |
85 | { | 28 | { |
86 | switch (id) { | 29 | switch (id) { |
@@ -135,83 +78,56 @@ static char *intel_dsm_mux_type(u8 type) | |||
135 | 78 | ||
136 | static void intel_dsm_platform_mux_info(void) | 79 | static void intel_dsm_platform_mux_info(void) |
137 | { | 80 | { |
138 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 81 | int i; |
139 | struct acpi_object_list input; | 82 | union acpi_object *pkg, *connector_count; |
140 | union acpi_object params[4]; | 83 | |
141 | union acpi_object *pkg; | 84 | pkg = acpi_evaluate_dsm_typed(intel_dsm_priv.dhandle, intel_dsm_guid, |
142 | int i, ret; | 85 | INTEL_DSM_REVISION_ID, INTEL_DSM_FN_PLATFORM_MUX_INFO, |
143 | 86 | NULL, ACPI_TYPE_PACKAGE); | |
144 | input.count = 4; | 87 | if (!pkg) { |
145 | input.pointer = params; | 88 | DRM_DEBUG_DRIVER("failed to evaluate _DSM\n"); |
146 | params[0].type = ACPI_TYPE_BUFFER; | 89 | return; |
147 | params[0].buffer.length = sizeof(intel_dsm_guid); | ||
148 | params[0].buffer.pointer = (char *)intel_dsm_guid; | ||
149 | params[1].type = ACPI_TYPE_INTEGER; | ||
150 | params[1].integer.value = INTEL_DSM_REVISION_ID; | ||
151 | params[2].type = ACPI_TYPE_INTEGER; | ||
152 | params[2].integer.value = INTEL_DSM_FN_PLATFORM_MUX_INFO; | ||
153 | params[3].type = ACPI_TYPE_PACKAGE; | ||
154 | params[3].package.count = 0; | ||
155 | params[3].package.elements = NULL; | ||
156 | |||
157 | ret = acpi_evaluate_object(intel_dsm_priv.dhandle, "_DSM", &input, | ||
158 | &output); | ||
159 | if (ret) { | ||
160 | DRM_DEBUG_DRIVER("failed to evaluate _DSM: %d\n", ret); | ||
161 | goto out; | ||
162 | } | 90 | } |
163 | 91 | ||
164 | pkg = (union acpi_object *)output.pointer; | 92 | connector_count = &pkg->package.elements[0]; |
165 | 93 | DRM_DEBUG_DRIVER("MUX info connectors: %lld\n", | |
166 | if (pkg->type == ACPI_TYPE_PACKAGE) { | 94 | (unsigned long long)connector_count->integer.value); |
167 | union acpi_object *connector_count = &pkg->package.elements[0]; | 95 | for (i = 1; i < pkg->package.count; i++) { |
168 | DRM_DEBUG_DRIVER("MUX info connectors: %lld\n", | 96 | union acpi_object *obj = &pkg->package.elements[i]; |
169 | (unsigned long long)connector_count->integer.value); | 97 | union acpi_object *connector_id = &obj->package.elements[0]; |
170 | for (i = 1; i < pkg->package.count; i++) { | 98 | union acpi_object *info = &obj->package.elements[1]; |
171 | union acpi_object *obj = &pkg->package.elements[i]; | 99 | DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n", |
172 | union acpi_object *connector_id = | 100 | (unsigned long long)connector_id->integer.value); |
173 | &obj->package.elements[0]; | 101 | DRM_DEBUG_DRIVER(" port id: %s\n", |
174 | union acpi_object *info = &obj->package.elements[1]; | 102 | intel_dsm_port_name(info->buffer.pointer[0])); |
175 | DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n", | 103 | DRM_DEBUG_DRIVER(" display mux info: %s\n", |
176 | (unsigned long long)connector_id->integer.value); | 104 | intel_dsm_mux_type(info->buffer.pointer[1])); |
177 | DRM_DEBUG_DRIVER(" port id: %s\n", | 105 | DRM_DEBUG_DRIVER(" aux/dc mux info: %s\n", |
178 | intel_dsm_port_name(info->buffer.pointer[0])); | 106 | intel_dsm_mux_type(info->buffer.pointer[2])); |
179 | DRM_DEBUG_DRIVER(" display mux info: %s\n", | 107 | DRM_DEBUG_DRIVER(" hpd mux info: %s\n", |
180 | intel_dsm_mux_type(info->buffer.pointer[1])); | 108 | intel_dsm_mux_type(info->buffer.pointer[3])); |
181 | DRM_DEBUG_DRIVER(" aux/dc mux info: %s\n", | ||
182 | intel_dsm_mux_type(info->buffer.pointer[2])); | ||
183 | DRM_DEBUG_DRIVER(" hpd mux info: %s\n", | ||
184 | intel_dsm_mux_type(info->buffer.pointer[3])); | ||
185 | } | ||
186 | } | 109 | } |
187 | 110 | ||
188 | out: | 111 | ACPI_FREE(pkg); |
189 | kfree(output.pointer); | ||
190 | } | 112 | } |
191 | 113 | ||
192 | static bool intel_dsm_pci_probe(struct pci_dev *pdev) | 114 | static bool intel_dsm_pci_probe(struct pci_dev *pdev) |
193 | { | 115 | { |
194 | acpi_handle dhandle; | 116 | acpi_handle dhandle; |
195 | int ret; | ||
196 | 117 | ||
197 | dhandle = ACPI_HANDLE(&pdev->dev); | 118 | dhandle = ACPI_HANDLE(&pdev->dev); |
198 | if (!dhandle) | 119 | if (!dhandle) |
199 | return false; | 120 | return false; |
200 | 121 | ||
201 | if (!acpi_has_method(dhandle, "_DSM")) { | 122 | if (!acpi_check_dsm(dhandle, intel_dsm_guid, INTEL_DSM_REVISION_ID, |
123 | 1 << INTEL_DSM_FN_PLATFORM_MUX_INFO)) { | ||
202 | DRM_DEBUG_KMS("no _DSM method for intel device\n"); | 124 | DRM_DEBUG_KMS("no _DSM method for intel device\n"); |
203 | return false; | 125 | return false; |
204 | } | 126 | } |
205 | 127 | ||
206 | ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS); | ||
207 | if (ret < 0) { | ||
208 | DRM_DEBUG_KMS("failed to get supported _DSM functions\n"); | ||
209 | return false; | ||
210 | } | ||
211 | |||
212 | intel_dsm_priv.dhandle = dhandle; | 128 | intel_dsm_priv.dhandle = dhandle; |
213 | |||
214 | intel_dsm_platform_mux_info(); | 129 | intel_dsm_platform_mux_info(); |
130 | |||
215 | return true; | 131 | return true; |
216 | } | 132 | } |
217 | 133 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 129120473f6c..13c5af88a601 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | |||
@@ -87,55 +87,39 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version) | |||
87 | 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 | 87 | 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 |
88 | }; | 88 | }; |
89 | u32 mxms_args[] = { 0x00000000 }; | 89 | u32 mxms_args[] = { 0x00000000 }; |
90 | union acpi_object args[4] = { | 90 | union acpi_object argv4 = { |
91 | /* _DSM MUID */ | 91 | .buffer.type = ACPI_TYPE_BUFFER, |
92 | { .buffer.type = 3, | 92 | .buffer.length = sizeof(mxms_args), |
93 | .buffer.length = sizeof(muid), | 93 | .buffer.pointer = (char *)mxms_args, |
94 | .buffer.pointer = muid, | ||
95 | }, | ||
96 | /* spec says this can be zero to mean "highest revision", but | ||
97 | * of course there's at least one bios out there which fails | ||
98 | * unless you pass in exactly the version it supports.. | ||
99 | */ | ||
100 | { .integer.type = ACPI_TYPE_INTEGER, | ||
101 | .integer.value = (version & 0xf0) << 4 | (version & 0x0f), | ||
102 | }, | ||
103 | /* MXMS function */ | ||
104 | { .integer.type = ACPI_TYPE_INTEGER, | ||
105 | .integer.value = 0x00000010, | ||
106 | }, | ||
107 | /* Pointer to MXMS arguments */ | ||
108 | { .buffer.type = ACPI_TYPE_BUFFER, | ||
109 | .buffer.length = sizeof(mxms_args), | ||
110 | .buffer.pointer = (char *)mxms_args, | ||
111 | }, | ||
112 | }; | 94 | }; |
113 | struct acpi_object_list list = { ARRAY_SIZE(args), args }; | ||
114 | struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
115 | union acpi_object *obj; | 95 | union acpi_object *obj; |
116 | acpi_handle handle; | 96 | acpi_handle handle; |
117 | int ret; | 97 | int rev; |
118 | 98 | ||
119 | handle = ACPI_HANDLE(&device->pdev->dev); | 99 | handle = ACPI_HANDLE(&device->pdev->dev); |
120 | if (!handle) | 100 | if (!handle) |
121 | return false; | 101 | return false; |
122 | 102 | ||
123 | ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); | 103 | /* |
124 | if (ret) { | 104 | * spec says this can be zero to mean "highest revision", but |
125 | nv_debug(mxm, "DSM MXMS failed: %d\n", ret); | 105 | * of course there's at least one bios out there which fails |
106 | * unless you pass in exactly the version it supports.. | ||
107 | */ | ||
108 | rev = (version & 0xf0) << 4 | (version & 0x0f); | ||
109 | obj = acpi_evaluate_dsm(handle, muid, rev, 0x00000010, &argv4); | ||
110 | if (!obj) { | ||
111 | nv_debug(mxm, "DSM MXMS failed\n"); | ||
126 | return false; | 112 | return false; |
127 | } | 113 | } |
128 | 114 | ||
129 | obj = retn.pointer; | ||
130 | if (obj->type == ACPI_TYPE_BUFFER) { | 115 | if (obj->type == ACPI_TYPE_BUFFER) { |
131 | mxm->mxms = kmemdup(obj->buffer.pointer, | 116 | mxm->mxms = kmemdup(obj->buffer.pointer, |
132 | obj->buffer.length, GFP_KERNEL); | 117 | obj->buffer.length, GFP_KERNEL); |
133 | } else | 118 | } else if (obj->type == ACPI_TYPE_INTEGER) { |
134 | if (obj->type == ACPI_TYPE_INTEGER) { | ||
135 | nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value); | 119 | nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value); |
136 | } | 120 | } |
137 | 121 | ||
138 | kfree(obj); | 122 | ACPI_FREE(obj); |
139 | return mxm->mxms != NULL; | 123 | return mxm->mxms != NULL; |
140 | } | 124 | } |
141 | #endif | 125 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 1bc996c4f121..3c149617cfcb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
@@ -73,124 +73,66 @@ static const char nouveau_op_dsm_muid[] = { | |||
73 | 73 | ||
74 | static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) | 74 | static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) |
75 | { | 75 | { |
76 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 76 | int i; |
77 | struct acpi_object_list input; | ||
78 | union acpi_object params[4]; | ||
79 | union acpi_object *obj; | 77 | union acpi_object *obj; |
80 | int i, err; | ||
81 | char args_buff[4]; | 78 | char args_buff[4]; |
79 | union acpi_object argv4 = { | ||
80 | .buffer.type = ACPI_TYPE_BUFFER, | ||
81 | .buffer.length = 4, | ||
82 | .buffer.pointer = args_buff | ||
83 | }; | ||
82 | 84 | ||
83 | input.count = 4; | ||
84 | input.pointer = params; | ||
85 | params[0].type = ACPI_TYPE_BUFFER; | ||
86 | params[0].buffer.length = sizeof(nouveau_op_dsm_muid); | ||
87 | params[0].buffer.pointer = (char *)nouveau_op_dsm_muid; | ||
88 | params[1].type = ACPI_TYPE_INTEGER; | ||
89 | params[1].integer.value = 0x00000100; | ||
90 | params[2].type = ACPI_TYPE_INTEGER; | ||
91 | params[2].integer.value = func; | ||
92 | params[3].type = ACPI_TYPE_BUFFER; | ||
93 | params[3].buffer.length = 4; | ||
94 | /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ | 85 | /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ |
95 | for (i = 0; i < 4; i++) | 86 | for (i = 0; i < 4; i++) |
96 | args_buff[i] = (arg >> i * 8) & 0xFF; | 87 | args_buff[i] = (arg >> i * 8) & 0xFF; |
97 | params[3].buffer.pointer = args_buff; | ||
98 | 88 | ||
99 | err = acpi_evaluate_object(handle, "_DSM", &input, &output); | 89 | *result = 0; |
100 | if (err) { | 90 | obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100, |
101 | printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); | 91 | func, &argv4, ACPI_TYPE_BUFFER); |
102 | return err; | 92 | if (!obj) { |
103 | } | 93 | acpi_handle_info(handle, "failed to evaluate _DSM\n"); |
104 | 94 | return AE_ERROR; | |
105 | obj = (union acpi_object *)output.pointer; | 95 | } else { |
106 | 96 | if (obj->buffer.length == 4) { | |
107 | if (obj->type == ACPI_TYPE_INTEGER) | ||
108 | if (obj->integer.value == 0x80000002) { | ||
109 | return -ENODEV; | ||
110 | } | ||
111 | |||
112 | if (obj->type == ACPI_TYPE_BUFFER) { | ||
113 | if (obj->buffer.length == 4 && result) { | ||
114 | *result = 0; | ||
115 | *result |= obj->buffer.pointer[0]; | 97 | *result |= obj->buffer.pointer[0]; |
116 | *result |= (obj->buffer.pointer[1] << 8); | 98 | *result |= (obj->buffer.pointer[1] << 8); |
117 | *result |= (obj->buffer.pointer[2] << 16); | 99 | *result |= (obj->buffer.pointer[2] << 16); |
118 | *result |= (obj->buffer.pointer[3] << 24); | 100 | *result |= (obj->buffer.pointer[3] << 24); |
119 | } | 101 | } |
102 | ACPI_FREE(obj); | ||
120 | } | 103 | } |
121 | 104 | ||
122 | kfree(output.pointer); | ||
123 | return 0; | 105 | return 0; |
124 | } | 106 | } |
125 | 107 | ||
126 | static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) | 108 | static int nouveau_dsm(acpi_handle handle, int func, int arg) |
127 | { | 109 | { |
128 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 110 | int ret = 0; |
129 | struct acpi_object_list input; | ||
130 | union acpi_object params[4]; | ||
131 | union acpi_object *obj; | 111 | union acpi_object *obj; |
132 | int err; | 112 | union acpi_object argv4 = { |
133 | 113 | .integer.type = ACPI_TYPE_INTEGER, | |
134 | input.count = 4; | 114 | .integer.value = arg, |
135 | input.pointer = params; | 115 | }; |
136 | params[0].type = ACPI_TYPE_BUFFER; | 116 | |
137 | params[0].buffer.length = sizeof(nouveau_dsm_muid); | 117 | obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102, |
138 | params[0].buffer.pointer = (char *)nouveau_dsm_muid; | 118 | func, &argv4, ACPI_TYPE_INTEGER); |
139 | params[1].type = ACPI_TYPE_INTEGER; | 119 | if (!obj) { |
140 | params[1].integer.value = 0x00000102; | 120 | acpi_handle_info(handle, "failed to evaluate _DSM\n"); |
141 | params[2].type = ACPI_TYPE_INTEGER; | 121 | return AE_ERROR; |
142 | params[2].integer.value = func; | 122 | } else { |
143 | params[3].type = ACPI_TYPE_INTEGER; | ||
144 | params[3].integer.value = arg; | ||
145 | |||
146 | err = acpi_evaluate_object(handle, "_DSM", &input, &output); | ||
147 | if (err) { | ||
148 | printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); | ||
149 | return err; | ||
150 | } | ||
151 | |||
152 | obj = (union acpi_object *)output.pointer; | ||
153 | |||
154 | if (obj->type == ACPI_TYPE_INTEGER) | ||
155 | if (obj->integer.value == 0x80000002) | 123 | if (obj->integer.value == 0x80000002) |
156 | return -ENODEV; | 124 | ret = -ENODEV; |
157 | 125 | ACPI_FREE(obj); | |
158 | if (obj->type == ACPI_TYPE_BUFFER) { | ||
159 | if (obj->buffer.length == 4 && result) { | ||
160 | *result = 0; | ||
161 | *result |= obj->buffer.pointer[0]; | ||
162 | *result |= (obj->buffer.pointer[1] << 8); | ||
163 | *result |= (obj->buffer.pointer[2] << 16); | ||
164 | *result |= (obj->buffer.pointer[3] << 24); | ||
165 | } | ||
166 | } | 126 | } |
167 | 127 | ||
168 | kfree(output.pointer); | 128 | return ret; |
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* Returns 1 if a DSM function is usable and 0 otherwise */ | ||
173 | static int nouveau_test_dsm(acpi_handle test_handle, | ||
174 | int (*dsm_func)(acpi_handle, int, int, uint32_t *), | ||
175 | int sfnc) | ||
176 | { | ||
177 | u32 result = 0; | ||
178 | |||
179 | /* Function 0 returns a Buffer containing available functions. The args | ||
180 | * parameter is ignored for function 0, so just put 0 in it */ | ||
181 | if (dsm_func(test_handle, 0, 0, &result)) | ||
182 | return 0; | ||
183 | |||
184 | /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If | ||
185 | * the n-th bit is enabled, function n is supported */ | ||
186 | return result & 1 && result & (1 << sfnc); | ||
187 | } | 129 | } |
188 | 130 | ||
189 | static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) | 131 | static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) |
190 | { | 132 | { |
191 | mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); | 133 | mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); |
192 | mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); | 134 | mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); |
193 | return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL); | 135 | return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id); |
194 | } | 136 | } |
195 | 137 | ||
196 | static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) | 138 | static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) |
@@ -200,7 +142,7 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero | |||
200 | arg = NOUVEAU_DSM_POWER_SPEED; | 142 | arg = NOUVEAU_DSM_POWER_SPEED; |
201 | else | 143 | else |
202 | arg = NOUVEAU_DSM_POWER_STAMINA; | 144 | arg = NOUVEAU_DSM_POWER_STAMINA; |
203 | nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL); | 145 | nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg); |
204 | return 0; | 146 | return 0; |
205 | } | 147 | } |
206 | 148 | ||
@@ -260,11 +202,12 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) | |||
260 | nouveau_dsm_priv.other_handle = dhandle; | 202 | nouveau_dsm_priv.other_handle = dhandle; |
261 | return false; | 203 | return false; |
262 | } | 204 | } |
263 | if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) | 205 | if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102, |
206 | 1 << NOUVEAU_DSM_POWER)) | ||
264 | retval |= NOUVEAU_DSM_HAS_MUX; | 207 | retval |= NOUVEAU_DSM_HAS_MUX; |
265 | 208 | ||
266 | if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, | 209 | if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100, |
267 | NOUVEAU_DSM_OPTIMUS_CAPS)) | 210 | 1 << NOUVEAU_DSM_OPTIMUS_CAPS)) |
268 | retval |= NOUVEAU_DSM_HAS_OPT; | 211 | retval |= NOUVEAU_DSM_HAS_OPT; |
269 | 212 | ||
270 | if (retval & NOUVEAU_DSM_HAS_OPT) { | 213 | if (retval & NOUVEAU_DSM_HAS_OPT) { |
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 5f7e55f4b7f0..d22668f7d982 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
@@ -850,37 +850,23 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, | |||
850 | 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, | 850 | 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, |
851 | 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, | 851 | 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, |
852 | }; | 852 | }; |
853 | union acpi_object params[4]; | 853 | union acpi_object *obj; |
854 | struct acpi_object_list input; | ||
855 | struct acpi_device *adev; | 854 | struct acpi_device *adev; |
856 | unsigned long long value; | ||
857 | acpi_handle handle; | 855 | acpi_handle handle; |
858 | 856 | ||
859 | handle = ACPI_HANDLE(&client->dev); | 857 | handle = ACPI_HANDLE(&client->dev); |
860 | if (!handle || acpi_bus_get_device(handle, &adev)) | 858 | if (!handle || acpi_bus_get_device(handle, &adev)) |
861 | return -ENODEV; | 859 | return -ENODEV; |
862 | 860 | ||
863 | input.count = ARRAY_SIZE(params); | 861 | obj = acpi_evaluate_dsm_typed(handle, i2c_hid_guid, 1, 1, NULL, |
864 | input.pointer = params; | 862 | ACPI_TYPE_INTEGER); |
865 | 863 | if (!obj) { | |
866 | params[0].type = ACPI_TYPE_BUFFER; | ||
867 | params[0].buffer.length = sizeof(i2c_hid_guid); | ||
868 | params[0].buffer.pointer = i2c_hid_guid; | ||
869 | params[1].type = ACPI_TYPE_INTEGER; | ||
870 | params[1].integer.value = 1; | ||
871 | params[2].type = ACPI_TYPE_INTEGER; | ||
872 | params[2].integer.value = 1; /* HID function */ | ||
873 | params[3].type = ACPI_TYPE_PACKAGE; | ||
874 | params[3].package.count = 0; | ||
875 | params[3].package.elements = NULL; | ||
876 | |||
877 | if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_DSM", &input, | ||
878 | &value))) { | ||
879 | dev_err(&client->dev, "device _DSM execution failed\n"); | 864 | dev_err(&client->dev, "device _DSM execution failed\n"); |
880 | return -ENODEV; | 865 | return -ENODEV; |
881 | } | 866 | } |
882 | 867 | ||
883 | pdata->hid_descriptor_address = value; | 868 | pdata->hid_descriptor_address = obj->integer.value; |
869 | ACPI_FREE(obj); | ||
884 | 870 | ||
885 | return 0; | 871 | return 0; |
886 | } | 872 | } |
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index dbafcc8ef673..d2d1ceccad4b 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c | |||
@@ -186,7 +186,6 @@ static const char device_label_dsm_uuid[] = { | |||
186 | }; | 186 | }; |
187 | 187 | ||
188 | enum acpi_attr_enum { | 188 | enum acpi_attr_enum { |
189 | ACPI_ATTR_NONE = 0, | ||
190 | ACPI_ATTR_LABEL_SHOW, | 189 | ACPI_ATTR_LABEL_SHOW, |
191 | ACPI_ATTR_INDEX_SHOW, | 190 | ACPI_ATTR_INDEX_SHOW, |
192 | }; | 191 | }; |
@@ -194,84 +193,61 @@ enum acpi_attr_enum { | |||
194 | static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) | 193 | static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) |
195 | { | 194 | { |
196 | int len; | 195 | int len; |
197 | len = utf16s_to_utf8s((const wchar_t *)obj-> | 196 | len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer, |
198 | package.elements[1].string.pointer, | 197 | obj->string.length, |
199 | obj->package.elements[1].string.length, | ||
200 | UTF16_LITTLE_ENDIAN, | 198 | UTF16_LITTLE_ENDIAN, |
201 | buf, PAGE_SIZE); | 199 | buf, PAGE_SIZE); |
202 | buf[len] = '\n'; | 200 | buf[len] = '\n'; |
203 | } | 201 | } |
204 | 202 | ||
205 | static int | 203 | static int |
206 | dsm_get_label(acpi_handle handle, int func, | 204 | dsm_get_label(struct device *dev, char *buf, enum acpi_attr_enum attr) |
207 | struct acpi_buffer *output, | ||
208 | char *buf, enum acpi_attr_enum attribute) | ||
209 | { | 205 | { |
210 | struct acpi_object_list input; | 206 | acpi_handle handle; |
211 | union acpi_object params[4]; | 207 | union acpi_object *obj, *tmp; |
212 | union acpi_object *obj; | 208 | int len = -1; |
213 | int len = 0; | 209 | |
214 | 210 | handle = ACPI_HANDLE(dev); | |
215 | int err; | 211 | if (!handle) |
216 | |||
217 | input.count = 4; | ||
218 | input.pointer = params; | ||
219 | params[0].type = ACPI_TYPE_BUFFER; | ||
220 | params[0].buffer.length = sizeof(device_label_dsm_uuid); | ||
221 | params[0].buffer.pointer = (char *)device_label_dsm_uuid; | ||
222 | params[1].type = ACPI_TYPE_INTEGER; | ||
223 | params[1].integer.value = 0x02; | ||
224 | params[2].type = ACPI_TYPE_INTEGER; | ||
225 | params[2].integer.value = func; | ||
226 | params[3].type = ACPI_TYPE_PACKAGE; | ||
227 | params[3].package.count = 0; | ||
228 | params[3].package.elements = NULL; | ||
229 | |||
230 | err = acpi_evaluate_object(handle, "_DSM", &input, output); | ||
231 | if (err) | ||
232 | return -1; | 212 | return -1; |
233 | 213 | ||
234 | obj = (union acpi_object *)output->pointer; | 214 | obj = acpi_evaluate_dsm(handle, device_label_dsm_uuid, 0x2, |
235 | 215 | DEVICE_LABEL_DSM, NULL); | |
236 | switch (obj->type) { | 216 | if (!obj) |
237 | case ACPI_TYPE_PACKAGE: | 217 | return -1; |
238 | if (obj->package.count != 2) | 218 | |
239 | break; | 219 | tmp = obj->package.elements; |
240 | len = obj->package.elements[0].integer.value; | 220 | if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 && |
241 | if (buf) { | 221 | tmp[0].type == ACPI_TYPE_INTEGER && |
242 | if (attribute == ACPI_ATTR_INDEX_SHOW) | 222 | tmp[1].type == ACPI_TYPE_STRING) { |
243 | scnprintf(buf, PAGE_SIZE, "%llu\n", | 223 | /* |
244 | obj->package.elements[0].integer.value); | 224 | * The second string element is optional even when |
245 | else if (attribute == ACPI_ATTR_LABEL_SHOW) | 225 | * this _DSM is implemented; when not implemented, |
246 | dsm_label_utf16s_to_utf8s(obj, buf); | 226 | * this entry must return a null string. |
247 | kfree(output->pointer); | 227 | */ |
248 | return strlen(buf); | 228 | if (attr == ACPI_ATTR_INDEX_SHOW) |
249 | } | 229 | scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value); |
250 | kfree(output->pointer); | 230 | else if (attr == ACPI_ATTR_LABEL_SHOW) |
251 | return len; | 231 | dsm_label_utf16s_to_utf8s(tmp + 1, buf); |
252 | break; | 232 | len = strlen(buf) > 0 ? strlen(buf) : -1; |
253 | default: | ||
254 | kfree(output->pointer); | ||
255 | } | 233 | } |
256 | return -1; | 234 | |
235 | ACPI_FREE(obj); | ||
236 | |||
237 | return len; | ||
257 | } | 238 | } |
258 | 239 | ||
259 | static bool | 240 | static bool |
260 | device_has_dsm(struct device *dev) | 241 | device_has_dsm(struct device *dev) |
261 | { | 242 | { |
262 | acpi_handle handle; | 243 | acpi_handle handle; |
263 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
264 | 244 | ||
265 | handle = ACPI_HANDLE(dev); | 245 | handle = ACPI_HANDLE(dev); |
266 | |||
267 | if (!handle) | 246 | if (!handle) |
268 | return FALSE; | 247 | return false; |
269 | 248 | ||
270 | if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL, | 249 | return !!acpi_check_dsm(handle, device_label_dsm_uuid, 0x2, |
271 | ACPI_ATTR_NONE) > 0) | 250 | 1 << DEVICE_LABEL_DSM); |
272 | return TRUE; | ||
273 | |||
274 | return FALSE; | ||
275 | } | 251 | } |
276 | 252 | ||
277 | static umode_t | 253 | static umode_t |
@@ -290,44 +266,13 @@ acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n) | |||
290 | static ssize_t | 266 | static ssize_t |
291 | acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf) | 267 | acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf) |
292 | { | 268 | { |
293 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 269 | return dsm_get_label(dev, buf, ACPI_ATTR_LABEL_SHOW); |
294 | acpi_handle handle; | ||
295 | int length; | ||
296 | |||
297 | handle = ACPI_HANDLE(dev); | ||
298 | |||
299 | if (!handle) | ||
300 | return -1; | ||
301 | |||
302 | length = dsm_get_label(handle, DEVICE_LABEL_DSM, | ||
303 | &output, buf, ACPI_ATTR_LABEL_SHOW); | ||
304 | |||
305 | if (length < 1) | ||
306 | return -1; | ||
307 | |||
308 | return length; | ||
309 | } | 270 | } |
310 | 271 | ||
311 | static ssize_t | 272 | static ssize_t |
312 | acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf) | 273 | acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf) |
313 | { | 274 | { |
314 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 275 | return dsm_get_label(dev, buf, ACPI_ATTR_INDEX_SHOW); |
315 | acpi_handle handle; | ||
316 | int length; | ||
317 | |||
318 | handle = ACPI_HANDLE(dev); | ||
319 | |||
320 | if (!handle) | ||
321 | return -1; | ||
322 | |||
323 | length = dsm_get_label(handle, DEVICE_LABEL_DSM, | ||
324 | &output, buf, ACPI_ATTR_INDEX_SHOW); | ||
325 | |||
326 | if (length < 0) | ||
327 | return -1; | ||
328 | |||
329 | return length; | ||
330 | |||
331 | } | 276 | } |
332 | 277 | ||
333 | static struct device_attribute acpi_attr_label = { | 278 | static struct device_attribute acpi_attr_label = { |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e4ab7be65637..8256eb4ad057 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -64,6 +64,32 @@ bool acpi_ata_match(acpi_handle handle); | |||
64 | bool acpi_bay_match(acpi_handle handle); | 64 | bool acpi_bay_match(acpi_handle handle); |
65 | bool acpi_dock_match(acpi_handle handle); | 65 | bool acpi_dock_match(acpi_handle handle); |
66 | 66 | ||
67 | bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs); | ||
68 | union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, | ||
69 | int rev, int func, union acpi_object *argv4); | ||
70 | |||
71 | static inline union acpi_object * | ||
72 | acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, | ||
73 | union acpi_object *argv4, acpi_object_type type) | ||
74 | { | ||
75 | union acpi_object *obj; | ||
76 | |||
77 | obj = acpi_evaluate_dsm(handle, uuid, rev, func, argv4); | ||
78 | if (obj && obj->type != type) { | ||
79 | ACPI_FREE(obj); | ||
80 | obj = NULL; | ||
81 | } | ||
82 | |||
83 | return obj; | ||
84 | } | ||
85 | |||
86 | #define ACPI_INIT_DSM_ARGV4(cnt, eles) \ | ||
87 | { \ | ||
88 | .package.type = ACPI_TYPE_PACKAGE, \ | ||
89 | .package.count = (cnt), \ | ||
90 | .package.elements = (eles) \ | ||
91 | } | ||
92 | |||
67 | #ifdef CONFIG_ACPI | 93 | #ifdef CONFIG_ACPI |
68 | 94 | ||
69 | #include <linux/proc_fs.h> | 95 | #include <linux/proc_fs.h> |