aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-02-19 12:55:52 -0500
committerAlex Deucher <alexander.deucher@amd.com>2013-02-20 08:51:21 -0500
commit43a23aa450cc19fe8996caf09e7e21ae5f6e56e8 (patch)
tree84492903b219c0be8637157d41a170272250be7e
parentd0418894142f88041d2b7b5aa4f8bf3178d89514 (diff)
drm/radeon: properly validate the atpx interface
Some bioses don't set the function mask correctly which caused required functions to be disabled. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=53111 Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c73
1 files changed, 71 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 15f5ded65e0c..d96070bf8388 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -43,6 +43,12 @@ struct atpx_verify_interface {
43 u32 function_bits; /* supported functions bit vector */ 43 u32 function_bits; /* supported functions bit vector */
44} __packed; 44} __packed;
45 45
46struct atpx_px_params {
47 u16 size; /* structure size in bytes (includes size field) */
48 u32 valid_flags; /* which flags are valid */
49 u32 flags; /* flags */
50} __packed;
51
46struct atpx_power_control { 52struct atpx_power_control {
47 u16 size; 53 u16 size;
48 u8 dgpu_state; 54 u8 dgpu_state;
@@ -123,9 +129,61 @@ static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mas
123} 129}
124 130
125/** 131/**
132 * radeon_atpx_validate_functions - validate ATPX functions
133 *
134 * @atpx: radeon atpx struct
135 *
136 * Validate that required functions are enabled (all asics).
137 * returns 0 on success, error on failure.
138 */
139static int radeon_atpx_validate(struct radeon_atpx *atpx)
140{
141 /* make sure required functions are enabled */
142 /* dGPU power control is required */
143 atpx->functions.power_cntl = true;
144
145 if (atpx->functions.px_params) {
146 union acpi_object *info;
147 struct atpx_px_params output;
148 size_t size;
149 u32 valid_bits;
150
151 info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
152 if (!info)
153 return -EIO;
154
155 memset(&output, 0, sizeof(output));
156
157 size = *(u16 *) info->buffer.pointer;
158 if (size < 10) {
159 printk("ATPX buffer is too small: %zu\n", size);
160 kfree(info);
161 return -EINVAL;
162 }
163 size = min(sizeof(output), size);
164
165 memcpy(&output, info->buffer.pointer, size);
166
167 valid_bits = output.flags & output.valid_flags;
168 /* if separate mux flag is set, mux controls are required */
169 if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
170 atpx->functions.i2c_mux_cntl = true;
171 atpx->functions.disp_mux_cntl = true;
172 }
173 /* if any outputs are muxed, mux controls are required */
174 if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
175 ATPX_TV_SIGNAL_MUXED |
176 ATPX_DFP_SIGNAL_MUXED))
177 atpx->functions.disp_mux_cntl = true;
178
179 kfree(info);
180 }
181 return 0;
182}
183
184/**
126 * radeon_atpx_verify_interface - verify ATPX 185 * radeon_atpx_verify_interface - verify ATPX
127 * 186 *
128 * @handle: acpi handle
129 * @atpx: radeon atpx struct 187 * @atpx: radeon atpx struct
130 * 188 *
131 * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function 189 * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
@@ -406,8 +464,19 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
406 */ 464 */
407static int radeon_atpx_init(void) 465static int radeon_atpx_init(void)
408{ 466{
467 int r;
468
409 /* set up the ATPX handle */ 469 /* set up the ATPX handle */
410 return radeon_atpx_verify_interface(&radeon_atpx_priv.atpx); 470 r = radeon_atpx_verify_interface(&radeon_atpx_priv.atpx);
471 if (r)
472 return r;
473
474 /* validate the atpx setup */
475 r = radeon_atpx_validate(&radeon_atpx_priv.atpx);
476 if (r)
477 return r;
478
479 return 0;
411} 480}
412 481
413/** 482/**