OSDN Git Service

drm/amd/display: dal_ddc_i2c_payloads_create can fail causing panic
authorAric Cyr <aric.cyr@amd.com>
Thu, 30 Jan 2020 19:46:53 +0000 (14:46 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 25 Feb 2020 16:02:22 +0000 (11:02 -0500)
[Why]
Since the i2c payload allocation can fail need to check return codes

[How]
Clean up i2c payload allocations and check for errors

Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Reviewed-by: Joshua Aberback <Joshua.Aberback@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c

index a5586f6..256889e 100644 (file)
@@ -126,22 +126,16 @@ struct aux_payloads {
        struct vector payloads;
 };
 
-static struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count)
+static bool dal_ddc_i2c_payloads_create(
+               struct dc_context *ctx,
+               struct i2c_payloads *payloads,
+               uint32_t count)
 {
-       struct i2c_payloads *payloads;
-
-       payloads = kzalloc(sizeof(struct i2c_payloads), GFP_KERNEL);
-
-       if (!payloads)
-               return NULL;
-
        if (dal_vector_construct(
                &payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
-               return payloads;
-
-       kfree(payloads);
-       return NULL;
+               return true;
 
+       return false;
 }
 
 static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
@@ -154,14 +148,12 @@ static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
        return p->payloads.count;
 }
 
-static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
+static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads *p)
 {
-       if (!p || !*p)
+       if (!p)
                return;
-       dal_vector_destruct(&(*p)->payloads);
-       kfree(*p);
-       *p = NULL;
 
+       dal_vector_destruct(&p->payloads);
 }
 
 #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -524,9 +516,13 @@ bool dal_ddc_service_query_ddc_data(
 
        uint32_t payloads_num = write_payloads + read_payloads;
 
+
        if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
                return false;
 
+       if (!payloads_num)
+               return false;
+
        /*TODO: len of payload data for i2c and aux is uint8!!!!,
         *  but we want to read 256 over i2c!!!!*/
        if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
@@ -557,23 +553,25 @@ bool dal_ddc_service_query_ddc_data(
                        ret = dal_ddc_submit_aux_command(ddc, &payload);
                }
        } else {
-               struct i2c_payloads *payloads =
-                       dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
+               struct i2c_command command = {0};
+               struct i2c_payloads payloads;
+
+               if (!dal_ddc_i2c_payloads_create(ddc->ctx, &payloads, payloads_num))
+                       return false;
 
-               struct i2c_command command = {
-                       .payloads = dal_ddc_i2c_payloads_get(payloads),
-                       .number_of_payloads = 0,
-                       .engine = DDC_I2C_COMMAND_ENGINE,
-                       .speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
+               command.payloads = dal_ddc_i2c_payloads_get(&payloads);
+               command.number_of_payloads = 0;
+               command.engine = DDC_I2C_COMMAND_ENGINE;
+               command.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
 
                dal_ddc_i2c_payloads_add(
-                       payloads, address, write_size, write_buf, true);
+                       &payloads, address, write_size, write_buf, true);
 
                dal_ddc_i2c_payloads_add(
-                       payloads, address, read_size, read_buf, false);
+                       &payloads, address, read_size, read_buf, false);
 
                command.number_of_payloads =
-                       dal_ddc_i2c_payloads_get_count(payloads);
+                       dal_ddc_i2c_payloads_get_count(&payloads);
 
                ret = dm_helpers_submit_i2c(
                                ddc->ctx,