kernel: nvidia-oot: Fix KMD coverity defects

Fix INT30-C, ARR30-C, EXP34-C, and MEM30-C coverity defects for channel.c

Jira CAMERASW-29897

Change-Id: I0ae0ee26273455b6e5a80a0ea5099e648dbc4097
Signed-off-by: yangxu <yangxu@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3265973
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Xiaoming Xiang <xxiang@nvidia.com>
Reviewed-by: Praveen AC <pac@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
This commit is contained in:
yangxu
2024-12-11 09:27:13 +00:00
committed by Jon Hunter
parent 1cd89f4693
commit e078bbbe94

View File

@@ -115,15 +115,25 @@ static u32 gang_mode_height(enum camera_gang_mode gang_mode,
static void update_gang_mode_params(struct tegra_channel *chan) static void update_gang_mode_params(struct tegra_channel *chan)
{ {
u32 numerator_product = 0;
chan->gang_width = gang_mode_width(chan->gang_mode, chan->gang_width = gang_mode_width(chan->gang_mode,
chan->format.width); chan->format.width);
chan->gang_height = gang_mode_height(chan->gang_mode, chan->gang_height = gang_mode_height(chan->gang_mode,
chan->format.height); chan->format.height);
chan->gang_bytesperline = ((chan->gang_width * if (__builtin_umul_overflow(chan->gang_width, chan->fmtinfo->bpp.numerator,
chan->fmtinfo->bpp.numerator) / &numerator_product)) {
chan->fmtinfo->bpp.denominator); dev_err(chan->vi->dev,
chan->gang_sizeimage = chan->gang_bytesperline * "%s: calculate the width product failed due to an overflow\n", __func__);
chan->format.height; return;
}
chan->gang_bytesperline = (numerator_product / chan->fmtinfo->bpp.denominator);
if (__builtin_umul_overflow(chan->gang_bytesperline, chan->format.height,
&chan->gang_sizeimage)) {
dev_err(chan->vi->dev,
"%s: update gang size image failed due to an overflow\n", __func__);
return;
}
gang_buffer_offsets(chan); gang_buffer_offsets(chan);
} }
@@ -157,7 +167,13 @@ static u32 get_aligned_buffer_size(struct tegra_channel *chan,
u32 temp_size, size; u32 temp_size, size;
height_aligned = roundup(height, chan->height_align); height_aligned = roundup(height, chan->height_align);
temp_size = bytesperline * height_aligned;
if (__builtin_umul_overflow(bytesperline, height_aligned, &temp_size)) {
dev_err(&chan->video->dev,
"%s: calculate the buffer size failed due to an overflow\n", __func__);
return 0;
}
size = roundup(temp_size, chan->size_align); size = roundup(temp_size, chan->size_align);
return size; return size;
@@ -257,7 +273,15 @@ static void tegra_channel_update_format(struct tegra_channel *chan,
{ {
u32 denominator = (!bpp->denominator) ? 1 : bpp->denominator; u32 denominator = (!bpp->denominator) ? 1 : bpp->denominator;
u32 numerator = (!bpp->numerator) ? 1 : bpp->numerator; u32 numerator = (!bpp->numerator) ? 1 : bpp->numerator;
u32 bytesperline = (width * numerator / denominator); u32 scaled_width = 0;
u32 bytesperline = 0;
if (__builtin_umul_overflow(width, numerator, &scaled_width)) {
dev_err(&chan->video->dev, "%s: update format failed due to an overflow\n",
__func__);
return;
}
bytesperline = (scaled_width / denominator);
/* Align stride */ /* Align stride */
if (chan->vi->fops->vi_stride_align) if (chan->vi->fops->vi_stride_align)
@@ -389,7 +413,12 @@ void release_buffer(struct tegra_channel *chan,
s64 frame_arrived_ts = 0; s64 frame_arrived_ts = 0;
/* release one frame */ /* release one frame */
vbuf->sequence = chan->sequence++; vbuf->sequence = chan->sequence;
if (__builtin_uadd_overflow(chan->sequence, 1, &chan->sequence)) {
dev_err(&chan->video->dev,
"%s: release buffer failed due to an overflow\n", __func__);
return;
}
vbuf->field = V4L2_FIELD_NONE; vbuf->field = V4L2_FIELD_NONE;
vb2_set_plane_payload(&vbuf->vb2_buf, vb2_set_plane_payload(&vbuf->vb2_buf,
0, chan->format.sizeimage); 0, chan->format.sizeimage);
@@ -543,7 +572,12 @@ static void add_buffer_to_ring(struct tegra_channel *chan,
/* Mark buffer state as error before start */ /* Mark buffer state as error before start */
spin_lock(&chan->buffer_lock); spin_lock(&chan->buffer_lock);
chan->buffer_state[chan->save_index] = VB2_BUF_STATE_ERROR; chan->buffer_state[chan->save_index] = VB2_BUF_STATE_ERROR;
chan->buffers[chan->save_index++] = vb; chan->buffers[chan->save_index] = vb;
if (__builtin_uadd_overflow(chan->save_index, 1, &chan->save_index)) {
dev_err(&chan->video->dev,
"%s: save the buffer to the ring failed due to an overflow\n", __func__);
return;
}
if (chan->save_index >= chan->capture_queue_depth) if (chan->save_index >= chan->capture_queue_depth)
chan->save_index = 0; chan->save_index = 0;
chan->num_buffers++; chan->num_buffers++;
@@ -552,7 +586,7 @@ static void add_buffer_to_ring(struct tegra_channel *chan,
static void update_state_to_buffer(struct tegra_channel *chan, int state) static void update_state_to_buffer(struct tegra_channel *chan, int state)
{ {
int save_index = (chan->save_index - PREVIOUS_BUFFER_DEC_INDEX); int save_index = ((int)chan->save_index - PREVIOUS_BUFFER_DEC_INDEX);
/* save index decrements by 2 as 3 bufs are added in ring buffer */ /* save index decrements by 2 as 3 bufs are added in ring buffer */
if (save_index < 0) if (save_index < 0)
@@ -596,7 +630,7 @@ void tegra_channel_ec_close(struct tegra_mc_vi *vi)
/* clear all channles sync point fifo context */ /* clear all channles sync point fifo context */
list_for_each_entry(chan, &vi->vi_chans, list) { list_for_each_entry(chan, &vi->vi_chans, list) {
memset(&chan->syncpoint_fifo[0], memset(chan->syncpoint_fifo,
0, sizeof(chan->syncpoint_fifo)); 0, sizeof(chan->syncpoint_fifo));
} }
} }
@@ -979,6 +1013,11 @@ int tegra_channel_set_power(struct tegra_channel *chan, bool on)
} }
/* Power on CSI at the last to complete calibration of mipi lanes */ /* Power on CSI at the last to complete calibration of mipi lanes */
if ((chan->num_subdevs <= 0) || (chan->num_subdevs > MAX_SUBDEVICES)) {
dev_err(chan->vi->dev, "%s: set power failed due to an invalid num_subdevs value\n",
__func__);
return -EINVAL;
}
for (num_sd = chan->num_subdevs - 1; num_sd >= 0; num_sd--) { for (num_sd = chan->num_subdevs - 1; num_sd >= 0; num_sd--) {
sd = chan->subdev[num_sd]; sd = chan->subdev[num_sd];
@@ -1138,10 +1177,17 @@ tegra_channel_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
if (f->index >= bitmap_weight(fmts_bitmap, MAX_FORMAT_NUM)) if (f->index >= bitmap_weight(fmts_bitmap, MAX_FORMAT_NUM))
return -EINVAL; return -EINVAL;
for (i = 0; i < f->index + 1; i++, index++) for (i = 0; i < f->index + 1; i++, index++) {
index = find_next_bit(fmts_bitmap, MAX_FORMAT_NUM, index); index = find_next_bit(fmts_bitmap, MAX_FORMAT_NUM, index);
if (index >= MAX_FORMAT_NUM)
break;
}
index -= 1; if (__builtin_usub_overflow(index, 1, &index)) {
dev_err(chan->vi->dev, "%s: update pixel format failed due to an overflow\n",
__func__);
return -EOVERFLOW;
}
f->pixelformat = tegra_core_get_fourcc_by_idx(chan, index); f->pixelformat = tegra_core_get_fourcc_by_idx(chan, index);
return 0; return 0;
@@ -1324,6 +1370,12 @@ int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)
if (!s_data) if (!s_data)
break; break;
if (ctrl->val >= ARRAY_SIZE(switch_ctrl_qmenu)) {
dev_err(&chan->video->dev,
"%s: update enable override failed due to an invalid value\n",
__func__);
return -EINVAL;
}
if (switch_ctrl_qmenu[ctrl->val] == SWITCH_ON) { if (switch_ctrl_qmenu[ctrl->val] == SWITCH_ON) {
s_data->override_enable = true; s_data->override_enable = true;
dev_dbg(&chan->video->dev, dev_dbg(&chan->video->dev,
@@ -1343,6 +1395,12 @@ int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)
&chan->fmtinfo->bpp, 0); &chan->fmtinfo->bpp, 0);
break; break;
case TEGRA_CAMERA_CID_VI_SIZE_ALIGN: case TEGRA_CAMERA_CID_VI_SIZE_ALIGN:
if (ctrl->val >= ARRAY_SIZE(size_align_ctrl_qmenu)) {
dev_err(&chan->video->dev,
"%s: update size alignment failed due to an invalid value\n",
__func__);
return -EINVAL;
}
chan->size_align = size_align_ctrl_qmenu[ctrl->val]; chan->size_align = size_align_ctrl_qmenu[ctrl->val];
tegra_channel_update_format(chan, chan->format.width, tegra_channel_update_format(chan, chan->format.width,
chan->format.height, chan->format.height,
@@ -2123,8 +2181,13 @@ __tegra_channel_try_format(struct tegra_channel *chan,
&pix->width, &pix->height, &pix->bytesperline); &pix->width, &pix->height, &pix->bytesperline);
pix->sizeimage = get_aligned_buffer_size(chan, pix->sizeimage = get_aligned_buffer_size(chan,
pix->bytesperline, pix->height); pix->bytesperline, pix->height);
if (chan->fmtinfo->fourcc == V4L2_PIX_FMT_NV16) if (chan->fmtinfo->fourcc == V4L2_PIX_FMT_NV16) {
pix->sizeimage *= 2; if (__builtin_umul_overflow(pix->sizeimage, 2, &pix->sizeimage)) {
dev_err(chan->vi->dev, "%s: update size image failed due to an overflow\n",
__func__);
return -EOVERFLOW;
}
}
return ret; return ret;
} }
@@ -2492,21 +2555,24 @@ static int tegra_channel_csi_init(struct tegra_channel *chan)
int idx = 0; int idx = 0;
struct tegra_mc_vi *vi = chan->vi; struct tegra_mc_vi *vi = chan->vi;
int ret = 0; int ret = 0;
unsigned int portnum = 0;
chan->gang_mode = CAMERA_NO_GANG_MODE; chan->gang_mode = CAMERA_NO_GANG_MODE;
chan->total_ports = 0; chan->total_ports = 0;
memset(&chan->port[0], INVALID_CSI_PORT, TEGRA_CSI_BLOCKS); memset(&chan->port[0], INVALID_CSI_PORT, TEGRA_CSI_BLOCKS);
memset(&chan->syncpoint_fifo[0], 0, sizeof(chan->syncpoint_fifo)); memset(chan->syncpoint_fifo, 0, sizeof(chan->syncpoint_fifo));
if (chan->pg_mode) { if (chan->pg_mode) {
/* If VI has 4 existing channels, chan->id will start /* If VI has 4 existing channels, chan->id will start
* from 4 for the first TPG channel, which uses PORT_A(0). * from 4 for the first TPG channel, which uses PORT_A(0).
* To get the correct PORT number, subtract existing number of * To get the correct PORT number, subtract existing number of
* channels from chan->id. * channels from chan->id.
*/ */
chan->port[0] = (chan->id - vi->num_channels) if (__builtin_usub_overflow(chan->id, vi->num_channels, &portnum)) {
% NUM_TPG_INSTANCE; dev_err(vi->dev, "%s: csi init failed due to an overflow\n", __func__);
chan->virtual_channel = (chan->id - vi->num_channels) return -EOVERFLOW;
/ NUM_TPG_INSTANCE; }
chan->port[0] = portnum % NUM_TPG_INSTANCE;
chan->virtual_channel = portnum / NUM_TPG_INSTANCE;
WARN_ON(chan->port[0] > vi->csi->num_tpg_channels); WARN_ON(chan->port[0] > vi->csi->num_tpg_channels);
chan->numlanes = 2; chan->numlanes = 2;
@@ -2534,6 +2600,7 @@ int tegra_channel_init_video(struct tegra_channel *chan)
{ {
struct tegra_mc_vi *vi = chan->vi; struct tegra_mc_vi *vi = chan->vi;
int ret = 0, len = 0; int ret = 0, len = 0;
unsigned int portnum = 0;
if (chan->video) { if (chan->video) {
dev_err(&chan->video->dev, "video device already allocated\n"); dev_err(&chan->video->dev, "video device already allocated\n");
@@ -2541,6 +2608,10 @@ int tegra_channel_init_video(struct tegra_channel *chan)
} }
chan->video = video_device_alloc(); chan->video = video_device_alloc();
if (chan->video == NULL) {
dev_err(vi->dev, "%s: video device alloc error\n", __func__);
return -EINVAL;
}
/* Initialize the media entity... */ /* Initialize the media entity... */
chan->pad.flags = MEDIA_PAD_FL_SINK; chan->pad.flags = MEDIA_PAD_FL_SINK;
@@ -2563,9 +2634,18 @@ int tegra_channel_init_video(struct tegra_channel *chan)
chan->video->fops = &tegra_channel_fops; chan->video->fops = &tegra_channel_fops;
chan->video->v4l2_dev = &vi->v4l2_dev; chan->video->v4l2_dev = &vi->v4l2_dev;
chan->video->queue = &chan->queue; chan->video->queue = &chan->queue;
if (chan->pg_mode) {
if (__builtin_usub_overflow(chan->id, vi->num_channels, &portnum)) {
dev_err(&chan->video->dev,
"%s: video device init failed due to an overflow\n", __func__);
ret = -EOVERFLOW;
goto ctrl_init_error;
}
} else {
portnum = chan->port[0];
}
len = snprintf(chan->video->name, sizeof(chan->video->name), "%s-%s-%u", len = snprintf(chan->video->name, sizeof(chan->video->name), "%s-%s-%u",
dev_name(vi->dev), chan->pg_mode ? "tpg" : "output", dev_name(vi->dev), chan->pg_mode ? "tpg" : "output", portnum);
chan->pg_mode ? (chan->id - vi->num_channels) : chan->port[0]);
if (len < 0) { if (len < 0) {
ret = -EINVAL; ret = -EINVAL;
goto ctrl_init_error; goto ctrl_init_error;
@@ -2585,9 +2665,9 @@ int tegra_channel_init_video(struct tegra_channel *chan)
return ret; return ret;
ctrl_init_error: ctrl_init_error:
video_device_release(chan->video);
media_entity_cleanup(&chan->video->entity); media_entity_cleanup(&chan->video->entity);
v4l2_ctrl_handler_free(&chan->ctrl_handler); v4l2_ctrl_handler_free(&chan->ctrl_handler);
video_device_release(chan->video);
return ret; return ret;
} }
EXPORT_SYMBOL(tegra_channel_init_video); EXPORT_SYMBOL(tegra_channel_init_video);