drm/sun4i: Remove VLA usage
PATCH 1/1 drm/sun4i: Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a kmalloc allocation and moves all the size calculations to the start to do an allocation. If an upper bounds on the mode timing calculations could be determined, a fixed stack size could be used instead.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 107 +++++++++++++++---------- 1 file changed, 64 insertions(+), 43 deletions(-)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +64 -43
@@ -13,6 +13,7 @@#include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/reset.h> +#include <linux/slab.h> #include <linux/phy/phy.h>
@@ -247,10 +248,8 @@ static u16 sun6i_dsi_crc_compute(u8 const *buffer, size_t len)return crc_ccitt (0xffff , buffer, len); } -static u16 sun6i_dsi_crc_repeat_compute (u8 pd,size_t len) +static u16 sun6i_dsi_crc_repeat (u8 pd,u8 *buffer,size_t len) { -u8 buffer[len]; -memset (buffer, pd, len);return sun6i_dsi_crc_compute (buffer, len);
@@ -274,11 +273,11 @@ static u32 sun6i_dsi_build_blk0_pkt(u8 vc, u16 wc) wc & 0xff, wc >> 8); } -static u32 sun6i_dsi_build_blk1_pkt (u16 pd,size_t len) +static u32 sun6i_dsi_build_blk1_pkt (u16 pd,u8 *buffer,size_t len) {u32 val =SUN6I_DSI_BLK_PD (pd); -return val |SUN6I_DSI_BLK_PF (sun6i_dsi_crc_repeat_compute (pd, len)); +return val |SUN6I_DSI_BLK_PF (sun6i_dsi_crc_repeat (pd, buffer, len)); }static void sun6i_dsi_inst_abort (struct sun6i_dsi *dsi)
@@ -452,6 +451,54 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,struct mipi_dsi_device *device = dsi->device;unsigned int Bpp =mipi_dsi_pixel_format_to_bpp (device->format) /8 ;u16 hbp, hfp, hsa, hblk, vblk; +size_t bytes; +u8 *buffer; + +/* Do all timing calculations up front to allocate buffer space */ + +/* +* A sync period is composed of a blanking packet (4 bytes + +* payload + 2 bytes) and a sync event packet (4 bytes). Its +* minimal size is therefore 10 bytes +*/ +#define HSA_PACKET_OVERHEAD 10 + hsa =max ((unsigned int )HSA_PACKET_OVERHEAD , + (mode->hsync_end - mode->hsync_start) * Bpp -HSA_PACKET_OVERHEAD ); + +/* +* The backporch is set using a blanking packet (4 bytes + +* payload + 2 bytes). Its minimal size is therefore 6 bytes +*/ +#define HBP_PACKET_OVERHEAD 6 + hbp =max ((unsigned int )HBP_PACKET_OVERHEAD , + (mode->hsync_start - mode->hdisplay) * Bpp -HBP_PACKET_OVERHEAD ); + +/* +* The frontporch is set using a blanking packet (4 bytes + +* payload + 2 bytes). Its minimal size is therefore 6 bytes +*/ +#define HFP_PACKET_OVERHEAD 6 + hfp =max ((unsigned int )HFP_PACKET_OVERHEAD , + (mode->htotal - mode->hsync_end) * Bpp -HFP_PACKET_OVERHEAD ); + +/* +* hblk seems to be the line + porches length. +*/ + hblk = mode->htotal * Bpp - hsa; + +/* +* And I'm not entirely sure what vblk is about. The driver in +* Allwinner BSP is using a rather convoluted calculation +* there only for 4 lanes. However, using 0 (the !4 lanes +* case) even with a 4 lanes screen seems to work... +*/ + vblk =0 ; + +/* How many bytes do we need to send all payloads? */ + bytes =max_t (size_t,max (max (hfp, hblk),max (hsa, hbp)), vblk); + buffer =kmalloc (bytes,GFP_KERNEL ); +if (WARN_ON (!buffer)) +return ;regmap_write (dsi->regs,SUN6I_DSI_BASIC_CTL_REG ,0 );
@@ -485,63 +532,37 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,SUN6I_DSI_BASIC_SIZE1_VACT (mode->vdisplay) | SUN6I_DSI_BASIC_SIZE1_VT(mode->vtotal)); -/* -* A sync period is composed of a blanking packet (4 bytes + -* payload + 2 bytes) and a sync event packet (4 bytes). Its -* minimal size is therefore 10 bytes -*/ -#define HSA_PACKET_OVERHEAD 10 - hsa =max ((unsigned int )HSA_PACKET_OVERHEAD , - (mode->hsync_end - mode->hsync_start) * Bpp -HSA_PACKET_OVERHEAD ); +/* sync */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HSA0_REG ,sun6i_dsi_build_blk0_pkt (device->channel, hsa));regmap_write (dsi->regs,SUN6I_DSI_BLK_HSA1_REG , -sun6i_dsi_build_blk1_pkt (0 , hsa)); +sun6i_dsi_build_blk1_pkt (0 , buffer, hsa)); -/* -* The backporch is set using a blanking packet (4 bytes + -* payload + 2 bytes). Its minimal size is therefore 6 bytes -*/ -#define HBP_PACKET_OVERHEAD 6 - hbp =max ((unsigned int )HBP_PACKET_OVERHEAD , - (mode->hsync_start - mode->hdisplay) * Bpp -HBP_PACKET_OVERHEAD ); +/* backporch */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HBP0_REG ,sun6i_dsi_build_blk0_pkt (device->channel, hbp));regmap_write (dsi->regs,SUN6I_DSI_BLK_HBP1_REG , -sun6i_dsi_build_blk1_pkt (0 , hbp)); +sun6i_dsi_build_blk1_pkt (0 , buffer, hbp)); -/* -* The frontporch is set using a blanking packet (4 bytes + -* payload + 2 bytes). Its minimal size is therefore 6 bytes -*/ -#define HFP_PACKET_OVERHEAD 6 - hfp =max ((unsigned int )HFP_PACKET_OVERHEAD , - (mode->htotal - mode->hsync_end) * Bpp -HFP_PACKET_OVERHEAD ); +/* frontporch */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HFP0_REG ,sun6i_dsi_build_blk0_pkt (device->channel, hfp));regmap_write (dsi->regs,SUN6I_DSI_BLK_HFP1_REG , -sun6i_dsi_build_blk1_pkt (0 , hfp)); +sun6i_dsi_build_blk1_pkt (0 , buffer, hfp)); -/* -* hblk seems to be the line + porches length. -*/ - hblk = mode->htotal * Bpp - hsa; +/* hblk */ regmap_write (dsi->regs,SUN6I_DSI_BLK_HBLK0_REG ,sun6i_dsi_build_blk0_pkt (device->channel, hblk));regmap_write (dsi->regs,SUN6I_DSI_BLK_HBLK1_REG , -sun6i_dsi_build_blk1_pkt (0 , hblk)); +sun6i_dsi_build_blk1_pkt (0 , buffer, hblk)); -/* -* And I'm not entirely sure what vblk is about. The driver in -* Allwinner BSP is using a rather convoluted calculation -* there only for 4 lanes. However, using 0 (the !4 lanes -* case) even with a 4 lanes screen seems to work... -*/ - vblk =0 ; +/* vblk */ regmap_write (dsi->regs,SUN6I_DSI_BLK_VBLK0_REG ,sun6i_dsi_build_blk0_pkt (device->channel, vblk));regmap_write (dsi->regs,SUN6I_DSI_BLK_VBLK1_REG , -sun6i_dsi_build_blk1_pkt (0 , vblk)); +sun6i_dsi_build_blk1_pkt (0 , buffer, vblk)); + +kfree (buffer); } static int sun6i_dsi_start(struct sun6i_dsi *dsi,
Signature · 6 lines
2.17.1 -- Kees Cook Pixel Security
Maxime Ripard
AppliedQuoted 8 lines · Kees Cook
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a kmalloc allocation and moves all the size calculations to the start to do an allocation. If an upper bounds on the mode timing calculations could be determined, a fixed stack size could be used instead.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA at mail.gmail.com
Signed-off-by Kees Cook <[email protected]>
Applied, thanks!
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180704/553477ce/attachment-0001.sig>