Skip to content

Commit c51756d

Browse files
keesmripard
authored andcommitted
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 Signed-off-by: Kees Cook <[email protected]> Signed-off-by: Maxime Ripard <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/20180629184740.GA37415@beast
1 parent 968d72e commit c51756d

File tree

1 file changed

+64
-43
lines changed

1 file changed

+64
-43
lines changed

drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/pm_runtime.h>
1414
#include <linux/regmap.h>
1515
#include <linux/reset.h>
16+
#include <linux/slab.h>
1617

1718
#include <linux/phy/phy.h>
1819

@@ -247,10 +248,8 @@ static u16 sun6i_dsi_crc_compute(u8 const *buffer, size_t len)
247248
return crc_ccitt(0xffff, buffer, len);
248249
}
249250

250-
static u16 sun6i_dsi_crc_repeat_compute(u8 pd, size_t len)
251+
static u16 sun6i_dsi_crc_repeat(u8 pd, u8 *buffer, size_t len)
251252
{
252-
u8 buffer[len];
253-
254253
memset(buffer, pd, len);
255254

256255
return sun6i_dsi_crc_compute(buffer, len);
@@ -274,11 +273,11 @@ static u32 sun6i_dsi_build_blk0_pkt(u8 vc, u16 wc)
274273
wc & 0xff, wc >> 8);
275274
}
276275

277-
static u32 sun6i_dsi_build_blk1_pkt(u16 pd, size_t len)
276+
static u32 sun6i_dsi_build_blk1_pkt(u16 pd, u8 *buffer, size_t len)
278277
{
279278
u32 val = SUN6I_DSI_BLK_PD(pd);
280279

281-
return val | SUN6I_DSI_BLK_PF(sun6i_dsi_crc_repeat_compute(pd, len));
280+
return val | SUN6I_DSI_BLK_PF(sun6i_dsi_crc_repeat(pd, buffer, len));
282281
}
283282

284283
static void sun6i_dsi_inst_abort(struct sun6i_dsi *dsi)
@@ -452,6 +451,54 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
452451
struct mipi_dsi_device *device = dsi->device;
453452
unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8;
454453
u16 hbp, hfp, hsa, hblk, vblk;
454+
size_t bytes;
455+
u8 *buffer;
456+
457+
/* Do all timing calculations up front to allocate buffer space */
458+
459+
/*
460+
* A sync period is composed of a blanking packet (4 bytes +
461+
* payload + 2 bytes) and a sync event packet (4 bytes). Its
462+
* minimal size is therefore 10 bytes
463+
*/
464+
#define HSA_PACKET_OVERHEAD 10
465+
hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
466+
(mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
467+
468+
/*
469+
* The backporch is set using a blanking packet (4 bytes +
470+
* payload + 2 bytes). Its minimal size is therefore 6 bytes
471+
*/
472+
#define HBP_PACKET_OVERHEAD 6
473+
hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
474+
(mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
475+
476+
/*
477+
* The frontporch is set using a blanking packet (4 bytes +
478+
* payload + 2 bytes). Its minimal size is therefore 6 bytes
479+
*/
480+
#define HFP_PACKET_OVERHEAD 6
481+
hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
482+
(mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
483+
484+
/*
485+
* hblk seems to be the line + porches length.
486+
*/
487+
hblk = mode->htotal * Bpp - hsa;
488+
489+
/*
490+
* And I'm not entirely sure what vblk is about. The driver in
491+
* Allwinner BSP is using a rather convoluted calculation
492+
* there only for 4 lanes. However, using 0 (the !4 lanes
493+
* case) even with a 4 lanes screen seems to work...
494+
*/
495+
vblk = 0;
496+
497+
/* How many bytes do we need to send all payloads? */
498+
bytes = max_t(size_t, max(max(hfp, hblk), max(hsa, hbp)), vblk);
499+
buffer = kmalloc(bytes, GFP_KERNEL);
500+
if (WARN_ON(!buffer))
501+
return;
455502

456503
regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, 0);
457504

@@ -485,63 +532,37 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
485532
SUN6I_DSI_BASIC_SIZE1_VACT(mode->vdisplay) |
486533
SUN6I_DSI_BASIC_SIZE1_VT(mode->vtotal));
487534

488-
/*
489-
* A sync period is composed of a blanking packet (4 bytes +
490-
* payload + 2 bytes) and a sync event packet (4 bytes). Its
491-
* minimal size is therefore 10 bytes
492-
*/
493-
#define HSA_PACKET_OVERHEAD 10
494-
hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
495-
(mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
535+
/* sync */
496536
regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA0_REG,
497537
sun6i_dsi_build_blk0_pkt(device->channel, hsa));
498538
regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA1_REG,
499-
sun6i_dsi_build_blk1_pkt(0, hsa));
539+
sun6i_dsi_build_blk1_pkt(0, buffer, hsa));
500540

501-
/*
502-
* The backporch is set using a blanking packet (4 bytes +
503-
* payload + 2 bytes). Its minimal size is therefore 6 bytes
504-
*/
505-
#define HBP_PACKET_OVERHEAD 6
506-
hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
507-
(mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
541+
/* backporch */
508542
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP0_REG,
509543
sun6i_dsi_build_blk0_pkt(device->channel, hbp));
510544
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP1_REG,
511-
sun6i_dsi_build_blk1_pkt(0, hbp));
545+
sun6i_dsi_build_blk1_pkt(0, buffer, hbp));
512546

513-
/*
514-
* The frontporch is set using a blanking packet (4 bytes +
515-
* payload + 2 bytes). Its minimal size is therefore 6 bytes
516-
*/
517-
#define HFP_PACKET_OVERHEAD 6
518-
hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
519-
(mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
547+
/* frontporch */
520548
regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP0_REG,
521549
sun6i_dsi_build_blk0_pkt(device->channel, hfp));
522550
regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP1_REG,
523-
sun6i_dsi_build_blk1_pkt(0, hfp));
551+
sun6i_dsi_build_blk1_pkt(0, buffer, hfp));
524552

525-
/*
526-
* hblk seems to be the line + porches length.
527-
*/
528-
hblk = mode->htotal * Bpp - hsa;
553+
/* hblk */
529554
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK0_REG,
530555
sun6i_dsi_build_blk0_pkt(device->channel, hblk));
531556
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK1_REG,
532-
sun6i_dsi_build_blk1_pkt(0, hblk));
557+
sun6i_dsi_build_blk1_pkt(0, buffer, hblk));
533558

534-
/*
535-
* And I'm not entirely sure what vblk is about. The driver in
536-
* Allwinner BSP is using a rather convoluted calculation
537-
* there only for 4 lanes. However, using 0 (the !4 lanes
538-
* case) even with a 4 lanes screen seems to work...
539-
*/
540-
vblk = 0;
559+
/* vblk */
541560
regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK0_REG,
542561
sun6i_dsi_build_blk0_pkt(device->channel, vblk));
543562
regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK1_REG,
544-
sun6i_dsi_build_blk1_pkt(0, vblk));
563+
sun6i_dsi_build_blk1_pkt(0, buffer, vblk));
564+
565+
kfree(buffer);
545566
}
546567

547568
static int sun6i_dsi_start(struct sun6i_dsi *dsi,

0 commit comments

Comments
 (0)