ubwcp: set attribute path cleanup

Ensure buffer size is sufficient during re-configuration.
Ensure unused ioctl values are set to 0.
Fix use of uninitialized value when only plane-1 data is present.
Register mmap ula pa only if ubwcp configuration is successful.
Clarify failure handling of set attribute call.
Cleanup related code.

Change-Id: Ia6ac54e13aa2be1c4a1dc2d4b4a7715dad3aa142
Signed-off-by: Amol Jadi <quic_ajadi@quicinc.com>
This commit is contained in:
Amol Jadi
2023-04-27 21:11:41 -07:00
committed by Gerrit - the friendly Code Review server
parent ff5feb8adc
commit cce20f5e49
2 changed files with 67 additions and 77 deletions

View File

@@ -1174,10 +1174,7 @@ err:
return ret;
}
/* calculate ULA buffer parms
* TBD: how do we make sure uv_start address (not the offset)
* is aligned per requirement: cache line
*/
/* calculate ULA buffer parms */
static int ubwcp_calc_ula_params(struct ubwcp_driver *ubwcp,
struct ubwcp_buffer_attrs *attr,
size_t *ula_size,
@@ -1211,6 +1208,7 @@ static int ubwcp_calc_ula_params(struct ubwcp_driver *ubwcp,
*/
missing_plane = missing_plane_from_format(attr->image_format);
DBG_BUF_ATTR("ula params -->");
DBG_BUF_ATTR("ioctl_image_format : %d, std_format: %d", attr->image_format, format);
DBG_BUF_ATTR("planes_in_format : %d", planes);
DBG_BUF_ATTR("missing_plane : %d", missing_plane);
@@ -1246,13 +1244,8 @@ static int ubwcp_calc_ula_params(struct ubwcp_driver *ubwcp,
}
}
//TBD: cleanup
*ula_size = size;
DBG_BUF_ATTR("Before page align: Total ULA_Size: %d (0x%x) (planes + planar padding)",
*ula_size, *ula_size);
*ula_size = UBWCP_ALIGN(size, 4096);
DBG_BUF_ATTR("After page align : Total ULA_Size: %d (0x%x) (planes + planar padding)",
*ula_size, *ula_size);
DBG_BUF_ATTR("ULA_Size: %zu (0x%x) (before 4K align: %zu)", *ula_size, *ula_size, size);
return 0;
}
@@ -1274,12 +1267,19 @@ static int ubwcp_calc_ubwcp_buf_params(struct ubwcp_driver *ubwcp,
/* convert ioctl image format to standard image format */
format = to_std_format(attr->image_format);
missing_plane = missing_plane_from_format(attr->image_format);
planes = planes_in_format(format); //pass in 0 (RGB) should return 1
planes = planes_in_format(format);
DBG_BUF_ATTR("ubwcp params -->");
DBG_BUF_ATTR("ioctl_image_format : %d, std_format: %d", attr->image_format, format);
DBG_BUF_ATTR("planes_in_format : %d", planes);
DBG_BUF_ATTR("missing_plane : %d", missing_plane);
*md_p0 = 0;
*pd_p0 = 0;
*md_p1 = 0;
*pd_p1 = 0;
*stride_tp10_b = 0;
if (!missing_plane) {
*md_p0 = metadata_buf_sz(ubwcp, format, attr->width, attr->height, 0);
*pd_p0 = pixeldata_buf_sz(ubwcp, format, attr->width, attr->height, 0);
@@ -1289,23 +1289,17 @@ static int ubwcp_calc_ubwcp_buf_params(struct ubwcp_driver *ubwcp,
}
} else {
if (missing_plane == 1) {
*md_p0 = 0;
*pd_p0 = 0;
*md_p1 = metadata_buf_sz(ubwcp, format, attr->width, attr->height, 1);
*pd_p1 = pixeldata_buf_sz(ubwcp, format, attr->width, attr->height, 1);
} else {
*md_p0 = metadata_buf_sz(ubwcp, format, attr->width, attr->height, 0);
*pd_p0 = pixeldata_buf_sz(ubwcp, format, attr->width, attr->height, 0);
*md_p1 = 0;
*pd_p1 = 0;
}
}
if (format == TP10) {
stride_tp10_p = UBWCP_ALIGN(attr->width, 192);
*stride_tp10_b = (stride_tp10_p/3) + stride_tp10_p;
} else {
*stride_tp10_b = 0;
}
return 0;
@@ -1372,18 +1366,27 @@ static void ubwcp_dma_unmap(struct ubwcp_buf *buf)
}
}
static bool verify_dma_buf_size(struct ubwcp_buf *buf, size_t min_size)
{
size_t dma_len;
dma_len = sg_dma_len(buf->sgt->sgl);
if (dma_len < min_size) {
ERR("dma len: %zu is less than min ubwcp buffer size: %zu", dma_len, min_size);
return false;
} else
return true;
}
/* dma map ubwcp buffer */
static int ubwcp_dma_map(struct ubwcp_buf *buf,
struct device *dev,
size_t iova_min_size,
dma_addr_t *iova)
{
int ret = 0;
struct dma_buf *dma_buf = buf->dma_buf;
struct dma_buf_attachment *attachment;
struct sg_table *sgt;
size_t dma_len;
/* Map buffer to SMMU and get IOVA */
attachment = dma_buf_attach(dma_buf, dev);
@@ -1408,14 +1411,6 @@ static int ubwcp_dma_map(struct ubwcp_buf *buf,
goto err_unmap;
}
/* ensure that dma_buf is big enough for the new attrs */
dma_len = sg_dma_len(sgt->sgl);
if (dma_len < iova_min_size) {
ERR("dma len: %d is less than min ubwcp buffer size: %d",
dma_len, iova_min_size);
goto err_unmap;
}
*iova = sg_dma_address(sgt->sgl);
buf->attachment = attachment;
buf->sgt = sgt;
@@ -1500,13 +1495,9 @@ static void print_mmdata_desc(struct ubwcp_hw_meta_metadata *mmdata)
/* set buffer attributes:
* Failure:
* If a call to ubwcp_set_buf_attrs() fails, any attributes set from a previously
* successful ubwcp_set_buf_attrs() will be also removed. Thus,
* ubwcp_set_buf_attrs() implicitly does "unset previous attributes" and
* then "try to set these new attributes".
*
* The result of a failed call to ubwcp_set_buf_attrs() will leave the buffer
* in a linear mode, NOT with attributes from earlier successful call.
* This call may fail for multiple reasons and it will leave the buffer in an undefined state.
* In some situations it may leave the buffer in linear mapped state, and in other situations it
* may leave the buffer in previously set attributes state.
*/
int ubwcp_set_buf_attrs(struct dma_buf *dmabuf, struct ubwcp_buffer_attrs *attr)
{
@@ -1570,32 +1561,21 @@ int ubwcp_set_buf_attrs(struct dma_buf *dmabuf, struct ubwcp_buffer_attrs *attr)
mmdata = &buf->mmdata;
is_non_lin_buf = (buf->buf_attr.image_format != UBWCP_LINEAR);
//TBD: now that we have single exit point for all errors,
//we can limit this call to error only?
//also see if this can be part of reset_buf_attrs()
DBG_BUF_ATTR("resetting mmap to linear");
/* remove any earlier dma buf mmap configuration */
ret = ubwcp->mmap_config_fptr(buf->dma_buf, true, 0, 0);
if (ret) {
ERR("dma_buf_mmap_config() failed: %d", ret);
if (!ubwcp_buf_attrs_valid(ubwcp, attr)) {
ERR("Invalid buf attrs");
goto unlock;
}
if (!ubwcp_buf_attrs_valid(ubwcp, attr)) {
ERR("Invalid buf attrs");
goto err;
/* note: this also checks if buf is mmap'ed */
ret = ubwcp->mmap_config_fptr(buf->dma_buf, true, 0, 0);
if (ret) {
ERR("dma_buf_mmap_config(0,0) failed: %d", ret);
goto unlock;
}
if (attr->image_format == UBWCP_LINEAR) {
DBG_BUF_ATTR("Linear format requested");
/* linear format request with permanent range xlation doesn't
* make sense. need to define behavior if this happens.
* note: with perm set, desc is allocated to this buffer.
*/
//TBD: UBWCP_ASSERT(!buf->perm);
if (buf->buf_attr_set)
reset_buf_attrs(buf);
@@ -1615,35 +1595,27 @@ int ubwcp_set_buf_attrs(struct dma_buf *dmabuf, struct ubwcp_buffer_attrs *attr)
std_image_format = to_std_format(attr->image_format);
if (std_image_format == STD_IMAGE_FORMAT_INVALID) {
ERR("Unable to map ioctl image format to std image format");
goto err;
goto unlock;
}
/* Calculate uncompressed-buffer size. */
DBG_BUF_ATTR("");
DBG_BUF_ATTR("");
DBG_BUF_ATTR("Calculating ula params -->");
ret = ubwcp_calc_ula_params(ubwcp, attr, &ula_size, &ula_y_plane_size, &uv_start_offset);
if (ret) {
ERR("ubwcp_calc_ula_params() failed: %d", ret);
goto err;
goto unlock;
}
ret = ubwcp_validate_uv_align(ubwcp, attr, ula_y_plane_size, uv_start_offset);
if (ret) {
ERR("ubwcp_validate_uv_align() failed: %d", ret);
goto err;
goto unlock;
}
DBG_BUF_ATTR("");
DBG_BUF_ATTR("");
DBG_BUF_ATTR("Calculating ubwcp params -->");
ret = ubwcp_calc_ubwcp_buf_params(ubwcp, attr,
&metadata_p0, &pixeldata_p0,
&metadata_p1, &pixeldata_p1,
&stride_tp10_b);
ret = ubwcp_calc_ubwcp_buf_params(ubwcp, attr, &metadata_p0, &pixeldata_p0, &metadata_p1,
&pixeldata_p1, &stride_tp10_b);
if (ret) {
ERR("ubwcp_calc_buf_params() failed: %d", ret);
goto err;
goto unlock;
}
iova_min_size = metadata_p0 + pixeldata_p0 + metadata_p1 + pixeldata_p1;
@@ -1674,19 +1646,10 @@ int ubwcp_set_buf_attrs(struct dma_buf *dmabuf, struct ubwcp_buffer_attrs *attr)
DBG_BUF_ATTR("Allocated ULA_PA: 0x%p of size: 0x%zx", ula_pa, ula_size);
DBG_BUF_ATTR("");
/* inform ULA-PA to dma-heap: needed for dma-heap to do CMOs later on */
DBG_BUF_ATTR("Calling mmap_config(): ULA_PA: 0x%p size: 0x%zx", ula_pa, ula_size);
ret = ubwcp->mmap_config_fptr(buf->dma_buf, false, buf->ula_pa,
buf->ula_size);
if (ret) {
ERR("dma_buf_mmap_config() failed: %d", ret);
goto err;
}
/* dma map only the first time attribute is set */
if (!buf->buf_attr_set) {
/* linear -> ubwcp. map ubwcp buffer */
ret = ubwcp_dma_map(buf, ubwcp->dev_buf_cb, iova_min_size, &iova_base);
ret = ubwcp_dma_map(buf, ubwcp->dev_buf_cb, &iova_base);
if (ret) {
ERR("ubwcp_dma_map() failed: %d", ret);
goto err;
@@ -1695,6 +1658,9 @@ int ubwcp_set_buf_attrs(struct dma_buf *dmabuf, struct ubwcp_buffer_attrs *attr)
iova_base, iova_min_size, iova_base + iova_min_size);
}
if(!verify_dma_buf_size(buf, iova_min_size))
goto err;
uv_start = ula_pa + uv_start_offset;
if (!IS_ALIGNED(uv_start, 64)) {
ERR("ERROR: uv_start is NOT aligned to cache line");
@@ -1751,9 +1717,18 @@ int ubwcp_set_buf_attrs(struct dma_buf *dmabuf, struct ubwcp_buffer_attrs *attr)
goto err;
}
/* inform ULA-PA to dma-heap */
DBG_BUF_ATTR("Calling mmap_config(): ULA_PA: 0x%p size: 0x%zx", ula_pa, ula_size);
ret = ubwcp->mmap_config_fptr(buf->dma_buf, false, buf->ula_pa, buf->ula_size);
if (ret) {
ERR("dma_buf_mmap_config() failed: %d", ret);
if (!is_non_lin_buf)
dec_num_non_lin_buffers(ubwcp);
goto err;
}
buf->buf_attr = *attr;
buf->buf_attr_set = true;
//TBD: UBWCP_ASSERT(!buf->perm);
mutex_unlock(&buf->lock);
trace_ubwcp_set_buf_attrs_end(dmabuf);
return 0;
@@ -2325,6 +2300,16 @@ static long ubwcp_ioctl(struct file *file, unsigned int ioctl_num, unsigned long
return -EFAULT;
}
DBG("IOCTL : SET_BUF_ATTR: fd = %d", buf_attr_ioctl.fd);
if (buf_attr_ioctl.attr.unused1 || buf_attr_ioctl.attr.unused2
|| buf_attr_ioctl.attr.unused3 || buf_attr_ioctl.attr.unused4
|| buf_attr_ioctl.attr.unused5 || buf_attr_ioctl.attr.unused6
|| buf_attr_ioctl.attr.unused7 || buf_attr_ioctl.attr.unused8
|| buf_attr_ioctl.attr.unused9) {
ERR("ERROR: buf attr unused values must be set to 0");
return -EINVAL;
}
return ubwcp_set_buf_attrs_ioctl(&buf_attr_ioctl);
case UBWCP_IOCTL_GET_HW_VER: