summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/accel/amdxdna/amdxdna_gem.c2
-rw-r--r--drivers/accel/ivpu/ivpu_job.c10
-rw-r--r--drivers/acpi/acpi_ipmi.c2
-rw-r--r--drivers/acpi/acpica/utnonansi.c9
-rw-r--r--drivers/acpi/processor_idle.c4
-rw-r--r--drivers/acpi/resource.c6
-rw-r--r--drivers/acpi/riscv/cpuidle.c2
-rw-r--r--drivers/acpi/sysfs.c14
-rw-r--r--drivers/base/regmap/regcache.c2
-rw-r--r--drivers/block/rbd.c23
-rw-r--r--drivers/cpuidle/driver.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c71
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c220
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c103
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c91
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ih_v6_1.c2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c56
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c46
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c12
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c99
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h14
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.c15
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c10
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c13
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c7
-rw-r--r--drivers/gpu/drm/drm_connector.c12
-rw-r--r--drivers/gpu/drm/drm_displayid_internal.h2
-rw-r--r--drivers/gpu/drm/drm_edid.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c41
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c11
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c4
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_exec.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_uvmm.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c1
-rw-r--r--drivers/gpu/drm/radeon/r100.c13
-rw-r--r--drivers/gpu/drm/sysfb/drm_sysfb_helper.h2
-rw-r--r--drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c13
-rw-r--r--drivers/gpu/drm/sysfb/efidrm.c7
-rw-r--r--drivers/gpu/drm/sysfb/vesadrm.c6
-rw-r--r--drivers/gpu/drm/xe/Makefile4
-rw-r--r--drivers/gpu/drm/xe/regs/xe_gtt_defs.h6
-rw-r--r--drivers/gpu/drm/xe/xe_device.c3
-rw-r--r--drivers/gpu/drm/xe/xe_guc_capture.c10
-rw-r--r--drivers/gpu/drm/xe/xe_pt.c133
-rw-r--r--drivers/i2c/busses/i2c-i801.c2
-rw-r--r--drivers/i2c/busses/i2c-mpc.c2
-rw-r--r--drivers/input/rmi4/rmi_driver.c39
-rw-r--r--drivers/input/rmi4/rmi_f30.c2
-rw-r--r--drivers/input/rmi4/rmi_f3a.c2
-rw-r--r--drivers/input/serio/gscps2.c1
-rw-r--r--drivers/ntb/hw/amd/ntb_hw_amd.c20
-rw-r--r--drivers/ntb/hw/epf/ntb_hw_epf.c3
-rw-r--r--drivers/of/base.c4
-rw-r--r--drivers/of/property.c8
-rw-r--r--drivers/platform/x86/amd/pmc/pmc.c9
-rw-r--r--drivers/pwm/pwm-rzg2l-gpt.c8
-rw-r--r--drivers/regulator/da9121-regulator.c18
-rw-r--r--drivers/regulator/pca9450-regulator.c7
-rw-r--r--drivers/rtc/Kconfig7
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/interface.c44
-rw-r--r--drivers/rtc/rtc-88pm886.c2
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c2
-rw-r--r--drivers/rtc/rtc-ab-eoz9.c2
-rw-r--r--drivers/rtc/rtc-ab8500.c8
-rw-r--r--drivers/rtc/rtc-abx80x.c23
-rw-r--r--drivers/rtc/rtc-aspeed.c1
-rw-r--r--drivers/rtc/rtc-bd70528.c8
-rw-r--r--drivers/rtc/rtc-bq32k.c11
-rw-r--r--drivers/rtc/rtc-cmos.c6
-rw-r--r--drivers/rtc/rtc-cros-ec.c4
-rw-r--r--drivers/rtc/rtc-ds1307.c207
-rw-r--r--drivers/rtc/rtc-ds1374.c2
-rw-r--r--drivers/rtc/rtc-ds1672.c2
-rw-r--r--drivers/rtc/rtc-ds3232.c2
-rw-r--r--drivers/rtc/rtc-em3027.c2
-rw-r--r--drivers/rtc/rtc-fm3130.c2
-rw-r--r--drivers/rtc/rtc-hym8563.c4
-rw-r--r--drivers/rtc/rtc-isl12022.c2
-rw-r--r--drivers/rtc/rtc-isl12026.c4
-rw-r--r--drivers/rtc/rtc-isl1208.c25
-rw-r--r--drivers/rtc/rtc-m41t80.c22
-rw-r--r--drivers/rtc/rtc-m41t93.c488
-rw-r--r--drivers/rtc/rtc-max31335.c4
-rw-r--r--drivers/rtc/rtc-max6900.c2
-rw-r--r--drivers/rtc/rtc-max77686.c10
-rw-r--r--drivers/rtc/rtc-max8997.c4
-rw-r--r--drivers/rtc/rtc-max8998.c4
-rw-r--r--drivers/rtc/rtc-mpfs.c2
-rw-r--r--drivers/rtc/rtc-msc313.c4
-rw-r--r--drivers/rtc/rtc-mv.c23
-rw-r--r--drivers/rtc/rtc-nct3018y.c2
-rw-r--r--drivers/rtc/rtc-pcap.c179
-rw-r--r--drivers/rtc/rtc-pcf2127.c8
-rw-r--r--drivers/rtc/rtc-pcf85063.c12
-rw-r--r--drivers/rtc/rtc-pcf8523.c2
-rw-r--r--drivers/rtc/rtc-pcf8563.c6
-rw-r--r--drivers/rtc/rtc-pcf8583.c2
-rw-r--r--drivers/rtc/rtc-renesas-rtca3.c26
-rw-r--r--drivers/rtc/rtc-rs5c372.c12
-rw-r--r--drivers/rtc/rtc-rv3029c2.c4
-rw-r--r--drivers/rtc/rtc-rv8803.c8
-rw-r--r--drivers/rtc/rtc-rx6110.c2
-rw-r--r--drivers/rtc/rtc-rx8010.c2
-rw-r--r--drivers/rtc/rtc-rx8025.c4
-rw-r--r--drivers/rtc/rtc-rx8581.c2
-rw-r--r--drivers/rtc/rtc-s35390a.c4
-rw-r--r--drivers/rtc/rtc-s5m.c12
-rw-r--r--drivers/rtc/rtc-sd2405al.c2
-rw-r--r--drivers/rtc/rtc-sd3078.c2
-rw-r--r--drivers/rtc/rtc-tps6594.c4
-rw-r--r--drivers/rtc/rtc-x1205.c2
-rw-r--r--drivers/soundwire/bus.c28
-rw-r--r--drivers/spi/spi-dw-mmio.c1
-rw-r--r--drivers/spi/spi-dw.h1
-rw-r--r--drivers/spi/spi-imx.c3
-rw-r--r--drivers/spi/spi-rpc-if.c6
-rw-r--r--drivers/spi/spi-uniphier.c4
-rw-r--r--drivers/spi/spi.c10
-rw-r--r--drivers/thermal/intel/therm_throt.c7
-rw-r--r--drivers/thermal/testing/command.c36
-rw-r--r--drivers/thermal/testing/thermal_testing.h8
-rw-r--r--drivers/thermal/testing/zone.c7
-rw-r--r--drivers/video/fbdev/core/fbcon.c14
-rw-r--r--drivers/video/fbdev/core/fbmem.c12
-rw-r--r--drivers/video/fbdev/core/fbsysfs.c10
-rw-r--r--drivers/video/fbdev/goldfishfb.c13
-rw-r--r--drivers/video/fbdev/pm2fb.c1
-rw-r--r--drivers/video/fbdev/vga16fb.c4
-rw-r--r--drivers/video/fbdev/via/via-core.c7
151 files changed, 1867 insertions, 1025 deletions
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index 63976c3bcbe0..891112c2cddf 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -1300,7 +1300,7 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
args->handle, args->offset, args->size);
if (args->direction == SYNC_DIRECT_FROM_DEVICE)
- ret = amdxdna_hwctx_sync_debug_bo(abo->client, args->handle);
+ ret = amdxdna_hwctx_sync_debug_bo(client, args->handle);
put_obj:
drm_gem_object_put(gobj);
diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c
index 521931d1f7fc..b24f31a8b567 100644
--- a/drivers/accel/ivpu/ivpu_job.c
+++ b/drivers/accel/ivpu/ivpu_job.c
@@ -208,9 +208,9 @@ static int ivpu_hws_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq
ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->id,
priority);
if (ret)
- return ret;
+ ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id);
- return 0;
+ return ret;
}
static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
@@ -281,10 +281,10 @@ static int ivpu_cmdq_register(struct ivpu_file_priv *file_priv, struct ivpu_cmdq
}
ret = ivpu_register_db(file_priv, cmdq);
- if (ret)
- return ret;
+ if (ret && vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW)
+ ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id);
- return 0;
+ return ret;
}
static int ivpu_cmdq_unregister(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c
index 79ce6e72bf29..2dbed92d54b3 100644
--- a/drivers/acpi/acpi_ipmi.c
+++ b/drivers/acpi/acpi_ipmi.c
@@ -490,7 +490,7 @@ static void ipmi_bmc_gone(int iface)
mutex_lock(&driver_data.ipmi_lock);
list_for_each_entry_safe(iter, temp,
&driver_data.ipmi_devices, head) {
- if (iter->ipmi_ifnum != iface) {
+ if (iter->ipmi_ifnum == iface) {
ipmi_device = iter;
__ipmi_dev_kill(iter);
break;
diff --git a/drivers/acpi/acpica/utnonansi.c b/drivers/acpi/acpica/utnonansi.c
index 3a7952be6545..93867ad7f342 100644
--- a/drivers/acpi/acpica/utnonansi.c
+++ b/drivers/acpi/acpica/utnonansi.c
@@ -168,7 +168,16 @@ void acpi_ut_safe_strncpy(char *dest, char *source, acpi_size dest_size)
{
/* Always terminate destination string */
+#ifdef __KERNEL__
strscpy_pad(dest, source, dest_size);
+#else
+ /*
+ * strscpy_pad() is not defined in ACPICA tools builds, so use strncpy()
+ * and directly NUL-terminate the destination string in that case.
+ */
+ strncpy(dest, source, dest_size);
+ dest[dest_size - 1] = 0;
+#endif
}
#endif
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 390ab5f1d313..4482cf28f56a 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1143,7 +1143,7 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
return 0;
}
-int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
+int __weak __cpuidle acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
{
return -ENODEV;
}
@@ -1156,7 +1156,7 @@ int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
*
* Return: 0 for success or negative value for error
*/
-static int acpi_idle_lpi_enter(struct cpuidle_device *dev,
+static int __cpuidle acpi_idle_lpi_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct acpi_processor *pr;
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index bc8050d8a6f5..56df4599d360 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -871,7 +871,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
/**
- * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
+ * acpi_dev_free_resource_list - Free resource from acpi_dev_get_resources().
* @list: The head of the resource list to free.
*/
void acpi_dev_free_resource_list(struct list_head *list)
@@ -991,7 +991,7 @@ static int __acpi_dev_get_resources(struct acpi_device *adev,
*
* The resultant struct resource objects are put on the list pointed to by
* @list, that must be empty initially, as members of struct resource_entry
- * objects. Callers of this routine should use %acpi_dev_free_resource_list() to
+ * objects. Callers of this routine should use acpi_dev_free_resource_list() to
* free that list.
*
* The number of resources in the output list is returned on success, an error
@@ -1032,7 +1032,7 @@ static int is_memory(struct acpi_resource *ares, void *not_used)
* The resultant struct resource objects are put on the list pointed to
* by @list, that must be empty initially, as members of struct
* resource_entry objects. Callers of this routine should use
- * %acpi_dev_free_resource_list() to free that list.
+ * acpi_dev_free_resource_list() to free that list.
*
* The number of resources in the output list is returned on success,
* an error code reflecting the error condition is returned otherwise.
diff --git a/drivers/acpi/riscv/cpuidle.c b/drivers/acpi/riscv/cpuidle.c
index 624f9bbdb58c..c76dbabff702 100644
--- a/drivers/acpi/riscv/cpuidle.c
+++ b/drivers/acpi/riscv/cpuidle.c
@@ -66,7 +66,7 @@ int acpi_processor_ffh_lpi_probe(unsigned int cpu)
return acpi_cpu_init_idle(cpu);
}
-int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
+int __cpuidle acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
{
u32 state = lpi->address;
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index a625de3c3c8b..908cc5c7e643 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -17,12 +17,12 @@
#ifdef CONFIG_ACPI_DEBUG
/*
* ACPI debug sysfs I/F, including:
- * /sys/modules/acpi/parameters/debug_layer
- * /sys/modules/acpi/parameters/debug_level
- * /sys/modules/acpi/parameters/trace_method_name
- * /sys/modules/acpi/parameters/trace_state
- * /sys/modules/acpi/parameters/trace_debug_layer
- * /sys/modules/acpi/parameters/trace_debug_level
+ * /sys/module/acpi/parameters/debug_layer
+ * /sys/module/acpi/parameters/debug_level
+ * /sys/module/acpi/parameters/trace_method_name
+ * /sys/module/acpi/parameters/trace_state
+ * /sys/module/acpi/parameters/trace_debug_layer
+ * /sys/module/acpi/parameters/trace_debug_level
*/
struct acpi_dlayer {
@@ -269,7 +269,7 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
#endif /* CONFIG_ACPI_DEBUG */
-/* /sys/modules/acpi/parameters/aml_debug_output */
+/* /sys/module/acpi/parameters/aml_debug_output */
module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object,
byte, 0644);
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 27616b05111c..aa8f2efed779 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -245,7 +245,7 @@ err_exit:
if (map->cache_ops->exit) {
dev_dbg(map->dev, "Destroying %s cache\n", map->cache_ops->name);
map->lock(map->lock_arg);
- ret = map->cache_ops->exit(map);
+ map->cache_ops->exit(map);
map->unlock(map->lock_arg);
}
err_free_reg_defaults:
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 90c13de47cff..ac90d81aa294 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -580,14 +580,7 @@ static const struct bus_type rbd_bus_type = {
.bus_groups = rbd_bus_groups,
};
-static void rbd_root_dev_release(struct device *dev)
-{
-}
-
-static struct device rbd_root_dev = {
- .init_name = "rbd",
- .release = rbd_root_dev_release,
-};
+static struct device *rbd_root_dev;
static __printf(2, 3)
void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
@@ -5378,7 +5371,7 @@ static struct rbd_device *__rbd_dev_create(struct rbd_spec *spec)
rbd_dev->dev.bus = &rbd_bus_type;
rbd_dev->dev.type = &rbd_device_type;
- rbd_dev->dev.parent = &rbd_root_dev;
+ rbd_dev->dev.parent = rbd_root_dev;
device_initialize(&rbd_dev->dev);
return rbd_dev;
@@ -7324,15 +7317,13 @@ static int __init rbd_sysfs_init(void)
{
int ret;
- ret = device_register(&rbd_root_dev);
- if (ret < 0) {
- put_device(&rbd_root_dev);
- return ret;
- }
+ rbd_root_dev = root_device_register("rbd");
+ if (IS_ERR(rbd_root_dev))
+ return PTR_ERR(rbd_root_dev);
ret = bus_register(&rbd_bus_type);
if (ret < 0)
- device_unregister(&rbd_root_dev);
+ root_device_unregister(rbd_root_dev);
return ret;
}
@@ -7340,7 +7331,7 @@ static int __init rbd_sysfs_init(void)
static void __exit rbd_sysfs_cleanup(void)
{
bus_unregister(&rbd_bus_type);
- device_unregister(&rbd_root_dev);
+ root_device_unregister(rbd_root_dev);
}
static int __init rbd_slab_init(void)
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 370664c47e65..e355b42043cf 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -195,14 +195,6 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
s->exit_latency_ns = 0;
else
s->exit_latency = div_u64(s->exit_latency_ns, NSEC_PER_USEC);
-
- /*
- * Warn if the exit latency of a CPU idle state exceeds its
- * target residency which is assumed to never happen in cpuidle
- * in multiple places.
- */
- if (s->exit_latency_ns > s->target_residency_ns)
- pr_warn("Idle state %d target residency too low\n", i);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 9783a3cefb04..da325863ad76 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -558,7 +558,7 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev)
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
- uint64_t *bo_size, void *metadata_buffer,
+ uint64_t *bo_size, void **metadata_buffer,
size_t buffer_size, uint32_t *metadata_size,
uint32_t *flags, int8_t *xcp_id)
{
@@ -593,9 +593,24 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
*dmabuf_adev = adev;
if (bo_size)
*bo_size = amdgpu_bo_size(bo);
- if (metadata_buffer)
- r = amdgpu_bo_get_metadata(bo, metadata_buffer, buffer_size,
- metadata_size, &metadata_flags);
+ if (metadata_buffer) {
+ /* first get metadata_size by buffer = NULL */
+ r = amdgpu_bo_get_metadata(bo, NULL, 0,
+ metadata_size, NULL);
+
+ /* user buf_size is bigger than bo metadata_size
+ * allocate a buf at kernel space and copy */
+ if (*metadata_size <= buffer_size) {
+ *metadata_buffer = kzalloc(*metadata_size, GFP_KERNEL);
+
+ if (!*metadata_buffer)
+ return -ENOMEM;
+
+ r = amdgpu_bo_get_metadata(bo, *metadata_buffer, *metadata_size,
+ NULL, &metadata_flags);
+ } else
+ r = -EINVAL;
+ }
if (flags) {
*flags = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
KFD_IOC_ALLOC_MEM_FLAGS_VRAM
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 5333e052d56d..e443a7277299 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -262,7 +262,7 @@ uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
- uint64_t *bo_size, void *metadata_buffer,
+ uint64_t *bo_size, void **metadata_buffer,
size_t buffer_size, uint32_t *metadata_size,
uint32_t *flags, int8_t *xcp_id);
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index d54794e5b18b..35fe2c974699 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1914,13 +1914,6 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
mutex_lock(&mem->lock);
- /* Unpin MMIO/DOORBELL BO's that were pinned during allocation */
- if (mem->alloc_flags &
- (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
- KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
- amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo);
- }
-
mapped_to_gpu_memory = mem->mapped_to_gpu_memory;
is_imported = mem->is_imported;
mutex_unlock(&mem->lock);
@@ -1934,6 +1927,15 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
return -EBUSY;
}
+ /* At this point the BO is guaranteed to be freed, so unpin the
+ * MMIO/DOORBELL BOs that were pinned during allocation.
+ */
+ if (mem->alloc_flags &
+ (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
+ KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
+ amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo);
+ }
+
/* Make sure restore workers don't access the BO any more */
mutex_lock(&process_info->lock);
if (!list_empty(&mem->validate_list))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 115b134b4cd1..c2e6495a28bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -247,13 +247,17 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
goto free_partial_kdata;
break;
+ case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
+ if (size < sizeof(struct drm_amdgpu_cs_chunk_cp_gfx_shadow))
+ goto free_partial_kdata;
+ break;
+
case AMDGPU_CHUNK_ID_DEPENDENCIES:
case AMDGPU_CHUNK_ID_SYNCOBJ_IN:
case AMDGPU_CHUNK_ID_SYNCOBJ_OUT:
case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES:
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT:
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL:
- case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
break;
default:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index 0d7f6cd74f79..ce35b415093d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -326,7 +326,6 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
struct drm_file *filp, struct amdgpu_ctx *ctx)
{
struct amdgpu_fpriv *fpriv = filp->driver_priv;
- u32 current_stable_pstate;
int r;
r = amdgpu_ctx_priority_permit(filp, priority);
@@ -344,36 +343,21 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
ctx->generation = amdgpu_vm_generation(mgr->adev, &fpriv->vm);
ctx->init_priority = priority;
ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET;
-
- r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
- if (r)
- return r;
-
- if (mgr->adev->pm.stable_pstate_ctx)
- ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate;
- else
- ctx->stable_pstate = current_stable_pstate;
+ ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE;
return 0;
}
-static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
- u32 stable_pstate)
+static int __amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
+ u32 stable_pstate)
{
struct amdgpu_device *adev = ctx->mgr->adev;
enum amd_dpm_forced_level level;
+ struct amdgpu_ctx *current_ctx;
u32 current_stable_pstate;
- int r;
+ int r = 0;
- mutex_lock(&adev->pm.stable_pstate_ctx_lock);
- if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) {
- r = -EBUSY;
- goto done;
- }
-
- r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
- if (r || (stable_pstate == current_stable_pstate))
- goto done;
+ lockdep_assert_held(&adev->pm.stable_pstate_ctx_lock);
switch (stable_pstate) {
case AMDGPU_CTX_STABLE_PSTATE_NONE:
@@ -392,17 +376,41 @@ static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
break;
default:
- r = -EINVAL;
- goto done;
+ return -EINVAL;
}
+ current_ctx = adev->pm.stable_pstate_ctx;
+ if (current_ctx && current_ctx != ctx)
+ return -EBUSY;
+
+ r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
+ if (r || current_stable_pstate == stable_pstate)
+ return r;
+
r = amdgpu_dpm_force_performance_level(adev, level);
+ if (r)
+ return r;
- if (level == AMD_DPM_FORCED_LEVEL_AUTO)
- adev->pm.stable_pstate_ctx = NULL;
- else
+ if (!current_ctx) {
adev->pm.stable_pstate_ctx = ctx;
-done:
+ /*
+ * Serialized by context taking ownership for the first time
+ * while holding adev->pm.stable_pstate_ctx_lock).
+ */
+ WRITE_ONCE(ctx->stable_pstate, current_stable_pstate);
+ }
+
+ return 0;
+}
+
+static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
+ u32 stable_pstate)
+{
+ struct amdgpu_device *adev = ctx->mgr->adev;
+ int r;
+
+ mutex_lock(&adev->pm.stable_pstate_ctx_lock);
+ r = __amdgpu_ctx_set_stable_pstate(ctx, stable_pstate);
mutex_unlock(&adev->pm.stable_pstate_ctx_lock);
return r;
@@ -428,7 +436,12 @@ static void amdgpu_ctx_fini(struct kref *ref)
}
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
- amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate);
+ mutex_lock(&adev->pm.stable_pstate_ctx_lock);
+ if (adev->pm.stable_pstate_ctx == ctx) {
+ __amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate);
+ adev->pm.stable_pstate_ctx = NULL;
+ }
+ mutex_unlock(&adev->pm.stable_pstate_ctx_lock);
drm_dev_exit(idx);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index 27830518a230..e77db76b48b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -22,8 +22,9 @@
*
*/
-#include <generated/utsrelease.h>
#include <linux/devcoredump.h>
+#include <linux/utsname.h>
+#include <drm/drm_exec.h>
#include "amdgpu_dev_coredump.h"
#include "atom.h"
@@ -207,28 +208,143 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
}
}
+static void
+amdgpu_devcoredump_print_ibs(struct drm_printer *p,
+ struct amdgpu_coredump_info *coredump,
+ bool sizing_pass)
+{
+ struct amdgpu_device *adev = coredump->adev;
+ struct amdgpu_bo_va_mapping *mapping;
+ struct amdgpu_bo *abo;
+ struct drm_exec exec;
+ struct amdgpu_vm *vm;
+ u32 *ib_content;
+ u64 va_start, offset;
+ u8 *kptr;
+ u32 off;
+ int r;
+
+ /*
+ * On the sizing pass there is no VM to look up and no BO to lock; the
+ * size estimate doesn't depend on whether the IB BOs are reachable.
+ * Just emit the per-IB headers (the content is not written anywhere).
+ */
+ if (sizing_pass) {
+ for (int i = 0; i < coredump->num_ibs; i++) {
+ drm_printf(p, "\nIB #%d 0x%llx %d dw\n", i,
+ coredump->ibs[i].gpu_addr,
+ coredump->ibs[i].ib_size_dw);
+ }
+ return;
+ }
+
+ /*
+ * Lock the VM root PD and every IB BO together in a single drm_exec
+ * ticket. Reserving the IB BOs one by one while the root PD is held
+ * would be a recursive reservation_ww_class_mutex acquire without a
+ * ww_acquire_ctx, which trips lockdep and self-deadlocks for IB BOs
+ * that share their dma_resv with the root PD (always-valid BOs).
+ */
+ drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 1 + coredump->num_ibs);
+ drm_exec_until_all_locked(&exec) {
+ vm = amdgpu_vm_lock_by_pasid(adev, coredump->pasid, &exec);
+ if (!vm)
+ goto unlock;
+
+ for (int i = 0; i < coredump->num_ibs; i++) {
+ u64 pfn = (coredump->ibs[i].gpu_addr &
+ AMDGPU_GMC_HOLE_MASK) / AMDGPU_GPU_PAGE_SIZE;
+
+ mapping = amdgpu_vm_bo_lookup_mapping(vm, pfn);
+ if (!mapping)
+ continue;
+
+ abo = mapping->bo_va->base.bo;
+ r = drm_exec_lock_obj(&exec, &abo->tbo.base);
+ drm_exec_retry_on_contention(&exec);
+ if (r)
+ goto unlock;
+ }
+ }
+
+ for (int i = 0; i < coredump->num_ibs; i++) {
+ bool emit_content = false;
+
+ ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4,
+ GFP_KERNEL);
+ if (!ib_content)
+ continue;
+
+ va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
+ mapping = amdgpu_vm_bo_lookup_mapping(vm,
+ va_start / AMDGPU_GPU_PAGE_SIZE);
+ if (!mapping)
+ goto output_ib_content;
+
+ abo = mapping->bo_va->base.bo;
+ offset = va_start - mapping->start * AMDGPU_GPU_PAGE_SIZE;
+
+ if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
+ struct amdgpu_res_cursor cursor;
+
+ off = 0;
+
+ if (abo->tbo.resource->mem_type != TTM_PL_VRAM)
+ goto output_ib_content;
+
+ amdgpu_res_first(abo->tbo.resource, offset,
+ coredump->ibs[i].ib_size_dw * 4, &cursor);
+ while (cursor.remaining) {
+ amdgpu_device_mm_access(adev, cursor.start / 4,
+ &ib_content[off], cursor.size / 4,
+ false);
+ off += cursor.size;
+ amdgpu_res_next(&cursor, cursor.size);
+ }
+ emit_content = true;
+ } else {
+ r = ttm_bo_kmap(&abo->tbo, 0, PFN_UP(abo->tbo.base.size),
+ &abo->kmap);
+ if (r)
+ goto output_ib_content;
+
+ kptr = amdgpu_bo_kptr(abo);
+ kptr += offset;
+ memcpy(ib_content, kptr, coredump->ibs[i].ib_size_dw * 4);
+
+ amdgpu_bo_kunmap(abo);
+ emit_content = true;
+ }
+
+output_ib_content:
+ drm_printf(p, "\nIB #%d 0x%llx %d dw\n", i,
+ coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw);
+ if (emit_content) {
+ for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
+ drm_printf(p, "0x%08x\n", ib_content[j]);
+ }
+ kvfree(ib_content);
+ }
+
+unlock:
+ drm_exec_fini(&exec);
+}
+
static ssize_t
amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_info *coredump)
{
- struct amdgpu_device *adev = coredump->adev;
struct drm_printer p;
struct drm_print_iterator iter;
struct amdgpu_vm_fault_info *fault_info;
- struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_ip_block *ip_block;
- struct amdgpu_res_cursor cursor;
- struct amdgpu_bo *abo, *root;
- uint64_t va_start, offset;
struct amdgpu_ring *ring;
- struct amdgpu_vm *vm;
- u32 *ib_content;
- uint8_t *kptr;
- int ver, i, j, r;
+ int ver, i, j;
u32 ring_idx, off;
bool sizing_pass;
sizing_pass = buffer == NULL;
iter.data = buffer;
+ iter.start = 0;
iter.offset = 0;
iter.remain = count;
@@ -236,7 +352,7 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
drm_printf(&p, "**** AMDGPU Device Coredump ****\n");
drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n");
- drm_printf(&p, "kernel: " UTS_RELEASE "\n");
+ drm_printf(&p, "kernel: %s\n", init_utsname()->release);
drm_printf(&p, "module: " KBUILD_MODNAME "\n");
drm_printf(&p, "time: %ptSp\n", &coredump->reset_time);
@@ -342,86 +458,8 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
else if (coredump->reset_vram_lost)
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
- if (coredump->num_ibs) {
- /* Don't try to lookup the VM or map the BOs when calculating the
- * size required to store the devcoredump.
- */
- if (sizing_pass)
- vm = NULL;
- else
- vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid);
-
- for (int i = 0; i < coredump->num_ibs && (sizing_pass || vm); i++) {
- ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4,
- GFP_KERNEL);
- if (!ib_content)
- continue;
-
- /* vm=NULL can only happen when 'sizing_pass' is true. Skip to the
- * drm_printf() calls (ib_content doesn't need to be initialized
- * as its content won't be written anywhere).
- */
- if (!vm)
- goto output_ib_content;
-
- va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
- mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE);
- if (!mapping)
- goto free_ib_content;
-
- offset = va_start - (mapping->start * AMDGPU_GPU_PAGE_SIZE);
- abo = amdgpu_bo_ref(mapping->bo_va->base.bo);
- r = amdgpu_bo_reserve(abo, false);
- if (r)
- goto free_ib_content;
-
- if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
- off = 0;
-
- if (abo->tbo.resource->mem_type != TTM_PL_VRAM)
- goto unreserve_abo;
-
- amdgpu_res_first(abo->tbo.resource, offset,
- coredump->ibs[i].ib_size_dw * 4,
- &cursor);
- while (cursor.remaining) {
- amdgpu_device_mm_access(adev, cursor.start / 4,
- &ib_content[off], cursor.size / 4,
- false);
- off += cursor.size;
- amdgpu_res_next(&cursor, cursor.size);
- }
- } else {
- r = ttm_bo_kmap(&abo->tbo, 0,
- PFN_UP(abo->tbo.base.size),
- &abo->kmap);
- if (r)
- goto unreserve_abo;
-
- kptr = amdgpu_bo_kptr(abo);
- kptr += offset;
- memcpy(ib_content, kptr,
- coredump->ibs[i].ib_size_dw * 4);
-
- amdgpu_bo_kunmap(abo);
- }
-
-output_ib_content:
- drm_printf(&p, "\nIB #%d 0x%llx %d dw\n",
- i, coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw);
- for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
- drm_printf(&p, "0x%08x\n", ib_content[j]);
-unreserve_abo:
- if (vm)
- amdgpu_bo_unreserve(abo);
-free_ib_content:
- kvfree(ib_content);
- }
- if (vm) {
- amdgpu_bo_unreserve(root);
- amdgpu_bo_unref(&root);
- }
- }
+ if (coredump->num_ibs)
+ amdgpu_devcoredump_print_ibs(&p, coredump, sizing_pass);
return count - iter.remain;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 942f0251c748..211d30f03d25 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3043,7 +3043,7 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D3Entry);
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_blocks[i].status.valid)
+ if (!adev->ip_blocks[i].status.valid || !adev->ip_blocks[i].status.hw)
continue;
/* displays are handled in phase1 */
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)
@@ -3771,6 +3771,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
mutex_init(&adev->gfx.workload_profile_mutex);
mutex_init(&adev->vcn.workload_profile_mutex);
+ spin_lock_init(&adev->irq.lock);
+
amdgpu_device_init_apu_flags(adev);
r = amdgpu_device_check_arguments(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 212c14d99f6b..76da3f932f24 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -1094,6 +1094,11 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
* If that number is larger than the size of the array, the ioctl must
* be retried.
*/
+ if (!bo_va) {
+ r = -ENOENT;
+ goto out_exec;
+ }
+
if (args->num_entries > INT_MAX / sizeof(*vm_entries)) {
r = -EINVAL;
goto out_exec;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 1e190fb54a97..85372af1216d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1664,12 +1664,13 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
struct drm_gpu_scheduler *sched = &ring->sched;
struct drm_sched_entity entity;
+ unsigned int ib_size_dw = 16;
static atomic_t counter;
struct dma_fence *f;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
void *owner;
- int i, r;
+ int r;
/* Initialize the scheduler entity */
r = drm_sched_entity_init(&entity, DRM_SCHED_PRIORITY_NORMAL,
@@ -1687,7 +1688,7 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
owner = (void *)(unsigned long)atomic_inc_return(&counter);
r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
- 64, 0, &job,
+ ib_size_dw * sizeof(uint32_t), 0, &job,
AMDGPU_KERNEL_JOB_ID_CLEANER_SHADER);
if (r)
goto err;
@@ -1697,9 +1698,8 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
job->run_cleaner_shader = true;
ib = &job->ibs[0];
- for (i = 0; i <= ring->funcs->align_mask; ++i)
- ib->ptr[i] = ring->funcs->nop;
- ib->length_dw = ring->funcs->align_mask + 1;
+ memset32(ib->ptr, ring->funcs->nop, ib_size_dw);
+ ib->length_dw = ib_size_dw;
f = amdgpu_job_submit(job);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index d23a91d029aa..0ea32561c4bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -272,7 +272,20 @@ static bool amdgpu_gtt_mgr_intersects(struct ttm_resource_manager *man,
const struct ttm_place *place,
size_t size)
{
- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
+ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
+ const u32 num_pages = PFN_UP(size);
+
+ if (!place->lpfn)
+ return true;
+
+ if (!amdgpu_gtt_mgr_has_gart_addr(res))
+ return false;
+
+ if (place->fpfn >= (node->start + num_pages) ||
+ (place->lpfn && place->lpfn <= node->start))
+ return false;
+
+ return true;
}
/**
@@ -290,7 +303,20 @@ static bool amdgpu_gtt_mgr_compatible(struct ttm_resource_manager *man,
const struct ttm_place *place,
size_t size)
{
- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
+ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
+ const u32 num_pages = PFN_UP(size);
+
+ if (!place->lpfn)
+ return true;
+
+ if (!amdgpu_gtt_mgr_has_gart_addr(res))
+ return false;
+
+ if (node->start < place->fpfn ||
+ (place->lpfn && (node->start + num_pages) > place->lpfn))
+ return false;
+
+ return true;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 254a4e983f40..53be764968e4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -309,8 +309,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
unsigned int irq, flags;
int r;
- spin_lock_init(&adev->irq.lock);
-
/* Enable MSI if not disabled by module parameter */
adev->irq.msi_enabled = false;
@@ -547,7 +545,7 @@ void amdgpu_irq_delegate(struct amdgpu_device *adev,
unsigned int num_dw)
{
amdgpu_ih_ring_write(adev, &adev->irq.ih_soft, entry->iv_entry, num_dw);
- schedule_work(&adev->irq.ih_soft_work);
+ queue_work(system_unbound_wq, &adev->irq.ih_soft_work);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c
index d5d71fd7c70d..61450af539a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c
@@ -16,6 +16,17 @@
#ifdef CONFIG_LOCKDEP
+struct amdgpu_lockdep_dummy_locks {
+ struct mutex reset_lock;
+ struct mutex userq_sch_mutex;
+ struct mutex userq_mutex;
+ struct mutex notifier_lock;
+ struct mutex vram_lock;
+ struct mutex srbm_mutex;
+ struct mutex grbm_idx_mutex;
+ spinlock_t mmio_idx_lock;
+};
+
/* Lock class keys for associating with real driver locks */
static struct lock_class_key amdgpu_userq_sch_mutex_key;
static struct lock_class_key amdgpu_userq_mutex_key;
@@ -84,72 +95,65 @@ void amdgpu_lockdep_set_class(struct amdgpu_device *adev)
int amdgpu_lockdep_init(void)
{
struct amdgpu_reset_domain *reset_domain = NULL;
- struct amdgpu_reset_control reset_ctl;
- struct mutex userq_sch_mutex;
- struct mutex userq_mutex;
- struct mutex notifier_lock;
- struct mutex vram_lock;
- struct mutex srbm_mutex;
- struct mutex grbm_idx_mutex;
- spinlock_t mmio_idx_lock;
+ struct amdgpu_lockdep_dummy_locks *locks;
unsigned long flags;
+ locks = kzalloc(sizeof(*locks), GFP_KERNEL);
+ if (!locks)
+ return -ENOMEM;
+
/*
* Initialize dummy reset domain
*/
reset_domain = amdgpu_reset_create_reset_domain(SINGLE_DEVICE,
"lockdep_test");
- if (!reset_domain)
+ if (!reset_domain) {
+ kfree(locks);
return -ENOMEM;
-
+ }
/* Initialize dummy locks */
- mutex_init(&userq_sch_mutex);
- mutex_init(&userq_mutex);
- mutex_init(&notifier_lock);
- mutex_init(&vram_lock);
- mutex_init(&reset_ctl.reset_lock);
- mutex_init(&srbm_mutex);
- mutex_init(&grbm_idx_mutex);
- spin_lock_init(&mmio_idx_lock);
+ mutex_init(&locks->userq_sch_mutex);
+ mutex_init(&locks->userq_mutex);
+ mutex_init(&locks->notifier_lock);
+ mutex_init(&locks->vram_lock);
+ mutex_init(&locks->reset_lock);
+ mutex_init(&locks->srbm_mutex);
+ mutex_init(&locks->grbm_idx_mutex);
+ spin_lock_init(&locks->mmio_idx_lock);
/*
* Associate dummy locks with the same class keys used for real
* driver locks. This ensures lockdep connects the ordering learned
* here with the actual locks used at runtime.
*/
- lockdep_set_class(&userq_sch_mutex, &amdgpu_userq_sch_mutex_key);
- lockdep_set_class(&userq_mutex, &amdgpu_userq_mutex_key);
- lockdep_set_class(&notifier_lock, &amdgpu_notifier_lock_key);
- lockdep_set_class(&vram_lock, &amdgpu_vram_lock_key);
+ lockdep_set_class(&locks->userq_sch_mutex, &amdgpu_userq_sch_mutex_key);
+ lockdep_set_class(&locks->userq_mutex, &amdgpu_userq_mutex_key);
+ lockdep_set_class(&locks->notifier_lock, &amdgpu_notifier_lock_key);
+ lockdep_set_class(&locks->vram_lock, &amdgpu_vram_lock_key);
lockdep_set_class(&reset_domain->sem, &amdgpu_reset_sem_key);
- lockdep_set_class(&reset_ctl.reset_lock, &amdgpu_reset_lock_key);
- lockdep_set_class(&srbm_mutex, &amdgpu_srbm_lock_key);
- lockdep_set_class(&grbm_idx_mutex, &amdgpu_grbm_lock_key);
- lockdep_set_class(&mmio_idx_lock, &amdgpu_mmio_lock_key);
-
+ lockdep_set_class(&locks->reset_lock, &amdgpu_reset_lock_key);
+ lockdep_set_class(&locks->srbm_mutex, &amdgpu_srbm_lock_key);
+ lockdep_set_class(&locks->grbm_idx_mutex, &amdgpu_grbm_lock_key);
+ lockdep_set_class(&locks->mmio_idx_lock, &amdgpu_mmio_lock_key);
/*
* Take locks in the correct order to train lockdep.
* This establishes the dependency chain.
*/
/* Level 1: Global userq scheduler mutex (outermost) */
- mutex_lock(&userq_sch_mutex);
+ mutex_lock(&locks->userq_sch_mutex);
/* Level 2: Per-context userq mutex */
- mutex_lock(&userq_mutex);
-
+ mutex_lock(&locks->userq_mutex);
/* Level 3: MMU notifier lock */
- mutex_lock(&notifier_lock);
-
+ mutex_lock(&locks->notifier_lock);
/* Level 4: VRAM allocator lock */
- mutex_lock(&vram_lock);
-
+ mutex_lock(&locks->vram_lock);
/* Level 5: Reset domain semaphore */
down_read(&reset_domain->sem);
/* Level 6: Reset control lock */
- mutex_lock(&reset_ctl.reset_lock);
-
+ mutex_lock(&locks->reset_lock);
/*
* Mark potential memory reclaim boundary.
* GPU operations might trigger memory allocation/reclaim.
@@ -157,36 +161,35 @@ int amdgpu_lockdep_init(void)
fs_reclaim_acquire(GFP_KERNEL);
/* Level 7: SRBM register access */
- mutex_lock(&srbm_mutex);
-
+ mutex_lock(&locks->srbm_mutex);
/* Level 8: GRBM index access */
- mutex_lock(&grbm_idx_mutex);
+ mutex_lock(&locks->grbm_idx_mutex);
/* Level 9: MMIO index access (innermost lock, spinlock) */
- spin_lock_irqsave(&mmio_idx_lock, flags);
-
+ spin_lock_irqsave(&locks->mmio_idx_lock, flags);
/*
* All locks acquired in order.
* Lockdep has now learned the valid dependency chain.
*/
/* Release in reverse order */
- spin_unlock_irqrestore(&mmio_idx_lock, flags);
- mutex_unlock(&grbm_idx_mutex);
- mutex_unlock(&srbm_mutex);
-
+ spin_unlock_irqrestore(&locks->mmio_idx_lock, flags);
+ mutex_unlock(&locks->grbm_idx_mutex);
+ mutex_unlock(&locks->srbm_mutex);
fs_reclaim_release(GFP_KERNEL);
- mutex_unlock(&reset_ctl.reset_lock);
+ mutex_unlock(&locks->reset_lock);
up_read(&reset_domain->sem);
- mutex_unlock(&vram_lock);
- mutex_unlock(&notifier_lock);
- mutex_unlock(&userq_mutex);
- mutex_unlock(&userq_sch_mutex);
+
+ mutex_unlock(&locks->vram_lock);
+ mutex_unlock(&locks->notifier_lock);
+ mutex_unlock(&locks->userq_mutex);
+ mutex_unlock(&locks->userq_sch_mutex);
/* Cleanup */
amdgpu_reset_put_reset_domain(reset_domain);
+ kfree(locks);
pr_info("AMDGPU: Lockdep annotations initialized (9 lock levels)\n");
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 2740de94e93c..16c060badaee 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
if (new_mem->mem_type == TTM_PL_TT ||
new_mem->mem_type == AMDGPU_PL_PREEMPT) {
+ if (old_mem && (old_mem->mem_type == TTM_PL_TT ||
+ old_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+ r = ttm_bo_wait_ctx(bo, ctx);
+ if (r)
+ return r;
+
+ amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
+ }
+
r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem);
if (r)
return r;
@@ -549,6 +558,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
ttm_bo_assign_mem(bo, new_mem);
return 0;
}
+ if ((old_mem->mem_type == TTM_PL_TT ||
+ old_mem->mem_type == AMDGPU_PL_PREEMPT) &&
+ (new_mem->mem_type == TTM_PL_TT ||
+ new_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+ amdgpu_bo_move_notify(bo, evict, new_mem);
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_assign_mem(bo, new_mem);
+ return 0;
+ }
if (old_mem->mem_type == AMDGPU_PL_GDS ||
old_mem->mem_type == AMDGPU_PL_GWS ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 3a3bc0d370fa..480bf88def46 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -135,7 +135,7 @@ MODULE_FIRMWARE(FIRMWARE_VEGA12);
MODULE_FIRMWARE(FIRMWARE_VEGA20);
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
-static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo);
+static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *abo);
static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
uint32_t size,
@@ -158,7 +158,7 @@ static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
amdgpu_bo_kunmap(bo);
amdgpu_bo_unpin(bo);
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
- amdgpu_uvd_force_into_uvd_segment(bo);
+ amdgpu_uvd_force_into_vcpu_segment(bo);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
if (r)
goto err;
@@ -188,6 +188,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
const struct common_firmware_header *hdr;
unsigned int family_id;
int i, j, r;
+ u32 vcpu_bo_domain;
INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler);
@@ -319,12 +320,20 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+ /* UVD 5.0 and newer HW can use 64 bit addressing. */
+ adev->uvd.address_64_bit =
+ !amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0);
+
+ vcpu_bo_domain = AMDGPU_GEM_DOMAIN_VRAM;
+ if (adev->uvd.address_64_bit)
+ vcpu_bo_domain |= AMDGPU_GEM_DOMAIN_GTT;
+
for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
if (adev->uvd.harvest_config & (1 << j))
continue;
+
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM |
- AMDGPU_GEM_DOMAIN_GTT,
+ vcpu_bo_domain,
&adev->uvd.inst[j].vcpu_bo,
&adev->uvd.inst[j].gpu_addr,
&adev->uvd.inst[j].cpu_addr);
@@ -339,10 +348,6 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
adev->uvd.filp[i] = NULL;
}
- /* from uvd v5.0 HW addressing capacity increased to 64 bits */
- if (!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0))
- adev->uvd.address_64_bit = true;
-
r = amdgpu_uvd_create_msg_bo_helper(adev, 128 << 10, &adev->uvd.ib_bo);
if (r)
return r;
@@ -545,6 +550,24 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
}
}
+static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *bo)
+{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ struct amdgpu_bo *vcpu_bo = adev->uvd.inst[0].vcpu_bo;
+ struct amdgpu_res_cursor vcpu_cur;
+
+ amdgpu_res_first(vcpu_bo->tbo.resource, 0,
+ amdgpu_bo_size(vcpu_bo), &vcpu_cur);
+
+ bo->placement.num_placement = 1;
+ bo->placement.placement = &bo->placements[0];
+ bo->placements[0].fpfn = ALIGN_DOWN(vcpu_cur.start, SZ_256M) >> PAGE_SHIFT;
+ bo->placements[0].lpfn = bo->placements[0].fpfn + (SZ_256M >> PAGE_SHIFT);
+ bo->placements[0].mem_type = vcpu_bo->tbo.resource->mem_type;
+ if (bo->placements[0].mem_type == TTM_PL_VRAM)
+ bo->placements[0].flags |= TTM_PL_FLAG_CONTIGUOUS;
+}
+
static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
{
int i;
@@ -595,13 +618,10 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
if (!ctx->parser->adev->uvd.address_64_bit) {
/* check if it's a message or feedback command */
cmd = amdgpu_ib_get_value(ctx->ib, ctx->idx) >> 1;
- if (cmd == 0x0 || cmd == 0x3) {
- /* yes, force it into VRAM */
- uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM;
-
- amdgpu_bo_placement_from_domain(bo, domain);
- }
- amdgpu_uvd_force_into_uvd_segment(bo);
+ if (cmd == 0x0 || cmd == 0x3)
+ amdgpu_uvd_force_into_vcpu_segment(bo);
+ else
+ amdgpu_uvd_force_into_uvd_segment(bo);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &tctx);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 7d51880b4860..fee4c94c2585 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2920,47 +2920,56 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
}
/**
- * amdgpu_vm_lock_by_pasid - return an amdgpu_vm and its root bo from a pasid, if possible.
+ * amdgpu_vm_lock_by_pasid - look up a VM by PASID and lock its root PD
* @adev: amdgpu device pointer
- * @root: root BO of the VM
* @pasid: PASID of the VM
- * The caller needs to unreserve and unref the root bo on success.
+ * @exec: drm_exec context to lock the root PD in
+ *
+ * Must be called from within a drm_exec_until_all_locked() loop; the caller
+ * runs drm_exec_retry_on_contention() afterwards. The drm_exec context holds
+ * a reference on the root BO until it is finalised.
+ *
+ * Return: the VM on success, or NULL if the PASID has no VM, the VM is being
+ * torn down, or locking the root PD failed.
*/
struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
- struct amdgpu_bo **root, u32 pasid)
+ u32 pasid, struct drm_exec *exec)
{
unsigned long irqflags;
+ struct amdgpu_bo *root;
struct amdgpu_vm *vm;
int r;
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
vm = xa_load(&adev->vm_manager.pasids, pasid);
- *root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
+ root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
- if (!*root)
+ if (!root)
return NULL;
- r = amdgpu_bo_reserve(*root, true);
- if (r)
- goto error_unref;
+ r = drm_exec_lock_obj(exec, &root->tbo.base);
+ if (r) {
+ amdgpu_bo_unref(&root);
+ return NULL;
+ }
/* Double check that the VM still exists */
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
vm = xa_load(&adev->vm_manager.pasids, pasid);
- if (vm && vm->root.bo != *root)
+ if (vm && vm->root.bo != root)
vm = NULL;
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
- if (!vm)
- goto error_unlock;
+ if (!vm) {
+ drm_exec_unlock_obj(exec, &root->tbo.base);
+ amdgpu_bo_unref(&root);
+ return NULL;
+ }
- return vm;
-error_unlock:
- amdgpu_bo_unreserve(*root);
+ /* The drm_exec context holds its own reference on the root BO. */
+ amdgpu_bo_unref(&root);
-error_unref:
- amdgpu_bo_unref(root);
- return NULL;
+ return vm;
}
/**
@@ -2982,33 +2991,49 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
uint64_t ts, bool write_fault)
{
bool is_compute_context = false;
- struct amdgpu_bo *root;
+ struct drm_exec exec;
uint64_t value, flags;
struct amdgpu_vm *vm;
int r;
- vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid);
- if (!vm)
+ drm_exec_init(&exec, 0, 1);
+ drm_exec_until_all_locked(&exec) {
+ vm = amdgpu_vm_lock_by_pasid(adev, pasid, &exec);
+ drm_exec_retry_on_contention(&exec);
+ if (!vm)
+ break;
+ }
+ if (!vm) {
+ drm_exec_fini(&exec);
return false;
+ }
is_compute_context = vm->is_compute_context;
if (is_compute_context) {
- /* Unreserve root since svm_range_restore_pages might try to reserve it. */
- /* TODO: rework svm_range_restore_pages so that this isn't necessary. */
- amdgpu_bo_unreserve(root);
+ /* Release the root PD lock since svm_range_restore_pages
+ * might try to take it.
+ * TODO: rework svm_range_restore_pages so that this isn't
+ * necessary.
+ */
+ drm_exec_fini(&exec);
if (!svm_range_restore_pages(adev, pasid, vmid,
- node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
- amdgpu_bo_unref(&root);
+ node_id, addr >> PAGE_SHIFT, ts, write_fault))
return true;
- }
- amdgpu_bo_unref(&root);
/* Re-acquire the VM lock, could be that the VM was freed in between. */
- vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid);
- if (!vm)
+ drm_exec_init(&exec, 0, 1);
+ drm_exec_until_all_locked(&exec) {
+ vm = amdgpu_vm_lock_by_pasid(adev, pasid, &exec);
+ drm_exec_retry_on_contention(&exec);
+ if (!vm)
+ break;
+ }
+ if (!vm) {
+ drm_exec_fini(&exec);
return false;
+ }
}
addr /= AMDGPU_GPU_PAGE_SIZE;
@@ -3032,7 +3057,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
value = 0;
}
- r = dma_resv_reserve_fences(root->tbo.base.resv, 1);
+ r = dma_resv_reserve_fences(vm->root.bo->tbo.base.resv, 1);
if (r) {
pr_debug("failed %d to reserve fence slot\n", r);
goto error_unlock;
@@ -3046,12 +3071,10 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
r = amdgpu_vm_update_pdes(adev, vm, true);
error_unlock:
- amdgpu_bo_unreserve(root);
+ drm_exec_fini(&exec);
if (r < 0)
dev_err(adev->dev, "Can't handle page fault (%d)\n", r);
- amdgpu_bo_unref(&root);
-
return false;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 3695299f1a03..b32f51a78cd8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -592,7 +592,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
bool write_fault);
struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
- struct amdgpu_bo **root, u32 pasid);
+ u32 pasid, struct drm_exec *exec);
void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 47721d0c3781..81a759a98725 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -4071,6 +4071,41 @@ err_priv_inst:
return r;
}
+static void gfx_v9_0_deactivate_kcq_hqd(struct amdgpu_device *adev)
+{
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
+ for (int i = 0; i < adev->gfx.num_compute_rings; i++) {
+ u32 tmp;
+ struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
+
+ mutex_lock(&adev->srbm_mutex);
+ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0);
+ tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
+ /* disable the queue if it's active */
+ if (tmp & CP_HQD_ACTIVE__ACTIVE_MASK) {
+ int j;
+
+ WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1);
+ for (j = 0; j < adev->usec_timeout; j++) {
+ tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
+ if (!(tmp & CP_HQD_ACTIVE__ACTIVE_MASK))
+ break;
+ udelay(1);
+ }
+ if (j == AMDGPU_MAX_USEC_TIMEOUT) {
+ DRM_DEBUG("comp_%u_%u_%u dequeue request failed.\n",
+ ring->me, ring->pipe, ring->queue);
+ /* Manual disable if dequeue request times out */
+ WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, 0);
+ }
+ WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 0);
+ }
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
+ }
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
+}
+
static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@ -4095,6 +4130,10 @@ static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
return 0;
}
+ if ((adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev) &&
+ amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_MODE2)
+ gfx_v9_0_deactivate_kcq_hqd(adev);
+
/* Use deinitialize sequence from CAIL when unbinding device from driver,
* otherwise KIQ is hanging when binding back
*/
diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c
index 95b3f4e55ec3..699c274d357e 100644
--- a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c
@@ -790,7 +790,7 @@ static void ih_v6_1_set_interrupt_funcs(struct amdgpu_device *adev)
const struct amdgpu_ip_block_version ih_v6_1_ip_block = {
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 6,
- .minor = 0,
+ .minor = 1,
.rev = 0,
.funcs = &ih_v6_1_ip_funcs,
};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index a2b100d14425..531e20748198 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1299,18 +1299,11 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
return -EINVAL;
}
- devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr),
- GFP_KERNEL);
- if (!devices_arr)
- return -ENOMEM;
+ devices_arr = memdup_array_user((void *)args->device_ids_array_ptr,
+ args->n_devices, sizeof(*devices_arr));
- err = copy_from_user(devices_arr,
- (void __user *)args->device_ids_array_ptr,
- args->n_devices * sizeof(*devices_arr));
- if (err != 0) {
- err = -EFAULT;
- goto copy_from_user_failed;
- }
+ if (IS_ERR(devices_arr))
+ return PTR_ERR(devices_arr);
mutex_lock(&p->mutex);
pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle));
@@ -1391,7 +1384,6 @@ get_mem_obj_from_handle_failed:
map_memory_to_gpu_failed:
sync_memory_failed:
mutex_unlock(&p->mutex);
-copy_from_user_failed:
kfree(devices_arr);
return err;
@@ -1416,18 +1408,11 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
return -EINVAL;
}
- devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr),
- GFP_KERNEL);
- if (!devices_arr)
- return -ENOMEM;
+ devices_arr = memdup_array_user((void *)args->device_ids_array_ptr,
+ args->n_devices, sizeof(*devices_arr));
- err = copy_from_user(devices_arr,
- (void __user *)args->device_ids_array_ptr,
- args->n_devices * sizeof(*devices_arr));
- if (err != 0) {
- err = -EFAULT;
- goto copy_from_user_failed;
- }
+ if (IS_ERR(devices_arr))
+ return PTR_ERR(devices_arr);
mutex_lock(&p->mutex);
pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle));
@@ -1493,7 +1478,6 @@ get_mem_obj_from_handle_failed:
unmap_memory_from_gpu_failed:
sync_memory_failed:
mutex_unlock(&p->mutex);
-copy_from_user_failed:
kfree(devices_arr);
return err;
}
@@ -1562,16 +1546,10 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
if (!dev)
return -EINVAL;
- if (args->metadata_ptr) {
- metadata_buffer = kzalloc(args->metadata_size, GFP_KERNEL);
- if (!metadata_buffer)
- return -ENOMEM;
- }
-
/* Get dmabuf info from KGD */
r = amdgpu_amdkfd_get_dmabuf_info(dev->adev, args->dmabuf_fd,
&dmabuf_adev, &args->size,
- metadata_buffer, args->metadata_size,
+ &metadata_buffer, args->metadata_size,
&args->metadata_size, &flags, &xcp_id);
if (r)
goto exit;
@@ -1583,7 +1561,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
args->flags = flags;
/* Copy metadata buffer to user mode */
- if (metadata_buffer) {
+ if (metadata_buffer && args->metadata_ptr) {
r = copy_to_user((void __user *)args->metadata_ptr,
metadata_buffer, args->metadata_size);
if (r != 0)
@@ -2359,17 +2337,11 @@ static int criu_restore_devices(struct kfd_process *p,
if (*priv_offset + (args->num_devices * sizeof(*device_privs)) > max_priv_data_size)
return -EINVAL;
- device_buckets = kmalloc_objs(*device_buckets, args->num_devices);
- if (!device_buckets)
- return -ENOMEM;
+ device_buckets = memdup_array_user((void *)args->devices,
+ args->num_devices, sizeof(*device_buckets));
- ret = copy_from_user(device_buckets, (void __user *)args->devices,
- args->num_devices * sizeof(*device_buckets));
- if (ret) {
- pr_err("Failed to copy devices buckets from user\n");
- ret = -EFAULT;
- goto exit;
- }
+ if (IS_ERR(device_buckets))
+ return PTR_ERR(device_buckets);
for (i = 0; i < args->num_devices; i++) {
struct kfd_node *dev;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
index 05c74887fd6f..fdcf7f2d1b5b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
@@ -153,14 +153,16 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
u32 inx;
mutex_lock(&kfd->doorbell_mutex);
+
inx = find_first_zero_bit(kfd->doorbell_bitmap, PAGE_SIZE / sizeof(u32));
+ if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) {
+ mutex_unlock(&kfd->doorbell_mutex);
+ return NULL;
+ }
__set_bit(inx, kfd->doorbell_bitmap);
mutex_unlock(&kfd->doorbell_mutex);
- if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
- return NULL;
-
*doorbell_off = amdgpu_doorbell_index_on_bar(kfd->adev,
kfd->doorbells,
inx,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 28dc6886c1ff..226e76ae0be7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -424,7 +424,7 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
migrate.dst = migrate.src + npages;
scratch = (dma_addr_t *)(migrate.dst + npages);
- kfd_smi_event_migration_start(node, p->lead_thread->pid,
+ kfd_smi_event_migration_start(node, p->lead_thread,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
0, node->id, prange->prefetch_loc,
prange->preferred_loc, trigger);
@@ -462,7 +462,7 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
out_free:
kvfree(buf);
- kfd_smi_event_migration_end(node, p->lead_thread->pid,
+ kfd_smi_event_migration_end(node, p->lead_thread,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
0, node->id, trigger, r);
out:
@@ -727,7 +727,7 @@ svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange,
migrate.fault_page = fault_page;
scratch = (dma_addr_t *)(migrate.dst + npages);
- kfd_smi_event_migration_start(node, p->lead_thread->pid,
+ kfd_smi_event_migration_start(node, p->lead_thread,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
node->id, 0, prange->prefetch_loc,
prange->preferred_loc, trigger);
@@ -766,7 +766,7 @@ svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange,
out_free:
kvfree(buf);
- kfd_smi_event_migration_end(node, p->lead_thread->pid,
+ kfd_smi_event_migration_end(node, p->lead_thread,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
node->id, 0, trigger, r);
out:
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 368283d53077..ca71fa726e32 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -1175,10 +1175,12 @@ static void kfd_process_remove_sysfs(struct kfd_process *p)
if (!p->kobj)
return;
- sysfs_remove_file(p->kobj, &p->attr_pasid);
- kobject_del(p->kobj_queues);
- kobject_put(p->kobj_queues);
- p->kobj_queues = NULL;
+ if (p->kobj_queues) {
+ sysfs_remove_file(p->kobj, &p->attr_pasid);
+ kobject_del(p->kobj_queues);
+ kobject_put(p->kobj_queues);
+ p->kobj_queues = NULL;
+ }
for (i = 0; i < p->n_pdds; i++) {
pdd = p->pdds[i];
@@ -1186,17 +1188,21 @@ static void kfd_process_remove_sysfs(struct kfd_process *p)
sysfs_remove_file(p->kobj, &pdd->attr_vram);
sysfs_remove_file(p->kobj, &pdd->attr_sdma);
- sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict);
- if (pdd->dev->kfd2kgd->get_cu_occupancy)
- sysfs_remove_file(pdd->kobj_stats,
- &pdd->attr_cu_occupancy);
- kobject_del(pdd->kobj_stats);
- kobject_put(pdd->kobj_stats);
- pdd->kobj_stats = NULL;
+ if (pdd->kobj_stats) {
+ sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict);
+ if (pdd->dev->kfd2kgd->get_cu_occupancy)
+ sysfs_remove_file(pdd->kobj_stats,
+ &pdd->attr_cu_occupancy);
+ kobject_del(pdd->kobj_stats);
+ kobject_put(pdd->kobj_stats);
+ pdd->kobj_stats = NULL;
+ }
}
for_each_set_bit(i, p->svms.bitmap_supported, p->n_pdds) {
pdd = p->pdds[i];
+ if (!pdd->kobj_counters)
+ continue;
sysfs_remove_file(pdd->kobj_counters, &pdd->attr_faults);
sysfs_remove_file(pdd->kobj_counters, &pdd->attr_page_in);
@@ -1254,6 +1260,13 @@ static void kfd_process_wq_release(struct work_struct *work)
kfd_debugfs_remove_process(p);
+ /*
+ * Remove the proc/sysfs entries before destroying PDDs. The removal path
+ * walks the PDD array and sysfs callbacks dereference PDD fields, so the
+ * backing data must remain valid until sysfs removal has completed.
+ */
+ kfd_process_remove_sysfs(p);
+
kfd_process_kunmap_signal_bo(p);
kfd_process_free_outstanding_kfd_bos(p);
svm_range_list_fini(p);
@@ -1267,11 +1280,6 @@ static void kfd_process_wq_release(struct work_struct *work)
put_task_struct(p->lead_thread);
- /* the last step is removing process entries under /sys
- * to indicate the process has been terminated.
- */
- kfd_process_remove_sysfs(p);
-
kfree(p);
}
@@ -1969,7 +1977,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger)
struct kfd_process_device *pdd = p->pdds[i];
struct device *dev = pdd->dev->adev->dev;
- kfd_smi_event_queue_eviction(pdd->dev, p->lead_thread->pid,
+ kfd_smi_event_queue_eviction(pdd->dev, p->lead_thread,
trigger);
r = pdd->dev->dqm->ops.evict_process_queues(pdd->dev->dqm,
@@ -1999,7 +2007,7 @@ fail:
if (n_evicted == 0)
break;
- kfd_smi_event_queue_restore(pdd->dev, p->lead_thread->pid);
+ kfd_smi_event_queue_restore(pdd->dev, p->lead_thread);
if (pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm,
&pdd->qpd))
@@ -2022,7 +2030,7 @@ int kfd_process_restore_queues(struct kfd_process *p)
struct kfd_process_device *pdd = p->pdds[i];
struct device *dev = pdd->dev->adev->dev;
- kfd_smi_event_queue_restore(pdd->dev, p->lead_thread->pid);
+ kfd_smi_event_queue_restore(pdd->dev, p->lead_thread);
r = pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm,
&pdd->qpd);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index 44e39ce222b7..0ac35789b239 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -962,8 +962,8 @@ static void set_queue_properties_from_criu(struct queue_properties *qp,
qp->priority = q_data->priority;
qp->queue_address = q_data->q_address;
qp->queue_size = q_data->q_size;
- qp->read_ptr = (uint32_t *) q_data->read_ptr_addr;
- qp->write_ptr = (uint32_t *) q_data->write_ptr_addr;
+ qp->read_ptr = (void __user *)q_data->read_ptr_addr;
+ qp->write_ptr = (void __user *)q_data->write_ptr_addr;
qp->eop_ring_buffer_address = q_data->eop_ring_buffer_address;
qp->eop_ring_buffer_size = q_data->eop_ring_buffer_size;
qp->ctx_save_restore_area_address = q_data->ctx_save_restore_area_address;
@@ -1042,10 +1042,18 @@ int kfd_criu_restore_queue(struct kfd_process *p,
memset(&qp, 0, sizeof(qp));
set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->adev->gfx.xcc_mask));
+ ret = kfd_queue_acquire_buffers(pdd, &qp);
+ if (ret) {
+ pr_debug("failed to acquire user queue buffers for CRIU\n");
+ goto exit;
+ }
+
print_queue_properties(&qp);
ret = pqm_create_queue(&p->pqm, pdd->dev, &qp, &queue_id, q_data, mqd, ctl_stack, NULL);
if (ret) {
+ kfd_queue_unref_bo_vas(pdd, &qp);
+ kfd_queue_release_buffers(pdd, &qp);
pr_err("Failed to create new queue err:%d\n", ret);
goto exit;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
index dfbde5a571f6..e659cd50eb0b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
@@ -195,17 +195,35 @@ static void add_event_to_kfifo(pid_t pid, struct kfd_node *dev,
rcu_read_unlock();
}
+/**
+ * kfd_smi_task_to_pid - Convert task to namespace-aware PID
+ * @task: task_struct pointer (typically p->lead_thread)
+ *
+ * Returns the PID as it appears in the task's own PID namespace.
+ * For containerized processes, this returns the container-local PID
+ * (what getpid() returns), not the global host PID.
+ *
+ * Returns 0 if task is NULL.
+ */
+static inline pid_t kfd_smi_task_to_pid(struct task_struct *task)
+{
+ return task ? task_tgid_nr_ns(task, task_active_pid_ns(task)) : 0;
+}
+
__printf(4, 5)
-static void kfd_smi_event_add(pid_t pid, struct kfd_node *dev,
+static void kfd_smi_event_add(struct task_struct *task, struct kfd_node *dev,
unsigned int event, char *fmt, ...)
{
char fifo_in[KFD_SMI_EVENT_MSG_SIZE];
int len;
va_list args;
+ pid_t pid;
if (list_empty(&dev->smi_clients))
return;
+ pid = kfd_smi_task_to_pid(task);
+
len = snprintf(fifo_in, sizeof(fifo_in), "%x ", event);
va_start(args, fmt);
@@ -234,14 +252,15 @@ void kfd_smi_event_update_gpu_reset(struct kfd_node *dev, bool post_reset,
amdgpu_reset_get_desc(reset_context, reset_cause,
sizeof(reset_cause));
- kfd_smi_event_add(0, dev, event, KFD_EVENT_FMT_UPDATE_GPU_RESET(
+ kfd_smi_event_add(NULL, dev, event, KFD_EVENT_FMT_UPDATE_GPU_RESET(
dev->reset_seq_num, reset_cause));
}
void kfd_smi_event_update_thermal_throttling(struct kfd_node *dev,
uint64_t throttle_bitmask)
{
- kfd_smi_event_add(0, dev, KFD_SMI_EVENT_THERMAL_THROTTLE, KFD_EVENT_FMT_THERMAL_THROTTLING(
+ kfd_smi_event_add(NULL, dev, KFD_SMI_EVENT_THERMAL_THROTTLE,
+ KFD_EVENT_FMT_THERMAL_THROTTLING(
throttle_bitmask,
amdgpu_dpm_get_thermal_throttling_counter(dev->adev)));
}
@@ -254,67 +273,67 @@ void kfd_smi_event_update_vmfault(struct kfd_node *dev, uint16_t pasid)
if (task_info) {
/* Report VM faults from user applications, not retry from kernel */
if (task_info->task.pid)
- kfd_smi_event_add(task_info->tgid, dev,
- KFD_SMI_EVENT_VMFAULT,
- KFD_EVENT_FMT_VMFAULT(task_info->task.pid,
- task_info->task.comm));
+ kfd_smi_event_add(NULL, dev, KFD_SMI_EVENT_VMFAULT, KFD_EVENT_FMT_VMFAULT(
+ task_info->task.pid, task_info->task.comm));
amdgpu_vm_put_task_info(task_info);
}
}
-void kfd_smi_event_page_fault_start(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_page_fault_start(struct kfd_node *node, struct task_struct *task,
unsigned long address, bool write_fault,
ktime_t ts)
{
- kfd_smi_event_add(pid, node, KFD_SMI_EVENT_PAGE_FAULT_START,
- KFD_EVENT_FMT_PAGEFAULT_START(ktime_to_ns(ts), pid,
- address, node->id, write_fault ? 'W' : 'R'));
+ kfd_smi_event_add(task, node, KFD_SMI_EVENT_PAGE_FAULT_START,
+ KFD_EVENT_FMT_PAGEFAULT_START(ktime_to_ns(ts),
+ kfd_smi_task_to_pid(task), address, node->id,
+ write_fault ? 'W' : 'R'));
}
-void kfd_smi_event_page_fault_end(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_page_fault_end(struct kfd_node *node, struct task_struct *task,
unsigned long address, bool migration)
{
- kfd_smi_event_add(pid, node, KFD_SMI_EVENT_PAGE_FAULT_END,
+ kfd_smi_event_add(task, node, KFD_SMI_EVENT_PAGE_FAULT_END,
KFD_EVENT_FMT_PAGEFAULT_END(ktime_get_boottime_ns(),
- pid, address, node->id, migration ? 'M' : 'U'));
+ kfd_smi_task_to_pid(task), address, node->id,
+ migration ? 'M' : 'U'));
}
-void kfd_smi_event_migration_start(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_migration_start(struct kfd_node *node, struct task_struct *task,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to,
uint32_t prefetch_loc, uint32_t preferred_loc,
uint32_t trigger)
{
- kfd_smi_event_add(pid, node, KFD_SMI_EVENT_MIGRATE_START,
- KFD_EVENT_FMT_MIGRATE_START(
- ktime_get_boottime_ns(), pid, start, end - start,
- from, to, prefetch_loc, preferred_loc, trigger));
+ kfd_smi_event_add(task, node, KFD_SMI_EVENT_MIGRATE_START,
+ KFD_EVENT_FMT_MIGRATE_START(ktime_get_boottime_ns(),
+ kfd_smi_task_to_pid(task), start, end - start, from,
+ to, prefetch_loc, preferred_loc, trigger));
}
-void kfd_smi_event_migration_end(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_migration_end(struct kfd_node *node, struct task_struct *task,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to, uint32_t trigger,
int error_code)
{
- kfd_smi_event_add(pid, node, KFD_SMI_EVENT_MIGRATE_END,
- KFD_EVENT_FMT_MIGRATE_END(
- ktime_get_boottime_ns(), pid, start, end - start,
- from, to, trigger, error_code));
+ kfd_smi_event_add(task, node, KFD_SMI_EVENT_MIGRATE_END,
+ KFD_EVENT_FMT_MIGRATE_END(ktime_get_boottime_ns(),
+ kfd_smi_task_to_pid(task), start, end - start, from,
+ to, trigger, error_code));
}
-void kfd_smi_event_queue_eviction(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_queue_eviction(struct kfd_node *node, struct task_struct *task,
uint32_t trigger)
{
- kfd_smi_event_add(pid, node, KFD_SMI_EVENT_QUEUE_EVICTION,
- KFD_EVENT_FMT_QUEUE_EVICTION(ktime_get_boottime_ns(), pid,
- node->id, trigger));
+ kfd_smi_event_add(task, node, KFD_SMI_EVENT_QUEUE_EVICTION,
+ KFD_EVENT_FMT_QUEUE_EVICTION(ktime_get_boottime_ns(),
+ kfd_smi_task_to_pid(task), node->id, trigger));
}
-void kfd_smi_event_queue_restore(struct kfd_node *node, pid_t pid)
+void kfd_smi_event_queue_restore(struct kfd_node *node, struct task_struct *task)
{
- kfd_smi_event_add(pid, node, KFD_SMI_EVENT_QUEUE_RESTORE,
- KFD_EVENT_FMT_QUEUE_RESTORE(ktime_get_boottime_ns(), pid,
- node->id, '0'));
+ kfd_smi_event_add(task, node, KFD_SMI_EVENT_QUEUE_RESTORE,
+ KFD_EVENT_FMT_QUEUE_RESTORE(ktime_get_boottime_ns(),
+ kfd_smi_task_to_pid(task), node->id, '0'));
}
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
@@ -329,21 +348,23 @@ void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
for (i = 0; i < p->n_pdds; i++) {
struct kfd_process_device *pdd = p->pdds[i];
- kfd_smi_event_add(p->lead_thread->pid, pdd->dev,
+ kfd_smi_event_add(p->lead_thread, pdd->dev,
KFD_SMI_EVENT_QUEUE_RESTORE,
KFD_EVENT_FMT_QUEUE_RESTORE(ktime_get_boottime_ns(),
- p->lead_thread->pid, pdd->dev->id, 'R'));
+ kfd_smi_task_to_pid(p->lead_thread),
+ pdd->dev->id, 'R'));
}
kfd_unref_process(p);
}
-void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, struct task_struct *task,
unsigned long address, unsigned long last,
uint32_t trigger)
{
- kfd_smi_event_add(pid, node, KFD_SMI_EVENT_UNMAP_FROM_GPU,
+ kfd_smi_event_add(task, node, KFD_SMI_EVENT_UNMAP_FROM_GPU,
KFD_EVENT_FMT_UNMAP_FROM_GPU(ktime_get_boottime_ns(),
- pid, address, last - address + 1, node->id, trigger));
+ kfd_smi_task_to_pid(task), address,
+ last - address + 1, node->id, trigger));
}
void kfd_smi_event_process(struct kfd_process_device *pdd, bool start)
@@ -358,7 +379,7 @@ void kfd_smi_event_process(struct kfd_process_device *pdd, bool start)
task_info = amdgpu_vm_get_task_info_vm(avm);
if (task_info) {
- kfd_smi_event_add(task_info->tgid, pdd->dev,
+ kfd_smi_event_add(NULL, pdd->dev,
start ? KFD_SMI_EVENT_PROCESS_START :
KFD_SMI_EVENT_PROCESS_END,
KFD_EVENT_FMT_PROCESS(task_info->task.pid,
@@ -387,7 +408,7 @@ int kfd_smi_event_open(struct kfd_node *dev, uint32_t *fd)
spin_lock_init(&client->lock);
client->events = 0;
client->dev = dev;
- client->pid = current->tgid;
+ client->pid = kfd_smi_task_to_pid(current);
client->suser = capable(CAP_SYS_ADMIN);
spin_lock(&dev->smi_lock);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
index bb4d72b57387..afa93d7cfa7f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
@@ -32,25 +32,25 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_node *dev,
uint64_t throttle_bitmask);
void kfd_smi_event_update_gpu_reset(struct kfd_node *dev, bool post_reset,
struct amdgpu_reset_context *reset_context);
-void kfd_smi_event_page_fault_start(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_page_fault_start(struct kfd_node *node, struct task_struct *task,
unsigned long address, bool write_fault,
ktime_t ts);
-void kfd_smi_event_page_fault_end(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_page_fault_end(struct kfd_node *node, struct task_struct *task,
unsigned long address, bool migration);
-void kfd_smi_event_migration_start(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_migration_start(struct kfd_node *node, struct task_struct *task,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to,
uint32_t prefetch_loc, uint32_t preferred_loc,
uint32_t trigger);
-void kfd_smi_event_migration_end(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_migration_end(struct kfd_node *node, struct task_struct *task,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to, uint32_t trigger,
int error_code);
-void kfd_smi_event_queue_eviction(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_queue_eviction(struct kfd_node *node, struct task_struct *task,
uint32_t trigger);
-void kfd_smi_event_queue_restore(struct kfd_node *node, pid_t pid);
+void kfd_smi_event_queue_restore(struct kfd_node *node, struct task_struct *task);
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm);
-void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, pid_t pid,
+void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, struct task_struct *task,
unsigned long address, unsigned long last,
uint32_t trigger);
void kfd_smi_event_process(struct kfd_process_device *pdd, bool start);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 3841943da5ec..0900bb23349e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1144,7 +1144,7 @@ static int
svm_range_split_tail(struct svm_range *prange, uint64_t new_last,
struct list_head *insert_list, struct list_head *remap_list)
{
- unsigned long last_align_down = ALIGN_DOWN(prange->last, 512);
+ unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512);
unsigned long start_align = ALIGN(prange->start, 512);
bool huge_page_mapping = last_align_down > start_align;
struct svm_range *tail = NULL;
@@ -1168,7 +1168,7 @@ static int
svm_range_split_head(struct svm_range *prange, uint64_t new_start,
struct list_head *insert_list, struct list_head *remap_list)
{
- unsigned long last_align_down = ALIGN_DOWN(prange->last, 512);
+ unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512);
unsigned long start_align = ALIGN(prange->start, 512);
bool huge_page_mapping = last_align_down > start_align;
struct svm_range *head = NULL;
@@ -1181,8 +1181,8 @@ svm_range_split_head(struct svm_range *prange, uint64_t new_start,
list_add(&head->list, insert_list);
- if (huge_page_mapping && head->last + 1 > start_align &&
- head->last + 1 < last_align_down && (!IS_ALIGNED(head->last, 512)))
+ if (huge_page_mapping && new_start > start_align &&
+ new_start < last_align_down && !IS_ALIGNED(new_start, 512))
list_add(&head->update_list, remap_list);
return 0;
@@ -1408,7 +1408,7 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
return -EINVAL;
}
- kfd_smi_event_unmap_from_gpu(pdd->dev, p->lead_thread->pid,
+ kfd_smi_event_unmap_from_gpu(pdd->dev, p->lead_thread,
start, last, trigger);
r = svm_range_unmap_from_gpu(pdd->dev->adev,
@@ -3205,7 +3205,7 @@ retry_write_locked:
svms, prange->start, prange->last, best_loc,
prange->actual_loc);
- kfd_smi_event_page_fault_start(node, p->lead_thread->pid, addr,
+ kfd_smi_event_page_fault_start(node, p->lead_thread, addr,
write_fault, timestamp);
/* Align migration range start and size to granularity size */
@@ -3248,7 +3248,7 @@ retry_write_locked:
r, svms, start, last);
out_migrate_fail:
- kfd_smi_event_page_fault_end(node, p->lead_thread->pid, addr,
+ kfd_smi_event_page_fault_end(node, p->lead_thread, addr,
migration);
out_unlock_range:
@@ -4115,6 +4115,7 @@ exit:
list_for_each_entry_safe(criu_svm_md, next, &svms->criu_svm_metadata_list, list) {
pr_debug("freeing criu_svm_md[]\n\tstart: 0x%llx\n",
criu_svm_md->data.start_addr);
+ list_del(&criu_svm_md->list);
kfree(criu_svm_md);
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 97ab1e83b318..d3a8d681227a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -12942,13 +12942,11 @@ static bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
struct drm_plane_state *new_plane_state, *old_plane_state;
drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
- new_plane_state = drm_atomic_get_plane_state(state, plane);
- old_plane_state = drm_atomic_get_plane_state(state, plane);
+ new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+ old_plane_state = drm_atomic_get_old_plane_state(state, plane);
- if (IS_ERR(new_plane_state) || IS_ERR(old_plane_state)) {
- drm_err(dev, "Failed to get plane state for plane %s\n", plane->name);
- return false;
- }
+ if (!old_plane_state || !new_plane_state)
+ continue;
if (old_plane_state->fb && new_plane_state->fb &&
get_mem_type(old_plane_state->fb) != get_mem_type(new_plane_state->fb))
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index f257ea91a34d..c6f94eb71ffa 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -95,8 +95,11 @@ static u32 edid_extract_panel_id(struct edid *edid)
(u32)EDID_PRODUCT_ID(edid);
}
-static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct dc_edid_caps *edid_caps)
+static void apply_edid_quirks(struct dc_link *link, struct edid *edid,
+ struct dc_edid_caps *edid_caps)
{
+ struct amdgpu_dm_connector *aconnector = link->priv;
+ struct drm_device *dev = aconnector->base.dev;
uint32_t panel_id = edid_extract_panel_id(edid);
switch (panel_id) {
@@ -126,6 +129,11 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct
drm_dbg_driver(dev, "Disabling VSC on monitor with panel id %X\n", panel_id);
edid_caps->panel_patch.disable_colorimetry = true;
break;
+ /* Workaround for monitors that get corrupted by the PHY SSC reduction */
+ case drm_edid_encode_panel_id('D', 'E', 'L', 0x4147):
+ drm_dbg_driver(dev, "Skip PHY SSC reduction on panel id %X\n", panel_id);
+ link->wa_flags.skip_phy_ssc_reduction = true;
+ break;
default:
return;
}
@@ -147,7 +155,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
{
struct amdgpu_dm_connector *aconnector = link->priv;
struct drm_connector *connector = &aconnector->base;
- struct drm_device *dev = connector->dev;
struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL;
struct cea_sad *sads;
int sad_count = -1;
@@ -188,7 +195,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
edid_caps->frl_dsc_max_frl_rate, edid_caps->frl_dsc_total_chunk_kbytes);
}
- apply_edid_quirks(dev, edid_buf, edid_caps);
+ apply_edid_quirks(link, edid_buf, edid_caps);
sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
if (sad_count <= 0)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index e957657b06c7..c7f8e08feaf4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1859,6 +1859,7 @@ static const struct drm_plane_funcs dm_plane_funcs = {
.atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state,
.atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state,
.format_mod_supported = amdgpu_dm_plane_format_mod_supported,
+ .format_mod_supported_async = amdgpu_dm_plane_format_mod_supported,
#ifdef AMD_PRIVATE_COLOR
.atomic_set_property = dm_atomic_plane_set_property,
.atomic_get_property = dm_atomic_plane_get_property,
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
index 00c4be7c3aa4..ff47af3854b6 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
@@ -158,7 +158,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn31_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
@@ -184,7 +183,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn31_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
index dd6f11ecb9c9..24f6304011ae 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
@@ -230,7 +230,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn314_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
@@ -255,7 +254,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn314_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index 103013e2a0de..a69824e1eb26 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -419,6 +419,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn35_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
+ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
@@ -438,6 +439,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn35_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
+ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
index fb1145691410..a214ddbd4c86 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
@@ -227,9 +227,14 @@ static int smu_v15_0_0_system_features_control(struct smu_context *smu, bool en)
struct amdgpu_device *adev = smu->adev;
int ret = 0;
- if (!en && !adev->in_s0ix)
+ if (!en && !adev->in_s0ix) {
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
+ /* SMU resets BIF_FB_EN to zero, re-enable MC access on APUs with SMU V15 */
+ if (!ret && adev->nbio.funcs && adev->nbio.funcs->mc_access_enable)
+ adev->nbio.funcs->mc_access_enable(adev, true);
+ }
+
return ret;
}
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 3fa4d2082cd7..11646453aaac 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -3571,7 +3571,7 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
/**
* drm_mode_get_tile_group - get a reference to an existing tile group
* @dev: DRM device
- * @topology: 8-bytes unique per monitor.
+ * @topology_id: 9-byte unique ID per monitor.
*
* Use the unique bytes to get a reference to an existing tile group.
*
@@ -3579,14 +3579,14 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
* tile group or NULL if not found.
*/
struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
- const char topology[8])
+ const char topology_id[9])
{
struct drm_tile_group *tg;
int id;
mutex_lock(&dev->mode_config.idr_mutex);
idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
- if (!memcmp(tg->group_data, topology, 8)) {
+ if (!memcmp(tg->group_data, topology_id, sizeof(tg->group_data))) {
if (!kref_get_unless_zero(&tg->refcount))
tg = NULL;
mutex_unlock(&dev->mode_config.idr_mutex);
@@ -3601,7 +3601,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
/**
* drm_mode_create_tile_group - create a tile group from a displayid description
* @dev: DRM device
- * @topology: 8-bytes unique per monitor.
+ * @topology_id: 9-byte unique ID per monitor.
*
* Create a tile group for the unique monitor, and get a unique
* identifier for the tile group.
@@ -3610,7 +3610,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
* new tile group or NULL.
*/
struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
- const char topology[8])
+ const char topology_id[9])
{
struct drm_tile_group *tg;
int ret;
@@ -3620,7 +3620,7 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
return NULL;
kref_init(&tg->refcount);
- memcpy(tg->group_data, topology, 8);
+ memcpy(tg->group_data, topology_id, sizeof(tg->group_data));
tg->dev = dev;
mutex_lock(&dev->mode_config.idr_mutex);
diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h
index 5b1b32f73516..4590d6a3d821 100644
--- a/drivers/gpu/drm/drm_displayid_internal.h
+++ b/drivers/gpu/drm/drm_displayid_internal.h
@@ -109,7 +109,7 @@ struct displayid_tiled_block {
u8 topo[3];
u8 tile_size[4];
u8 tile_pixel_bezel[5];
- u8 topology_id[8];
+ u8 topology_id[9];
} __packed;
struct displayid_detailed_timings_1 {
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 404208bf23a6..df3c25bac761 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -7575,6 +7575,14 @@ static void drm_parse_tiled_block(struct drm_connector *connector,
u8 num_v_tile, num_h_tile;
struct drm_tile_group *tg;
+ /* tiled block payload per spec: cap 1 + topo 3 + size 4 + bezel 5 + id 9 = 22 */
+ if (block->num_bytes < 22) {
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Unexpected tiled block size %u\n",
+ connector->base.id, connector->name, block->num_bytes);
+ return;
+ }
+
w = tile->tile_size[0] | tile->tile_size[1] << 8;
h = tile->tile_size[2] | tile->tile_size[3] << 8;
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index 0e4f0678c53c..9d0d47c79dd1 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -288,6 +288,12 @@ static void intel_crtc_put_color_blobs(struct intel_crtc_state *crtc_state)
drm_property_blob_put(crtc_state->pre_csc_lut);
drm_property_blob_put(crtc_state->post_csc_lut);
+
+ crtc_state->hw.degamma_lut = NULL;
+ crtc_state->hw.gamma_lut = NULL;
+ crtc_state->hw.ctm = NULL;
+ crtc_state->pre_csc_lut = NULL;
+ crtc_state->post_csc_lut = NULL;
}
void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 189ae2d3cfc9..7bc9b956554b 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1256,9 +1256,22 @@ static void skl_sanitize_cdclk(struct intel_display *display)
cdctl = intel_de_read(display, CDCLK_CTL);
expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
skl_cdclk_decimal(display->cdclk.hw.cdclk);
- if (cdctl == expected)
- /* All well; nothing to sanitize */
- return;
+
+ if (cdctl != expected) {
+ cdctl &= ~CDCLK_FREQ_DECIMAL_MASK;
+ cdctl |= expected & CDCLK_FREQ_DECIMAL_MASK;
+
+ if (cdctl != expected)
+ goto sanitize;
+
+ drm_dbg_kms(display->drm, "Sanitizing CDCLK decimal divider (CDCLK_CTL 0x%x, expected 0x%x)\n",
+ intel_de_read(display, CDCLK_CTL), expected);
+
+ intel_de_write(display, CDCLK_CTL, expected);
+ }
+
+ /* All well; nothing to sanitize */
+ return;
sanitize:
drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
@@ -2354,11 +2367,25 @@ static void bxt_sanitize_cdclk(struct intel_display *display)
* (PIPE_NONE).
*/
cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
- expected &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
+ cdctl |= bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
- if (cdctl == expected)
- /* All well; nothing to sanitize */
- return;
+ if (cdctl != expected) {
+ if (DISPLAY_VER(display) < 20) {
+ cdctl &= ~CDCLK_FREQ_DECIMAL_MASK;
+ cdctl |= expected & CDCLK_FREQ_DECIMAL_MASK;
+ }
+
+ if (cdctl != expected)
+ goto sanitize;
+
+ drm_dbg_kms(display->drm, "Sanitizing CDCLK decimal divider (CDCLK_CTL 0x%x, expected 0x%x)\n",
+ intel_de_read(display, CDCLK_CTL), expected);
+
+ intel_de_write(display, CDCLK_CTL, expected);
+ }
+
+ /* All well; nothing to sanitize */
+ return;
sanitize:
drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 205978c9feb6..6296635c4e79 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2652,9 +2652,6 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
/* 3. Select Thunderbolt */
mtl_port_buf_ctl_io_selection(encoder);
- /* 4. Enable Panel Power if PPS is required */
- intel_pps_on(intel_dp);
-
/* 5. Enable the port PLL */
intel_ddi_enable_clock(encoder, crtc_state);
@@ -3708,6 +3705,14 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
else if (display->platform.geminilake || display->platform.broxton)
bxt_dpio_phy_set_lane_optim_mask(encoder,
crtc_state->lane_lat_optim_mask);
+
+ /*
+ * There is no direct connection between the PLL and PPS, however
+ * enabling PPS before PLL is required to avoid PLL/DDI BUF timeouts
+ * during system resume. Do that matching the Bspec order as well.
+ */
+ if (DISPLAY_VER(display) >= 14)
+ intel_pps_on(&dig_port->dp);
}
static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index bcdc50491347..0aa3e6b4c781 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -726,6 +726,10 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
if (ret)
return ret;
+ ret = intel_pfit_compute_config(pipe_config, conn_state);
+ if (ret)
+ return ret;
+
for_each_joiner_candidate(connector, adjusted_mode, num_joined_pipes) {
if (num_joined_pipes > 1)
pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 6ac0f23570f3..aeafe1742d30 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -613,6 +613,7 @@ set_proto_ctx_engines_parallel_submit(struct i915_user_extension __user *base,
return -EINVAL;
}
+ slot = array_index_nospec(slot, set->num_engines);
if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) {
drm_dbg(&i915->drm,
"Invalid placement[%d], already occupied\n", slot);
diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
index c01a01aee32b..a08ab1cfea9b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_exec.c
+++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
@@ -331,10 +331,10 @@ nouveau_exec_ucopy(struct nouveau_exec_job_args *args,
return 0;
-err_free_pushs:
- u_free(args->push.s);
err_free_ins:
u_free(args->in_sync.s);
+err_free_pushs:
+ u_free(args->push.s);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
index 36445915aa58..f5e4756b4de4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
@@ -1779,10 +1779,10 @@ nouveau_uvmm_vm_bind_ucopy(struct nouveau_uvmm_bind_job_args *args,
return 0;
-err_free_ops:
- u_free(args->op.s);
err_free_ins:
u_free(args->in_sync.s);
+err_free_ops:
+ u_free(args->op.s);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
index 4c7745cd6ae5..7fd967a2554f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -315,6 +315,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
i, us, fw);
}
}
+ nvkm_done(acr->wpr);
return -EINVAL;
}
nvkm_done(acr->wpr);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 3ac1a79b6f13..533215d6e9cb 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -906,6 +906,7 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
{
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
struct radeon_fence *fence;
+ uint64_t cur_src_offset, cur_dst_offset;
uint32_t cur_pages;
uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE;
uint32_t pitch;
@@ -934,6 +935,10 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
cur_pages = 8191;
}
num_gpu_pages -= cur_pages;
+ cur_src_offset = src_offset +
+ (uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
+ cur_dst_offset = dst_offset +
+ (uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
/* pages are in Y direction - height
page width in X direction - width */
@@ -950,13 +955,13 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
RADEON_DP_SRC_SOURCE_MEMORY |
RADEON_GMC_CLR_CMP_CNTL_DIS |
RADEON_GMC_WR_MSK_DIS);
- radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10));
- radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10));
+ radeon_ring_write(ring, (pitch << 22) | (cur_src_offset >> 10));
+ radeon_ring_write(ring, (pitch << 22) | (cur_dst_offset >> 10));
radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
radeon_ring_write(ring, 0);
radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
- radeon_ring_write(ring, num_gpu_pages);
- radeon_ring_write(ring, num_gpu_pages);
+ radeon_ring_write(ring, 0);
+ radeon_ring_write(ring, 0);
radeon_ring_write(ring, cur_pages | (stride_pixels << 16));
}
radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));
diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
index 2a2b553366fb..547f2327af5e 100644
--- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
+++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
@@ -50,7 +50,7 @@ struct resource *drm_sysfb_get_memory_si(struct drm_device *dev,
int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si,
const struct drm_format_info *format,
unsigned int width, unsigned int height, u64 size);
-u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
+s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
unsigned int height, unsigned int stride, u64 size);
#endif
diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
index 749290196c6a..1c479ce0e503 100644
--- a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
+++ b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
@@ -2,6 +2,7 @@
#include <linux/export.h>
#include <linux/limits.h>
+#include <linux/math64.h>
#include <linux/minmax.h>
#include <linux/screen_info.h>
@@ -56,18 +57,24 @@ int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si
unsigned int width, unsigned int height, u64 size)
{
u64 lfb_linelength = si->lfb_linelength;
+ s64 stride;
if (!lfb_linelength)
lfb_linelength = drm_format_info_min_pitch(format, 0, width);
- return drm_sysfb_get_validated_int0(dev, "stride", lfb_linelength, div64_u64(size, height));
+ stride = drm_sysfb_get_validated_size0(dev, "stride", lfb_linelength,
+ div64_u64(size, height));
+ if (stride < INT_MIN || stride > INT_MAX)
+ return -EINVAL;
+
+ return (int)stride; /* stride or negative errno code */
}
EXPORT_SYMBOL(drm_sysfb_get_stride_si);
-u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
+s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
unsigned int height, unsigned int stride, u64 size)
{
- u64 vsize = PAGE_ALIGN(height * stride);
+ u64 vsize = mul_u32_u32(height, stride);
return drm_sysfb_get_validated_size0(dev, "visible size", vsize, size);
}
diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c
index 1a1e36700976..3f9cd5d03efb 100644
--- a/drivers/gpu/drm/sysfb/efidrm.c
+++ b/drivers/gpu/drm/sysfb/efidrm.c
@@ -152,7 +152,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
const struct screen_info *si;
const struct drm_format_info *format;
int width, height, stride;
- u64 vsize, mem_flags;
+ s64 vsize;
+ u64 mem_flags;
struct resource resbuf;
struct resource *res;
struct efidrm_device *efi;
@@ -206,8 +207,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
if (stride < 0)
return ERR_PTR(stride);
vsize = drm_sysfb_get_visible_size_si(dev, si, height, stride, resource_size(res));
- if (!vsize)
- return ERR_PTR(-EINVAL);
+ if (vsize < 0)
+ return ERR_PTR(vsize);
drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n",
&format->format, width, height, stride);
diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c
index dbc317778d54..6a67b2d2e451 100644
--- a/drivers/gpu/drm/sysfb/vesadrm.c
+++ b/drivers/gpu/drm/sysfb/vesadrm.c
@@ -402,7 +402,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
const struct screen_info *si;
const struct drm_format_info *format;
int width, height, stride;
- u64 vsize;
+ s64 vsize;
struct resource resbuf;
struct resource *res;
struct vesadrm_device *vesa;
@@ -457,8 +457,8 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
if (stride < 0)
return ERR_PTR(stride);
vsize = drm_sysfb_get_visible_size_si(dev, si, height, stride, resource_size(res));
- if (!vsize)
- return ERR_PTR(-EINVAL);
+ if (vsize < 0)
+ return ERR_PTR(vsize);
drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n",
&format->format, width, height, stride);
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 09661f079d03..8e7b146880f4 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -16,14 +16,14 @@ subdir-ccflags-y += -I$(obj) -I$(src)
hostprogs := xe_gen_wa_oob
generated_oob := $(obj)/generated/xe_wa_oob.c $(obj)/generated/xe_wa_oob.h
quiet_cmd_wa_oob = GEN $(notdir $(generated_oob))
- cmd_wa_oob = mkdir -p $(@D); $^ $(generated_oob)
+ cmd_wa_oob = mkdir -p $(@D); $(obj)/xe_gen_wa_oob $(src)/xe_wa_oob.rules $(generated_oob)
$(obj)/generated/%_wa_oob.c $(obj)/generated/%_wa_oob.h: $(obj)/xe_gen_wa_oob \
$(src)/xe_wa_oob.rules
$(call cmd,wa_oob)
generated_device_oob := $(obj)/generated/xe_device_wa_oob.c $(obj)/generated/xe_device_wa_oob.h
quiet_cmd_device_wa_oob = GEN $(notdir $(generated_device_oob))
- cmd_device_wa_oob = mkdir -p $(@D); $^ $(generated_device_oob)
+ cmd_device_wa_oob = mkdir -p $(@D); $(obj)/xe_gen_wa_oob $(src)/xe_device_wa_oob.rules $(generated_device_oob)
$(obj)/generated/%_device_wa_oob.c $(obj)/generated/%_device_wa_oob.h: $(obj)/xe_gen_wa_oob \
$(src)/xe_device_wa_oob.rules
$(call cmd,device_wa_oob)
diff --git a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
index 4d83461e538b..d6bc19ef277b 100644
--- a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
@@ -9,7 +9,11 @@
#define XELPG_GGTT_PTE_PAT0 BIT_ULL(52)
#define XELPG_GGTT_PTE_PAT1 BIT_ULL(53)
-#define XE_PTE_ADDR_MASK GENMASK_ULL(51, 12)
+/*
+ * Mask for PTE address bits [51:shift].
+ * shift is the lower address boundary of page.
+ */
+#define XE_PAGE_ADDR_MASK(shift) GENMASK_ULL(51, (shift))
#define GGTT_PTE_VFID GENMASK_ULL(11, 2)
#define GUC_GGTT_TOP 0xFEE00000
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index d224861b6f6f..abe25aedeead 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -526,7 +526,8 @@ int xe_device_init_early(struct xe_device *xe)
err = ttm_device_init(&xe->ttm, &xe_ttm_funcs, xe->drm.dev,
xe->drm.anon_inode->i_mapping,
- xe->drm.vma_offset_manager, 0);
+ xe->drm.vma_offset_manager,
+ TTM_ALLOCATION_POOL_BENEFICIAL_ORDER(get_order(SZ_2M)));
if (err)
return err;
diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c
index 21f7caf9ea08..1a019137ddf4 100644
--- a/drivers/gpu/drm/xe/xe_guc_capture.c
+++ b/drivers/gpu/drm/xe/xe_guc_capture.c
@@ -461,8 +461,14 @@ static void guc_capture_alloc_steered_lists(struct xe_guc *guc)
if (!list || guc->capture->extlists)
return;
- total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) *
- guc_capture_get_steer_reg_num(guc_to_xe(guc));
+ {
+ xe_dss_mask_t all_dss;
+
+ total = bitmap_weighted_or(all_dss, gt->fuse_topo.g_dss_mask,
+ gt->fuse_topo.c_dss_mask,
+ XE_MAX_DSS_FUSE_BITS) *
+ guc_capture_get_steer_reg_num(guc_to_xe(guc));
+ }
if (!total)
return;
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 2669ff5ee747..18a98667c0e6 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -1602,23 +1602,21 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level,
return false;
}
-/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */
-#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size) \
-({ \
- BUILD_BUG_ON(!__builtin_constant_p(page_size)); \
- ilog2(page_size) - XE_PTE_SHIFT; \
-})
-
static int generate_reclaim_entry(struct xe_tile *tile,
struct xe_page_reclaim_list *prl,
u64 pte, struct xe_pt *xe_child)
{
struct xe_gt *gt = tile->primary_gt;
struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries;
- u64 phys_addr = pte & XE_PTE_ADDR_MASK;
+ bool is_2m = xe_child->level == 1 && (pte & XE_PDE_PS_2M);
+ bool is_64k = xe_child->level == 0 && ((pte & XE_PTE_PS64) || xe_child->is_compact);
+ u32 page_shift = is_2m ? ilog2(SZ_2M) : is_64k ? ilog2(SZ_64K) : ilog2(SZ_4K);
+ /* Physical address bits start at page shift: 2M->[51:21], 64K->[51:16], 4K->[51:12] */
+ u64 phys_addr = pte & XE_PAGE_ADDR_MASK(page_shift);
+ /* Page address is relative to 4K page regardless of entry level */
u64 phys_page = phys_addr >> XE_PTE_SHIFT;
int num_entries = prl->num_entries;
- u32 reclamation_size;
+ u32 reclamation_size = page_shift - XE_PTE_SHIFT;
xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL);
xe_tile_assert(tile, reclaim_entries);
@@ -1633,18 +1631,12 @@ static int generate_reclaim_entry(struct xe_tile *tile,
* Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes.
* Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim
*/
- if (xe_child->level == 0 && !(pte & XE_PTE_PS64)) {
- xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1);
- reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K); /* reclamation_size = 0 */
- xe_tile_assert(tile, phys_addr % SZ_4K == 0);
- } else if (xe_child->level == 0) {
- xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1);
- reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */
- xe_tile_assert(tile, phys_addr % SZ_64K == 0);
- } else if (xe_child->level == 1 && pte & XE_PDE_PS_2M) {
+ if (is_2m) {
xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT, 1);
- reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M); /* reclamation_size = 9 */
- xe_tile_assert(tile, phys_addr % SZ_2M == 0);
+ } else if (is_64k) {
+ xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1);
+ } else if (xe_child->level == 0) {
+ xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1);
} else {
xe_page_reclaim_list_abort(tile->primary_gt, prl,
"unsupported PTE level=%u pte=%#llx",
@@ -1665,6 +1657,48 @@ static int generate_reclaim_entry(struct xe_tile *tile,
return 0;
}
+static int add_pte_to_prl(struct xe_tile *tile, struct xe_page_reclaim_list *prl,
+ struct xe_pt *xe_child, u64 pte, u64 addr)
+{
+ /*
+ * In rare scenarios, pte may not be written yet due to racy conditions.
+ * In such cases, invalidate the PRL and fallback to full PPC invalidation.
+ */
+ if (!pte) {
+ xe_page_reclaim_list_abort(tile->primary_gt, prl,
+ "found zero pte at addr=%#llx", addr);
+ return -EINVAL;
+ }
+
+ /* Ensure it is a defined page */
+ xe_tile_assert(tile, xe_child->level == 0 ||
+ (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G)));
+
+ /* Account for NULL terminated entry on end (-1) */
+ if (prl->num_entries >= XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
+ xe_page_reclaim_list_abort(tile->primary_gt, prl,
+ "overflow while adding pte=%#llx", pte);
+ return -ENOSPC;
+ }
+
+ return generate_reclaim_entry(tile, prl, pte, xe_child);
+}
+
+static bool add_compact_pt_prl(struct xe_tile *tile, struct xe_page_reclaim_list *prl,
+ struct xe_device *xe, struct xe_pt *compact_pt, u64 addr)
+{
+ struct iosys_map *map = &compact_pt->bo->vmap;
+
+ for (pgoff_t i = 0; i < SZ_2M / SZ_64K && xe_page_reclaim_list_valid(prl); i++) {
+ u64 pte = xe_map_rd(xe, map, i * sizeof(u64), u64);
+
+ if (add_pte_to_prl(tile, prl, compact_pt, pte, addr + i * SZ_64K))
+ break;
+ }
+
+ return xe_page_reclaim_list_valid(prl);
+}
+
static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
unsigned int level, u64 addr, u64 next,
struct xe_ptw **child,
@@ -1674,21 +1708,22 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base);
struct xe_pt_stage_unbind_walk *xe_walk =
container_of(walk, typeof(*xe_walk), base);
- struct xe_device *xe = tile_to_xe(xe_walk->tile);
+ struct xe_page_reclaim_list *prl = xe_walk->prl;
+ struct xe_tile *tile = xe_walk->tile;
+ struct xe_device *xe = tile_to_xe(tile);
pgoff_t first = xe_pt_offset(addr, xe_child->level, walk);
bool killed;
XE_WARN_ON(!*child);
XE_WARN_ON(!level);
/* Check for leaf node */
- if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) &&
+ if (prl && xe_page_reclaim_list_valid(prl) &&
xe_child->level <= MAX_HUGEPTE_LEVEL) {
struct iosys_map *leaf_map = &xe_child->bo->vmap;
pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk);
for (pgoff_t i = 0; i < count; i++) {
u64 pte;
- int ret;
/*
* If not a leaf pt, skip unless non-leaf pt is interleaved between
@@ -1698,10 +1733,23 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
u64 pt_size = 1ULL << walk->shifts[xe_child->level];
bool edge_pt = (i == 0 && !IS_ALIGNED(addr, pt_size)) ||
(i == count - 1 && !IS_ALIGNED(next, pt_size));
-
- if (!edge_pt) {
- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt,
- xe_walk->prl,
+ struct xe_pt *child_pt =
+ container_of(xe_child->base.children[first + i],
+ struct xe_pt, base);
+
+ /* Compact PTs always fill a full 2M-aligned slot, never an edge. */
+ XE_WARN_ON(child_pt->is_compact && edge_pt);
+ if (edge_pt)
+ continue;
+
+ /* Walker never descends into compact PTs, descend now */
+ if (child_pt->is_compact) {
+ if (!add_compact_pt_prl(tile, prl, xe, child_pt,
+ addr + (u64)i * pt_size))
+ break;
+ } else {
+ xe_page_reclaim_list_abort(tile->primary_gt,
+ prl,
"PT is skipped by walk at level=%u offset=%lu",
xe_child->level, first + i);
break;
@@ -1711,37 +1759,12 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
- /*
- * In rare scenarios, pte may not be written yet due to racy conditions.
- * In such cases, invalidate the PRL and fallback to full PPC invalidation.
- */
- if (!pte) {
- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl,
- "found zero pte at addr=%#llx", addr);
+ if (add_pte_to_prl(tile, prl, xe_child, pte, addr))
break;
- }
-
- /* Ensure it is a defined page */
- xe_tile_assert(xe_walk->tile, xe_child->level == 0 ||
- (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G)));
/* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */
if (pte & XE_PTE_PS64)
i += 15; /* Skip other 15 consecutive 4K pages in the 64K page */
-
- /* Account for NULL terminated entry on end (-1) */
- if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
- ret = generate_reclaim_entry(xe_walk->tile, xe_walk->prl,
- pte, xe_child);
- if (ret)
- break;
- } else {
- /* overflow, mark as invalid */
- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl,
- "overflow while adding pte=%#llx",
- pte);
- break;
- }
}
}
@@ -1751,7 +1774,7 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
* Verify if any PTE are potentially dropped at non-leaf levels, either from being
* killed or the page walk covers the region.
*/
- if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) &&
+ if (prl && xe_page_reclaim_list_valid(prl) &&
xe_child->level > MAX_HUGEPTE_LEVEL && xe_child->num_live) {
bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base);
@@ -1760,7 +1783,7 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
* we need to invalidate the PRL.
*/
if (killed || covered)
- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl,
+ xe_page_reclaim_list_abort(tile->primary_gt, prl,
"kill at level=%u addr=%#llx next=%#llx num_live=%u",
level, addr, next, xe_child->num_live);
}
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 32a3cef02c7b..b29c99ed3883 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -931,13 +931,13 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
*/
if (hwpec)
iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv));
-out:
/*
* Unlock the SMBus device for use by BIOS/ACPI,
* and clear status flags if not done already.
*/
iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));
+out:
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
mutex_unlock(&priv->acpi_lock);
return ret;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 28c5c5c1fb7a..a21fa45bd64c 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -844,7 +844,7 @@ static int fsl_i2c_probe(struct platform_device *op)
"fsl,timeout", &mpc_ops.timeout);
if (!result) {
- mpc_ops.timeout *= HZ / 1000000;
+ mpc_ops.timeout = mpc_ops.timeout * HZ / 1000000;
if (mpc_ops.timeout < 5)
mpc_ops.timeout = 5;
} else {
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 49a59da6a841..5d49a9021c7d 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -616,8 +616,8 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
unsigned int presence_offset;
unsigned int map_offset;
unsigned int offset;
+ unsigned int num_registers;
unsigned int reg;
- int i;
int b;
int ret;
@@ -643,7 +643,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
ret = rmi_read_block(d, addr, buf, size_presence_reg);
if (ret)
return ret;
- addr += size_presence_reg;
+ ++addr;
if (buf[0] == 0) {
if (size_presence_reg < 3)
@@ -657,7 +657,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
memset(presence_map, 0, sizeof(presence_map));
map_offset = 0;
- for (i = presence_offset; i < size_presence_reg; i++) {
+ for (int i = presence_offset; i < size_presence_reg; i++) {
for (b = 0; b < 8; b++) {
if (buf[i] & BIT(b)) {
if (map_offset >= RMI_REG_DESC_PRESENCE_BITS)
@@ -697,28 +697,41 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
if (ret)
return ret;
- reg = find_first_bit(presence_map, RMI_REG_DESC_PRESENCE_BITS);
offset = 0;
- for (i = 0; i < rdesc->num_registers; i++) {
- struct rmi_register_desc_item *item = &rdesc->registers[i];
+ num_registers = 0;
+ for_each_set_bit(reg, presence_map, RMI_REG_DESC_PRESENCE_BITS) {
+ struct rmi_register_desc_item *item = &rdesc->registers[num_registers];
int item_size;
+ if (offset >= rdesc->struct_size)
+ break;
+
item_size = rmi_parse_register_desc_item(item,
&struct_buf[offset],
rdesc->struct_size - offset);
- if (item_size < 0)
- return item_size;
+ if (item_size < 0) {
+ dev_warn(&d->dev,
+ "%s: Failed to parse register %d descriptor, ignoring it\n",
+ __func__, reg);
+ break;
+ }
item->reg = reg;
offset += item_size;
- rmi_dbg(RMI_DEBUG_CORE, &d->dev,
- "%s: reg: %d reg size: %u subpackets: %d\n", __func__,
- item->reg, item->reg_size, item->num_subpackets);
+ if (item->reg_size == 0) {
+ dev_warn(&d->dev,
+ "%s: Register %d has 0 size, ignoring it\n",
+ __func__, item->reg);
+ } else {
+ rmi_dbg(RMI_DEBUG_CORE, &d->dev,
+ "%s: reg: %d reg size: %u subpackets: %d\n", __func__,
+ item->reg, item->reg_size, item->num_subpackets);
- reg = find_next_bit(presence_map,
- RMI_REG_DESC_PRESENCE_BITS, reg + 1);
+ num_registers++;
+ }
}
+ rdesc->num_registers = num_registers;
return 0;
}
diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
index 35045f161dc2..b2155c8e20e7 100644
--- a/drivers/input/rmi4/rmi_f30.c
+++ b/drivers/input/rmi4/rmi_f30.c
@@ -233,7 +233,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
f30->gpioled_key_map = devm_kcalloc(&fn->dev,
- button_count,
+ f30->gpioled_count,
sizeof(f30->gpioled_key_map[0]),
GFP_KERNEL);
if (!f30->gpioled_key_map) {
diff --git a/drivers/input/rmi4/rmi_f3a.c b/drivers/input/rmi4/rmi_f3a.c
index 0e8baed84dbb..a0777644eef0 100644
--- a/drivers/input/rmi4/rmi_f3a.c
+++ b/drivers/input/rmi4/rmi_f3a.c
@@ -132,7 +132,7 @@ static int rmi_f3a_map_gpios(struct rmi_function *fn, struct f3a_data *f3a,
int button_count = min_t(u8, f3a->gpio_count, TRACKSTICK_RANGE_END);
f3a->gpio_key_map = devm_kcalloc(&fn->dev,
- button_count,
+ f3a->gpio_count,
sizeof(f3a->gpio_key_map[0]),
GFP_KERNEL);
if (!f3a->gpio_key_map) {
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 22b2f57fd91f..bf9b993f5733 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -219,6 +219,7 @@ static void gscps2_read_data(struct gscps2port *ps2port)
ps2port->buffer[ps2port->append].str = status;
ps2port->buffer[ps2port->append].data =
gscps2_readb_input(ps2port->addr);
+ ps2port->append = (ps2port->append + 1) & BUFFER_SIZE;
} while (true);
}
diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c
index 1a163596ddf5..36bee0d8ac6c 100644
--- a/drivers/ntb/hw/amd/ntb_hw_amd.c
+++ b/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -376,7 +376,7 @@ static int amd_ntb_link_disable(struct ntb_dev *ntb)
if (ndev->ntb.topo == NTB_TOPO_SEC)
return -EINVAL;
- dev_dbg(&ntb->pdev->dev, "Enabling Link.\n");
+ dev_dbg(&ntb->pdev->dev, "Disabling Link.\n");
return 0;
}
@@ -1328,15 +1328,15 @@ static const struct ntb_dev_data dev_data[] = {
};
static const struct pci_device_id amd_ntb_pci_tbl[] = {
- { PCI_VDEVICE(AMD, 0x145b), (kernel_ulong_t)&dev_data[0] },
- { PCI_VDEVICE(AMD, 0x148b), (kernel_ulong_t)&dev_data[1] },
- { PCI_VDEVICE(AMD, 0x14c0), (kernel_ulong_t)&dev_data[1] },
- { PCI_VDEVICE(AMD, 0x14c3), (kernel_ulong_t)&dev_data[1] },
- { PCI_VDEVICE(AMD, 0x155a), (kernel_ulong_t)&dev_data[1] },
- { PCI_VDEVICE(AMD, 0x17d4), (kernel_ulong_t)&dev_data[1] },
- { PCI_VDEVICE(AMD, 0x17d7), (kernel_ulong_t)&dev_data[2] },
- { PCI_VDEVICE(HYGON, 0x145b), (kernel_ulong_t)&dev_data[0] },
- { 0, }
+ { PCI_VDEVICE(AMD, 0x145b), .driver_data = (kernel_ulong_t)&dev_data[0] },
+ { PCI_VDEVICE(AMD, 0x148b), .driver_data = (kernel_ulong_t)&dev_data[1] },
+ { PCI_VDEVICE(AMD, 0x14c0), .driver_data = (kernel_ulong_t)&dev_data[1] },
+ { PCI_VDEVICE(AMD, 0x14c3), .driver_data = (kernel_ulong_t)&dev_data[1] },
+ { PCI_VDEVICE(AMD, 0x155a), .driver_data = (kernel_ulong_t)&dev_data[1] },
+ { PCI_VDEVICE(AMD, 0x17d4), .driver_data = (kernel_ulong_t)&dev_data[1] },
+ { PCI_VDEVICE(AMD, 0x17d7), .driver_data = (kernel_ulong_t)&dev_data[2] },
+ { PCI_VDEVICE(HYGON, 0x145b), .driver_data = (kernel_ulong_t)&dev_data[0] },
+ { }
};
MODULE_DEVICE_TABLE(pci, amd_ntb_pci_tbl);
diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c
index af5755472842..c47607d4f8a7 100644
--- a/drivers/ntb/hw/epf/ntb_hw_epf.c
+++ b/drivers/ntb/hw/epf/ntb_hw_epf.c
@@ -729,7 +729,8 @@ static void ntb_epf_deinit_pci(struct ntb_epf_dev *ndev)
struct pci_dev *pdev = ndev->ntb.pdev;
pci_iounmap(pdev, ndev->ctrl_reg);
- pci_iounmap(pdev, ndev->peer_spad_reg);
+ if (ndev->barno_map[BAR_PEER_SPAD] != ndev->barno_map[BAR_CONFIG])
+ pci_iounmap(pdev, ndev->peer_spad_reg);
pci_iounmap(pdev, ndev->db_reg);
pci_release_regions(pdev);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 7cb0d7e88247..6e7a42dedad3 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2160,7 +2160,7 @@ static bool of_check_bad_map(const __be32 *map, int len)
* @map_mask_name: optional property name of the mask to use.
* @filter_np: pointer to an optional filter node, or NULL to allow bypass.
* If non-NULL, the map property must exist (-ENODEV if absent). If
- * *filter_np is also non-NULL, only entries targeting that node match.
+ * ``*filter_np`` is also non-NULL, only entries targeting that node match.
* @arg: pointer to a &struct of_phandle_args for the result. On success,
* @arg->args_count will be set to the number of output specifier cells
* as defined by @cells_name in the target node, and
@@ -2350,7 +2350,7 @@ EXPORT_SYMBOL_GPL(of_map_iommu_id);
* stream/device ID) used as the lookup key in the msi-map table.
* @filter_np: pointer to an optional filter node, or NULL to allow bypass.
* If non-NULL, the map property must exist (-ENODEV if absent). If
- * *filter_np is also non-NULL, only entries targeting that node match.
+ * ``*filter_np`` is also non-NULL, only entries targeting that node match.
* @arg: pointer to a &struct of_phandle_args for the result. On success,
* @arg->args_count will be set to the number of output specifier cells
* and @arg->args[0..args_count-1] will contain the translated output
diff --git a/drivers/of/property.c b/drivers/of/property.c
index b276d1de3222..72cf12907de0 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1172,6 +1172,14 @@ of_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
unsigned int i;
int ret;
+ /*
+ * This function should return -ENOENT for out of bound indexes,
+ * but the OF API uses signed indexes and consider negative indexes
+ * as invalid. Catch them here to correctly implement the fwnode API.
+ */
+ if ((int)index < 0)
+ return -ENOENT;
+
if (nargs_prop)
ret = of_parse_phandle_with_args(to_of_node(fwnode), prop,
nargs_prop, index, &of_args);
diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c
index b2eb9909f6a4..d50ea62fa2f3 100644
--- a/drivers/platform/x86/amd/pmc/pmc.c
+++ b/drivers/platform/x86/amd/pmc/pmc.c
@@ -645,9 +645,12 @@ static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg)
rtc_device = rtc_class_open("rtc0");
if (!rtc_device)
return 0;
- rc = rtc_read_alarm(rtc_device, &alarm);
- if (rc)
- return rc;
+ rc = rtc_read_next_alarm(rtc_device, &alarm);
+ if (rc) {
+ if (rc == -ENOENT)
+ dev_dbg(pdev->dev, "no alarm pending\n");
+ return rc == -ENOENT ? 0 : rc;
+ }
if (!alarm.enabled) {
dev_dbg(pdev->dev, "alarm not enabled\n");
return 0;
diff --git a/drivers/pwm/pwm-rzg2l-gpt.c b/drivers/pwm/pwm-rzg2l-gpt.c
index 4856af080e8e..dfa1d11a48a8 100644
--- a/drivers/pwm/pwm-rzg2l-gpt.c
+++ b/drivers/pwm/pwm-rzg2l-gpt.c
@@ -81,7 +81,7 @@ struct rzg2l_gpt_chip {
void __iomem *mmio;
struct mutex lock; /* lock to protect shared channel resources */
unsigned long rate_khz;
- u32 period_ticks[RZG2L_MAX_HW_CHANNELS];
+ u64 period_ticks[RZG2L_MAX_HW_CHANNELS];
u32 channel_request_count[RZG2L_MAX_HW_CHANNELS];
u32 channel_enable_count[RZG2L_MAX_HW_CHANNELS];
};
@@ -408,14 +408,14 @@ static int rzg2l_gpt_probe(struct platform_device *pdev)
rate = clk_get_rate(clk);
if (!rate)
- return dev_err_probe(dev, -EINVAL, "The gpt clk rate is 0");
+ return dev_err_probe(dev, -EINVAL, "The gpt clk rate is 0\n");
/*
* Refuse clk rates > 1 GHz to prevent overflow later for computing
* period and duty cycle.
*/
if (rate > NSEC_PER_SEC)
- return dev_err_probe(dev, -EINVAL, "The gpt clk rate is > 1GHz");
+ return dev_err_probe(dev, -EINVAL, "The gpt clk rate is > 1GHz\n");
/*
* Rate is in MHz and is always integer for peripheral clk
@@ -424,7 +424,7 @@ static int rzg2l_gpt_probe(struct platform_device *pdev)
*/
rzg2l_gpt->rate_khz = rate / KILO;
if (rzg2l_gpt->rate_khz * KILO != rate)
- return dev_err_probe(dev, -EINVAL, "Rate is not multiple of 1000");
+ return dev_err_probe(dev, -EINVAL, "Rate is not multiple of 1000\n");
mutex_init(&rzg2l_gpt->lock);
diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c
index 2b150bb4d471..36a52f707602 100644
--- a/drivers/regulator/da9121-regulator.c
+++ b/drivers/regulator/da9121-regulator.c
@@ -1195,15 +1195,15 @@ static void da9121_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id da9121_i2c_id[] = {
- {"da9121", DA9121_TYPE_DA9121_DA9130},
- {"da9130", DA9121_TYPE_DA9121_DA9130},
- {"da9217", DA9121_TYPE_DA9217},
- {"da9122", DA9121_TYPE_DA9122_DA9131},
- {"da9131", DA9121_TYPE_DA9122_DA9131},
- {"da9220", DA9121_TYPE_DA9220_DA9132},
- {"da9132", DA9121_TYPE_DA9220_DA9132},
- {"da9141", DA9121_TYPE_DA9141},
- {"da9142", DA9121_TYPE_DA9142},
+ {"da9121", DA9121_SUBTYPE_DA9121},
+ {"da9130", DA9121_SUBTYPE_DA9130},
+ {"da9217", DA9121_SUBTYPE_DA9217},
+ {"da9122", DA9121_SUBTYPE_DA9122},
+ {"da9131", DA9121_SUBTYPE_DA9131},
+ {"da9220", DA9121_SUBTYPE_DA9220},
+ {"da9132", DA9121_SUBTYPE_DA9132},
+ {"da9141", DA9121_SUBTYPE_DA9141},
+ {"da9142", DA9121_SUBTYPE_DA9142},
{},
};
MODULE_DEVICE_TABLE(i2c, da9121_i2c_id);
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index 45d7dc44c2cd..c41db70fa052 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -44,6 +44,7 @@ struct pca9450 {
unsigned int rcnt;
int irq;
bool sd_vsel_fixed_low;
+ int default_t_off_deb;
};
static const struct regmap_range pca9450_status_range = {
@@ -1209,7 +1210,7 @@ static int pca9450_of_init(struct pca9450 *pca9450)
ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-off-debounce-us", &val);
if (ret == -EINVAL)
- t_off_deb = T_OFF_DEB_120US;
+ t_off_deb = pca9450->default_t_off_deb;
else if (ret)
return ret;
else {
@@ -1304,21 +1305,25 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
case PCA9450_TYPE_PCA9450A:
regulator_desc = pca9450a_regulators;
pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators);
+ pca9450->default_t_off_deb = T_OFF_DEB_120US;
type_name = "pca9450a";
break;
case PCA9450_TYPE_PCA9450BC:
regulator_desc = pca9450bc_regulators;
pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators);
+ pca9450->default_t_off_deb = T_OFF_DEB_120US;
type_name = "pca9450bc";
break;
case PCA9450_TYPE_PCA9451A:
regulator_desc = pca9451a_regulators;
pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators);
+ pca9450->default_t_off_deb = T_OFF_DEB_2MS;
type_name = "pca9451a";
break;
case PCA9450_TYPE_PCA9452:
regulator_desc = pca9451a_regulators;
pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators);
+ pca9450->default_t_off_deb = T_OFF_DEB_2MS;
type_name = "pca9452";
break;
default:
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 364afc73f8ab..01def8231873 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1763,13 +1763,6 @@ config RTC_DRV_STMP
This driver can also be built as a module. If so, the module
will be called rtc-stmp3xxx.
-config RTC_DRV_PCAP
- tristate "PCAP RTC"
- depends on EZX_PCAP
- help
- If you say Y here you will get support for the RTC found on
- the PCAP2 ASIC used on some Motorola phones.
-
config RTC_DRV_MC13XXX
depends on MFD_MC13XXX
tristate "Freescale MC13xxx RTC"
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6cf7e066314e..0347645b021f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -128,7 +128,6 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o
obj-$(CONFIG_RTC_DRV_OPTEE) += rtc-optee.o
obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o
-obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o
obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o
obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 1906f4884a83..96626f8068f9 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -384,6 +384,46 @@ done:
return err;
}
+/**
+ * rtc_read_next_alarm - read the next expiring alarm
+ * @rtc: RTC device
+ * @alarm: storage for the alarm information
+ *
+ * Read the next expiring alarm from the RTC timerqueue. This returns
+ * the alarm that will actually fire next, which may be different from
+ * rtc_read_alarm() if multiple timers are queued (e.g., alarmtimer
+ * and wakealarm sysfs both active).
+ *
+ * Returns: 0 on success, -ENOENT if no alarm is pending, or other error.
+ */
+int rtc_read_next_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+ struct timerqueue_node *next;
+ int err;
+
+ if (!rtc || !alarm)
+ return -EINVAL;
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return err;
+
+ next = timerqueue_getnext(&rtc->timerqueue);
+ if (!next) {
+ err = -ENOENT;
+ goto unlock;
+ }
+
+ memset(alarm, 0, sizeof(struct rtc_wkalrm));
+ alarm->time = rtc_ktime_to_tm(next->expires);
+ alarm->enabled = 1;
+
+unlock:
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_read_next_alarm);
+
int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
int err;
@@ -635,8 +675,8 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable);
/**
* rtc_handle_legacy_irq - AIE, UIE and PIE event hook
* @rtc: pointer to the rtc device
- * @num: number of occurence of the event
- * @mode: type of the event, RTC_AF, RTC_UF of RTC_PF
+ * @num: number of occurrence of the event
+ * @mode: type of the event, RTC_AF, RTC_UF or RTC_PF
*
* This function is called when an AIE, UIE or PIE mode interrupt
* has occurred (or been emulated).
diff --git a/drivers/rtc/rtc-88pm886.c b/drivers/rtc/rtc-88pm886.c
index 57e9b0a66eed..13aa3ae82239 100644
--- a/drivers/rtc/rtc-88pm886.c
+++ b/drivers/rtc/rtc-88pm886.c
@@ -78,7 +78,7 @@ static int pm886_rtc_probe(struct platform_device *pdev)
}
static const struct platform_device_id pm886_rtc_id_table[] = {
- { "88pm886-rtc", },
+ { .name = "88pm886-rtc" },
{ }
};
MODULE_DEVICE_TABLE(platform, pm886_rtc_id_table);
diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
index 684f9898d768..6439ca427c32 100644
--- a/drivers/rtc/rtc-ab-b5ze-s3.c
+++ b/drivers/rtc/rtc-ab-b5ze-s3.c
@@ -933,7 +933,7 @@ MODULE_DEVICE_TABLE(of, abb5zes3_dt_match);
#endif
static const struct i2c_device_id abb5zes3_id[] = {
- { "abb5zes3" },
+ { .name = "abb5zes3" },
{ }
};
MODULE_DEVICE_TABLE(i2c, abb5zes3_id);
diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c
index de002f7a39bf..b75f4f665076 100644
--- a/drivers/rtc/rtc-ab-eoz9.c
+++ b/drivers/rtc/rtc-ab-eoz9.c
@@ -546,7 +546,7 @@ MODULE_DEVICE_TABLE(of, abeoz9_dt_match);
#endif
static const struct i2c_device_id abeoz9_id[] = {
- { "abeoz9" },
+ { .name = "abeoz9" },
{ }
};
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index ed2b6b8bb3bf..0978bd0a3393 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -284,11 +284,10 @@ static ssize_t ab8500_sysfs_show_rtc_calibration(struct device *dev,
retval = ab8500_rtc_get_calibration(dev, &calibration);
if (retval < 0) {
dev_err(dev, "Failed to read RTC calibration attribute\n");
- sprintf(buf, "0\n");
return retval;
}
- return sprintf(buf, "%d\n", calibration);
+ return sysfs_emit(buf, "%d\n", calibration);
}
static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR,
@@ -324,14 +323,13 @@ static const struct rtc_class_ops ab8500_rtc_ops = {
};
static const struct platform_device_id ab85xx_rtc_ids[] = {
- { "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, },
+ { .name = "ab8500-rtc" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids);
static int ab8500_rtc_probe(struct platform_device *pdev)
{
- const struct platform_device_id *platid = platform_get_device_id(pdev);
int err;
struct rtc_device *rtc;
u8 rtc_ctrl;
@@ -367,7 +365,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
if (IS_ERR(rtc))
return PTR_ERR(rtc);
- rtc->ops = (struct rtc_class_ops *)platid->driver_data;
+ rtc->ops = &ab8500_rtc_ops;
err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
rtc_alarm_handler, IRQF_ONESHOT,
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 00d7de64ed3e..5486d9d0b1e5 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -545,7 +545,8 @@ static int abx80x_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
status &= ~ABX8XX_STATUS_BLF;
- tmp = i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
+ tmp = i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS,
+ status);
if (tmp < 0)
return tmp;
@@ -752,16 +753,16 @@ static int abx80x_setup_nvmem(struct abx80x_priv *priv)
}
static const struct i2c_device_id abx80x_id[] = {
- { "abx80x", ABX80X },
- { "ab0801", AB0801 },
- { "ab0803", AB0803 },
- { "ab0804", AB0804 },
- { "ab0805", AB0805 },
- { "ab1801", AB1801 },
- { "ab1803", AB1803 },
- { "ab1804", AB1804 },
- { "ab1805", AB1805 },
- { "rv1805", RV1805 },
+ { .name = "abx80x", .driver_data = ABX80X },
+ { .name = "ab0801", .driver_data = AB0801 },
+ { .name = "ab0803", .driver_data = AB0803 },
+ { .name = "ab0804", .driver_data = AB0804 },
+ { .name = "ab0805", .driver_data = AB0805 },
+ { .name = "ab1801", .driver_data = AB1801 },
+ { .name = "ab1803", .driver_data = AB1803 },
+ { .name = "ab1804", .driver_data = AB1804 },
+ { .name = "ab1805", .driver_data = AB1805 },
+ { .name = "rv1805", .driver_data = RV1805 },
{ }
};
MODULE_DEVICE_TABLE(i2c, abx80x_id);
diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c
index 0d0053b52f9b..8f5b440f8c0a 100644
--- a/drivers/rtc/rtc-aspeed.c
+++ b/drivers/rtc/rtc-aspeed.c
@@ -111,6 +111,7 @@ static const struct of_device_id aspeed_rtc_match[] = {
{ .compatible = "aspeed,ast2400-rtc", },
{ .compatible = "aspeed,ast2500-rtc", },
{ .compatible = "aspeed,ast2600-rtc", },
+ { .compatible = "aspeed,ast2700-rtc", },
{}
};
MODULE_DEVICE_TABLE(of, aspeed_rtc_match);
diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c
index 4c8599761b2e..482810b61495 100644
--- a/drivers/rtc/rtc-bd70528.c
+++ b/drivers/rtc/rtc-bd70528.c
@@ -341,10 +341,10 @@ static int bd70528_probe(struct platform_device *pdev)
}
static const struct platform_device_id bd718x7_rtc_id[] = {
- { "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
- { "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },
- { "bd72720-rtc", ROHM_CHIP_TYPE_BD72720 },
- { },
+ { .name = "bd71828-rtc", .driver_data = ROHM_CHIP_TYPE_BD71828 },
+ { .name = "bd71815-rtc", .driver_data = ROHM_CHIP_TYPE_BD71815 },
+ { .name = "bd72720-rtc", .driver_data = ROHM_CHIP_TYPE_BD72720 },
+ { }
};
MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
index 7ad34539be4d..573231613e52 100644
--- a/drivers/rtc/rtc-bq32k.c
+++ b/drivers/rtc/rtc-bq32k.c
@@ -16,6 +16,7 @@
#include <linux/kstrtox.h>
#include <linux/errno.h>
#include <linux/bcd.h>
+#include <linux/delay.h>
#define BQ32K_SECONDS 0x00 /* Seconds register address */
#define BQ32K_SECONDS_MASK 0x7F /* Mask over seconds value */
@@ -89,9 +90,17 @@ static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len)
static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct bq32k_regs regs;
int error;
+ /*
+ * When the device doesn't have the interrupt connected, prevent
+ * userpace from polling the RTC registers too frequently.
+ */
+ if (client->irq <= 0)
+ usleep_range(2000, 2500);
+
error = bq32k_read(dev, &regs, 0, sizeof(regs));
if (error)
return error;
@@ -304,7 +313,7 @@ static void bq32k_remove(struct i2c_client *client)
}
static const struct i2c_device_id bq32k_id[] = {
- { "bq32000" },
+ { .name = "bq32000" },
{ }
};
MODULE_DEVICE_TABLE(i2c, bq32k_id);
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index f89ab58f5048..fa04ece151b8 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -934,6 +934,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
unsigned char rtc_control;
unsigned address_space;
u32 flags = 0;
+ bool hpet_registered = false;
struct nvmem_config nvmem_cfg = {
.name = "cmos_nvram",
.word_size = 1,
@@ -1091,6 +1092,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
" failed in rtc_init().");
goto cleanup1;
}
+ hpet_registered = true;
} else
rtc_cmos_int_handler = cmos_interrupt;
@@ -1140,6 +1142,10 @@ cleanup2:
if (is_valid_irq(rtc_irq))
free_irq(rtc_irq, cmos_rtc.rtc);
cleanup1:
+ if (hpet_registered) {
+ hpet_mask_rtc_irq_bit(RTC_IRQMASK);
+ hpet_unregister_irq_handler(cmos_interrupt);
+ }
cmos_rtc.dev = NULL;
cleanup0:
if (RTC_IOMAPPED)
diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
index e956505a06fb..f3ecd017e2f7 100644
--- a/drivers/rtc/rtc-cros-ec.c
+++ b/drivers/rtc/rtc-cros-ec.c
@@ -388,8 +388,8 @@ static void cros_ec_rtc_remove(struct platform_device *pdev)
}
static const struct platform_device_id cros_ec_rtc_id[] = {
- { DRV_NAME, 0 },
- {}
+ { .name = DRV_NAME },
+ { }
};
MODULE_DEVICE_TABLE(platform, cros_ec_rtc_id);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 7205c59ff729..0707ded5368b 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -269,6 +269,16 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
if (tmp & DS1338_BIT_OSF)
return -EINVAL;
break;
+ case ds_1337:
+ case ds_1339:
+ case ds_1341:
+ case ds_3231:
+ ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &tmp);
+ if (ret)
+ return ret;
+ if (tmp & DS1337_BIT_OSF)
+ return -EINVAL;
+ break;
case ds_1340:
if (tmp & DS1340_BIT_nEOSC)
return -EINVAL;
@@ -279,13 +289,6 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
if (tmp & DS1340_BIT_OSF)
return -EINVAL;
break;
- case ds_1341:
- ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &tmp);
- if (ret)
- return ret;
- if (tmp & DS1337_BIT_OSF)
- return -EINVAL;
- break;
case ds_1388:
ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp);
if (ret)
@@ -308,7 +311,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
t->tm_hour = bcd2bin(tmp);
/* rx8130 is bit position, not BCD */
if (ds1307->type == rx_8130)
- t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f);
+ t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f) - 1;
else
t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f);
@@ -380,14 +383,17 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL,
DS1338_BIT_OSF, 0);
break;
- case ds_1340:
- regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,
- DS1340_BIT_OSF, 0);
- break;
+ case ds_1337:
+ case ds_1339:
case ds_1341:
+ case ds_3231:
regmap_update_bits(ds1307->regmap, DS1337_REG_STATUS,
DS1337_BIT_OSF, 0);
break;
+ case ds_1340:
+ regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,
+ DS1340_BIT_OSF, 0);
+ break;
case ds_1388:
regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG,
DS1388_BIT_OSF, 0);
@@ -1063,24 +1069,24 @@ static const struct chip_desc chips[last_ds_type] = {
};
static const struct i2c_device_id ds1307_id[] = {
- { "ds1307", ds_1307 },
- { "ds1308", ds_1308 },
- { "ds1337", ds_1337 },
- { "ds1338", ds_1338 },
- { "ds1339", ds_1339 },
- { "ds1388", ds_1388 },
- { "ds1340", ds_1340 },
- { "ds1341", ds_1341 },
- { "ds3231", ds_3231 },
- { "m41t0", m41t0 },
- { "m41t00", m41t00 },
- { "m41t11", m41t11 },
- { "mcp7940x", mcp794xx },
- { "mcp7941x", mcp794xx },
- { "pt7c4338", ds_1307 },
- { "rx8025", rx_8025 },
- { "isl12057", ds_1337 },
- { "rx8130", rx_8130 },
+ { .name = "ds1307", .driver_data = ds_1307 },
+ { .name = "ds1308", .driver_data = ds_1308 },
+ { .name = "ds1337", .driver_data = ds_1337 },
+ { .name = "ds1338", .driver_data = ds_1338 },
+ { .name = "ds1339", .driver_data = ds_1339 },
+ { .name = "ds1388", .driver_data = ds_1388 },
+ { .name = "ds1340", .driver_data = ds_1340 },
+ { .name = "ds1341", .driver_data = ds_1341 },
+ { .name = "ds3231", .driver_data = ds_3231 },
+ { .name = "m41t0", .driver_data = m41t0 },
+ { .name = "m41t00", .driver_data = m41t00 },
+ { .name = "m41t11", .driver_data = m41t11 },
+ { .name = "mcp7940x", .driver_data = mcp794xx },
+ { .name = "mcp7941x", .driver_data = mcp794xx },
+ { .name = "pt7c4338", .driver_data = ds_1307 },
+ { .name = "rx8025", .driver_data = rx_8025 },
+ { .name = "isl12057", .driver_data = ds_1337 },
+ { .name = "rx8130", .driver_data = rx_8130 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1307_id);
@@ -1409,7 +1415,7 @@ static void ds1307_hwmon_register(struct ds1307 *ds1307)
{
}
-#endif /* CONFIG_RTC_DRV_DS1307_HWMON */
+#endif /* IS_REACHABLE(CONFIG_HWMON) */
/*----------------------------------------------------------------------*/
@@ -1658,18 +1664,153 @@ static int ds3231_clks_register(struct ds1307 *ds1307)
return 0;
}
+/* ds1307 RTC clock output support */
+static unsigned long ds1307_clk_rates[] = {
+ 1,
+ 4096,
+ 8192,
+ 32768,
+};
+
+static unsigned long ds1307_clk_sqw_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ int ret;
+ unsigned int rate_id;
+ struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+ ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &rate_id);
+ if (ret)
+ return ret;
+
+ rate_id &= (DS1307_BIT_RS1 | DS1307_BIT_RS0);
+
+ return ds1307_clk_rates[rate_id];
+}
+
+static int ds1307_clk_sqw_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ds1307_clk_rates); i++) {
+ if (req->rate <= ds1307_clk_rates[i]) {
+ req->rate = ds1307_clk_rates[i];
+ return 0;
+ }
+ }
+
+ /* Default rate 1Hz */
+ req->rate = ds1307_clk_rates[0];
+
+ return 0;
+}
+
+static int ds1307_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int id, ret;
+ struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+ for (id = 0; id < ARRAY_SIZE(ds1307_clk_rates); id++) {
+ if (ds1307_clk_rates[id] == rate)
+ break;
+ }
+
+ if (id >= ARRAY_SIZE(ds1307_clk_rates))
+ return -EINVAL;
+
+ ret = regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL,
+ DS1307_BIT_RS0 | DS1307_BIT_RS1, id);
+
+ return ret;
+}
+
+static int ds1307_clk_sqw_prepare(struct clk_hw *hw)
+{
+ int ret;
+ struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+ ret = regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL,
+ DS1307_BIT_SQWE, DS1307_BIT_SQWE);
+
+ return ret;
+}
+
+static void ds1307_clk_sqw_unprepare(struct clk_hw *hw)
+{
+ struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+ regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL,
+ DS1307_BIT_SQWE, ~DS1307_BIT_SQWE);
+}
+
+static int ds1307_clk_sqw_is_prepared(struct clk_hw *hw)
+{
+ int ret;
+ struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+ unsigned int status;
+
+ ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &status);
+ if (ret)
+ return ret;
+
+ return !!(status & DS1307_BIT_SQWE);
+}
+
+static const struct clk_ops ds1307_clk_sqw_ops = {
+ .prepare = ds1307_clk_sqw_prepare,
+ .unprepare = ds1307_clk_sqw_unprepare,
+ .is_prepared = ds1307_clk_sqw_is_prepared,
+ .recalc_rate = ds1307_clk_sqw_recalc_rate,
+ .set_rate = ds1307_clk_sqw_set_rate,
+ .determine_rate = ds1307_clk_sqw_determine_rate,
+};
+
+static int rtc_ds1307_clks_register(struct ds1307 *ds1307)
+{
+ struct device_node *node = ds1307->dev->of_node;
+ struct clk *clk;
+ struct clk_init_data init = {0};
+
+ init.name = "ds1307_clk_sqw";
+ init.ops = &ds1307_clk_sqw_ops;
+
+ ds1307->clks[0].init = &init;
+
+ /* Register the clock with CCF */
+ clk = devm_clk_register(ds1307->dev, &ds1307->clks[0]);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ if (node)
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return 0;
+}
+
static void ds1307_clks_register(struct ds1307 *ds1307)
{
int ret;
- if (ds1307->type != ds_3231)
+ switch (ds1307->type) {
+ case ds_3231:
+ ret = ds3231_clks_register(ds1307);
+ break;
+
+ case ds_1307:
+ ret = rtc_ds1307_clks_register(ds1307);
+ break;
+
+ default:
return;
+ }
- ret = ds3231_clks_register(ds1307);
if (ret) {
dev_warn(ds1307->dev, "unable to register clock device %d\n",
ret);
}
+
}
#else
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index c2359eb86bc9..8c247215d611 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -52,7 +52,7 @@
#define DS1374_REG_TCR 0x09 /* Trickle Charge */
static const struct i2c_device_id ds1374_id[] = {
- { "ds1374" },
+ { .name = "ds1374" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1374_id);
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 6e5314215d00..c610beb55bb5 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -133,7 +133,7 @@ static int ds1672_probe(struct i2c_client *client)
}
static const struct i2c_device_id ds1672_id[] = {
- { "ds1672" },
+ { .name = "ds1672" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1672_id);
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 18f35823b4b5..d1ef9e0dad34 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -566,7 +566,7 @@ static int ds3232_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ds3232_id[] = {
- { "ds3232" },
+ { .name = "ds3232" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds3232_id);
diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c
index dc1ccbc65dcb..d555e5d59881 100644
--- a/drivers/rtc/rtc-em3027.c
+++ b/drivers/rtc/rtc-em3027.c
@@ -129,7 +129,7 @@ static int em3027_probe(struct i2c_client *client)
}
static const struct i2c_device_id em3027_id[] = {
- { "em3027" },
+ { .name = "em3027" },
{ }
};
MODULE_DEVICE_TABLE(i2c, em3027_id);
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index f82728ebac0c..28bb6d3f644e 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -53,7 +53,7 @@ struct fm3130 {
int data_valid;
};
static const struct i2c_device_id fm3130_id[] = {
- { "fm3130" },
+ { .name = "fm3130" },
{ }
};
MODULE_DEVICE_TABLE(i2c, fm3130_id);
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index 7a170c0f9710..3156aa5f2d9f 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -564,8 +564,8 @@ static int hym8563_probe(struct i2c_client *client)
}
static const struct i2c_device_id hym8563_id[] = {
- { "hym8563" },
- {}
+ { .name = "hym8563" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, hym8563_id);
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index 5fc52dc64213..bc36288854ee 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -604,7 +604,7 @@ static const struct of_device_id isl12022_dt_match[] = {
MODULE_DEVICE_TABLE(of, isl12022_dt_match);
static const struct i2c_device_id isl12022_id[] = {
- { "isl12022" },
+ { .name = "isl12022" },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl12022_id);
diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c
index 45a2c9f676c5..b86a325d8a23 100644
--- a/drivers/rtc/rtc-isl12026.c
+++ b/drivers/rtc/rtc-isl12026.c
@@ -485,8 +485,8 @@ static const struct of_device_id isl12026_dt_match[] = {
MODULE_DEVICE_TABLE(of, isl12026_dt_match);
static const struct i2c_device_id isl12026_id[] = {
- { "isl12026" },
- { },
+ { .name = "isl12026" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, isl12026_id);
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index f71a6bb77b2a..9bdd5d121571 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -110,11 +110,11 @@ static const struct isl1208_config config_raa215300_a0 = {
};
static const struct i2c_device_id isl1208_id[] = {
- { "isl1208", .driver_data = (kernel_ulong_t)&config_isl1208 },
- { "isl1209", .driver_data = (kernel_ulong_t)&config_isl1209 },
- { "isl1218", .driver_data = (kernel_ulong_t)&config_isl1218 },
- { "isl1219", .driver_data = (kernel_ulong_t)&config_isl1219 },
- { "raa215300_a0", .driver_data = (kernel_ulong_t)&config_raa215300_a0 },
+ { .name = "isl1208", .driver_data = (kernel_ulong_t)&config_isl1208 },
+ { .name = "isl1209", .driver_data = (kernel_ulong_t)&config_isl1209 },
+ { .name = "isl1218", .driver_data = (kernel_ulong_t)&config_isl1218 },
+ { .name = "isl1219", .driver_data = (kernel_ulong_t)&config_isl1219 },
+ { .name = "raa215300_a0", .driver_data = (kernel_ulong_t)&config_raa215300_a0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl1208_id);
@@ -822,6 +822,11 @@ static const struct nvmem_config isl1208_nvmem_config = {
.reg_write = isl1208_nvmem_write,
};
+static void isl1208_disable_irq_wake_action(void *data)
+{
+ disable_irq_wake((unsigned long)data);
+}
+
static int isl1208_setup_irq(struct i2c_client *client, int irq)
{
int rc = devm_request_threaded_irq(&client->dev, irq, NULL,
@@ -831,7 +836,15 @@ static int isl1208_setup_irq(struct i2c_client *client, int irq)
client);
if (!rc) {
device_init_wakeup(&client->dev, true);
- enable_irq_wake(irq);
+ rc = enable_irq_wake(irq);
+ if (rc)
+ return rc;
+
+ rc = devm_add_action_or_reset(&client->dev,
+ isl1208_disable_irq_wake_action,
+ (void *)(unsigned long)irq);
+ if (rc)
+ return rc;
} else {
dev_err(&client->dev,
"Unable to request irq %d, no alarm support\n",
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index b26afef37d9c..3c8c379392c1 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -71,17 +71,17 @@
#define M41T80_FEATURE_SQ_ALT BIT(4) /* RSx bits are in reg 4 */
static const struct i2c_device_id m41t80_id[] = {
- { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
- { "m41t65", M41T80_FEATURE_WD },
- { "m41t80", M41T80_FEATURE_SQ },
- { "m41t81", M41T80_FEATURE_HT | M41T80_FEATURE_SQ},
- { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
- { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
- { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
- { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
- { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
- { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
- { "rv4162", M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT },
+ { .name = "m41t62", .driver_data = M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
+ { .name = "m41t65", .driver_data = M41T80_FEATURE_WD },
+ { .name = "m41t80", .driver_data = M41T80_FEATURE_SQ },
+ { .name = "m41t81", .driver_data = M41T80_FEATURE_HT | M41T80_FEATURE_SQ},
+ { .name = "m41t81s", .driver_data = M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { .name = "m41t82", .driver_data = M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { .name = "m41t83", .driver_data = M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { .name = "m41st84", .driver_data = M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { .name = "m41st85", .driver_data = M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { .name = "m41st87", .driver_data = M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+ { .name = "rv4162", .driver_data = M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT },
{ }
};
MODULE_DEVICE_TABLE(i2c, m41t80_id);
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 9444cb5f5190..fa7a4b5f848d 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -12,6 +12,9 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/clk-provider.h>
+#include <linux/watchdog.h>
#define M41T93_REG_SSEC 0
#define M41T93_REG_ST_SEC 1
@@ -21,7 +24,23 @@
#define M41T93_REG_DAY 5
#define M41T93_REG_MON 6
#define M41T93_REG_YEAR 7
-
+#define M41T93_REG_AL1_MONTH 0xa
+#define M41T93_REG_AL1_DATE 0xb
+#define M41T93_REG_AL1_HOUR 0xc
+#define M41T93_REG_AL1_MIN 0xd
+#define M41T93_REG_AL1_SEC 0xe
+#define M41T93_BIT_A1IE BIT(7)
+#define M41T93_BIT_ABE BIT(5)
+#define M41T93_FLAG_AF1 BIT(6)
+#define M41T93_SRAM_BASE 0x19
+#define M41T93_REG_SQW 0x13
+#define M41T93_SQW_RS_MASK 0xf0
+#define M41T93_SQW_RS_SHIFT 4
+#define M41T93_BIT_SQWE BIT(6)
+#define M41T93_REG_WATCHDOG 0x9
+#define M41T93_WDT_RB_MASK 0x3
+#define M41T93_WDT_BMB_MASK 0x7c
+#define M41T93_WDT_BMB_SHIFT 2
#define M41T93_REG_ALM_HOUR_HT 0xc
#define M41T93_REG_FLAGS 0xf
@@ -31,23 +50,23 @@
#define M41T93_FLAG_BL (1 << 4)
#define M41T93_FLAG_HT (1 << 6)
-static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data)
-{
- u8 buf[2];
-
- /* MSB must be '1' to write */
- buf[0] = addr | 0x80;
- buf[1] = data;
-
- return spi_write(spi, buf, sizeof(buf));
-}
+struct m41t93_data {
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+#ifdef CONFIG_COMMON_CLK
+ struct clk_hw clks;
+#endif
+#ifdef CONFIG_WATCHDOG
+ struct watchdog_device wdd;
+#endif
+};
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- int tmp;
- u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */
- u8 * const data = &buf[1]; /* ptr to first data byte */
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ int tmp, ret;
+ u8 buf[8] = {0}; /* 8 data bytes */
+ u8 * const data = &buf[0]; /* ptr to first data byte */
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -56,31 +75,31 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon, tm->tm_year, tm->tm_wday);
if (tm->tm_year < 100) {
- dev_warn(&spi->dev, "unsupported date (before 2000-01-01).\n");
+ dev_warn(dev, "unsupported date (before 2000-01-01).\n");
return -EINVAL;
}
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_OF) {
- dev_warn(&spi->dev, "OF bit is set, resetting.\n");
- m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
+ dev_warn(dev, "OF bit is set, resetting.\n");
+ regmap_write(m41t93->regmap, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0) {
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0) {
+ return ret;
} else if (tmp & M41T93_FLAG_OF) {
/* OF cannot be immediately reset: oscillator has to be
* restarted. */
u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
- dev_warn(&spi->dev,
+ dev_warn(dev,
"OF bit is still set, kickstarting clock.\n");
- m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
+ regmap_write(m41t93->regmap, M41T93_REG_ST_SEC, reset_osc);
reset_osc &= ~M41T93_FLAG_ST;
- m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
+ regmap_write(m41t93->regmap, M41T93_REG_ST_SEC, reset_osc);
}
}
@@ -94,14 +113,13 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
data[M41T93_REG_MON] = bin2bcd(tm->tm_mon + 1);
data[M41T93_REG_YEAR] = bin2bcd(tm->tm_year % 100);
- return spi_write(spi, buf, sizeof(buf));
+ return regmap_bulk_write(m41t93->regmap, M41T93_REG_SSEC, buf, sizeof(buf));
}
static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- const u8 start_addr = 0;
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
u8 buf[8];
int century_after_1900;
int tmp;
@@ -113,32 +131,32 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
case after poweron. Time is valid after resetting HT bit.
2. oscillator fail bit (OF) is set: time is invalid.
*/
- tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_ALM_HOUR_HT, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_HT) {
- dev_dbg(&spi->dev, "HT bit is set, reenable clock update.\n");
- m41t93_set_reg(spi, M41T93_REG_ALM_HOUR_HT,
- tmp & ~M41T93_FLAG_HT);
+ dev_dbg(dev, "HT bit is set, reenable clock update.\n");
+ regmap_write(m41t93->regmap, M41T93_REG_ALM_HOUR_HT,
+ tmp & ~M41T93_FLAG_HT);
}
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_OF) {
ret = -EINVAL;
- dev_warn(&spi->dev, "OF bit is set, write time to restart.\n");
+ dev_warn(dev, "OF bit is set, write time to restart.\n");
}
if (tmp & M41T93_FLAG_BL)
- dev_warn(&spi->dev, "BL bit is set, replace battery.\n");
+ dev_warn(dev, "BL bit is set, replace battery.\n");
/* read actual time/date */
- tmp = spi_write_then_read(spi, &start_addr, 1, buf, sizeof(buf));
- if (tmp < 0)
- return tmp;
+ ret = regmap_bulk_read(m41t93->regmap, M41T93_REG_SSEC, buf, sizeof(buf));
+ if (ret < 0)
+ return ret;
tm->tm_sec = bcd2bin(buf[M41T93_REG_ST_SEC]);
tm->tm_min = bcd2bin(buf[M41T93_REG_MIN]);
@@ -159,41 +177,407 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
return ret;
}
+static int m41t93_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ int ret;
+ unsigned int val;
+ u8 alarm_vals[5] = {0};
+
+ ret = regmap_bulk_write(m41t93->regmap, M41T93_REG_AL1_DATE, alarm_vals, 4);
+ if (ret)
+ return ret;
+
+ /* Set alarm values */
+ alarm_vals[0] = bin2bcd(alrm->time.tm_mon + 1) & 0x1f;
+ alarm_vals[1] = bin2bcd(alrm->time.tm_mday) & 0x3f;
+ alarm_vals[2] = bin2bcd(alrm->time.tm_hour) & 0x3f;
+ alarm_vals[3] = bin2bcd(alrm->time.tm_min) & 0x7f;
+ alarm_vals[4] = bin2bcd(alrm->time.tm_sec) & 0x7f;
+
+ if (alrm->enabled) {
+ /* Enable alarm IRQ generation */
+ alarm_vals[0] |= M41T93_BIT_A1IE | M41T93_BIT_ABE;
+ }
+
+ /* Preserve SQWE bit */
+ ret = regmap_read(m41t93->regmap, M41T93_REG_AL1_MONTH, &val);
+ if (ret)
+ return ret;
+
+ alarm_vals[0] |= val & 0x40;
+
+ ret = regmap_bulk_write(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ alarm_vals, sizeof(alarm_vals));
+ if (ret)
+ return ret;
+
+ /* Device address pointer is now at FLAG register, move it to other location
+ * to finish setting alarm, as recommended by the datasheet.
+ * We do read of AL1_MONTH register to achieve this.
+ */
+ ret = regmap_read(m41t93->regmap, M41T93_REG_AL1_MONTH, &val);
+ if (ret)
+ return ret;
+
+ if (bcd2bin(val & 0x1f) == (alrm->time.tm_mon & 0x1f))
+ dev_notice(dev, "Alarm set successfully\n");
+
+ return 0;
+}
+
+static int m41t93_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ int ret;
+ unsigned int val;
+ u8 alarm_vals[5] = {0};
+
+ ret = regmap_bulk_read(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ alarm_vals, sizeof(alarm_vals));
+ if (ret)
+ return ret;
+
+ alrm->time.tm_mon = bcd2bin(alarm_vals[0] & 0x1f) - 1;
+ alrm->time.tm_mday = bcd2bin(alarm_vals[1] & 0x3f);
+ alrm->time.tm_hour = bcd2bin(alarm_vals[2] & 0x3f);
+ alrm->time.tm_min = bcd2bin(alarm_vals[3] & 0x7f);
+ alrm->time.tm_sec = bcd2bin(alarm_vals[4] & 0x7f);
+
+ alrm->enabled = !!(alarm_vals[0] & M41T93_BIT_A1IE);
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &val);
+ if (ret)
+ return ret;
+
+ alrm->pending = (val & M41T93_FLAG_AF1) && alrm->enabled;
+
+ return 0;
+}
+
+static int m41t93_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ unsigned int val;
+ int ret;
+
+ val = enabled ? M41T93_BIT_A1IE | M41T93_BIT_ABE : 0;
+
+ ret = regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ M41T93_BIT_A1IE | M41T93_BIT_ABE, val);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static const struct rtc_class_ops m41t93_rtc_ops = {
.read_time = m41t93_get_time,
.set_time = m41t93_set_time,
+ .set_alarm = m41t93_set_alarm,
+ .read_alarm = m41t93_get_alarm,
+ .alarm_irq_enable = m41t93_alarm_irq_enable,
+};
+
+#ifdef CONFIG_COMMON_CLK
+#define clk_sqw_to_m41t93_data(clk) \
+ container_of(clk, struct m41t93_data, clks)
+
+/* m41t93 RTC clock output support */
+static unsigned long m41t93_clk_rates[] = {
+ 0,
+ 32768, /* RS3:RS0 = 0b0001 */
+ 8192,
+ 4096,
+ 2048,
+ 1024,
+ 512,
+ 256,
+ 128,
+ 64,
+ 32,
+ 16,
+ 8,
+ 4,
+ 2,
+ 1, /* RS3:RS0 = 0b1111 */
+};
+
+static unsigned long m41t93_clk_sqw_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ int ret;
+ unsigned int rate_id;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_SQW, &rate_id);
+ if (ret)
+ return ret;
+
+ rate_id &= M41T93_SQW_RS_MASK;
+ rate_id >>= M41T93_SQW_RS_SHIFT;
+
+ return m41t93_clk_rates[rate_id];
+}
+
+static int m41t93_clk_sqw_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(m41t93_clk_rates); i++) {
+ if (req->rate >= m41t93_clk_rates[i]) {
+ req->rate = m41t93_clk_rates[i];
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int m41t93_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int id, ret;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ for (id = 0; id < ARRAY_SIZE(m41t93_clk_rates); id++) {
+ if (m41t93_clk_rates[id] == rate)
+ break;
+ }
+
+ if (id >= ARRAY_SIZE(m41t93_clk_rates))
+ return -EINVAL;
+
+ ret = regmap_update_bits(m41t93->regmap, M41T93_REG_SQW,
+ M41T93_SQW_RS_MASK, id << M41T93_SQW_RS_SHIFT);
+
+ return ret;
+}
+
+static int m41t93_clk_sqw_prepare(struct clk_hw *hw)
+{
+ int ret;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ ret = regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ M41T93_BIT_SQWE, M41T93_BIT_SQWE);
+
+ return ret;
+}
+
+static void m41t93_clk_sqw_unprepare(struct clk_hw *hw)
+{
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ M41T93_BIT_SQWE, 0);
+}
+
+static int m41t93_clk_sqw_is_prepared(struct clk_hw *hw)
+{
+ int ret;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+ unsigned int status;
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_AL1_MONTH, &status);
+ if (ret)
+ return ret;
+
+ return !!(status & M41T93_BIT_SQWE);
+}
+
+static const struct clk_ops m41t93_clk_sqw_ops = {
+ .prepare = m41t93_clk_sqw_prepare,
+ .unprepare = m41t93_clk_sqw_unprepare,
+ .is_prepared = m41t93_clk_sqw_is_prepared,
+ .recalc_rate = m41t93_clk_sqw_recalc_rate,
+ .set_rate = m41t93_clk_sqw_set_rate,
+ .determine_rate = m41t93_clk_sqw_determine_rate,
+};
+
+static int rtc_m41t93_clks_register(struct device *dev, struct m41t93_data *m41t93)
+{
+ struct device_node *node = dev->of_node;
+ struct clk *clk;
+ struct clk_init_data init = {0};
+
+ init.name = "m41t93_clk_sqw";
+ init.ops = &m41t93_clk_sqw_ops;
+
+ m41t93->clks.init = &init;
+
+ /* Register the clock with CCF */
+ clk = devm_clk_register(dev, &m41t93->clks);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ if (node)
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_WATCHDOG
+static int m41t93_wdt_ping(struct watchdog_device *wdd)
+{
+ u8 resolution, mult;
+ u8 val = 0;
+ int ret;
+ struct m41t93_data *m41t93 = watchdog_get_drvdata(wdd);
+
+ /* Resolution supported by hardware
+ * 0b00 : 1/16 seconds
+ * 0b01 : 1/4 second
+ * 0b10 : 1 second
+ * 0b11 : 4 seconds
+ */
+ resolution = 0x2; /* hardcode resolution to 1s */
+ mult = wdd->timeout;
+ val = resolution | (mult << M41T93_WDT_BMB_SHIFT & M41T93_WDT_BMB_MASK);
+
+ ret = regmap_write_bits(m41t93->regmap, M41T93_REG_WATCHDOG,
+ M41T93_WDT_RB_MASK | M41T93_WDT_BMB_MASK, val);
+
+ return ret;
+}
+
+static int m41t93_wdt_start(struct watchdog_device *wdd)
+{
+ return m41t93_wdt_ping(wdd);
+}
+
+static int m41t93_wdt_stop(struct watchdog_device *wdd)
+{
+ struct m41t93_data *m41t93 = watchdog_get_drvdata(wdd);
+
+ /* Write 0 to watchdog register */
+ return regmap_write_bits(m41t93->regmap, M41T93_REG_WATCHDOG,
+ M41T93_WDT_RB_MASK | M41T93_WDT_BMB_MASK, 0);
+}
+
+static int m41t93_wdt_set_timeout(struct watchdog_device *wdd,
+ unsigned int new_timeout)
+{
+ wdd->timeout = new_timeout;
+
+ return 0;
+}
+
+static const struct watchdog_info m41t93_wdt_info = {
+ .identity = "m41t93 rtc Watchdog",
+ .options = WDIOF_ALARMONLY | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+static const struct watchdog_ops m41t93_watchdog_ops = {
+ .owner = THIS_MODULE,
+ .start = m41t93_wdt_start,
+ .stop = m41t93_wdt_stop,
+ .ping = m41t93_wdt_ping,
+ .set_timeout = m41t93_wdt_set_timeout,
};
+static int m41t93_watchdog_register(struct device *dev, struct m41t93_data *m41t93)
+{
+ int ret;
+
+ m41t93->wdd.parent = dev;
+ m41t93->wdd.info = &m41t93_wdt_info;
+ m41t93->wdd.ops = &m41t93_watchdog_ops;
+ m41t93->wdd.min_timeout = 0;
+ m41t93->wdd.max_timeout = 10;
+ m41t93->wdd.timeout = 3; /* Default timeout is 3 sec */
+ m41t93->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
+
+ watchdog_set_drvdata(&m41t93->wdd, m41t93);
+
+ ret = devm_watchdog_register_device(dev, &m41t93->wdd);
+ if (ret) {
+ dev_warn(dev, "Failed to register watchdog\n");
+ return ret;
+ }
+
+ /* Disable watchdog at start */
+ ret = m41t93_wdt_stop(&m41t93->wdd);
+
+ return ret;
+}
+#endif
+
static struct spi_driver m41t93_driver;
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read_flag_mask = 0x00,
+ .write_flag_mask = 0x80,
+ .zero_flag_mask = true,
+};
+
static int m41t93_probe(struct spi_device *spi)
{
- struct rtc_device *rtc;
- int res;
+ int res, ret;
+ struct m41t93_data *m41t93;
spi->bits_per_word = 8;
spi_setup(spi);
- res = spi_w8r8(spi, M41T93_REG_WDAY);
+ m41t93 = devm_kzalloc(&spi->dev, sizeof(struct m41t93_data), GFP_KERNEL);
+
+ if (!m41t93)
+ return -ENOMEM;
+
+ /* Set up regmap to access device registers*/
+ m41t93->regmap = devm_regmap_init_spi(spi, &regmap_config);
+ if (IS_ERR(m41t93->regmap)) {
+ dev_err(&spi->dev, "regmap init failure\n");
+ return PTR_ERR(m41t93->regmap);
+ }
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_WDAY, &res);
+ if (ret < 0) {
+ dev_err(&spi->dev, "IO error\n");
+ return -EIO;
+ }
+
if (res < 0 || (res & 0xf8) != 0) {
dev_err(&spi->dev, "not found 0x%x.\n", res);
return -ENODEV;
}
- rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
- &m41t93_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
+ spi_set_drvdata(spi, m41t93);
+
+ m41t93->rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
+ &m41t93_rtc_ops, THIS_MODULE);
+ if (IS_ERR(m41t93->rtc))
+ return PTR_ERR(m41t93->rtc);
- spi_set_drvdata(spi, rtc);
+#ifdef CONFIG_COMMON_CLK
+ ret = rtc_m41t93_clks_register(&spi->dev, m41t93);
+ if (ret)
+ dev_warn(&spi->dev, "Unable to register clock\n");
+#endif
+#ifdef CONFIG_WATCHDOG
+ ret = m41t93_watchdog_register(&spi->dev, m41t93);
+ if (ret)
+ dev_warn(&spi->dev, "Unable to register watchdog\n");
+#endif
return 0;
}
+static const struct of_device_id m41t93_dt_match[] = {
+ { .compatible = "st,m41t93" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, m41t93_dt_match);
+
static struct spi_driver m41t93_driver = {
.driver = {
.name = "rtc-m41t93",
+ .of_match_table = m41t93_dt_match,
},
.probe = m41t93_probe,
};
diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c
index 952b455071d6..595816973851 100644
--- a/drivers/rtc/rtc-max31335.c
+++ b/drivers/rtc/rtc-max31335.c
@@ -745,8 +745,8 @@ static int max31335_probe(struct i2c_client *client)
}
static const struct i2c_device_id max31335_id[] = {
- { "max31331", (kernel_ulong_t)&chip[ID_MAX31331] },
- { "max31335", (kernel_ulong_t)&chip[ID_MAX31335] },
+ { .name = "max31331", .driver_data = (kernel_ulong_t)&chip[ID_MAX31331] },
+ { .name = "max31335", .driver_data = (kernel_ulong_t)&chip[ID_MAX31335] },
{ }
};
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
index 7be31fce5bc7..8ef6d0fcd032 100644
--- a/drivers/rtc/rtc-max6900.c
+++ b/drivers/rtc/rtc-max6900.c
@@ -215,7 +215,7 @@ static int max6900_probe(struct i2c_client *client)
}
static const struct i2c_device_id max6900_id[] = {
- { "max6900" },
+ { .name = "max6900" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max6900_id);
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 3cdfd78a07cc..375565a3bddf 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -866,11 +866,11 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
max77686_rtc_suspend, max77686_rtc_resume);
static const struct platform_device_id rtc_id[] = {
- { "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, },
- { "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data, },
- { "max77620-rtc", .driver_data = (kernel_ulong_t)&max77620_drv_data, },
- { "max77714-rtc", .driver_data = (kernel_ulong_t)&max77714_drv_data, },
- {},
+ { .name = "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data },
+ { .name = "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data },
+ { .name = "max77620-rtc", .driver_data = (kernel_ulong_t)&max77620_drv_data },
+ { .name = "max77714-rtc", .driver_data = (kernel_ulong_t)&max77714_drv_data },
+ { }
};
MODULE_DEVICE_TABLE(platform, rtc_id);
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index e7618d715bd8..89203c92e2cd 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -512,8 +512,8 @@ static void max8997_rtc_shutdown(struct platform_device *pdev)
}
static const struct platform_device_id rtc_id[] = {
- { "max8997-rtc", 0 },
- {},
+ { .name = "max8997-rtc" },
+ { }
};
MODULE_DEVICE_TABLE(platform, rtc_id);
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c
index c873b4509b3c..a2c946edcd1a 100644
--- a/drivers/rtc/rtc-max8998.c
+++ b/drivers/rtc/rtc-max8998.c
@@ -299,8 +299,8 @@ no_irq:
}
static const struct platform_device_id max8998_rtc_id[] = {
- { "max8998-rtc", TYPE_MAX8998 },
- { "lp3974-rtc", TYPE_LP3974 },
+ { .name = "max8998-rtc", .driver_data = TYPE_MAX8998 },
+ { .name = "lp3974-rtc", .driver_data = TYPE_LP3974 },
{ }
};
MODULE_DEVICE_TABLE(platform, max8998_rtc_id);
diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c
index 6aa3eae575d2..ece6de4a6adb 100644
--- a/drivers/rtc/rtc-mpfs.c
+++ b/drivers/rtc/rtc-mpfs.c
@@ -112,7 +112,7 @@ static int mpfs_rtc_settime(struct device *dev, struct rtc_time *tm)
ctrl |= CONTROL_UPLOAD_BIT;
writel(ctrl, rtcdev->base + CONTROL_REG);
- ret = read_poll_timeout(readl, prog, prog & CONTROL_UPLOAD_BIT, 0, UPLOAD_TIMEOUT_US,
+ ret = read_poll_timeout(readl, prog, !(prog & CONTROL_UPLOAD_BIT), 0, UPLOAD_TIMEOUT_US,
false, rtcdev->base + CONTROL_REG);
if (ret) {
dev_err(dev, "timed out uploading time to rtc");
diff --git a/drivers/rtc/rtc-msc313.c b/drivers/rtc/rtc-msc313.c
index 8d7737e0e2e0..6ef9c4efd7c9 100644
--- a/drivers/rtc/rtc-msc313.c
+++ b/drivers/rtc/rtc-msc313.c
@@ -160,7 +160,7 @@ static const struct rtc_class_ops msc313_rtc_ops = {
static irqreturn_t msc313_rtc_interrupt(s32 irq, void *dev_id)
{
- struct msc313_rtc *priv = dev_get_drvdata(dev_id);
+ struct msc313_rtc *priv = dev_id;
u16 reg;
reg = readw(priv->rtc_base + REG_RTC_STATUS_INT);
@@ -206,7 +206,7 @@ static int msc313_rtc_probe(struct platform_device *pdev)
priv->rtc_dev->range_max = U32_MAX;
ret = devm_request_irq(dev, irq, msc313_rtc_interrupt, IRQF_SHARED,
- dev_name(&pdev->dev), &pdev->dev);
+ dev_name(&pdev->dev), priv);
if (ret) {
dev_err(dev, "Could not request IRQ\n");
return ret;
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index c27ad626d09f..f88976fd6d5d 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -301,6 +301,28 @@ static const struct of_device_id rtc_mv_of_match_table[] = {
MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table);
#endif
+#ifdef CONFIG_PM_SLEEP
+static int mv_rtc_suspend(struct device *dev)
+{
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev) && pdata->irq >= 0)
+ enable_irq_wake(pdata->irq);
+ return 0;
+}
+
+static int mv_rtc_resume(struct device *dev)
+{
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev) && pdata->irq >= 0)
+ disable_irq_wake(pdata->irq);
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mv_rtc_pm_ops, mv_rtc_suspend, mv_rtc_resume);
+
/*
* mv_rtc_remove() lives in .exit.text. For drivers registered via
* module_platform_driver_probe() this is ok because they cannot get unbound at
@@ -312,6 +334,7 @@ static struct platform_driver mv_rtc_driver __refdata = {
.driver = {
.name = "rtc-mv",
.of_match_table = of_match_ptr(rtc_mv_of_match_table),
+ .pm = &mv_rtc_pm_ops,
},
};
diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c
index cd4b1db902e9..700a395fad3a 100644
--- a/drivers/rtc/rtc-nct3018y.c
+++ b/drivers/rtc/rtc-nct3018y.c
@@ -572,7 +572,7 @@ static int nct3018y_probe(struct i2c_client *client)
}
static const struct i2c_device_id nct3018y_id[] = {
- { "nct3018y" },
+ { .name = "nct3018y" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nct3018y_id);
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c
deleted file mode 100644
index d6651611a0c6..000000000000
--- a/drivers/rtc/rtc-pcap.c
+++ /dev/null
@@ -1,179 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * pcap rtc code for Motorola EZX phones
- *
- * Copyright (c) 2008 guiming zhuo <gmzhuo@gmail.com>
- * Copyright (c) 2009 Daniel Ribeiro <drwyrm@gmail.com>
- *
- * Based on Motorola's rtc.c Copyright (c) 2003-2005 Motorola
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mfd/ezx-pcap.h>
-#include <linux/rtc.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-
-struct pcap_rtc {
- struct pcap_chip *pcap;
- struct rtc_device *rtc;
-};
-
-static irqreturn_t pcap_rtc_irq(int irq, void *_pcap_rtc)
-{
- struct pcap_rtc *pcap_rtc = _pcap_rtc;
- unsigned long rtc_events;
-
- if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ))
- rtc_events = RTC_IRQF | RTC_UF;
- else if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA))
- rtc_events = RTC_IRQF | RTC_AF;
- else
- rtc_events = 0;
-
- rtc_update_irq(pcap_rtc->rtc, 1, rtc_events);
- return IRQ_HANDLED;
-}
-
-static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
- struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
- struct rtc_time *tm = &alrm->time;
- unsigned long secs;
- u32 tod; /* time of day, seconds since midnight */
- u32 days; /* days since 1/1/1970 */
-
- ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TODA, &tod);
- secs = tod & PCAP_RTC_TOD_MASK;
-
- ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, &days);
- secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY;
-
- rtc_time64_to_tm(secs, tm);
-
- return 0;
-}
-
-static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
- struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
- unsigned long secs = rtc_tm_to_time64(&alrm->time);
- u32 tod, days;
-
- tod = secs % SEC_PER_DAY;
- ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TODA, tod);
-
- days = secs / SEC_PER_DAY;
- ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, days);
-
- return 0;
-}
-
-static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
- unsigned long secs;
- u32 tod, days;
-
- ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TOD, &tod);
- secs = tod & PCAP_RTC_TOD_MASK;
-
- ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAY, &days);
- secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY;
-
- rtc_time64_to_tm(secs, tm);
-
- return 0;
-}
-
-static int pcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
- unsigned long secs = rtc_tm_to_time64(tm);
- u32 tod, days;
-
- tod = secs % SEC_PER_DAY;
- ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TOD, tod);
-
- days = secs / SEC_PER_DAY;
- ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAY, days);
-
- return 0;
-}
-
-static int pcap_rtc_irq_enable(struct device *dev, int pirq, unsigned int en)
-{
- struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
-
- if (en)
- enable_irq(pcap_to_irq(pcap_rtc->pcap, pirq));
- else
- disable_irq(pcap_to_irq(pcap_rtc->pcap, pirq));
-
- return 0;
-}
-
-static int pcap_rtc_alarm_irq_enable(struct device *dev, unsigned int en)
-{
- return pcap_rtc_irq_enable(dev, PCAP_IRQ_TODA, en);
-}
-
-static const struct rtc_class_ops pcap_rtc_ops = {
- .read_time = pcap_rtc_read_time,
- .set_time = pcap_rtc_set_time,
- .read_alarm = pcap_rtc_read_alarm,
- .set_alarm = pcap_rtc_set_alarm,
- .alarm_irq_enable = pcap_rtc_alarm_irq_enable,
-};
-
-static int __init pcap_rtc_probe(struct platform_device *pdev)
-{
- struct pcap_rtc *pcap_rtc;
- int timer_irq, alarm_irq;
- int err = -ENOMEM;
-
- pcap_rtc = devm_kzalloc(&pdev->dev, sizeof(struct pcap_rtc),
- GFP_KERNEL);
- if (!pcap_rtc)
- return err;
-
- pcap_rtc->pcap = dev_get_drvdata(pdev->dev.parent);
-
- platform_set_drvdata(pdev, pcap_rtc);
-
- pcap_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
- if (IS_ERR(pcap_rtc->rtc))
- return PTR_ERR(pcap_rtc->rtc);
-
- pcap_rtc->rtc->ops = &pcap_rtc_ops;
- pcap_rtc->rtc->range_max = (1 << 14) * 86400ULL - 1;
-
- timer_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ);
- alarm_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA);
-
- err = devm_request_irq(&pdev->dev, timer_irq, pcap_rtc_irq, 0,
- "RTC Timer", pcap_rtc);
- if (err)
- return err;
-
- err = devm_request_irq(&pdev->dev, alarm_irq, pcap_rtc_irq, 0,
- "RTC Alarm", pcap_rtc);
- if (err)
- return err;
-
- return devm_rtc_register_device(pcap_rtc->rtc);
-}
-
-static struct platform_driver pcap_rtc_driver = {
- .driver = {
- .name = "pcap-rtc",
- },
-};
-
-module_platform_driver_probe(pcap_rtc_driver, pcap_rtc_probe);
-
-MODULE_DESCRIPTION("Motorola pcap rtc driver");
-MODULE_AUTHOR("guiming zhuo <gmzhuo@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index e4785c5a55d0..1995e9f2756d 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -1449,10 +1449,10 @@ static const struct regmap_bus pcf2127_i2c_regmap = {
static struct i2c_driver pcf2127_i2c_driver;
static const struct i2c_device_id pcf2127_i2c_id[] = {
- { "pcf2127", (kernel_ulong_t)&pcf21xx_cfg[PCF2127] },
- { "pcf2129", (kernel_ulong_t)&pcf21xx_cfg[PCF2129] },
- { "pca2129", (kernel_ulong_t)&pcf21xx_cfg[PCF2129] },
- { "pcf2131", (kernel_ulong_t)&pcf21xx_cfg[PCF2131] },
+ { .name = "pcf2127", .driver_data = (kernel_ulong_t)&pcf21xx_cfg[PCF2127] },
+ { .name = "pcf2129", .driver_data = (kernel_ulong_t)&pcf21xx_cfg[PCF2129] },
+ { .name = "pca2129", .driver_data = (kernel_ulong_t)&pcf21xx_cfg[PCF2129] },
+ { .name = "pcf2131", .driver_data = (kernel_ulong_t)&pcf21xx_cfg[PCF2131] },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index f643e0bd7351..01e209d88f5f 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -665,12 +665,12 @@ static const struct pcf85063_config config_rv8263 = {
};
static const struct i2c_device_id pcf85063_ids[] = {
- { "pca85073a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
- { "pcf85063", .driver_data = (kernel_ulong_t)&config_pcf85063 },
- { "pcf85063tp", .driver_data = (kernel_ulong_t)&config_pcf85063tp },
- { "pcf85063a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
- { "rv8263", .driver_data = (kernel_ulong_t)&config_rv8263 },
- {}
+ { .name = "pca85073a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
+ { .name = "pcf85063", .driver_data = (kernel_ulong_t)&config_pcf85063 },
+ { .name = "pcf85063tp", .driver_data = (kernel_ulong_t)&config_pcf85063tp },
+ { .name = "pcf85063a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
+ { .name = "rv8263", .driver_data = (kernel_ulong_t)&config_rv8263 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pcf85063_ids);
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index 2c63c0ffd05a..e8354953836c 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -495,7 +495,7 @@ static int pcf8523_probe(struct i2c_client *client)
}
static const struct i2c_device_id pcf8523_id[] = {
- { "pcf8523" },
+ { .name = "pcf8523" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf8523_id);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index b281e9489df1..81d13733b1e9 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -557,9 +557,9 @@ static int pcf8563_probe(struct i2c_client *client)
}
static const struct i2c_device_id pcf8563_id[] = {
- { "pcf8563" },
- { "rtc8564" },
- { "pca8565" },
+ { .name = "pcf8563" },
+ { .name = "rtc8564" },
+ { .name = "pca8565" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf8563_id);
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index 652b9dfa7566..df5e20cbc26c 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -297,7 +297,7 @@ static int pcf8583_probe(struct i2c_client *client)
}
static const struct i2c_device_id pcf8583_id[] = {
- { "pcf8583" },
+ { .name = "pcf8583" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf8583_id);
diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c
index cbabaa4dc96a..b3875d041de5 100644
--- a/drivers/rtc/rtc-renesas-rtca3.c
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -103,7 +103,7 @@ enum rtca3_alrm_set_step {
/**
* struct rtca3_ppb_per_cycle - PPB per cycle
- * @ten_sec: PPB per cycle in 10 seconds adjutment mode
+ * @ten_sec: PPB per cycle in 10 seconds adjustment mode
* @sixty_sec: PPB per cycle in 60 seconds adjustment mode
*/
struct rtca3_ppb_per_cycle {
@@ -228,12 +228,19 @@ static void rtca3_prepare_cntalrm_regs_for_read(struct rtca3_priv *priv, bool cn
}
}
+static u32 rtca3_decode_year(u8 mask, u16 year)
+{
+ u8 y = FIELD_GET(mask, year);
+ u32 century = bcd2bin((y == 0x99) ? 0x19 : 0x20);
+
+ return (century * 100 + bcd2bin(y)) - 1900;
+}
+
static int rtca3_read_time(struct device *dev, struct rtc_time *tm)
{
struct rtca3_priv *priv = dev_get_drvdata(dev);
u8 sec, min, hour, wday, mday, month, tmp;
u8 trials = 0;
- u32 year100;
u16 year;
guard(spinlock_irqsave)(&priv->lock);
@@ -274,9 +281,7 @@ static int rtca3_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKCNT_WK, wday));
tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYCNT_DAY, mday));
tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONCNT_MONTH, month)) - 1;
- year = FIELD_GET(RTCA3_RYRCNT_YEAR, year);
- year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
- tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+ tm->tm_year = rtca3_decode_year(RTCA3_RYRCNT_YEAR, year);
return 0;
}
@@ -354,7 +359,6 @@ static int rtca3_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
struct rtca3_priv *priv = dev_get_drvdata(dev);
u8 sec, min, hour, wday, mday, month;
struct rtc_time *tm = &wkalrm->time;
- u32 year100;
u16 year;
guard(spinlock_irqsave)(&priv->lock);
@@ -373,9 +377,7 @@ static int rtca3_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKAR_DAYW, wday));
tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYAR_DATE, mday));
tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONAR_MON, month)) - 1;
- year = FIELD_GET(RTCA3_RYRAR_YR, year);
- year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
- tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+ tm->tm_year = rtca3_decode_year(RTCA3_RYRAR_YR, year);
wkalrm->enabled = !!(readb(priv->base + RTCA3_RCR1) & RTCA3_RCR1_AIE);
@@ -455,7 +457,7 @@ setup_failed:
* specified timeout for setup.
*/
writeb(rcr1 & ~RTCA3_RCR1_PIE, priv->base + RTCA3_RCR1);
- readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & ~RTCA3_RCR1_PIE),
+ readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & RTCA3_RCR1_PIE),
10, RTCA3_DEFAULT_TIMEOUT_US);
atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
}
@@ -634,6 +636,8 @@ static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv)
writeb(0, priv->base + RTCA3_RADJ);
ret = readb_poll_timeout(priv->base + RTCA3_RADJ, tmp, !tmp, 10,
RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
/* Start the RTC and enable automatic time error adjustment. */
mask = RTCA3_RCR2_START | RTCA3_RCR2_AADJE;
@@ -700,7 +704,7 @@ static void rtca3_action(void *data)
ret = reset_control_assert(priv->rstc);
if (ret)
- dev_err(dev, "Failed to de-assert reset!");
+ dev_err(dev, "Failed to assert reset!");
ret = pm_runtime_put_sync(dev);
if (ret < 0)
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 936f4f05c8c7..24bd795d9d95 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -75,12 +75,12 @@ enum rtc_type {
};
static const struct i2c_device_id rs5c372_id[] = {
- { "r2025sd", rtc_r2025sd },
- { "r2221tl", rtc_r2221tl },
- { "rs5c372a", rtc_rs5c372a },
- { "rs5c372b", rtc_rs5c372b },
- { "rv5c386", rtc_rv5c386 },
- { "rv5c387a", rtc_rv5c387a },
+ { .name = "r2025sd", .driver_data = rtc_r2025sd },
+ { .name = "r2221tl", .driver_data = rtc_r2221tl },
+ { .name = "rs5c372a", .driver_data = rtc_rs5c372a },
+ { .name = "rs5c372b", .driver_data = rtc_rs5c372b },
+ { .name = "rv5c386", .driver_data = rtc_rv5c386 },
+ { .name = "rv5c387a", .driver_data = rtc_rv5c387a },
{ }
};
MODULE_DEVICE_TABLE(i2c, rs5c372_id);
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 83331d1fcab0..98953af2a24a 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -807,8 +807,8 @@ static int rv3029_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id rv3029_id[] = {
- { "rv3029" },
- { "rv3029c2" },
+ { .name = "rv3029" },
+ { .name = "rv3029c2" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rv3029_id);
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 2bf988a89fd7..b9b5fee16ee4 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -631,10 +631,10 @@ static int rv8803_suspend(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(rv8803_pm_ops, rv8803_suspend, rv8803_resume);
static const struct i2c_device_id rv8803_id[] = {
- { "rv8803", rv_8803 },
- { "rv8804", rx_8804 },
- { "rx8803", rx_8803 },
- { "rx8900", rx_8900 },
+ { .name = "rv8803", .driver_data = rv_8803 },
+ { .name = "rv8804", .driver_data = rx_8804 },
+ { .name = "rx8803", .driver_data = rx_8803 },
+ { .name = "rx8900", .driver_data = rx_8900 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rv8803_id);
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c
index 07bf35ac8d79..1eacd470a27c 100644
--- a/drivers/rtc/rtc-rx6110.c
+++ b/drivers/rtc/rtc-rx6110.c
@@ -449,7 +449,7 @@ static const struct acpi_device_id rx6110_i2c_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, rx6110_i2c_acpi_match);
static const struct i2c_device_id rx6110_i2c_id[] = {
- { "rx6110" },
+ { .name = "rx6110" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx6110_i2c_id);
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
index 171240e50f48..ce3954132336 100644
--- a/drivers/rtc/rtc-rx8010.c
+++ b/drivers/rtc/rtc-rx8010.c
@@ -50,7 +50,7 @@
#define RX8010_ALARM_AE BIT(7)
static const struct i2c_device_id rx8010_id[] = {
- { "rx8010" },
+ { .name = "rx8010" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx8010_id);
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index c57081f9e02b..5eeaa929f3ef 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -71,8 +71,8 @@ enum rx_model {
};
static const struct i2c_device_id rx8025_id[] = {
- { "rx8025", model_rx_8025 },
- { "rx8035", model_rx_8035 },
+ { .name = "rx8025", .driver_data = model_rx_8025 },
+ { .name = "rx8035", .driver_data = model_rx_8035 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx8025_id);
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index 20c2dff01bae..cf4dab94c337 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -294,7 +294,7 @@ static int rx8581_probe(struct i2c_client *client)
}
static const struct i2c_device_id rx8581_id[] = {
- { "rx8581" },
+ { .name = "rx8581" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx8581_id);
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index a4678d7c6cf6..b72eef4fb099 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -51,7 +51,7 @@
#define S35390A_INT2_MODE_PMIN (BIT(3) | BIT(2)) /* INT2FE | INT2ME */
static const struct i2c_device_id s35390a_id[] = {
- { "s35390a" },
+ { .name = "s35390a" },
{ }
};
MODULE_DEVICE_TABLE(i2c, s35390a_id);
@@ -297,7 +297,7 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
else
sts = S35390A_INT2_MODE_NOINTR;
- /* set interupt mode*/
+ /* set interrupt mode*/
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
if (err < 0)
return err;
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index c6ed5a4ca8a0..aa706074ec3e 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -807,12 +807,12 @@ static int s5m_rtc_suspend(struct device *dev)
static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
static const struct platform_device_id s5m_rtc_id[] = {
- { "s5m-rtc", S5M8767X },
- { "s2mpg10-rtc", S2MPG10 },
- { "s2mps13-rtc", S2MPS13X },
- { "s2mps14-rtc", S2MPS14X },
- { "s2mps15-rtc", S2MPS15X },
- { },
+ { .name = "s5m-rtc", .driver_data = S5M8767X },
+ { .name = "s2mpg10-rtc", .driver_data = S2MPG10 },
+ { .name = "s2mps13-rtc", .driver_data = S2MPS13X },
+ { .name = "s2mps14-rtc", .driver_data = S2MPS14X },
+ { .name = "s2mps15-rtc", .driver_data = S2MPS15X },
+ { }
};
MODULE_DEVICE_TABLE(platform, s5m_rtc_id);
diff --git a/drivers/rtc/rtc-sd2405al.c b/drivers/rtc/rtc-sd2405al.c
index 708ea5d964de..7982a910a537 100644
--- a/drivers/rtc/rtc-sd2405al.c
+++ b/drivers/rtc/rtc-sd2405al.c
@@ -202,7 +202,7 @@ static int sd2405al_probe(struct i2c_client *client)
}
static const struct i2c_device_id sd2405al_id[] = {
- { "sd2405al" },
+ { .name = "sd2405al" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, sd2405al_id);
diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c
index 10cc1dcfc774..2c61f0e204a4 100644
--- a/drivers/rtc/rtc-sd3078.c
+++ b/drivers/rtc/rtc-sd3078.c
@@ -186,7 +186,7 @@ static int sd3078_probe(struct i2c_client *client)
}
static const struct i2c_device_id sd3078_id[] = {
- { "sd3078" },
+ { .name = "sd3078" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sd3078_id);
diff --git a/drivers/rtc/rtc-tps6594.c b/drivers/rtc/rtc-tps6594.c
index 7c6246e3f029..2cebd54c2dbf 100644
--- a/drivers/rtc/rtc-tps6594.c
+++ b/drivers/rtc/rtc-tps6594.c
@@ -485,8 +485,8 @@ static int tps6594_rtc_suspend(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_rtc_pm_ops, tps6594_rtc_suspend, tps6594_rtc_resume);
static const struct platform_device_id tps6594_rtc_id_table[] = {
- { "tps6594-rtc", },
- {}
+ { .name = "tps6594-rtc" },
+ { }
};
MODULE_DEVICE_TABLE(platform, tps6594_rtc_id_table);
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index b8a0fccef14e..bb1a5c86f621 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -663,7 +663,7 @@ static void x1205_remove(struct i2c_client *client)
}
static const struct i2c_device_id x1205_id[] = {
- { "x1205" },
+ { .name = "x1205" },
{ }
};
MODULE_DEVICE_TABLE(i2c, x1205_id);
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index f38a0f7d0f27..0490777fa406 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -1372,34 +1372,6 @@ int sdw_slave_get_current_bank(struct sdw_slave *slave)
}
EXPORT_SYMBOL_GPL(sdw_slave_get_current_bank);
-/**
- * sdw_slave_wait_for_init - Wait for device initialisation
- * @slave: Pointer to the SoundWire peripheral.
- * @timeout_ms: Timeout in milliseconds.
- *
- * Wait for a peripheral device to enumerate and be initialised by the
- * SoundWire core.
- *
- * Return: Zero on success, and a negative error code on failure.
- */
-int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms)
-{
- unsigned long time;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(timeout_ms));
- if (!time) {
- dev_err(&slave->dev, "Initialization not complete\n");
- sdw_show_ping_status(slave->bus, true);
- return -ETIMEDOUT;
- }
-
- slave->unattach_request = 0;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(sdw_slave_wait_for_init);
-
static int sdw_slave_set_frequency(struct sdw_slave *slave)
{
int scale_index;
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 4fc864d38cff..603e81a92c57 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -438,6 +438,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
{ .compatible = "amazon,alpine-dw-apb-ssi", .data = dw_spi_alpine_init},
{ .compatible = "renesas,rzn1-spi", .data = dw_spi_pssi_init},
{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_hssi_init},
+ { .compatible = "snps,dwc-ssi-2.00a", .data = dw_spi_hssi_init},
{ .compatible = "intel,keembay-ssi", .data = dw_spi_hssi_no_dma_init},
{
.compatible = "intel,mountevans-imc-ssi",
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 9cc79c566a70..2f2debc64e73 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -282,6 +282,7 @@ static inline void dw_spi_shutdown_chip(struct dw_spi *dws)
{
dw_spi_enable_chip(dws, 0);
dw_spi_set_clk(dws, 0);
+ dws->current_freq = 0;
}
extern void dw_spi_set_cs(struct spi_device *spi, bool enable);
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index ae9912905c67..79a6c1a60b0a 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -2152,7 +2152,8 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
if (spi_imx->usedma) {
ret = spi_imx_dma_transfer(spi_imx, transfer);
if (transfer->error & SPI_TRANS_FAIL_NO_START) {
- spi_imx->usedma = false;
+ controller->fallback = true;
+ spi_imx_setupxfer(spi, transfer);
if (spi_imx->target_mode)
return spi_imx_pio_transfer_target(spi, transfer);
else
diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index 1ef7bd91b3b3..b63c7856e758 100644
--- a/drivers/spi/spi-rpc-if.c
+++ b/drivers/spi/spi-rpc-if.c
@@ -206,8 +206,12 @@ static int rpcif_spi_suspend(struct device *dev)
static int rpcif_spi_resume(struct device *dev)
{
struct spi_controller *ctlr = dev_get_drvdata(dev);
+ struct rpcif *rpc = spi_controller_get_devdata(ctlr);
+ int ret;
- rpcif_hw_init(dev, false);
+ ret = rpcif_hw_init(rpc->dev, false);
+ if (ret)
+ return ret;
return spi_controller_resume(ctlr);
}
diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c
index cc20fd11f03f..86fce9a571da 100644
--- a/drivers/spi/spi-uniphier.c
+++ b/drivers/spi/spi-uniphier.c
@@ -656,6 +656,8 @@ static int uniphier_spi_probe(struct platform_device *pdev)
priv->host = host;
priv->is_save_param = false;
+ init_completion(&priv->xfer_done);
+
priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
@@ -679,8 +681,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
return ret;
}
- init_completion(&priv->xfer_done);
-
clk_rate = clk_get_rate(priv->clk);
host->max_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MIN_CLK_DIVIDER);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 76e3563c523f..f897789a44d1 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -355,12 +355,16 @@ EXPORT_SYMBOL_GPL(spi_get_device_id);
const void *spi_get_device_match_data(const struct spi_device *sdev)
{
const void *match;
+ const struct spi_device_id *id;
match = device_get_match_data(&sdev->dev);
if (match)
return match;
- return (const void *)spi_get_device_id(sdev)->driver_data;
+ id = spi_get_device_id(sdev);
+ if (!id)
+ return NULL;
+ return (const void *)id->driver_data;
}
EXPORT_SYMBOL_GPL(spi_get_device_match_data);
@@ -2975,12 +2979,12 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list,
acpi_spi_add_resource, &lookup);
- acpi_dev_free_resource_list(&resource_list);
-
if (ret < 0)
/* Found SPI in _CRS but it points to another controller */
return ERR_PTR(ret);
+ acpi_dev_free_resource_list(&resource_list);
+
if (!lookup.max_speed_hz &&
ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) &&
device_match_acpi_handle(lookup.ctlr->dev.parent, parent_handle)) {
diff --git a/drivers/thermal/intel/therm_throt.c b/drivers/thermal/intel/therm_throt.c
index 44fa4dd15dd1..45a8ef4a608b 100644
--- a/drivers/thermal/intel/therm_throt.c
+++ b/drivers/thermal/intel/therm_throt.c
@@ -529,8 +529,13 @@ static int thermal_throttle_online(unsigned int cpu)
{
struct thermal_state *state = &per_cpu(thermal_state, cpu);
struct device *dev = get_cpu_device(cpu);
+ int err;
u32 l;
+ err = thermal_throttle_add_dev(dev, cpu);
+ if (err)
+ return err;
+
state->package_throttle.level = PACKAGE_LEVEL;
state->core_throttle.level = CORE_LEVEL;
@@ -548,7 +553,7 @@ static int thermal_throttle_online(unsigned int cpu)
l = apic_read(APIC_LVTTHMR);
apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
- return thermal_throttle_add_dev(dev, cpu);
+ return err;
}
static int thermal_throttle_offline(unsigned int cpu)
diff --git a/drivers/thermal/testing/command.c b/drivers/thermal/testing/command.c
index fbf7ab9729b5..90e06c593327 100644
--- a/drivers/thermal/testing/command.c
+++ b/drivers/thermal/testing/command.c
@@ -86,7 +86,10 @@
#include "thermal_testing.h"
-struct dentry *d_testing;
+struct workqueue_struct *tt_wq __ro_after_init;
+
+struct dentry *d_testing __ro_after_init;
+static struct dentry *d_command __ro_after_init;
#define TT_COMMAND_SIZE 16
@@ -203,17 +206,42 @@ static const struct file_operations tt_command_fops = {
static int __init thermal_testing_init(void)
{
+ int error;
+
+ tt_wq = alloc_workqueue("thermal_testing", WQ_UNBOUND, 0);
+ if (!tt_wq)
+ return -ENOMEM;
+
d_testing = debugfs_create_dir("thermal-testing", NULL);
- if (!IS_ERR(d_testing))
- debugfs_create_file("command", 0200, d_testing, NULL,
- &tt_command_fops);
+ if (IS_ERR(d_testing)) {
+ error = PTR_ERR(d_testing);
+ goto destroy_wq;
+ }
+
+ d_command = debugfs_create_file("command", 0200, d_testing, NULL, &tt_command_fops);
+ if (IS_ERR(d_command)) {
+ error = PTR_ERR(d_command);
+ goto remove_d_testing;
+ }
return 0;
+
+remove_d_testing:
+ debugfs_remove(d_testing);
+destroy_wq:
+ destroy_workqueue(tt_wq);
+ return error;
}
module_init(thermal_testing_init);
static void __exit thermal_testing_exit(void)
{
+ /* First, prevent new commands from being entered. */
+ debugfs_remove(d_command);
+ /* Flush commands in progress (if any). */
+ flush_workqueue(tt_wq);
+ destroy_workqueue(tt_wq);
+ /* Remove the directory structure and clean up. */
debugfs_remove(d_testing);
tt_zone_cleanup();
}
diff --git a/drivers/thermal/testing/thermal_testing.h b/drivers/thermal/testing/thermal_testing.h
index c790a32aae4e..5880c9a63dba 100644
--- a/drivers/thermal/testing/thermal_testing.h
+++ b/drivers/thermal/testing/thermal_testing.h
@@ -1,4 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/workqueue.h>
+
+extern struct workqueue_struct *tt_wq;
+
+static inline void tt_queue_work(struct work_struct *work)
+{
+ queue_work(tt_wq, work);
+}
extern struct dentry *d_testing;
diff --git a/drivers/thermal/testing/zone.c b/drivers/thermal/testing/zone.c
index f7f9ca2f1f2c..6db26276dd41 100644
--- a/drivers/thermal/testing/zone.c
+++ b/drivers/thermal/testing/zone.c
@@ -13,7 +13,6 @@
#include <linux/idr.h>
#include <linux/list.h>
#include <linux/thermal.h>
-#include <linux/workqueue.h>
#include "thermal_testing.h"
@@ -207,7 +206,7 @@ int tt_add_tz(void)
INIT_WORK(&tt_work->work, tt_add_tz_work_fn);
tt_work->tt_zone = no_free_ptr(tt_zone);
- schedule_work(&(no_free_ptr(tt_work)->work));
+ tt_queue_work(&(no_free_ptr(tt_work)->work));
return 0;
}
@@ -269,7 +268,7 @@ int tt_del_tz(const char *arg)
INIT_WORK(&tt_work->work, tt_del_tz_work_fn);
tt_work->tt_zone = tt_zone;
- schedule_work(&(no_free_ptr(tt_work)->work));
+ tt_queue_work(&(no_free_ptr(tt_work)->work));
return 0;
}
@@ -358,7 +357,7 @@ int tt_zone_add_trip(const char *arg)
INIT_WORK(&tt_work->work, tt_zone_add_trip_work_fn);
tt_work->tt_zone = no_free_ptr(tt_zone);
tt_work->tt_trip = no_free_ptr(tt_trip);
- schedule_work(&(no_free_ptr(tt_work)->work));
+ tt_queue_work(&(no_free_ptr(tt_work)->work));
return 0;
}
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 9077d3b99357..9f5c4c101581 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -1273,6 +1273,7 @@ static void fbcon_deinit(struct vc_data *vc)
int idx;
fbcon_free_font(p);
+ p->mode = NULL;
idx = con2fb_map[vc->vc_num];
if (idx == -1)
@@ -1443,14 +1444,14 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
p = &fb_display[unit];
- if (var_to_display(p, var, info))
- return;
-
vc = vc_cons[unit].d;
if (!vc)
return;
+ if (var_to_display(p, var, info))
+ return;
+
default_mode = vc->vc_display_fg;
svc = *default_mode;
t = &fb_display[svc->vc_num];
@@ -2405,6 +2406,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
int resize, ret, old_width, old_height, old_charcount;
font_data_t *old_fontdata = p->fontdata;
const u8 *old_data = vc->vc_font.data;
+ unsigned short old_hi_font_mask = vc->vc_hi_font_mask;
font_data_get(data);
@@ -2451,6 +2453,12 @@ err_out:
vc->vc_font.height = old_height;
vc->vc_font.charcount = old_charcount;
+ /* Restore the hi_font state and screen buffer */
+ if (old_hi_font_mask && !vc->vc_hi_font_mask)
+ set_vc_hi_font(vc, true);
+ else if (!old_hi_font_mask && vc->vc_hi_font_mask)
+ set_vc_hi_font(vc, false);
+
font_data_put(data);
return ret;
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index e5221653ec2b..2f1c56e5a7a2 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -767,6 +767,18 @@ int fb_new_modelist(struct fb_info *info)
if (list_empty(&info->modelist))
return 1;
+ /*
+ * The new modelist may not contain the current mode (info->var), and
+ * fbcon_new_modelist() below only re-points consoles mapped to this
+ * framebuffer. Add the current mode here so info->var keeps a match
+ * even when fbcon is unbound.
+ */
+ if (!fb_match_mode(&info->var, &info->modelist)) {
+ fb_var_to_videomode(&mode, &info->var);
+ if (fb_add_videomode(&mode, &info->modelist))
+ return 1;
+ }
+
fbcon_new_modelist(info);
return 0;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index d9743ef35355..ea196603c7a8 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -10,6 +10,7 @@
#include <linux/major.h>
#include "fb_internal.h"
+#include "fbcon.h"
static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
{
@@ -108,8 +109,15 @@ static ssize_t store_modes(struct device *device,
if (fb_new_modelist(fb_info)) {
fb_destroy_modelist(&fb_info->modelist);
list_splice(&old_list, &fb_info->modelist);
- } else
+ } else {
+ /*
+ * fb_display[i].mode and fb_info->mode both point into the old
+ * list. Clear them before it is freed.
+ */
+ fbcon_delete_modelist(&old_list);
+ fb_info->mode = NULL;
fb_destroy_modelist(&old_list);
+ }
unlock_fb_info(fb_info);
console_unlock();
diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
index c9871281bc1d..e5d79886ea66 100644
--- a/drivers/video/fbdev/goldfishfb.c
+++ b/drivers/video/fbdev/goldfishfb.c
@@ -138,10 +138,12 @@ static int goldfish_fb_pan_display(struct fb_var_screeninfo *var,
writel(fb->fb.fix.smem_start + fb->fb.var.xres * 2 * var->yoffset,
fb->reg_base + FB_SET_BASE);
spin_unlock_irqrestore(&fb->lock, irq_flags);
- wait_event_timeout(fb->wait,
- fb->base_update_count != base_update_count, HZ / 15);
- if (fb->base_update_count == base_update_count)
+ if (!wait_event_timeout(fb->wait,
+ fb->base_update_count != base_update_count,
+ HZ / 15)) {
pr_err("%s: timeout waiting for base update\n", __func__);
+ return -ETIMEDOUT;
+ }
return 0;
}
@@ -251,7 +253,9 @@ static int goldfish_fb_probe(struct platform_device *pdev)
goto err_request_irq_failed;
writel(FB_INT_BASE_UPDATE_DONE, fb->reg_base + FB_INT_ENABLE);
- goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */
+ ret = goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */
+ if (ret)
+ goto err_pan_display_failed;
ret = register_framebuffer(&fb->fb);
if (ret)
@@ -259,6 +263,7 @@ static int goldfish_fb_probe(struct platform_device *pdev)
return 0;
err_register_framebuffer_failed:
+err_pan_display_failed:
free_irq(fb->irq, fb);
err_request_irq_failed:
err_fb_set_var_failed:
diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c
index 412ff249b5c7..058075a34c5d 100644
--- a/drivers/video/fbdev/pm2fb.c
+++ b/drivers/video/fbdev/pm2fb.c
@@ -1711,6 +1711,7 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_exit_both:
kfree(info->pixmap.addr);
err_exit_pixmap:
+ arch_phys_wc_del(default_par->wc_cookie);
iounmap(info->screen_base);
release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
err_exit_mmio:
diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c
index 22085d3668e8..cdd6b8de0ceb 100644
--- a/drivers/video/fbdev/vga16fb.c
+++ b/drivers/video/fbdev/vga16fb.c
@@ -1421,8 +1421,8 @@ static void vga16fb_remove(struct platform_device *dev)
}
static const struct platform_device_id vga16fb_driver_id_table[] = {
- {"ega-framebuffer", 0},
- {"vga-framebuffer", 0},
+ { .name = "ega-framebuffer" },
+ { .name = "vga-framebuffer" },
{ }
};
MODULE_DEVICE_TABLE(platform, vga16fb_driver_id_table);
diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c
index a8d4a3e2c65e..1632a669941a 100644
--- a/drivers/video/fbdev/via/via-core.c
+++ b/drivers/video/fbdev/via/via-core.c
@@ -234,6 +234,7 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
dma_addr_t descr_handle;
unsigned long flags;
int i;
+ int ret = 0;
struct scatterlist *sgentry;
dma_addr_t nextdesc;
@@ -290,8 +291,10 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
*/
wait_for_completion_timeout(&viafb_dma_completion, 1);
msleep(1);
- if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0)
+ if ((viafb_mmio_read(VDMA_CSR0) & VDMA_C_DONE) == 0) {
printk(KERN_ERR "VIA DMA timeout!\n");
+ ret = -ETIMEDOUT;
+ }
/*
* Clean up and we're done.
*/
@@ -301,7 +304,7 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
dma_free_coherent(&global_dev.pdev->dev,
nsg*sizeof(struct viafb_vx855_dma_descr), descrpages,
descr_handle);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
#endif /* CONFIG_VIDEO_VIA_CAMERA */