Skip to content

Commit 11a5c0b

Browse files
6by9naushir
authored andcommitted
media: rp1-cfe: Fix up link validation for CFE CFG input
After commit 5fd3e24 ("media: v4l2-subdev: Support hybrid links in v4l2_subdev_link_validate()") link_validate is called on V4L2 OUTPUT devices such as the CFE cfg buffers input. The CFE link_validate function was assuming it was always the sink of a link, which goes wrong on that port and does an invalid dereference. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
1 parent faa16be commit 11a5c0b

File tree

1 file changed

+101
-56
lines changed
  • drivers/media/platform/raspberrypi/rp1_cfe

1 file changed

+101
-56
lines changed

drivers/media/platform/raspberrypi/rp1_cfe/cfe.c

Lines changed: 101 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,101 +1658,143 @@ static const struct v4l2_file_operations cfe_fops = {
16581658
.mmap = vb2_fop_mmap,
16591659
};
16601660

1661-
static int cfe_video_link_validate(struct media_link *link)
1661+
static int cfe_video_link_validate(struct cfe_node *node,
1662+
struct v4l2_subdev *remote_sd,
1663+
struct v4l2_mbus_framefmt *remote_fmt)
16621664
{
1663-
struct video_device *vd = container_of(link->sink->entity,
1664-
struct video_device, entity);
1665-
struct cfe_node *node = container_of(vd, struct cfe_node, video_dev);
16661665
struct cfe_device *cfe = node->cfe;
1667-
struct v4l2_mbus_framefmt *source_fmt;
1668-
struct v4l2_subdev_state *state;
1669-
struct v4l2_subdev *source_sd;
1670-
int ret = 0;
1671-
1672-
cfe_dbg("%s: [%s] link \"%s\":%u -> \"%s\":%u\n", __func__,
1673-
node_desc[node->id].name,
1674-
link->source->entity->name, link->source->index,
1675-
link->sink->entity->name, link->sink->index);
16761666

1677-
if (!media_entity_remote_source_pad_unique(link->sink->entity)) {
1678-
cfe_err("video node %s pad not connected\n", vd->name);
1679-
return -ENOTCONN;
1680-
}
1681-
1682-
source_sd = media_entity_to_v4l2_subdev(link->source->entity);
1683-
1684-
state = v4l2_subdev_lock_and_get_active_state(source_sd);
1685-
1686-
source_fmt = v4l2_subdev_state_get_format(state,
1687-
link->source->index);
1688-
if (!source_fmt) {
1689-
ret = -EINVAL;
1690-
goto out;
1667+
if (!remote_fmt) {
1668+
return -EINVAL;
16911669
}
16921670

16931671
if (is_image_output_node(node)) {
16941672
struct v4l2_pix_format *pix_fmt = &node->vid_fmt.fmt.pix;
16951673
const struct cfe_fmt *fmt = NULL;
16961674
unsigned int i;
16971675

1698-
if (source_fmt->width != pix_fmt->width ||
1699-
source_fmt->height != pix_fmt->height) {
1676+
if (remote_fmt->width != pix_fmt->width ||
1677+
remote_fmt->height != pix_fmt->height) {
17001678
cfe_err("Wrong width or height %ux%u (remote pad set to %ux%u)\n",
17011679
pix_fmt->width, pix_fmt->height,
1702-
source_fmt->width,
1703-
source_fmt->height);
1704-
ret = -EINVAL;
1705-
goto out;
1680+
remote_fmt->width,
1681+
remote_fmt->height);
1682+
return -EINVAL;
17061683
}
17071684

17081685
for (i = 0; i < ARRAY_SIZE(formats); i++) {
1709-
if (formats[i].code == source_fmt->code &&
1686+
if (formats[i].code == remote_fmt->code &&
17101687
formats[i].fourcc == pix_fmt->pixelformat) {
17111688
fmt = &formats[i];
17121689
break;
17131690
}
17141691
}
17151692
if (!fmt) {
17161693
cfe_err("Format mismatch!\n");
1717-
ret = -EINVAL;
1718-
goto out;
1694+
return -EINVAL;
17191695
}
17201696
} else if (is_csi2_node(node) && is_meta_output_node(node)) {
17211697
struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta;
17221698
const struct cfe_fmt *fmt;
1723-
u32 source_size;
1699+
u32 remote_size;
17241700

1725-
fmt = find_format_by_code(source_fmt->code);
1701+
fmt = find_format_by_code(remote_fmt->code);
17261702
if (!fmt || fmt->fourcc != meta_fmt->dataformat) {
17271703
cfe_err("Metadata format mismatch!\n");
1728-
ret = -EINVAL;
1729-
goto out;
1704+
return -EINVAL;
17301705
}
17311706

1732-
source_size = DIV_ROUND_UP(source_fmt->width * source_fmt->height * fmt->depth, 8);
1707+
remote_size = DIV_ROUND_UP(remote_fmt->width * remote_fmt->height * fmt->depth, 8);
17331708

1734-
if (source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) {
1709+
if (remote_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) {
17351710
cfe_err("Bad metadata mbus format\n");
1736-
ret = -EINVAL;
1737-
goto out;
1711+
return -EINVAL;
17381712
}
17391713

1740-
if (source_size > meta_fmt->buffersize) {
1714+
if (remote_size > meta_fmt->buffersize) {
17411715
cfe_err("Metadata buffer too small: %u < %u\n",
1742-
meta_fmt->buffersize, source_size);
1743-
ret = -EINVAL;
1744-
goto out;
1716+
meta_fmt->buffersize, remote_size);
1717+
return -EINVAL;
17451718
}
17461719
}
17471720

1748-
out:
1721+
return 0;
1722+
}
1723+
1724+
static int cfe_video_link_validate_output(struct media_link *link)
1725+
{
1726+
struct video_device *vd = container_of(link->source->entity,
1727+
struct video_device, entity);
1728+
struct cfe_node *node = container_of(vd, struct cfe_node, video_dev);
1729+
struct cfe_device *cfe = node->cfe;
1730+
struct v4l2_mbus_framefmt *sink_fmt;
1731+
struct v4l2_subdev_state *state;
1732+
struct v4l2_subdev *sink_sd;
1733+
int ret;
1734+
1735+
cfe_dbg("%s: [%s] link \"%s\":%u -> \"%s\":%u\n", __func__,
1736+
node_desc[node->id].name,
1737+
link->source->entity->name, link->source->index,
1738+
link->sink->entity->name, link->sink->index);
1739+
1740+
if (!media_entity_remote_source_pad_unique(link->source->entity)) {
1741+
cfe_err("video node %s pad not connected\n", vd->name);
1742+
return -ENOTCONN;
1743+
}
1744+
1745+
sink_sd = media_entity_to_v4l2_subdev(link->sink->entity);
1746+
1747+
state = v4l2_subdev_lock_and_get_active_state(sink_sd);
1748+
1749+
sink_fmt = v4l2_subdev_state_get_format(state, link->sink->index);
1750+
1751+
ret = cfe_video_link_validate(node, sink_sd, sink_fmt);
1752+
1753+
v4l2_subdev_unlock_state(state);
1754+
1755+
return ret;
1756+
}
1757+
1758+
static int cfe_video_link_validate_capture(struct media_link *link)
1759+
{
1760+
struct video_device *vd = container_of(link->sink->entity,
1761+
struct video_device, entity);
1762+
struct cfe_node *node = container_of(vd, struct cfe_node, video_dev);
1763+
struct cfe_device *cfe = node->cfe;
1764+
struct v4l2_mbus_framefmt *source_fmt;
1765+
struct v4l2_subdev_state *state;
1766+
struct v4l2_subdev *source_sd;
1767+
int ret;
1768+
1769+
cfe_dbg("%s: [%s] link \"%s\":%u -> \"%s\":%u\n", __func__,
1770+
node_desc[node->id].name,
1771+
link->source->entity->name, link->source->index,
1772+
link->sink->entity->name, link->sink->index);
1773+
1774+
if (!media_entity_remote_source_pad_unique(link->sink->entity)) {
1775+
cfe_err("video node %s pad not connected\n", vd->name);
1776+
return -ENOTCONN;
1777+
}
1778+
1779+
source_sd = media_entity_to_v4l2_subdev(link->source->entity);
1780+
1781+
state = v4l2_subdev_lock_and_get_active_state(source_sd);
1782+
1783+
source_fmt = v4l2_subdev_state_get_format(state, link->source->index);
1784+
1785+
ret = cfe_video_link_validate(node, source_sd, source_fmt);
1786+
17491787
v4l2_subdev_unlock_state(state);
17501788

17511789
return ret;
17521790
}
17531791

1754-
static const struct media_entity_operations cfe_media_entity_ops = {
1755-
.link_validate = cfe_video_link_validate,
1792+
static const struct media_entity_operations cfe_media_entity_ops_output = {
1793+
.link_validate = cfe_video_link_validate_output,
1794+
};
1795+
1796+
static const struct media_entity_operations cfe_media_entity_ops_capture = {
1797+
.link_validate = cfe_video_link_validate_capture,
17561798
};
17571799

17581800
static int cfe_video_link_notify(struct media_link *link, u32 flags,
@@ -1917,12 +1959,15 @@ static int cfe_register_node(struct cfe_device *cfe, int id)
19171959
vdev->release = cfe_node_release;
19181960
vdev->fops = &cfe_fops;
19191961
vdev->ioctl_ops = &cfe_ioctl_ops;
1920-
vdev->entity.ops = &cfe_media_entity_ops;
19211962
vdev->v4l2_dev = &cfe->v4l2_dev;
1922-
vdev->vfl_dir = (node_supports_image_output(node) ||
1923-
node_supports_meta_output(node)) ?
1924-
VFL_DIR_RX :
1925-
VFL_DIR_TX;
1963+
if ((node_supports_image_output(node) ||
1964+
node_supports_meta_output(node))) {
1965+
vdev->entity.ops = &cfe_media_entity_ops_capture;
1966+
vdev->vfl_dir = VFL_DIR_RX;
1967+
} else {
1968+
vdev->entity.ops = &cfe_media_entity_ops_output;
1969+
vdev->vfl_dir = VFL_DIR_TX;
1970+
}
19261971
vdev->queue = q;
19271972
vdev->lock = &node->lock;
19281973
vdev->device_caps = node_desc[id].caps;

0 commit comments

Comments
 (0)