Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nouveau: properly check for _DSM function support

According to the ACPI spec version 4, section 9.14.1, _DSM functions
must return a value with the first bit enabled if any DSM functions are
supported for the given UUID and revision ID. For a given function index n
to be marked supported, bit n must be enabled.

Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Peter Lekensteyn and committed by
Dave Airlie
9075e85f 3b32a592

+22 -13
+22 -13
drivers/gpu/drm/nouveau/nouveau_acpi.c
··· 18 18 19 19 #include <linux/vga_switcheroo.h> 20 20 21 - #define NOUVEAU_DSM_SUPPORTED 0x00 22 - #define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 23 - 24 - #define NOUVEAU_DSM_ACTIVE 0x01 25 - #define NOUVEAU_DSM_ACTIVE_QUERY 0x00 26 - 27 21 #define NOUVEAU_DSM_LED 0x02 28 22 #define NOUVEAU_DSM_LED_STATE 0x00 29 23 #define NOUVEAU_DSM_LED_OFF 0x10 ··· 29 35 #define NOUVEAU_DSM_POWER_SPEED 0x01 30 36 #define NOUVEAU_DSM_POWER_STAMINA 0x02 31 37 38 + #define NOUVEAU_DSM_OPTIMUS_FN 0x1A 32 39 static struct nouveau_dsm_priv { 33 40 bool dsm_detected; 34 41 bool optimus_detected; ··· 143 148 return 0; 144 149 } 145 150 151 + /* Returns 1 if a DSM function is usable and 0 otherwise */ 152 + static int nouveau_test_dsm(acpi_handle test_handle, 153 + int (*dsm_func)(acpi_handle, int, int, uint32_t *), 154 + int sfnc) 155 + { 156 + u32 result = 0; 157 + 158 + /* Function 0 returns a Buffer containing available functions. The args 159 + * parameter is ignored for function 0, so just put 0 in it */ 160 + if (dsm_func(test_handle, 0, 0, &result)) 161 + return 0; 162 + 163 + /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If 164 + * the n-th bit is enabled, function n is supported */ 165 + return result & 1 && result & (1 << sfnc); 166 + } 167 + 146 168 static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) 147 169 { 148 170 mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); ··· 224 212 { 225 213 acpi_handle dhandle, nvidia_handle; 226 214 acpi_status status; 227 - int ret, retval = 0; 228 - uint32_t result; 215 + int retval = 0; 229 216 230 217 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); 231 218 if (!dhandle) ··· 235 224 return false; 236 225 } 237 226 238 - ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED, 239 - NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); 240 - if (ret == 0) 227 + if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) 241 228 retval |= NOUVEAU_DSM_HAS_MUX; 242 229 243 - ret = nouveau_optimus_dsm(dhandle, 0, 0, &result); 244 - if (ret == 0) 230 + if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, 231 + NOUVEAU_DSM_OPTIMUS_FN)) 245 232 retval |= NOUVEAU_DSM_HAS_OPT; 246 233 247 234 if (retval)