aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-12 17:45:52 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-12 17:45:52 -0500
commitfbb9c10d40f88011ac72f855c97e3bdd981026a9 (patch)
tree255b3c21fd859004310bfad0a829ea4392d4851b /drivers/gpu/drm/nouveau
parent3e7cc142c1e040fd4629ad34a54b1c5b46dc3dd3 (diff)
parent7ede9f8a1805b26b3141730c9deaea8bc95a64bc (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
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mxm/base.c48
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c131
2 files changed, 53 insertions, 126 deletions
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
74static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 74static 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
126static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 108static 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 */
173static 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
189static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) 131static 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
196static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) 138static 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) {