From f4cdf7ca9a1fdcca413157df19753f388a5a224e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 19 Aug 2026 10:09:22 -0700 Subject: Merge tag 'media/v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media updates from Mauro Carvalho Chehab: - v4l2-core: added ISP statistics support and per-block validation - v4l2-core: Allow unknown HDR10 white point and luminance - New camera sensors: Sony IMX678 and IMX471m, Himax HM1092 IR sensor - New codec: Milos: VPU v2.0 codec support - isp driver: gained support for Dreamchip RPPX1 ISP framework - vsp1 driver: gained support for RZ/T2H and RZ/N2H - Novalake driver: gained CVS support for new NVL hardware - dvb-core: fix feed leak on failed DMX_ADD_PID - several driver fixes, cleanups and minor improvements * tag 'media/v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (308 commits) media: ipu-bridge: check all DMI entries when overriding sensor rotation media: v4l2-async: avoid deleting unlinked ASC entry on link error media: rzg2l-cru: Align bytesperline to hardware DMA stride requirement media: intel/ipu6: fix async notifier cleanup leak on parse error media: staging/ipu7: fix async notifier UAF on probe error path media: amd: isp4: fix self-deadlock in isp4sd_pwron_and_init() error path media: amd: isp4: release partial allocations in isp4if_alloc_fw_gpumem() media: rcar-isp: Fix VSPX reference leaks media: rcar-isp: Release ISPCORE resources media: i2c: imx415: Release runtime PM reference on VBLANK error media: i2c: imx415: Return test pattern write errors media: renesas: vsp1: Declare index variables in for loop statement media: renesas: vsp1: Make reset control optional to support platforms without a reset line media: dt-bindings: media: renesas,vsp1: Document RZ/T2H and RZ/N2H SoCs media: dt-bindings: media: renesas,fcp: Document RZ/T2H and RZ/N2H SoCs media: nxp: imx8-isi: Add additional 32-bit RGB format support media: nxp: imx8-isi: Add 16-bit raw Bayer format support media: nxp: imx8-isi: Implement per-stream reference counting for multiplexed streams media: nxp: imx8-isi: Use BIT_ULL() for 64-bit stream masks media: nxp: imx8-isi: Correct color map between V4L2 and ISI ... --- drivers/crypto/omap-crypto.c | 225 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 drivers/crypto/omap-crypto.c (limited to 'drivers/crypto/omap-crypto.c') diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c new file mode 100644 index 000000000..7bd6869c2 --- /dev/null +++ b/drivers/crypto/omap-crypto.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * OMAP Crypto driver common support routines. + * + * Copyright (c) 2017 Texas Instruments Incorporated + * Tero Kristo + */ + +#include +#include +#include +#include + +#include "omap-crypto.h" + +static int omap_crypto_copy_sg_lists(int total, int bs, + struct scatterlist **sg, + struct scatterlist *new_sg, u16 flags) +{ + int n = sg_nents(*sg); + struct scatterlist *tmp; + + if (!(flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY)) { + new_sg = kmalloc_objs(*new_sg, n); + if (!new_sg) + return -ENOMEM; + + sg_init_table(new_sg, n); + } + + tmp = new_sg; + + while (*sg && total) { + int len = (*sg)->length; + + if (total < len) + len = total; + + if (len > 0) { + total -= len; + sg_set_page(tmp, sg_page(*sg), len, (*sg)->offset); + if (total <= 0) + sg_mark_end(tmp); + tmp = sg_next(tmp); + } + + *sg = sg_next(*sg); + } + + *sg = new_sg; + + return 0; +} + +static int omap_crypto_copy_sgs(int total, int bs, struct scatterlist **sg, + struct scatterlist *new_sg, u16 flags) +{ + void *buf; + int pages; + int new_len; + + new_len = ALIGN(total, bs); + pages = get_order(new_len); + + buf = (void *)__get_free_pages(GFP_ATOMIC, pages); + if (!buf) { + pr_err("%s: Couldn't allocate pages for unaligned cases.\n", + __func__); + return -ENOMEM; + } + + if (flags & OMAP_CRYPTO_COPY_DATA) { + scatterwalk_map_and_copy(buf, *sg, 0, total, 0); + if (flags & OMAP_CRYPTO_ZERO_BUF) + memset(buf + total, 0, new_len - total); + } + + if (!(flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY)) + sg_init_table(new_sg, 1); + + sg_set_buf(new_sg, buf, new_len); + + *sg = new_sg; + + return 0; +} + +static int omap_crypto_check_sg(struct scatterlist *sg, int total, int bs, + u16 flags) +{ + int len = 0; + int num_sg = 0; + + if (!IS_ALIGNED(total, bs)) + return OMAP_CRYPTO_NOT_ALIGNED; + + while (sg) { + num_sg++; + + if (!IS_ALIGNED(sg->offset, 4)) + return OMAP_CRYPTO_NOT_ALIGNED; + if (!IS_ALIGNED(sg->length, bs)) + return OMAP_CRYPTO_NOT_ALIGNED; +#ifdef CONFIG_ZONE_DMA + if (page_zonenum(sg_page(sg)) != ZONE_DMA) + return OMAP_CRYPTO_NOT_ALIGNED; +#endif + + len += sg->length; + sg = sg_next(sg); + + if (len >= total) + break; + } + + if ((flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY) && num_sg > 1) + return OMAP_CRYPTO_NOT_ALIGNED; + + if (len != total) + return OMAP_CRYPTO_BAD_DATA_LENGTH; + + return 0; +} + +int omap_crypto_align_sg(struct scatterlist **sg, int total, int bs, + struct scatterlist *new_sg, u16 flags, + u8 flags_shift, unsigned long *dd_flags) +{ + int ret; + + *dd_flags &= ~(OMAP_CRYPTO_COPY_MASK << flags_shift); + + if (flags & OMAP_CRYPTO_FORCE_COPY) + ret = OMAP_CRYPTO_NOT_ALIGNED; + else + ret = omap_crypto_check_sg(*sg, total, bs, flags); + + if (ret == OMAP_CRYPTO_NOT_ALIGNED) { + ret = omap_crypto_copy_sgs(total, bs, sg, new_sg, flags); + if (ret) + return ret; + *dd_flags |= OMAP_CRYPTO_DATA_COPIED << flags_shift; + } else if (ret == OMAP_CRYPTO_BAD_DATA_LENGTH) { + ret = omap_crypto_copy_sg_lists(total, bs, sg, new_sg, flags); + if (ret) + return ret; + if (!(flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY)) + *dd_flags |= OMAP_CRYPTO_SG_COPIED << flags_shift; + } else if (flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY) { + sg_set_buf(new_sg, sg_virt(*sg), (*sg)->length); + } + + return 0; +} +EXPORT_SYMBOL_GPL(omap_crypto_align_sg); + +static void omap_crypto_copy_data(struct scatterlist *src, + struct scatterlist *dst, + int offset, int len) +{ + int amt; + void *srcb, *dstb; + int srco = 0, dsto = offset; + + while (src && dst && len) { + if (srco >= src->length) { + srco -= src->length; + src = sg_next(src); + continue; + } + + if (dsto >= dst->length) { + dsto -= dst->length; + dst = sg_next(dst); + continue; + } + + amt = min(src->length - srco, dst->length - dsto); + amt = min(len, amt); + + srcb = kmap_atomic(sg_page(src)) + srco + src->offset; + dstb = kmap_atomic(sg_page(dst)) + dsto + dst->offset; + + memcpy(dstb, srcb, amt); + + flush_dcache_page(sg_page(dst)); + + kunmap_atomic(srcb); + kunmap_atomic(dstb); + + srco += amt; + dsto += amt; + len -= amt; + } +} + +void omap_crypto_cleanup(struct scatterlist *sg, struct scatterlist *orig, + int offset, int len, u8 flags_shift, + unsigned long flags) +{ + void *buf; + int pages; + + flags >>= flags_shift; + flags &= OMAP_CRYPTO_COPY_MASK; + + if (!flags) + return; + + buf = sg_virt(sg); + pages = get_order(len); + + if (orig && (flags & OMAP_CRYPTO_DATA_COPIED)) + omap_crypto_copy_data(sg, orig, offset, len); + + if (flags & OMAP_CRYPTO_DATA_COPIED) + free_pages((unsigned long)buf, pages); + else if (flags & OMAP_CRYPTO_SG_COPIED) + kfree(sg); +} +EXPORT_SYMBOL_GPL(omap_crypto_cleanup); + +MODULE_DESCRIPTION("OMAP crypto support library."); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Tero Kristo "); -- cgit v1.3.1