Compare commits

...

4 Commits

Author SHA1 Message Date
Akhil R
087418781c crypto: tegra: Use separate buffer for each host1x command
Allocate separate buffer for each host1x command. The single buffer used
for host1x commands can get corrupted when independent crypto operations
overlap.

Bug 4883011

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: I43029364c8e65e5014a5b7068cb45225c039aaf8
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3248913
(cherry picked from commit f6c3d49e92)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3262770
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
2024-12-17 15:56:55 -08:00
Jon Hunter
fe0a030fee media: camera: Fix build for Linux v6.8+
In Linux v6.8, the 'g_frame_interval' and 's_frame_interval' function
pointers were removed from the 'v4l2_subdev_video_ops' structure and
replaced by 'get_frame_interval' and 'set_frame_interval' that were
added to the 'v4l2_subdev_pad_ops' structure.

This change was previously fixed for the Tegra CSI driver by adding the
necessary conftest changes. A new update to the Tegra Cam V4L2 causes
the build to fail for Linux v6.8+ kernels because of the same issue. Fix
up the Tegra Cam V4L2 driver in the same way as the Tegra CSI driver,
but update the name of the conftest test to indicate that this is
applicable for both the 'get_frame_interval' and 'set_frame_interval'
function pointers.

Bug 4448428
Bug 4807063

Change-Id: Ica47f3aaece0bf81e2adc3c431056ea51b64a893
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3231775
(cherry picked from commit 91416b264c)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3262768
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-12-17 15:56:23 -08:00
Praveen AC
7ad4c09866 [t23x][camera]: Fix VIDIOC_G/S_PARM v4l2-compliance test fail.
Implemented VIDIOC_G/S_PARM ioctl calls to fix
v4l2-compliance test fail.

Bug 4807063

Change-Id: Ia03b161b5659c710976084f277064a44d10aec15
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3221436
(cherry picked from commit c3b8c1cd3e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3262767
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-12-17 15:56:15 -08:00
Akhil R
f41b74b8c3 crypto: tegra: Fix size of buffer allocated
Allocate the buffer based on the request instead of a fixed buffer
length. In operations which may require larger buffer size, a fixed
buffer may fail. Similar patch was added for AES algorithms. Fix the
same for HASH algorithms as well.

Bug 4908156

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: Idd2c1ceae1a85434a5a51154a17dce8c927bb66c
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3234055
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
(cherry picked from commit 3415677f0f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3235205
2024-10-24 08:31:48 -07:00
10 changed files with 187 additions and 81 deletions

View File

@@ -42,6 +42,7 @@ struct tegra_aes_reqctx {
u32 crypto_config;
u32 len;
u32 *iv;
u32 *cmdbuf;
};
struct tegra_aead_ctx {
@@ -69,6 +70,7 @@ struct tegra_aead_reqctx {
u32 key_id;
u32 iv[4];
u8 authdata[16];
u32 *cmdbuf;
};
struct tegra_cmac_ctx {
@@ -93,6 +95,7 @@ struct tegra_cmac_reqctx {
u32 key_id;
u32 *iv;
u32 result[CMAC_RESULT_REG_COUNT];
u32 *cmdbuf;
};
/* increment counter (128-bit int) */
@@ -213,7 +216,7 @@ static int tegra234_aes_cfg(u32 alg, bool encrypt)
static unsigned int tegra_aes_prep_cmd(struct tegra_se *se, struct tegra_aes_reqctx *rctx)
{
unsigned int data_count, res_bits, i = 0, j;
u32 *cpuvaddr = se->cmdbuf->addr;
u32 *cpuvaddr = rctx->cmdbuf;
dma_addr_t addr = rctx->datbuf.addr;
data_count = rctx->len / AES_BLOCK_SIZE;
@@ -292,16 +295,17 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
/* Prepare the command and submit for execution */
cmdlen = tegra_aes_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
/* Copy the result */
tegra_aes_update_iv(req, ctx);
scatterwalk_map_and_copy(rctx->datbuf.buf, req->dst, 0, req->cryptlen, 1);
/* Free the buffer */
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
dma_free_coherent(se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
kfree(rctx->cmdbuf);
crypto_finalize_skcipher_request(se->engine, req, ret);
return 0;
@@ -459,6 +463,13 @@ static int tegra_aes_crypt(struct skcipher_request *req, bool encrypt)
if (!req->cryptlen)
return 0;
if (ctx->alg == SE_ALG_ECB)
req->iv = NULL;
rctx->cmdbuf = kzalloc(SE_MAX_CMDLEN, GFP_KERNEL);
if (!rctx->cmdbuf)
return -ENOMEM;
rctx->encrypt = encrypt;
rctx->config = tegra234_aes_cfg(ctx->alg, encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, encrypt);
@@ -597,7 +608,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
static unsigned int tegra_gmac_prep_cmd(struct tegra_se *se, struct tegra_aead_reqctx *rctx)
{
unsigned int data_count, res_bits, i = 0;
u32 *cpuvaddr = se->cmdbuf->addr;
u32 *cpuvaddr = rctx->cmdbuf;
data_count = (rctx->assoclen / AES_BLOCK_SIZE);
res_bits = (rctx->assoclen % AES_BLOCK_SIZE) * 8;
@@ -635,7 +646,7 @@ static unsigned int tegra_gmac_prep_cmd(struct tegra_se *se, struct tegra_aead_r
static unsigned int tegra_gcm_crypt_prep_cmd(struct tegra_se *se, struct tegra_aead_reqctx *rctx)
{
unsigned int data_count, res_bits, i = 0, j;
u32 *cpuvaddr = se->cmdbuf->addr, op;
u32 *cpuvaddr = rctx->cmdbuf, op;
data_count = (rctx->cryptlen / AES_BLOCK_SIZE);
res_bits = (rctx->cryptlen % AES_BLOCK_SIZE) * 8;
@@ -755,7 +766,7 @@ static int tegra_gcm_do_gmac(struct tegra_aead_ctx *ctx, struct tegra_aead_reqct
cmdlen = tegra_gmac_prep_cmd(se, rctx);
return tegra_se_host1x_submit(se, cmdlen);
return tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
}
static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx *rctx)
@@ -772,7 +783,7 @@ static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
/* Prepare command and submit */
cmdlen = tegra_gcm_crypt_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
if (ret)
return ret;
@@ -786,7 +797,7 @@ static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
static int tegra_gcm_do_final(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx *rctx)
{
struct tegra_se *se = ctx->se;
u32 *cpuvaddr = se->cmdbuf->addr;
u32 *cpuvaddr = rctx->cmdbuf;
int cmdlen, ret, offset;
rctx->config = tegra234_aes_cfg(SE_ALG_GCM_FINAL, rctx->encrypt);
@@ -795,7 +806,7 @@ static int tegra_gcm_do_final(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
/* Prepare command and submit */
cmdlen = tegra_gcm_prep_final_cmd(se, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
if (ret)
return ret;
@@ -840,7 +851,7 @@ static inline int tegra_ccm_check_iv(const u8 *iv)
static unsigned int tegra_cbcmac_prep_cmd(struct tegra_se *se, struct tegra_aead_reqctx *rctx)
{
unsigned int data_count, i = 0;
u32 *cpuvaddr = se->cmdbuf->addr;
u32 *cpuvaddr = rctx->cmdbuf;
data_count = (rctx->inbuf.size / AES_BLOCK_SIZE) - 1;
@@ -873,7 +884,7 @@ static unsigned int tegra_cbcmac_prep_cmd(struct tegra_se *se, struct tegra_aead
static unsigned int tegra_ctr_prep_cmd(struct tegra_se *se, struct tegra_aead_reqctx *rctx)
{
unsigned int i = 0, j;
u32 *cpuvaddr = se->cmdbuf->addr;
u32 *cpuvaddr = rctx->cmdbuf;
cpuvaddr[i++] = host1x_opcode_setpayload(SE_CRYPTO_CTR_REG_COUNT);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->linear_ctr);
@@ -923,7 +934,7 @@ static int tegra_ccm_do_cbcmac(struct tegra_aead_ctx *ctx, struct tegra_aead_req
/* Prepare command and submit */
cmdlen = tegra_cbcmac_prep_cmd(se, rctx);
return tegra_se_host1x_submit(se, cmdlen);
return tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
}
static int tegra_ccm_set_msg_len(u8 *block, unsigned int msglen, int csize)
@@ -1130,7 +1141,7 @@ static int tegra_ccm_do_ctr(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx
/* Prepare command and submit */
cmdlen = tegra_ctr_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
if (ret)
return ret;
@@ -1231,6 +1242,7 @@ outbuf_err:
dma_free_coherent(ctx->se->dev, rctx->inbuf.size,
rctx->inbuf.buf, rctx->inbuf.addr);
kfree(rctx->cmdbuf);
crypto_finalize_aead_request(ctx->se->engine, req, ret);
return 0;
@@ -1304,6 +1316,7 @@ outbuf_err:
rctx->inbuf.buf, rctx->inbuf.addr);
/* Finalize the request if there are no errors */
kfree(rctx->cmdbuf);
crypto_finalize_aead_request(ctx->se->engine, req, ret);
return 0;
@@ -1434,6 +1447,10 @@ static int tegra_aead_crypt(struct aead_request *req, bool encrypt)
struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct tegra_aead_reqctx *rctx = aead_request_ctx(req);
rctx->cmdbuf = kzalloc(SE_MAX_CMDLEN, GFP_KERNEL);
if (!rctx->cmdbuf)
return -ENOMEM;
rctx->encrypt = encrypt;
return crypto_transfer_aead_request_to_engine(ctx->se->engine, req);
@@ -1465,7 +1482,7 @@ static int tegra_aead_setkey(struct crypto_aead *tfm,
static unsigned int tegra_cmac_prep_cmd(struct tegra_se *se, struct tegra_cmac_reqctx *rctx)
{
unsigned int data_count, res_bits = 0, i = 0, j;
u32 *cpuvaddr = se->cmdbuf->addr, op;
u32 *cpuvaddr = rctx->cmdbuf, op;
data_count = (rctx->datbuf.size / AES_BLOCK_SIZE);
@@ -1572,6 +1589,11 @@ static int tegra_cmac_do_update(struct ahash_request *req)
return 0;
}
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
return -ENOMEM;
/* Copy the previous residue first */
if (rctx->residue.size)
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
@@ -1595,7 +1617,7 @@ static int tegra_cmac_do_update(struct ahash_request *req)
cmdlen = tegra_cmac_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
/*
* If this is not the final update, copy the intermediate results
* from the registers so that it can be used in the next 'update'
@@ -1618,17 +1640,29 @@ static int tegra_cmac_do_final(struct ahash_request *req)
if (!req->nbytes && !rctx->total_len && ctx->fallback_tfm) {
return crypto_shash_tfm_digest(ctx->fallback_tfm,
rctx->datbuf.buf, 0, req->result);
NULL, 0, req->result);
}
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
rctx->datbuf.size = rctx->residue.size;
rctx->total_len += rctx->residue.size;
rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0);
if (rctx->residue.size) {
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->residue.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf) {
ret = -ENOMEM;
goto out_free;
}
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
}
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
/* Prepare command and submit */
cmdlen = tegra_cmac_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, rctx->cmdbuf, cmdlen);
if (ret)
goto out;
@@ -1640,10 +1674,14 @@ static int tegra_cmac_do_final(struct ahash_request *req)
writel(0, se->base + se->hw->regs->result + (i * 4));
out:
dma_free_coherent(se->dev, SE_SHA_BUFLEN,
rctx->datbuf.buf, rctx->datbuf.addr);
if (rctx->residue.size)
dma_free_coherent(se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
out_free:
dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm) * 2,
rctx->residue.buf, rctx->residue.addr);
kfree(rctx->cmdbuf);
return ret;
}
@@ -1754,18 +1792,16 @@ static int tegra_cmac_init(struct ahash_request *req)
rctx->task = SHA_FIRST;
rctx->blk_size = crypto_ahash_blocksize(tfm);
rctx->cmdbuf = kzalloc(SE_MAX_CMDLEN, GFP_KERNEL);
if (!rctx->cmdbuf)
return -ENOMEM;
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
&rctx->residue.addr, GFP_KERNEL);
if (!rctx->residue.buf)
goto resbuf_fail;
goto cmdbuf_free;
rctx->residue.size = 0;
rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
goto datbuf_fail;
rctx->datbuf.size = 0;
/* Clear any previous result */
@@ -1774,10 +1810,9 @@ static int tegra_cmac_init(struct ahash_request *req)
return 0;
datbuf_fail:
dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
rctx->residue.addr);
resbuf_fail:
cmdbuf_free:
kfree(rctx->cmdbuf);
return -ENOMEM;
}

View File

@@ -44,6 +44,7 @@ struct tegra_sha_reqctx {
unsigned int blk_size;
unsigned int task;
u32 key_id;
u32 *cmdbuf;
u32 result[HASH_RESULT_REG_COUNT];
struct ahash_request fallback_req;
};
@@ -305,7 +306,7 @@ static int tegra_sha_do_update(struct ahash_request *req)
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
unsigned int nblks, nresidue, size, ret;
u32 *cpuvaddr = ctx->se->cmdbuf->addr;
u32 *cpuvaddr = rctx->cmdbuf;
nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size;
nblks = (req->nbytes + rctx->residue.size) / rctx->blk_size;
@@ -335,6 +336,11 @@ static int tegra_sha_do_update(struct ahash_request *req)
return 0;
}
rctx->datbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->datbuf.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
return -ENOMEM;
/* Copy the previous residue first */
if (rctx->residue.size)
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
@@ -361,7 +367,7 @@ static int tegra_sha_do_update(struct ahash_request *req)
size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(ctx->se, size);
ret = tegra_se_host1x_submit(ctx->se, rctx->cmdbuf, size);
/*
* If this is not the final update, copy the intermediate results
@@ -371,6 +377,9 @@ static int tegra_sha_do_update(struct ahash_request *req)
if (!(rctx->task & SHA_FINAL))
tegra_sha_copy_hash_result(ctx->se, rctx);
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
return ret;
}
@@ -380,19 +389,28 @@ static int tegra_sha_do_final(struct ahash_request *req)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se;
u32 *cpuvaddr = se->cmdbuf->addr;
u32 *cpuvaddr = rctx->cmdbuf;
int size, ret = 0;
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
rctx->datbuf.size = rctx->residue.size;
rctx->total_len += rctx->residue.size;
rctx->config = tegra_sha_get_config(rctx->alg) |
SE_SHA_DST_MEMORY;
size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
if (rctx->residue.size) {
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->residue.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf) {
ret = -ENOMEM;
goto out_free;
}
ret = tegra_se_host1x_submit(se, size);
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
}
size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(se, rctx->cmdbuf, size);
if (ret)
goto out;
@@ -400,12 +418,16 @@ static int tegra_sha_do_final(struct ahash_request *req)
memcpy(req->result, rctx->digest.buf, rctx->digest.size);
out:
dma_free_coherent(se->dev, SE_SHA_BUFLEN,
rctx->datbuf.buf, rctx->datbuf.addr);
if (rctx->residue.size)
dma_free_coherent(se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
out_free:
dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm),
rctx->residue.buf, rctx->residue.addr);
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
rctx->digest.addr);
kfree(rctx->cmdbuf);
return ret;
}
@@ -530,6 +552,10 @@ static int tegra_sha_init(struct ahash_request *req)
rctx->blk_size = crypto_ahash_blocksize(tfm);
rctx->digest.size = crypto_ahash_digestsize(tfm);
rctx->cmdbuf = kzalloc(SE_MAX_CMDLEN, GFP_KERNEL);
if (!rctx->cmdbuf)
return -ENOMEM;
rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
&rctx->digest.addr, GFP_KERNEL);
if (!rctx->digest.buf)
@@ -540,20 +566,14 @@ static int tegra_sha_init(struct ahash_request *req)
if (!rctx->residue.buf)
goto resbuf_fail;
rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
goto datbuf_fail;
return 0;
datbuf_fail:
dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
rctx->residue.addr);
resbuf_fail:
dma_free_coherent(se->dev, SE_SHA_BUFLEN, rctx->datbuf.buf,
rctx->datbuf.addr);
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
rctx->digest.addr);
digbuf_fail:
kfree(rctx->cmdbuf);
return -ENOMEM;
}

View File

@@ -115,11 +115,11 @@ static int tegra_key_insert(struct tegra_se *se, const u8 *key,
u32 keylen, u16 slot, u32 alg)
{
const u32 *keyval = (u32 *)key;
u32 *addr = se->cmdbuf->addr, size;
u32 addr[100], size;
size = tegra_key_prep_ins_cmd(se, addr, keyval, keylen, slot, alg);
return tegra_se_host1x_submit(se, size);
return tegra_se_host1x_submit(se, addr, size);
}
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg)

View File

@@ -141,9 +141,10 @@ static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssi
return cmdbuf;
}
int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
int tegra_se_host1x_submit(struct tegra_se *se, u32 *cpuvaddr, u32 size)
{
struct host1x_job *job;
struct tegra_se_cmdbuf *cmdbuf;
int ret;
job = host1x_job_alloc(se->channel, 1, 0, true);
@@ -152,6 +153,12 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
return -ENOMEM;
}
cmdbuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
if (!cmdbuf)
goto job_put;
memcpy(cmdbuf->addr, cpuvaddr, size * 4);
job->syncpt = host1x_syncpt_get(se->syncpt);
job->syncpt_incrs = 1;
job->client = &se->client;
@@ -160,14 +167,14 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
job->engine_fallback_streamid = se->stream_id;
job->engine_streamid_offset = SE_STREAM_ID;
se->cmdbuf->words = size;
cmdbuf->words = size;
host1x_job_add_gather(job, &se->cmdbuf->bo, size, 0);
host1x_job_add_gather(job, &cmdbuf->bo, size, 0);
ret = host1x_job_pin(job, se->dev);
if (ret) {
dev_err(se->dev, "failed to pin host1x job\n");
goto job_put;
goto cmdbuf_put;
}
ret = host1x_job_submit(job);
@@ -184,10 +191,14 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
}
host1x_job_put(job);
tegra_se_cmdbuf_put(&cmdbuf->bo);
return 0;
job_unpin:
host1x_job_unpin(job);
cmdbuf_put:
tegra_se_cmdbuf_put(&cmdbuf->bo);
job_put:
host1x_job_put(job);
@@ -214,22 +225,14 @@ static int tegra_se_client_init(struct host1x_client *client)
se->syncpt_id = host1x_syncpt_id(se->syncpt);
se->cmdbuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
if (!se->cmdbuf) {
ret = -ENOMEM;
goto syncpt_put;
}
ret = se->hw->init_alg(se);
if (ret) {
dev_err(se->dev, "failed to register algorithms\n");
goto cmdbuf_put;
goto syncpt_put;
}
return 0;
cmdbuf_put:
tegra_se_cmdbuf_put(&se->cmdbuf->bo);
syncpt_put:
host1x_syncpt_put(se->syncpt);
channel_put:
@@ -243,7 +246,6 @@ static int tegra_se_client_deinit(struct host1x_client *client)
struct tegra_se *se = container_of(client, struct tegra_se, client);
se->hw->deinit_alg(se);
tegra_se_cmdbuf_put(&se->cmdbuf->bo);
host1x_syncpt_put(se->syncpt);
host1x_channel_put(se->channel);

View File

@@ -23,6 +23,7 @@
#define SE_OWNERSHIP_UID(x) FIELD_GET(GENMASK(7, 0), x)
#define TEGRA_GPSE_ID 3
#define SE_MAX_CMDLEN (100 * 4) /* max 100 commands of 4 bytes each */
#define SE_STREAM_ID 0x90
#define SE_SHA_CFG 0x4004
@@ -342,7 +343,6 @@
#define SE_CRYPTO_CTR_REG_COUNT 4
#define SE_MAX_KEYSLOT 15
#define SE_MAX_MEM_ALLOC SZ_4M
#define SE_SHA_BUFLEN 0x2000
#define SHA_FIRST BIT(0)
#define SHA_UPDATE BIT(1)
@@ -442,7 +442,6 @@ struct tegra_se {
const struct tegra_se_hw *hw;
struct host1x_client client;
struct host1x_channel *channel;
struct tegra_se_cmdbuf *cmdbuf;
struct crypto_engine *engine;
struct host1x_syncpt *syncpt;
struct device *dev;
@@ -525,7 +524,7 @@ void tegra_deinit_hash(struct tegra_se *se);
int tegra_key_submit(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg);
int tegra_se_host1x_submit(struct tegra_se *se, u32 size);
int tegra_se_host1x_submit(struct tegra_se *se, u32 *cpuvaddr, u32 size);
/* HOST1x OPCODES */
static inline u32 host1x_opcode_setpayload(unsigned int payload)

View File

@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* NVIDIA Tegra CSI Device
*
* Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -687,7 +686,7 @@ static int tegra_csi_set_format(struct v4l2_subdev *subdev,
}
static int tegra_csi_g_frame_interval(struct v4l2_subdev *sd,
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
struct v4l2_subdev_state *sd_state,
#endif
struct v4l2_subdev_frame_interval *vfi)
@@ -721,13 +720,13 @@ static int tegra_csi_enum_mbus_code(struct v4l2_subdev *sd,
static struct v4l2_subdev_video_ops tegra_csi_video_ops = {
.s_stream = tegra_csi_s_stream,
.g_input_status = tegra_csi_g_input_status,
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.g_frame_interval = tegra_csi_g_frame_interval,
#endif
};
static struct v4l2_subdev_pad_ops tegra_csi_pad_ops = {
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.get_frame_interval = tegra_csi_g_frame_interval,
#endif
.get_fmt = tegra_csi_get_format,

View File

@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2018-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* tegracam_v4l2 - tegra camera framework for v4l2 support
*
* Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/types.h>
#include <media/tegra-v4l2-camera.h>
#include <media/tegracam_core.h>
@@ -112,9 +114,30 @@ static int v4l2sd_g_input_status(struct v4l2_subdev *sd, u32 *status)
return 0;
}
static int cam_g_frame_interval(struct v4l2_subdev *sd,
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
struct v4l2_subdev_state *sd_state,
#endif
struct v4l2_subdev_frame_interval *ival)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct camera_common_data *s_data = to_camera_common_data(&client->dev);
if (!s_data)
return -EINVAL;
ival->interval.denominator = s_data->frmfmt[s_data->mode_prop_idx].framerates[0];
ival->interval.numerator = 1;
return 0;
}
static struct v4l2_subdev_video_ops v4l2sd_video_ops = {
.s_stream = v4l2sd_stream,
.g_input_status = v4l2sd_g_input_status,
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.g_frame_interval = cam_g_frame_interval,
.s_frame_interval = cam_g_frame_interval,
#endif
};
static struct v4l2_subdev_core_ops v4l2sd_core_ops = {
@@ -161,6 +184,10 @@ static int v4l2sd_set_fmt(struct v4l2_subdev *sd,
}
static struct v4l2_subdev_pad_ops v4l2sd_pad_ops = {
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.get_frame_interval = cam_g_frame_interval,
.set_frame_interval = cam_g_frame_interval,
#endif
.set_fmt = v4l2sd_set_fmt,
.get_fmt = v4l2sd_get_fmt,
.enum_mbus_code = camera_common_enum_mbus_code,

View File

@@ -2281,10 +2281,32 @@ static long tegra_channel_default_ioctl(struct file *file, void *fh,
return ret;
}
/* Implemented vidioc_s_parm and vidioc_g_parm ioctl to support multiple frame
* rates */
static int tegra_channel_s_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
struct tegra_channel *chan = video_drvdata(file);
struct v4l2_subdev *sd = chan->subdev_on_csi;
return v4l2_s_parm_cap(chan->video, sd, a);
}
static int tegra_channel_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
struct tegra_channel *chan = video_drvdata(file);
struct v4l2_subdev *sd = chan->subdev_on_csi;
return v4l2_g_parm_cap(chan->video, sd, a);
}
static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = {
.vidioc_querycap = tegra_channel_querycap,
.vidioc_enum_framesizes = tegra_channel_enum_framesizes,
.vidioc_enum_frameintervals = tegra_channel_enum_frameintervals,
.vidioc_s_parm = tegra_channel_s_parm,
.vidioc_g_parm = tegra_channel_g_parm,
.vidioc_enum_fmt_vid_cap = tegra_channel_enum_format,
.vidioc_g_fmt_vid_cap = tegra_channel_get_format,
.vidioc_s_fmt_vid_cap = tegra_channel_set_format,

View File

@@ -181,7 +181,7 @@ NV_CONFTEST_FUNCTION_COMPILE_TESTS += v4l2_async_subdev_nf_init
NV_CONFTEST_FUNCTION_COMPILE_TESTS += v4l2_async_notifier_init
NV_CONFTEST_FUNCTION_COMPILE_TESTS += v4l2_async_nf_init_has_v4l2_dev_arg
NV_CONFTEST_FUNCTION_COMPILE_TESTS += __v4l2_async_nf_add_subdev
NV_CONFTEST_FUNCTION_COMPILE_TESTS += v4l2_subdev_pad_ops_struct_has_get_frame_interval
NV_CONFTEST_FUNCTION_COMPILE_TESTS += v4l2_subdev_pad_ops_struct_has_get_set_frame_interval
NV_CONFTEST_FUNCTION_COMPILE_TESTS += v4l2_subdev_pad_ops_struct_has_dv_timings
NV_CONFTEST_FUNCTION_COMPILE_TESTS += vm_area_struct_has_const_vm_flags
NV_CONFTEST_GENERIC_COMPILE_TESTS += is_export_symbol_present_drm_gem_prime_fd_to_handle

View File

@@ -8082,10 +8082,12 @@ compile_test() {
compile_check_conftest "$CODE" "NV_V4L2_ASYNC_NF_ADD_SUBDEV_PRESENT" "" "functions"
;;
v4l2_subdev_pad_ops_struct_has_get_frame_interval)
v4l2_subdev_pad_ops_struct_has_get_set_frame_interval)
#
# Determine if struct v4l2_subdev_pad_ops has the 'get_frame_interval'
# function pointer.
# and 'set_frame_interval' function pointers. Note that it is only
# necessary to check for the presence of one because both were added
# by the same commit.
#
# Added by commit 287fe160834a ("media: v4l2-subdev: Turn
# .[gs]_frame_interval into pad operations") in Linux v6.8.
@@ -8098,7 +8100,7 @@ compile_test() {
}
"
compile_check_conftest "$CODE" \
"NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL" "" "types"
"NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL" "" "types"
;;
v4l2_subdev_pad_ops_struct_has_dv_timings)