mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
drm-misc-fixes for v7.2-rc5:
- Improve damage handling in appletbdrm. - Fix harmful fragmenting of MM by backing up TTM pages at native page order. - Fix timeout handling in amdxdna. - Fix imagination locking for map/unmap operations. - Fix mm leak in gpusvm eviction. - Properly zero page array in gpusvm mm scanning. - Prevent trusted shader bo's from being mapped again in vc4. - Validate shader array size in vmwgfx. - Fix length calculation bugs in ethosu. - Better error handling during pagemap migration. - Improve v3d suspend. - Kconfig updates for some panels. - Handle missing iovcc in ili9881c panel. - Fix vc4 unbind. - Add i2c error handling in gma500. - Fix kunit tests on pp64le and s390x. - Prevent rearming vc4 timer on shutdown. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAmpjDjgACgkQ/lWMcqZw E8NoIQ/+PaoFa25I+9e+RgtgjYWLKpYoRdDHi7u7zUPzr5Z7XzAGPUYG0lYc6Gxw zQicvLcMCiBW8+mwTBytLESIXn5SfjFP0KPYhCnyXSnDRdHiWj+nlXD1A0mG5YQ+ cFDYyyXS2Ka1TsdPbXr6f3zyNDSuhmRJbo6qGvEYR+KimyHMU8zqXPD6F4GazHd2 ocQrGzOP3608oJHRiGA5zs5IfupbO5uvQE9oJJ/mpdYxhd4B5hIK7t+8BfkqGJ16 4v1A5Bb6Gjw9tWZvzEcyIZ/wECrJ7Wgj5Jf87aTWh23Ufdmno3k884ezkYYyTAof CJEQ6Rr1kuhbDDGfekzW+5/Z55OJfWDhwhBh9I1897Y9JWPGAArB6zJj1iRaGRJ2 ictGAWqpQXq8rXqnYsKPmI610Ck1f1aQrC8KEEPHLqW/EfwzLz68YsS9qAnll1Z8 1rgstWDAFouBeBoW1YNVrM5CtlKzLTrCUa2PVeqaFbxtPEoMzXPZfuP9bUr0AJG7 uXbPpxoWtzL4BnsDoi1lpZbr02APcuwXC2n76JDj0wRZj+l6RWWWhDlEDHXMwb5s OTdtxSgYjiHCargTaL7i0gOFcHScZ901OcSdeLcUnwNDG6T4yLK1EhnX2SKE2lak xi0U5oDsnYdJ+WnHmlb1CIbUKRQWZjNENdRSKd48/OhLDaT4YQU= =cog2 -----END PGP SIGNATURE----- Merge tag 'drm-misc-fixes-2026-07-24' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes drm-misc-fixes for v7.2-rc5: - Improve damage handling in appletbdrm. - Fix harmful fragmenting of MM by backing up TTM pages at native page order. - Fix timeout handling in amdxdna. - Fix imagination locking for map/unmap operations. - Fix mm leak in gpusvm eviction. - Properly zero page array in gpusvm mm scanning. - Prevent trusted shader bo's from being mapped again in vc4. - Validate shader array size in vmwgfx. - Fix length calculation bugs in ethosu. - Better error handling during pagemap migration. - Improve v3d suspend. - Kconfig updates for some panels. - Handle missing iovcc in ili9881c panel. - Fix vc4 unbind. - Add i2c error handling in gma500. - Fix kunit tests on pp64le and s390x. - Prevent rearming vc4 timer on shutdown. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patch.msgid.link/07284633-6b9b-40f9-8949-b1516a42a34c@linux.intel.com
This commit is contained in:
commit
e24b02df4e
1
.mailmap
1
.mailmap
|
|
@ -540,6 +540,7 @@ Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
|
|||
Maciej W. Rozycki <macro@orcam.me.uk> <macro@linux-mips.org>
|
||||
Maharaja Kennadyrajan <quic_mkenna@quicinc.com> <mkenna@codeaurora.org>
|
||||
Maheshwar Ajja <quic_majja@quicinc.com> <majja@codeaurora.org>
|
||||
Maíra Canal <mairacanal@riseup.net> <maira.canal@usp.br>
|
||||
Malathi Gottam <quic_mgottam@quicinc.com> <mgottam@codeaurora.org>
|
||||
Manikanta Pubbisetty <quic_mpubbise@quicinc.com> <mpubbise@codeaurora.org>
|
||||
Manivannan Sadhasivam <mani@kernel.org> <manivannanece23@gmail.com>
|
||||
|
|
|
|||
|
|
@ -43,20 +43,22 @@ struct aie2_ctx_health {
|
|||
|
||||
static inline void aie2_tdr_signal(struct amdxdna_dev *xdna)
|
||||
{
|
||||
WRITE_ONCE(xdna->dev_handle->tdr_status, AIE2_TDR_SIGNALED);
|
||||
WRITE_ONCE(xdna->dev_handle->last_signal_ts, jiffies);
|
||||
}
|
||||
|
||||
static bool aie2_tdr_detect(struct amdxdna_dev *xdna)
|
||||
{
|
||||
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
|
||||
unsigned long last = READ_ONCE(ndev->last_signal_ts);
|
||||
|
||||
if (READ_ONCE(ndev->tdr_status) == AIE2_TDR_WAIT) {
|
||||
XDNA_ERR(xdna, "TDR timeout detected");
|
||||
return true;
|
||||
}
|
||||
if (!tdr_timeout_ms)
|
||||
return false;
|
||||
|
||||
WRITE_ONCE(ndev->tdr_status, AIE2_TDR_WAIT);
|
||||
return false;
|
||||
if (!time_after(jiffies, last + msecs_to_jiffies(tdr_timeout_ms)))
|
||||
return false;
|
||||
|
||||
XDNA_ERR(xdna, "TDR timeout detected");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void aie2_cmd_release(struct kref *ref)
|
||||
|
|
@ -434,6 +436,12 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
|
|||
mmput(job->mm);
|
||||
fence = ERR_PTR(ret);
|
||||
} else {
|
||||
/*
|
||||
* Command is successfully posted to hardware, update the
|
||||
* tdr timestamp. The total pending commands are limited.
|
||||
* So there will not be a case that driver keeps posting
|
||||
* commands without getting any hardware respond.
|
||||
*/
|
||||
aie2_tdr_signal(hwctx->client->xdna);
|
||||
}
|
||||
trace_xdna_job(sched_job, hwctx->name, "sent to device",
|
||||
|
|
@ -658,7 +666,9 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
|
|||
const struct drm_sched_init_args args = {
|
||||
.ops = &sched_ops,
|
||||
.credit_limit = HWCTX_MAX_CMDS,
|
||||
.timeout = msecs_to_jiffies(tdr_timeout_ms),
|
||||
.timeout = tdr_timeout_ms ?
|
||||
msecs_to_jiffies(tdr_timeout_ms) :
|
||||
MAX_SCHEDULE_TIMEOUT,
|
||||
.name = "amdxdna_js",
|
||||
.dev = xdna->ddev.dev,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -420,6 +420,7 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
|
|||
goto stop_fw;
|
||||
}
|
||||
|
||||
WRITE_ONCE(ndev->last_signal_ts, jiffies);
|
||||
ndev->dev_status = AIE2_DEV_START;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -143,11 +143,6 @@ struct aie2_exec_msg_ops {
|
|||
u32 (*get_chain_msg_op)(u32 cmd_op);
|
||||
};
|
||||
|
||||
enum aie2_tdr_status {
|
||||
AIE2_TDR_WAIT,
|
||||
AIE2_TDR_SIGNALED,
|
||||
};
|
||||
|
||||
struct amdxdna_dev_hdl {
|
||||
struct aie_device aie;
|
||||
const struct amdxdna_dev_priv *priv;
|
||||
|
|
@ -179,7 +174,7 @@ struct amdxdna_dev_hdl {
|
|||
u32 hwctx_num;
|
||||
|
||||
struct amdxdna_async_error last_async_err;
|
||||
enum aie2_tdr_status tdr_status;
|
||||
unsigned long last_signal_ts;
|
||||
};
|
||||
|
||||
struct aie2_hw_ops {
|
||||
|
|
|
|||
|
|
@ -192,9 +192,17 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
|
|||
return len;
|
||||
}
|
||||
|
||||
static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
||||
static bool feat_matrix_chained(struct ethosu_device *edev, struct feat_matrix *fm)
|
||||
{
|
||||
u32 storage = fm->precision >> 14;
|
||||
|
||||
return !ethosu_is_u65(edev) && storage == 2;
|
||||
}
|
||||
|
||||
static u64 feat_matrix_length(struct ethosu_device *edev,
|
||||
struct ethosu_validated_cmdstream_info *info,
|
||||
struct feat_matrix *fm,
|
||||
u32 x, u32 y, u32 c)
|
||||
u32 x, u32 y, u32 c, bool ofm)
|
||||
{
|
||||
u32 element_size, storage = fm->precision >> 14;
|
||||
int tile = 0;
|
||||
|
|
@ -203,6 +211,9 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
|||
if (fm->region < 0)
|
||||
return U64_MAX;
|
||||
|
||||
if (feat_matrix_chained(edev, fm))
|
||||
return 0;
|
||||
|
||||
switch (storage) {
|
||||
case 0:
|
||||
if (x >= fm->width0 + 1) {
|
||||
|
|
@ -223,6 +234,8 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
|||
tile = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return U64_MAX;
|
||||
}
|
||||
if (fm->base[tile] == U64_MAX)
|
||||
return U64_MAX;
|
||||
|
|
@ -231,10 +244,11 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
|||
|
||||
switch ((fm->precision >> 6) & 0x3) { // format
|
||||
case 0: //nhwc:
|
||||
addr += x * fm->stride_x + c;
|
||||
element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3);
|
||||
addr += x * fm->stride_x + c * element_size;
|
||||
break;
|
||||
case 1: //nhcwb16:
|
||||
element_size = BIT((fm->precision >> 1) & 0x3);
|
||||
element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3);
|
||||
|
||||
addr += (c / 16) * fm->stride_c + (16 * x + (c & 0xf)) * element_size;
|
||||
break;
|
||||
|
|
@ -250,6 +264,7 @@ static int calc_sizes(struct drm_device *ddev,
|
|||
u16 op, struct cmd_state *st,
|
||||
bool ifm, bool ifm2, bool weight, bool scale)
|
||||
{
|
||||
struct ethosu_device *edev = to_ethosu_device(ddev);
|
||||
u64 len;
|
||||
|
||||
if (ifm) {
|
||||
|
|
@ -267,8 +282,8 @@ static int calc_sizes(struct drm_device *ddev,
|
|||
if (ifm_height < 0 || ifm_width < 0)
|
||||
return -EINVAL;
|
||||
|
||||
len = feat_matrix_length(info, &st->ifm, ifm_width,
|
||||
ifm_height, st->ifm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm, ifm_width,
|
||||
ifm_height, st->ifm.depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm.region, st->ifm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
|
|
@ -276,8 +291,8 @@ static int calc_sizes(struct drm_device *ddev,
|
|||
}
|
||||
|
||||
if (ifm2) {
|
||||
len = feat_matrix_length(info, &st->ifm2, st->ifm.depth,
|
||||
0, st->ofm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm2, st->ifm.depth,
|
||||
0, st->ofm.depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm2.region, st->ifm2.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
|
|
@ -308,13 +323,14 @@ static int calc_sizes(struct drm_device *ddev,
|
|||
st->scale[0].base + st->scale[0].length);
|
||||
}
|
||||
|
||||
len = feat_matrix_length(info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth, true);
|
||||
dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ofm.region, st->ofm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
return -EINVAL;
|
||||
info->output_region[st->ofm.region] = true;
|
||||
if (!feat_matrix_chained(edev, &st->ofm))
|
||||
info->output_region[st->ofm.region] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -324,6 +340,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
|
|||
u16 op, struct cmd_state *st,
|
||||
bool ifm, bool ifm2)
|
||||
{
|
||||
struct ethosu_device *edev = to_ethosu_device(ddev);
|
||||
u32 height, width, depth;
|
||||
u64 len;
|
||||
|
||||
|
|
@ -332,8 +349,8 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
|
|||
width = st->ifm.broadcast & 0x2 ? 0 : st->ofm.width;
|
||||
depth = st->ifm.broadcast & 0x4 ? 0 : st->ofm.depth;
|
||||
|
||||
len = feat_matrix_length(info, &st->ifm, width,
|
||||
height, depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm, width,
|
||||
height, depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm.region, st->ifm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
|
|
@ -345,21 +362,22 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
|
|||
width = st->ifm2.broadcast & 0x2 ? 0 : st->ofm.width;
|
||||
depth = st->ifm2.broadcast & 0x4 ? 0 : st->ofm.depth;
|
||||
|
||||
len = feat_matrix_length(info, &st->ifm2, width,
|
||||
height, depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm2, width,
|
||||
height, depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm2.region, st->ifm2.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = feat_matrix_length(info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth, true);
|
||||
dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ofm.region, st->ofm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
return -EINVAL;
|
||||
info->output_region[st->ofm.region] = true;
|
||||
if (!feat_matrix_chained(edev, &st->ofm))
|
||||
info->output_region[st->ofm.region] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -781,7 +781,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
|
|||
const struct dev_pagemap *other = NULL;
|
||||
int err, i;
|
||||
|
||||
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
|
||||
pfns = kvcalloc(npages, sizeof(*pfns), GFP_KERNEL);
|
||||
if (!pfns)
|
||||
return DRM_GPUSVM_SCAN_UNPOPULATED;
|
||||
|
||||
|
|
@ -1753,8 +1753,10 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
|
|||
return -EFAULT;
|
||||
|
||||
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
|
||||
if (!pfns)
|
||||
if (!pfns) {
|
||||
mmput(mm);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hmm_range.hmm_pfns = pfns;
|
||||
while (!time_after(jiffies, timeout)) {
|
||||
|
|
|
|||
|
|
@ -727,8 +727,10 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
|
|||
}
|
||||
|
||||
err = ops->populate_devmem_pfn(devmem_allocation, npages, migrate.dst);
|
||||
if (err)
|
||||
goto err_aborted_migration;
|
||||
if (err) {
|
||||
npages = 0;
|
||||
goto err_finalize;
|
||||
}
|
||||
|
||||
own_pages = 0;
|
||||
|
||||
|
|
@ -807,8 +809,11 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
|
|||
msecs_to_jiffies(mdetails->timeslice_ms);
|
||||
|
||||
err_finalize:
|
||||
if (err)
|
||||
if (err) {
|
||||
drm_pagemap_migration_unlock_put_pages(npages, migrate.dst);
|
||||
for (i = npages; i < npages_in_range(start, end); ++i)
|
||||
migrate.dst[i] = 0;
|
||||
}
|
||||
err_aborted_migration:
|
||||
migrate_vma_pages(&migrate);
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
|
|||
struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
|
||||
struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
|
||||
u32 temp;
|
||||
int ret;
|
||||
|
||||
i2c_dev->status = I2C_STAT_INIT;
|
||||
i2c_dev->msg = pmsg;
|
||||
|
|
@ -109,9 +110,14 @@ static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
|
|||
HDMI_WRITE(HDMI_HI2CHCR, temp);
|
||||
HDMI_READ(HDMI_HI2CHCR);
|
||||
|
||||
while (i2c_dev->status != I2C_TRANSACTION_DONE)
|
||||
wait_for_completion_interruptible_timeout(&i2c_dev->complete,
|
||||
while (i2c_dev->status != I2C_TRANSACTION_DONE) {
|
||||
ret = wait_for_completion_interruptible_timeout(&i2c_dev->complete,
|
||||
10 * HZ);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!ret)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -130,7 +136,7 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
|||
{
|
||||
struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
|
||||
struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
|
||||
int i;
|
||||
int i, ret = 0;
|
||||
|
||||
mutex_lock(&i2c_dev->i2c_lock);
|
||||
|
||||
|
|
@ -142,9 +148,11 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
|||
for (i = 0; i < num; i++) {
|
||||
if (pmsg->len && pmsg->buf) {
|
||||
if (pmsg->flags & I2C_M_RD)
|
||||
xfer_read(adap, pmsg);
|
||||
ret = xfer_read(adap, pmsg);
|
||||
else
|
||||
xfer_write(adap, pmsg);
|
||||
ret = xfer_write(adap, pmsg);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
pmsg++; /* next message */
|
||||
}
|
||||
|
|
@ -154,6 +162,9 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
|||
|
||||
mutex_unlock(&i2c_dev->i2c_lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -747,6 +747,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
|
|||
|
||||
pvr_gem_object_get(pvr_obj);
|
||||
|
||||
mutex_lock(&vm_ctx->lock);
|
||||
err = drm_gpuvm_exec_lock(&vm_exec);
|
||||
if (err)
|
||||
goto err_cleanup;
|
||||
|
|
@ -756,6 +757,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
|
|||
drm_gpuvm_exec_unlock(&vm_exec);
|
||||
|
||||
err_cleanup:
|
||||
mutex_unlock(&vm_ctx->lock);
|
||||
pvr_vm_bind_op_fini(&bind_op);
|
||||
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ config DRM_PANEL_HIMAX_HX83121A
|
|||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_DISPLAY_DSC_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
help
|
||||
|
|
@ -332,6 +333,7 @@ config DRM_PANEL_ILITEK_ILI9882T
|
|||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_DISPLAY_DSC_HELPER
|
||||
help
|
||||
Say Y if you want to enable support for panels based on the
|
||||
|
|
@ -954,6 +956,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA8
|
|||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_DISPLAY_DSC_HELPER
|
||||
help
|
||||
Say Y or M here if you want to enable support for the
|
||||
|
|
|
|||
|
|
@ -2562,9 +2562,12 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi)
|
|||
"Couldn't get our power regulator\n");
|
||||
|
||||
ctx->iovcc = devm_regulator_get_optional(&dsi->dev, "iovcc");
|
||||
if (IS_ERR(ctx->iovcc))
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(ctx->iovcc),
|
||||
if (IS_ERR(ctx->iovcc)) {
|
||||
if (PTR_ERR(ctx->iovcc) != -ENODEV)
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(ctx->iovcc),
|
||||
"Couldn't get our iovcc regulator\n");
|
||||
ctx->iovcc = NULL;
|
||||
}
|
||||
|
||||
ctx->reset = devm_gpiod_get_optional(&dsi->dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset))
|
||||
|
|
|
|||
|
|
@ -95,13 +95,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test)
|
|||
sg_init_one(sgt->sgl, buf, TEST_SIZE);
|
||||
|
||||
/*
|
||||
* Set the DMA mask to 64-bits and map the sgtables
|
||||
* otherwise drm_gem_shmem_free will cause a warning
|
||||
* on debug kernels.
|
||||
* Map the sgtables otherwise drm_gem_shmem_free will cause a warning on
|
||||
* debug kernels.
|
||||
*/
|
||||
ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64));
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
|
|
@ -352,11 +348,19 @@ static int drm_gem_shmem_test_init(struct kunit *test)
|
|||
{
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
int ret;
|
||||
|
||||
/* Allocate a parent device */
|
||||
dev = drm_kunit_helper_alloc_device(test);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||
|
||||
/*
|
||||
* Set the DMA mask to 64-bits to avoid intermittent failures calling
|
||||
* drm_gem_shmem_get_pages_sgt().
|
||||
*/
|
||||
ret = dma_set_mask(dev, DMA_BIT_MASK(64));
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/*
|
||||
* The DRM core will automatically initialize the GEM core and create
|
||||
* a DRM Memory Manager object which provides an address space pool
|
||||
|
|
|
|||
|
|
@ -315,33 +315,16 @@ static const u32 appletbdrm_primary_plane_formats[] = {
|
|||
DRM_FORMAT_XRGB8888, /* emulated */
|
||||
};
|
||||
|
||||
static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *state)
|
||||
static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_plane_state)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
|
||||
struct drm_crtc *new_crtc = new_plane_state->crtc;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(new_plane_state);
|
||||
size_t frames_size = 0;
|
||||
struct drm_atomic_helper_damage_iter iter;
|
||||
struct drm_rect damage;
|
||||
size_t frames_size = 0;
|
||||
size_t request_size;
|
||||
int ret;
|
||||
|
||||
if (new_crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
else if (!new_plane_state->visible)
|
||||
return 0;
|
||||
|
||||
drm_atomic_helper_damage_iter_init(&iter, old_plane_state, new_plane_state);
|
||||
drm_atomic_helper_damage_iter_init(&iter, plane->state, new_plane_state);
|
||||
drm_atomic_for_each_plane_damage(&iter, &damage) {
|
||||
frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
|
||||
}
|
||||
|
|
@ -366,6 +349,29 @@ static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
|||
appletbdrm_state->request_size = request_size;
|
||||
appletbdrm_state->frames_size = frames_size;
|
||||
|
||||
return drm_gem_begin_shadow_fb_access(plane, new_plane_state);
|
||||
}
|
||||
|
||||
static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *state)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_crtc *new_crtc = new_plane_state->crtc;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
int ret;
|
||||
|
||||
if (new_crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
else if (!new_plane_state->visible)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -468,7 +474,7 @@ static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
|
|||
}
|
||||
|
||||
static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *old_state)
|
||||
struct drm_atomic_commit *old_state)
|
||||
{
|
||||
struct appletbdrm_device *adev = drm_to_adev(plane->dev);
|
||||
struct drm_device *drm = plane->dev;
|
||||
|
|
@ -552,7 +558,8 @@ static void appletbdrm_primary_plane_destroy_state(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs appletbdrm_primary_plane_helper_funcs = {
|
||||
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
|
||||
.begin_fb_access = appletbdrm_primary_plane_helper_begin_fb_access,
|
||||
.end_fb_access = drm_gem_end_shadow_fb_access,
|
||||
.atomic_check = appletbdrm_primary_plane_helper_atomic_check,
|
||||
.atomic_update = appletbdrm_primary_plane_helper_atomic_update,
|
||||
.atomic_disable = appletbdrm_primary_plane_helper_atomic_disable,
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@
|
|||
#include <drm/ttm/ttm_backup.h>
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/page-flags.h>
|
||||
#include <linux/swap.h>
|
||||
|
||||
#include "ttm_pool_internal.h"
|
||||
|
||||
/*
|
||||
* Need to map shmem indices to handle since a handle value
|
||||
* of 0 means error, following the swp_entry_t convention.
|
||||
|
|
@ -68,17 +69,23 @@ int ttm_backup_copy_page(struct file *backup, struct page *dst,
|
|||
}
|
||||
|
||||
/**
|
||||
* ttm_backup_backup_page() - Backup a page
|
||||
* ttm_backup_backup_folio() - Backup a folio
|
||||
* @backup: The struct backup pointer to use.
|
||||
* @page: The page to back up.
|
||||
* @writeback: Whether to perform immediate writeback of the page.
|
||||
* @folio: The folio to back up.
|
||||
* @order: The allocation order of @folio. Since TTM allocates higher-order
|
||||
* pages without __GFP_COMP, folio_nr_pages(@folio) would always
|
||||
* return 1; the caller must pass the true order explicitly.
|
||||
* @writeback: Whether to perform immediate writeback of the folio's pages.
|
||||
* This may have performance implications.
|
||||
* @idx: A unique integer for each page and each struct backup.
|
||||
* @idx: A unique integer for the first page of the folio and each struct backup.
|
||||
* This allows the backup implementation to avoid managing
|
||||
* its address space separately.
|
||||
* @page_gfp: The gfp value used when the page was allocated.
|
||||
* This is used for accounting purposes.
|
||||
* @folio_gfp: The gfp value used when the folio was allocated.
|
||||
* Currently unused.
|
||||
* @alloc_gfp: The gfp to be used when allocating memory.
|
||||
* @nr_pages_backed: Output. On a successful return, set to the number of
|
||||
* pages actually backed up, which may be less than (1 << @order)
|
||||
* if an -ENOMEM was encountered mid-folio.
|
||||
*
|
||||
* Context: If called from reclaim context, the caller needs to
|
||||
* assert that the shrinker gfp has __GFP_FS set, to avoid
|
||||
|
|
@ -87,53 +94,87 @@ int ttm_backup_copy_page(struct file *backup, struct page *dst,
|
|||
* that the shrinker gfp has __GFP_IO set, since without it,
|
||||
* we're not allowed to start backup IO.
|
||||
*
|
||||
* Return: A handle on success. Negative error code on failure.
|
||||
*
|
||||
* Note: This function could be extended to back up a folio and
|
||||
* implementations would then split the folio internally if needed.
|
||||
* Drawback is that the caller would then have to keep track of
|
||||
* the folio size- and usage.
|
||||
* Return: A handle for the first backed-up page on success (handles for
|
||||
* subsequent pages follow sequentially). -ENOMEM if no pages could be backed
|
||||
* up. Any other negative error code if a non-ENOMEM failure occurred; in that
|
||||
* case any pages backed up so far are truncated before returning.
|
||||
*/
|
||||
s64
|
||||
ttm_backup_backup_page(struct file *backup, struct page *page,
|
||||
bool writeback, pgoff_t idx, gfp_t page_gfp,
|
||||
gfp_t alloc_gfp)
|
||||
ttm_backup_backup_folio(struct file *backup, struct folio *folio,
|
||||
unsigned int order, bool writeback, pgoff_t idx,
|
||||
gfp_t folio_gfp, gfp_t alloc_gfp,
|
||||
pgoff_t *nr_pages_backed)
|
||||
{
|
||||
struct address_space *mapping = backup->f_mapping;
|
||||
unsigned long handle = 0;
|
||||
int nr_pages = 1 << order;
|
||||
struct folio *to_folio;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
to_folio = shmem_read_folio_gfp(mapping, idx, alloc_gfp);
|
||||
if (IS_ERR(to_folio))
|
||||
return PTR_ERR(to_folio);
|
||||
*nr_pages_backed = 0;
|
||||
|
||||
folio_mark_accessed(to_folio);
|
||||
folio_lock(to_folio);
|
||||
folio_mark_dirty(to_folio);
|
||||
copy_highpage(folio_file_page(to_folio, idx), page);
|
||||
handle = ttm_backup_shmem_idx_to_handle(idx);
|
||||
for (i = 0; i < nr_pages; ) {
|
||||
int to_nr, j;
|
||||
|
||||
if (writeback && !folio_mapped(to_folio) &&
|
||||
folio_clear_dirty_for_io(to_folio)) {
|
||||
folio_set_reclaim(to_folio);
|
||||
ret = shmem_writeout(to_folio, NULL, NULL);
|
||||
if (!folio_test_writeback(to_folio))
|
||||
folio_clear_reclaim(to_folio);
|
||||
/*
|
||||
* If writeout succeeds, it unlocks the folio. errors
|
||||
* are otherwise dropped, since writeout is only best
|
||||
* effort here.
|
||||
* Only inject past the first subpage so *nr_pages_backed is
|
||||
* always > 0 here, matching a genuine mid-compound -ENOMEM
|
||||
* and driving the caller's reactive split fallback instead
|
||||
* of an early, no-progress failure.
|
||||
*/
|
||||
if (ret)
|
||||
if (IS_ENABLED(CONFIG_FAULT_INJECTION) && i &&
|
||||
ttm_backup_fault_inject_folio())
|
||||
to_folio = ERR_PTR(-ENOMEM);
|
||||
else
|
||||
to_folio = shmem_read_folio_gfp(mapping, idx + i, alloc_gfp);
|
||||
if (IS_ERR(to_folio)) {
|
||||
int err = PTR_ERR(to_folio);
|
||||
|
||||
if (err == -ENOMEM && *nr_pages_backed)
|
||||
return ttm_backup_shmem_idx_to_handle(idx);
|
||||
|
||||
if (*nr_pages_backed) {
|
||||
shmem_truncate_range(file_inode(backup),
|
||||
(loff_t)idx << PAGE_SHIFT,
|
||||
((loff_t)(idx + i) << PAGE_SHIFT) - 1);
|
||||
/*
|
||||
* The pages just truncated are no longer
|
||||
* backed up; don't let the caller mistake
|
||||
* them for valid handles.
|
||||
*/
|
||||
*nr_pages_backed = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
to_nr = min_t(int, nr_pages - i,
|
||||
folio_next_index(to_folio) - (idx + i));
|
||||
|
||||
folio_mark_accessed(to_folio);
|
||||
folio_lock(to_folio);
|
||||
folio_mark_dirty(to_folio);
|
||||
|
||||
for (j = 0; j < to_nr; j++)
|
||||
copy_highpage(folio_file_page(to_folio, idx + i + j),
|
||||
folio_page(folio, i + j));
|
||||
|
||||
if (writeback && !folio_mapped(to_folio) &&
|
||||
folio_clear_dirty_for_io(to_folio)) {
|
||||
folio_set_reclaim(to_folio);
|
||||
ret = shmem_writeout(to_folio, NULL, NULL);
|
||||
if (!folio_test_writeback(to_folio))
|
||||
folio_clear_reclaim(to_folio);
|
||||
if (ret == AOP_WRITEPAGE_ACTIVATE)
|
||||
folio_unlock(to_folio);
|
||||
} else {
|
||||
folio_unlock(to_folio);
|
||||
} else {
|
||||
folio_unlock(to_folio);
|
||||
}
|
||||
|
||||
folio_put(to_folio);
|
||||
i += to_nr;
|
||||
*nr_pages_backed = i;
|
||||
}
|
||||
|
||||
folio_put(to_folio);
|
||||
|
||||
return handle;
|
||||
return ttm_backup_shmem_idx_to_handle(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -53,8 +53,23 @@
|
|||
#ifdef CONFIG_FAULT_INJECTION
|
||||
#include <linux/fault-inject.h>
|
||||
static DECLARE_FAULT_ATTR(backup_fault_inject);
|
||||
|
||||
/*
|
||||
* Exposed to ttm_backup.c so a mid-compound subpage can be made to fail
|
||||
* with -ENOMEM, exercising the reactive split-and-retry fallback in
|
||||
* ttm_pool_backup() for high-order backups.
|
||||
*/
|
||||
bool ttm_backup_fault_inject_folio(void)
|
||||
{
|
||||
return should_fail(&backup_fault_inject, 1);
|
||||
}
|
||||
#else
|
||||
#define should_fail(...) false
|
||||
|
||||
bool ttm_backup_fault_inject_folio(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -487,7 +502,7 @@ static void ttm_pool_split_for_swap(struct ttm_pool *pool, struct page *p)
|
|||
/**
|
||||
* DOC: Partial backup and restoration of a struct ttm_tt.
|
||||
*
|
||||
* Swapout using ttm_backup_backup_page() and swapin using
|
||||
* Swapout using ttm_backup_backup_folio() and swapin using
|
||||
* ttm_backup_copy_page() may fail.
|
||||
* The former most likely due to lack of swap-space or memory, the latter due
|
||||
* to lack of memory or because of signal interruption during waits.
|
||||
|
|
@ -1036,12 +1051,12 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
|||
{
|
||||
struct file *backup = tt->backup;
|
||||
struct page *page;
|
||||
unsigned long handle;
|
||||
gfp_t alloc_gfp;
|
||||
gfp_t gfp;
|
||||
int ret = 0;
|
||||
pgoff_t shrunken = 0;
|
||||
pgoff_t i, num_pages;
|
||||
pgoff_t i, j, num_pages, npages;
|
||||
pgoff_t nr_backed;
|
||||
|
||||
if (WARN_ON(ttm_tt_is_backed_up(tt)))
|
||||
return -EINVAL;
|
||||
|
|
@ -1119,9 +1134,11 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
|||
if (IS_ENABLED(CONFIG_FAULT_INJECTION) && should_fail(&backup_fault_inject, 1))
|
||||
num_pages = DIV_ROUND_UP(num_pages, 2);
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
s64 shandle;
|
||||
for (i = 0; i < num_pages; i += npages) {
|
||||
unsigned int order;
|
||||
s64 handle;
|
||||
|
||||
npages = 1;
|
||||
page = tt->pages[i];
|
||||
if (unlikely(!page))
|
||||
continue;
|
||||
|
|
@ -1130,19 +1147,61 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
|||
if (unlikely(ttm_backup_page_ptr_is_handle(page)))
|
||||
continue;
|
||||
|
||||
ttm_pool_split_for_swap(pool, page);
|
||||
order = ttm_pool_page_order(pool, page);
|
||||
npages = 1UL << order;
|
||||
|
||||
shandle = ttm_backup_backup_page(backup, page, flags->writeback, i,
|
||||
gfp, alloc_gfp);
|
||||
if (shandle < 0) {
|
||||
/* We allow partially shrunken tts */
|
||||
ret = shandle;
|
||||
/*
|
||||
* We don't allow dipping kernel reserves for high order backup
|
||||
*/
|
||||
if (order)
|
||||
alloc_gfp |= __GFP_NOMEMALLOC;
|
||||
else
|
||||
alloc_gfp &= ~__GFP_NOMEMALLOC;
|
||||
|
||||
/*
|
||||
* Back up the compound atomically at its native order. If
|
||||
* fault injection truncated num_pages mid-compound, skip
|
||||
* the partial tail rather than splitting.
|
||||
*/
|
||||
if (unlikely(i + npages > num_pages))
|
||||
break;
|
||||
|
||||
handle = ttm_backup_backup_folio(backup, page_folio(page),
|
||||
order, flags->writeback, i,
|
||||
gfp, alloc_gfp,
|
||||
&nr_backed);
|
||||
/*
|
||||
* Zero progress on this compound (whether order 0 or a
|
||||
* high-order compound that failed before backing up even
|
||||
* its first subpage) is unrecoverable: bail out rather than
|
||||
* looping forever with npages == nr_backed == 0 below.
|
||||
*/
|
||||
if (unlikely(handle < 0 && !nr_backed)) {
|
||||
ret = handle;
|
||||
break;
|
||||
}
|
||||
handle = shandle;
|
||||
tt->pages[i] = ttm_backup_handle_to_page_ptr(handle);
|
||||
__free_pages_gpu_account(page, 0, false);
|
||||
shrunken++;
|
||||
|
||||
for (j = 0; j < nr_backed; j++)
|
||||
tt->pages[i + j] = ttm_backup_handle_to_page_ptr(handle + j);
|
||||
|
||||
shrunken += nr_backed;
|
||||
|
||||
if (unlikely(nr_backed < npages)) {
|
||||
/*
|
||||
* Partial OOM backup: split the compound and free the
|
||||
* subpages whose content is now in shmem. Continue the
|
||||
* loop from the first un-backed order-0 page.
|
||||
*/
|
||||
ttm_pool_split_for_swap(pool, page);
|
||||
for (j = 0; j < nr_backed; j++)
|
||||
__free_pages_gpu_account(page + j, 0, false);
|
||||
npages = nr_backed;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fully backed up: free at native order. */
|
||||
page->private = 0;
|
||||
__free_pages_gpu_account(page, order, false);
|
||||
}
|
||||
|
||||
return shrunken ? shrunken : ret;
|
||||
|
|
|
|||
|
|
@ -22,4 +22,12 @@ static inline unsigned int ttm_pool_beneficial_order(struct ttm_pool *pool)
|
|||
return pool->alloc_flags & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implemented in ttm_pool.c, used by ttm_backup.c. Returns true if a fault
|
||||
* should be injected mid-compound to test the reactive split-and-retry
|
||||
* fallback in ttm_pool_backup(). Always returns false when
|
||||
* CONFIG_FAULT_INJECTION is disabled.
|
||||
*/
|
||||
bool ttm_backup_fault_inject_folio(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -571,6 +571,8 @@ extern bool super_pages;
|
|||
void v3d_init_hw_state(struct v3d_dev *v3d);
|
||||
int v3d_gem_init(struct drm_device *dev);
|
||||
void v3d_gem_destroy(struct drm_device *dev);
|
||||
void v3d_idle_axi(struct v3d_dev *v3d, int core);
|
||||
void v3d_idle_gca(struct v3d_dev *v3d);
|
||||
void v3d_reset_sms(struct v3d_dev *v3d);
|
||||
void v3d_reset(struct v3d_dev *v3d);
|
||||
void v3d_invalidate_caches(struct v3d_dev *v3d);
|
||||
|
|
|
|||
|
|
@ -36,9 +36,21 @@ v3d_init_core(struct v3d_dev *v3d, int core)
|
|||
V3D_CORE_WRITE(core, V3D_CTL_L2TFLEND, ~0);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
v3d_idle_axi(struct v3d_dev *v3d, int core)
|
||||
{
|
||||
if (v3d->ver >= V3D_GEN_71) {
|
||||
V3D_WRITE(V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ);
|
||||
|
||||
if (wait_for((V3D_READ(V3D_GMP_STATUS(v3d->ver)) &
|
||||
(V3D_GMP_STATUS_RD_COUNT_MASK |
|
||||
V3D_GMP_STATUS_WR_COUNT_MASK |
|
||||
V3D_GMP_STATUS_CFG_BUSY)) == 0, 100)) {
|
||||
drm_err(&v3d->drm, "Failed to wait for safe GMP shutdown\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
V3D_CORE_WRITE(core, V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ);
|
||||
|
||||
if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS(v3d->ver)) &
|
||||
|
|
@ -49,7 +61,7 @@ v3d_idle_axi(struct v3d_dev *v3d, int core)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
v3d_idle_gca(struct v3d_dev *v3d)
|
||||
{
|
||||
if (v3d->ver >= V3D_GEN_41)
|
||||
|
|
|
|||
|
|
@ -54,8 +54,15 @@ int v3d_power_suspend(struct device *dev)
|
|||
|
||||
v3d_clean_caches(v3d);
|
||||
|
||||
/* Wait until V3D has no active or pending AXI transactions. */
|
||||
v3d_idle_axi(v3d, 0);
|
||||
v3d_idle_gca(v3d);
|
||||
|
||||
ret = v3d_suspend_sms(v3d);
|
||||
if (ret) {
|
||||
/* Staying active: undo the GMP STOP_REQ from v3d_idle_axi(). */
|
||||
V3D_WRITE(V3D_GMP_CFG(v3d->ver),
|
||||
V3D_READ(V3D_GMP_CFG(v3d->ver)) & ~V3D_GMP_CFG_STOP_REQ);
|
||||
v3d_irq_enable(v3d);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -732,9 +732,13 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
|
|||
{
|
||||
struct vc4_bo *bo = to_vc4_bo(obj);
|
||||
|
||||
if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
|
||||
DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
|
||||
return -EINVAL;
|
||||
if (bo->validated_shader) {
|
||||
if (vma->vm_flags & VM_WRITE) {
|
||||
DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vm_flags_clear(vma, VM_MAYWRITE);
|
||||
}
|
||||
|
||||
mutex_lock(&bo->madv_lock);
|
||||
|
|
@ -1044,7 +1048,7 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused)
|
|||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
int i;
|
||||
|
||||
timer_delete(&vc4->bo_cache.time_timer);
|
||||
timer_shutdown_sync(&vc4->bo_cache.time_timer);
|
||||
cancel_work_sync(&vc4->bo_cache.time_work);
|
||||
|
||||
vc4_bo_cache_purge(dev);
|
||||
|
|
|
|||
|
|
@ -1752,7 +1752,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
|
|||
static void vc4_hvs_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(master);
|
||||
struct drm_device *drm = data;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(drm);
|
||||
struct vc4_hvs *hvs = vc4->hvs;
|
||||
struct drm_mm_node *node, *next;
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
|||
static void vc4_v3d_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(master);
|
||||
struct drm_device *drm = data;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(drm);
|
||||
|
||||
vc4_irq_uninstall(drm);
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,
|
|||
static int vmw_gb_surface_destroy(struct vmw_resource *res);
|
||||
static int
|
||||
vmw_gb_surface_define_internal(struct drm_device *dev,
|
||||
struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
const struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
struct drm_vmw_gb_surface_create_rep *rep,
|
||||
struct drm_file *file_priv);
|
||||
static int
|
||||
|
|
@ -1503,7 +1503,7 @@ int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
|
|||
*/
|
||||
static int
|
||||
vmw_gb_surface_define_internal(struct drm_device *dev,
|
||||
struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
const struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
struct drm_vmw_gb_surface_create_rep *rep,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
|
|
@ -1521,9 +1521,21 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
|
|||
req->base.svga3d_flags);
|
||||
|
||||
/* array_size must be null for non-GL3 host. */
|
||||
if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
|
||||
VMW_DEBUG_USER("SM4 surface not supported.\n");
|
||||
return -EINVAL;
|
||||
if (req->base.array_size > 0) {
|
||||
if (has_sm5_context(dev_priv)) {
|
||||
if (req->base.array_size > SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE) {
|
||||
VMW_DEBUG_USER("Invalid Surface Array Size.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (has_sm4_context(dev_priv)) {
|
||||
if (req->base.array_size > SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE) {
|
||||
VMW_DEBUG_USER("Invalid Surface Array Size.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
VMW_DEBUG_USER("SM4+ surface not supported.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_sm4_1_context(dev_priv)) {
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@
|
|||
* ttm_backup_handle_to_page_ptr() - Convert handle to struct page pointer
|
||||
* @handle: The handle to convert.
|
||||
*
|
||||
* Converts an opaque handle received from the
|
||||
* ttm_backup_backup_page() function to an (invalid)
|
||||
* struct page pointer suitable for a struct page array.
|
||||
* Converts an opaque handle received from a ttm_backup_backup_*()
|
||||
* function to an (invalid) struct page pointer suitable for a struct page array.
|
||||
*
|
||||
* Return: An (invalid) struct page pointer.
|
||||
*/
|
||||
|
|
@ -59,9 +58,10 @@ int ttm_backup_copy_page(struct file *backup, struct page *dst,
|
|||
pgoff_t handle, bool intr, gfp_t additional_gfp);
|
||||
|
||||
s64
|
||||
ttm_backup_backup_page(struct file *backup, struct page *page,
|
||||
bool writeback, pgoff_t idx, gfp_t page_gfp,
|
||||
gfp_t alloc_gfp);
|
||||
ttm_backup_backup_folio(struct file *backup, struct folio *folio,
|
||||
unsigned int order, bool writeback, pgoff_t idx,
|
||||
gfp_t folio_gfp, gfp_t alloc_gfp,
|
||||
pgoff_t *nr_pages_backed);
|
||||
|
||||
void ttm_backup_fini(struct file *backup);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user