From 8582e244e5fe72d2e9ace186fa8f3ed3bb4122e1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:22 +0100 Subject: drm/modes: parse_cmdline: Fix possible reference past end of string Before this commit, if the last option of a video=... option is for example "rotate" without a "=" after it then delim will point to the terminating 0 of the string, and value which is sets to will point one position past the end of the string. This commit fixes this by enforcing that the contents of delim equals '=' as it should be for options which take a value, this check is done in a new drm_mode_parse_cmdline_int helper function which factors out the common integer parsing code for all the options which take an int. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-1-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 68 ++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 38 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 88232698d7a0..3c3c7435225f 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1568,11 +1568,34 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length, return 0; } +static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) +{ + const char *value; + char *endp; + + /* + * delim must point to the '=', otherwise it is a syntax error and + * if delim points to the terminating zero, then delim + 1 wil point + * past the end of the string. + */ + if (*delim != '=') + return -EINVAL; + + value = delim + 1; + *int_ret = simple_strtol(value, &endp, 10); + + /* Make sure we have parsed something */ + if (endp == value) + return -EINVAL; + + return 0; +} + static int drm_mode_parse_cmdline_options(char *str, size_t len, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { - unsigned int rotation = 0; + unsigned int deg, margin, rotation = 0; char *sep = str; while ((sep = strchr(sep, ','))) { @@ -1588,13 +1611,7 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len, } if (!strncmp(option, "rotate", delim - option)) { - const char *value = delim + 1; - unsigned int deg; - - deg = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, °)) return -EINVAL; switch (deg) { @@ -1619,57 +1636,32 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len, } } else if (!strncmp(option, "reflect_x", delim - option)) { rotation |= DRM_MODE_REFLECT_X; - sep = delim; } else if (!strncmp(option, "reflect_y", delim - option)) { rotation |= DRM_MODE_REFLECT_Y; - sep = delim; } else if (!strncmp(option, "margin_right", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.right = margin; } else if (!strncmp(option, "margin_left", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.left = margin; } else if (!strncmp(option, "margin_top", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.top = margin; } else if (!strncmp(option, "margin_bottom", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.bottom = margin; } else { return -EINVAL; } + sep = delim; } mode->rotation_reflection = rotation; -- cgit From 83e14ea3a64f00897cc31974d3ae4e27e5a7405b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:23 +0100 Subject: drm/modes: parse_cmdline: Make various char pointers const We are not supposed to modify the passed in string, make char pointers used in drm_mode_parse_cmdline_options() const char * where possible. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-2-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 3c3c7435225f..654d4b6fecb3 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,15 +1591,15 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } -static int drm_mode_parse_cmdline_options(char *str, size_t len, +static int drm_mode_parse_cmdline_options(const char *str, size_t len, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { unsigned int deg, margin, rotation = 0; - char *sep = str; + const char *sep = str; while ((sep = strchr(sep, ','))) { - char *delim, *option; + const char *delim, *option; option = sep + 1; delim = strchr(option, '='); @@ -1718,8 +1718,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, bool named_mode = false, parse_extras = false; unsigned int bpp_off = 0, refresh_off = 0, options_off = 0; unsigned int mode_end = 0; - char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; - char *options_ptr = NULL; + const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; + const char *options_ptr = NULL; char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int ret; -- cgit From c2ed3e941901810ad3d55ce1935fa22c5007fee4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:24 +0100 Subject: drm/modes: parse_cmdline: Stop parsing extras after bpp / refresh at ', ' Before this commit it was impossible to add an extra mode argument after a bpp or refresh specifier, combined with an option, e.g. video=HDMI-1:720x480-24e,rotate=180 would not work, either the "e" to force enable would need to be dropped or the ",rotate=180", otherwise the mode_option would not be accepted. This commit fixes this by fixing the length calculation if extras_ptr is set to stop the extra parsing at the start of the options (stop at the ',' options_ptr points to). Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-3-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 654d4b6fecb3..a8aa7955fd45 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1721,7 +1721,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; const char *options_ptr = NULL; char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; - int ret; + int i, len, ret; #ifdef CONFIG_FB if (!mode_option) @@ -1841,9 +1841,11 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, else if (refresh_ptr) extra_ptr = refresh_end_ptr; - if (extra_ptr && - extra_ptr != options_ptr) { - int len = strlen(name) - (extra_ptr - name); + if (extra_ptr) { + if (options_ptr) + len = options_ptr - extra_ptr; + else + len = strlen(extra_ptr); ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false, connector, mode); -- cgit From cfb0881b8f621b656a9e23b31944a5db94cf5842 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:25 +0100 Subject: drm/modes: parse_cmdline: Accept extras directly after mode combined with options Before this commit it was impossible to combine an extra mode argument specified directly after the resolution with an option, e.g. video=HDMI-1:720x480e,rotate=180 would not work, either the "e" to force enable would need to be dropped or the ",rotate=180", otherwise the mode_option would not be accepted. This commit fixes this by setting parse_extras to true in this case, so that drm_mode_parse_cmdline_res_mode() parses the extra arguments directly after the resolution. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-4-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index a8aa7955fd45..f49401124727 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1794,6 +1794,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, mode_end = refresh_off; } else if (options_ptr) { mode_end = options_off; + parse_extras = true; } else { mode_end = strlen(name); parse_extras = true; -- cgit From 739b200c2edcaaa7a86f37b0c11db57956433dfb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:26 +0100 Subject: drm/modes: parse_cmdline: Rework drm_mode_parse_cmdline_options() Refactor drm_mode_parse_cmdline_options() so that it takes a pointer to the first option, rather then a pointer to the ',' before the first option. This is a preparation patch for allowing parsing of stand-alone options without a mode before them, e.g.: video=HDMI-1:margin_right=14,... Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-5-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index f49401124727..25e8edf4cfb8 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,23 +1591,21 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } -static int drm_mode_parse_cmdline_options(const char *str, size_t len, +static int drm_mode_parse_cmdline_options(const char *str, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { unsigned int deg, margin, rotation = 0; - const char *sep = str; + const char *delim, *option, *sep; - while ((sep = strchr(sep, ','))) { - const char *delim, *option; - - option = sep + 1; + option = str; + do { delim = strchr(option, '='); if (!delim) { delim = strchr(option, ','); if (!delim) - delim = str + len; + delim = option + strlen(option); } if (!strncmp(option, "rotate", delim - option)) { @@ -1661,8 +1659,9 @@ static int drm_mode_parse_cmdline_options(const char *str, size_t len, } else { return -EINVAL; } - sep = delim; - } + sep = strchr(delim, ','); + option = sep + 1; + } while (sep); mode->rotation_reflection = rotation; @@ -1855,9 +1854,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, } if (options_ptr) { - int len = strlen(name) - (options_ptr - name); - - ret = drm_mode_parse_cmdline_options(options_ptr, len, + ret = drm_mode_parse_cmdline_options(options_ptr + 1, connector, mode); if (ret) return false; -- cgit From 99e2716e053734b70434502867be24d20a3e2d84 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:27 +0100 Subject: drm/modes: parse_cmdline: Add freestanding argument to drm_mode_parse_cmdline_options() Add a freestanding function argument to drm_mode_parse_cmdline_options() similar to how drm_mode_parse_cmdline_extra() already has this. This is a preparation patch for allowing parsing of stand-alone options without a mode before them, e.g.: video=HDMI-1:margin_right=14,... Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-6-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 25e8edf4cfb8..80cb247c83c7 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1592,6 +1592,7 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) } static int drm_mode_parse_cmdline_options(const char *str, + bool freestanding, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { @@ -1663,6 +1664,9 @@ static int drm_mode_parse_cmdline_options(const char *str, option = sep + 1; } while (sep); + if (rotation && freestanding) + return -EINVAL; + mode->rotation_reflection = rotation; return 0; @@ -1855,6 +1859,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, if (options_ptr) { ret = drm_mode_parse_cmdline_options(options_ptr + 1, + false, connector, mode); if (ret) return false; -- cgit From 6a2d163756545aa3180d7851d5f8322b865e72be Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:28 +0100 Subject: drm/modes: parse_cmdline: Set bpp/refresh_specified after successful parsing drm_connector_get_cmdline_mode() calls drm_mode_parse_command_line_for_connector() with &connector->cmdline_mode as mode argument, so anything which we store in the mode arguments gets kept even if we return false. Avoid storing a possibly false-postive bpp/refresh_specified setting in connector->cmdline_mode by moving the setting of these to after successful parsing of the bpp/refresh parts of the video= argument. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-7-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 80cb247c83c7..72828fa9fc91 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1771,10 +1771,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, /* Try to locate the bpp and refresh specifiers, if any */ bpp_ptr = strchr(name, '-'); - if (bpp_ptr) { + if (bpp_ptr) bpp_off = bpp_ptr - name; - mode->bpp_specified = true; - } refresh_ptr = strchr(name, '@'); if (refresh_ptr) { @@ -1782,7 +1780,6 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, return false; refresh_off = refresh_ptr - name; - mode->refresh_specified = true; } /* Locate the start of named options */ @@ -1825,6 +1822,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode); if (ret) return false; + + mode->bpp_specified = true; } if (refresh_ptr) { @@ -1832,6 +1831,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, &refresh_end_ptr, mode); if (ret) return false; + + mode->refresh_specified = true; } /* -- cgit From 7b1cce760afe38b40f0989cdf10b2190dccf9815 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:29 +0100 Subject: drm/modes: parse_cmdline: Allow specifying stand-alone options Some options which can be specified on the commandline, such as margin_right=..., margin_left=..., etc. are applied not only to the specified mode, but to all modes. As such it would be nice if the user can simply say e.g. video=HDMI-1:margin_right=14,margin_left=24,margin_bottom=36,margin_top=42 This commit refactors drm_mode_parse_command_line_for_connector() to add support for this, and as a nice side effect also cleans up the function a bit. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-8-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 92 +++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 58 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 72828fa9fc91..2e82603f5d0a 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1677,17 +1677,6 @@ static const char * const drm_named_modes_whitelist[] = { "PAL", }; -static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) - if (!strncmp(mode, drm_named_modes_whitelist[i], size)) - return true; - - return false; -} - /** * drm_mode_parse_command_line_for_connector - parse command line modeline for connector * @mode_option: optional per connector mode option @@ -1718,7 +1707,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, struct drm_cmdline_mode *mode) { const char *name; - bool named_mode = false, parse_extras = false; + bool freestanding = false, parse_extras = false; unsigned int bpp_off = 0, refresh_off = 0, options_off = 0; unsigned int mode_end = 0; const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; @@ -1738,49 +1727,14 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, name = mode_option; - /* - * This is a bit convoluted. To differentiate between the - * named modes and poorly formatted resolutions, we need a - * bunch of things: - * - We need to make sure that the first character (which - * would be our resolution in X) is a digit. - * - If not, then it's either a named mode or a force on/off. - * To distinguish between the two, we need to run the - * extra parsing function, and if not, then we consider it - * a named mode. - * - * If this isn't enough, we should add more heuristics here, - * and matching unit-tests. - */ - if (!isdigit(name[0]) && name[0] != 'x') { - unsigned int namelen = strlen(name); - - /* - * Only the force on/off options can be in that case, - * and they all take a single character. - */ - if (namelen == 1) { - ret = drm_mode_parse_cmdline_extra(name, namelen, true, - connector, mode); - if (!ret) - return true; - } - - named_mode = true; - } - /* Try to locate the bpp and refresh specifiers, if any */ bpp_ptr = strchr(name, '-'); if (bpp_ptr) bpp_off = bpp_ptr - name; refresh_ptr = strchr(name, '@'); - if (refresh_ptr) { - if (named_mode) - return false; - + if (refresh_ptr) refresh_off = refresh_ptr - name; - } /* Locate the start of named options */ options_ptr = strchr(name, ','); @@ -1800,23 +1754,45 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, parse_extras = true; } - if (named_mode) { - if (mode_end + 1 > DRM_DISPLAY_MODE_LEN) - return false; + /* First check for a named mode */ + for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) { + ret = str_has_prefix(name, drm_named_modes_whitelist[i]); + if (ret == mode_end) { + if (refresh_ptr) + return false; /* named + refresh is invalid */ - if (!drm_named_mode_is_in_whitelist(name, mode_end)) - return false; + strcpy(mode->name, drm_named_modes_whitelist[i]); + mode->specified = true; + break; + } + } - strscpy(mode->name, name, mode_end + 1); - } else { + /* No named mode? Check for a normal mode argument, e.g. 1024x768 */ + if (!mode->specified && isdigit(name[0])) { ret = drm_mode_parse_cmdline_res_mode(name, mode_end, parse_extras, connector, mode); if (ret) return false; + + mode->specified = true; + } + + /* No mode? Check for freestanding extras and/or options */ + if (!mode->specified) { + unsigned int len = strlen(mode_option); + + if (bpp_ptr || refresh_ptr) + return false; /* syntax error */ + + if (len == 1 || (len >= 2 && mode_option[1] == ',')) + extra_ptr = mode_option; + else + options_ptr = mode_option - 1; + + freestanding = true; } - mode->specified = true; if (bpp_ptr) { ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode); @@ -1852,7 +1828,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, else len = strlen(extra_ptr); - ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false, + ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding, connector, mode); if (ret) return false; @@ -1860,7 +1836,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, if (options_ptr) { ret = drm_mode_parse_cmdline_options(options_ptr + 1, - false, + freestanding, connector, mode); if (ret) return false; -- cgit From 4e7a4a6fbdc669c44e6079f9d5eb25673749455f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:30 +0100 Subject: drm/modes: parse_cmdline: Add support for specifying panel_orientation (v2) Sometimes we want to override a connector's panel_orientation from the kernel commandline. Either for testing and for special cases, e.g. a kiosk like setup which uses a TV mounted in portrait mode. Users can already specify a "rotate" option through a video= kernel cmdline option. But that only supports 0/180 degrees (see drm_client_modeset TODO) and only works for in kernel modeset clients, not for userspace kms users. The "panel-orientation" connector property OTOH does support 90/270 degrees as it leaves dealing with the rotation up to userspace and this does work for userspace kms clients (at least those which support this property). Changes in v2: -Add missing ':' after @panel_orientation (reported by kbuild test robot) BugLink: https://gitlab.freedesktop.org/plymouth/plymouth/merge_requests/83 Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-9-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 2e82603f5d0a..119fed7ab815 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,6 +1591,33 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } +static int drm_mode_parse_panel_orientation(const char *delim, + struct drm_cmdline_mode *mode) +{ + const char *value; + + if (*delim != '=') + return -EINVAL; + + value = delim + 1; + delim = strchr(value, ','); + if (!delim) + delim = value + strlen(value); + + if (!strncmp(value, "normal", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (!strncmp(value, "upside_down", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (!strncmp(value, "left_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else if (!strncmp(value, "right_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else + return -EINVAL; + + return 0; +} + static int drm_mode_parse_cmdline_options(const char *str, bool freestanding, const struct drm_connector *connector, @@ -1657,6 +1684,9 @@ static int drm_mode_parse_cmdline_options(const char *str, return -EINVAL; mode->tv_margins.bottom = margin; + } else if (!strncmp(option, "panel_orientation", delim - option)) { + if (drm_mode_parse_panel_orientation(delim, mode)) + return -EINVAL; } else { return -EINVAL; } @@ -1715,6 +1745,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int i, len, ret; + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + #ifdef CONFIG_FB if (!mode_option) mode_option = fb_mode_option; -- cgit From 5b926617cdef41ce0696e09834991194b1759e28 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:31 +0100 Subject: drm/modes: parse_cmdline: Remove some unnecessary code (v2) fb_get_options() will return fb_mode_option if no video= argument is present on the kernel commandline, so there is no need to also do this in drm_mode_parse_command_line_for_connector() as our only caller uses fb_get_options() to get the mode_option argument. Changes in v2: -Split out the changes dealing with the initialization of the mode struct into a separate patch Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-10-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 119fed7ab815..beb764efe6b3 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1747,11 +1747,6 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; -#ifdef CONFIG_FB - if (!mode_option) - mode_option = fb_mode_option; -#endif - if (!mode_option) { mode->specified = false; return false; -- cgit From d1fe276b5115f0d581c3cfe6154633b3547e8aab Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:32 +0100 Subject: drm/modes: parse_cmdline: Explicitly memset the passed in drm_cmdline_mode struct Instead of only setting mode->specified on false on an early exit and leaving e.g. mode->bpp_specified and mode->refresh_specified as is, lets be consistent and just zero out the entire passed in struct at the top of drm_mode_parse_command_line_for_connector() Changes in v3: -Drop "mode->specified = false;" line instead of the "return false;" (oops) This crasher was reported-by: kernel test robot Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-11-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index beb764efe6b3..2a4eb619d7ad 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1745,12 +1745,11 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int i, len, ret; + memset(mode, 0, sizeof(*mode)); mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; - if (!mode_option) { - mode->specified = false; + if (!mode_option) return false; - } name = mode_option; -- cgit From f199af00186cb7eb2d842633e47689fb7b791e60 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 10 Dec 2019 11:24:37 +0100 Subject: drm/modes: tag unused variables to avoid warnings Some variables are set but never used. To avoid warning when compiling with W=1 and keep the algorithm like it is tag theses variables with _maybe_unused macro. Signed-off-by: Benjamin Gaignard Acked-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20191210102437.19377-1-benjamin.gaignard@st.com --- drivers/gpu/drm/drm_modes.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/drm_modes.c') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 2a4eb619d7ad..10336b144c72 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -233,7 +233,7 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, /* 3) Nominal HSync width (% of line period) - default 8 */ #define CVT_HSYNC_PERCENTAGE 8 unsigned int hblank_percentage; - int vsyncandback_porch, vback_porch, hblank; + int vsyncandback_porch, __maybe_unused vback_porch, hblank; /* estimated the horizontal period */ tmp1 = HV_FACTOR * 1000000 - @@ -386,9 +386,10 @@ drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay, int top_margin, bottom_margin; int interlace; unsigned int hfreq_est; - int vsync_plus_bp, vback_porch; - unsigned int vtotal_lines, vfieldrate_est, hperiod; - unsigned int vfield_rate, vframe_rate; + int vsync_plus_bp, __maybe_unused vback_porch; + unsigned int vtotal_lines, __maybe_unused vfieldrate_est; + unsigned int __maybe_unused hperiod; + unsigned int vfield_rate, __maybe_unused vframe_rate; int left_margin, right_margin; unsigned int total_active_pixels, ideal_duty_cycle; unsigned int hblank, total_pixels, pixel_freq; -- cgit