drivers/gpu/drm/imagination/pvr_power.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/imagination/pvr_power.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/imagination/pvr_power.c- Extension
.c- Size
- 16883 bytes
- Lines
- 727
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
pvr_device.hpvr_fw.hpvr_fw_startstop.hpvr_power.hpvr_queue.hpvr_rogue_fwif.hdrm/drm_drv.hdrm/drm_managed.hdrm/drm_print.hlinux/cleanup.hlinux/clk.hlinux/interrupt.hlinux/mutex.hlinux/of.hlinux/platform_device.hlinux/pm_domain.hlinux/pm_runtime.hlinux/pwrseq/consumer.hlinux/reset.hlinux/timer.hlinux/types.hlinux/workqueue.h
Detected Declarations
function pvr_device_lostfunction pvr_power_send_commandfunction pvr_power_request_idlefunction pvr_power_request_pwr_offfunction pvr_power_fw_disablefunction pvr_power_fw_enablefunction pvr_power_is_idlefunction pvr_watchdog_kccb_stalledfunction pvr_watchdog_workerfunction pvr_watchdog_initfunction pvr_power_init_manualfunction pvr_power_on_sequence_manualfunction pvr_power_off_sequence_manualfunction pvr_power_init_pwrseqfunction pvr_power_on_sequence_pwrseqfunction pvr_power_off_sequence_pwrseqfunction pvr_power_device_suspendfunction pvr_power_device_resumefunction pvr_power_device_idlefunction pvr_power_clear_errorfunction pvr_power_get_clearfunction pvr_power_resetfunction pvr_watchdog_finifunction pvr_power_domains_initfunction pvr_power_domains_fini
Annotated Snippet
if (pvr_dev->watchdog.kccb_stall_count == 2) {
pvr_dev->watchdog.kccb_stall_count = 0;
return true;
}
} else if (pvr_dev->watchdog.old_kccb_cmds_executed == kccb_cmds_executed) {
bool has_active_contexts;
mutex_lock(&pvr_dev->queues.lock);
has_active_contexts = list_empty(&pvr_dev->queues.active);
mutex_unlock(&pvr_dev->queues.lock);
if (has_active_contexts) {
/* Send a HEALTH_CHECK command so we can verify FW is still alive. */
struct rogue_fwif_kccb_cmd health_check_cmd;
health_check_cmd.cmd_type = ROGUE_FWIF_KCCB_CMD_HEALTH_CHECK;
pvr_kccb_send_cmd_powered(pvr_dev, &health_check_cmd, NULL);
}
} else {
pvr_dev->watchdog.old_kccb_cmds_executed = kccb_cmds_executed;
pvr_dev->watchdog.kccb_stall_count = 0;
}
return false;
}
static void
pvr_watchdog_worker(struct work_struct *work)
{
struct pvr_device *pvr_dev = container_of(work, struct pvr_device,
watchdog.work.work);
bool stalled;
if (pvr_dev->lost)
return;
if (pm_runtime_get_if_in_use(from_pvr_device(pvr_dev)->dev) <= 0)
goto out_requeue;
if (!READ_ONCE(pvr_dev->fw_dev.initialised))
goto out_pm_runtime_put;
stalled = pvr_watchdog_kccb_stalled(pvr_dev);
if (stalled) {
drm_err(from_pvr_device(pvr_dev), "FW stalled, trying hard reset");
pvr_power_reset(pvr_dev, true);
/* Device may be lost at this point. */
}
out_pm_runtime_put:
pm_runtime_put(from_pvr_device(pvr_dev)->dev);
out_requeue:
if (!pvr_dev->lost) {
queue_delayed_work(pvr_dev->sched_wq, &pvr_dev->watchdog.work,
msecs_to_jiffies(WATCHDOG_TIME_MS));
}
}
/**
* pvr_watchdog_init() - Initialise watchdog for device
* @pvr_dev: Target PowerVR device.
*
* Returns:
* * 0 on success, or
* * -%ENOMEM on out of memory.
*/
int
pvr_watchdog_init(struct pvr_device *pvr_dev)
{
INIT_DELAYED_WORK(&pvr_dev->watchdog.work, pvr_watchdog_worker);
return 0;
}
static int pvr_power_init_manual(struct pvr_device *pvr_dev)
{
struct drm_device *drm_dev = from_pvr_device(pvr_dev);
struct reset_control *reset;
reset = devm_reset_control_get_optional_exclusive(drm_dev->dev, NULL);
if (IS_ERR(reset))
return dev_err_probe(drm_dev->dev, PTR_ERR(reset),
"failed to get gpu reset line\n");
pvr_dev->reset = reset;
Annotation
- Immediate include surface: `pvr_device.h`, `pvr_fw.h`, `pvr_fw_startstop.h`, `pvr_power.h`, `pvr_queue.h`, `pvr_rogue_fwif.h`, `drm/drm_drv.h`, `drm/drm_managed.h`.
- Detected declarations: `function pvr_device_lost`, `function pvr_power_send_command`, `function pvr_power_request_idle`, `function pvr_power_request_pwr_off`, `function pvr_power_fw_disable`, `function pvr_power_fw_enable`, `function pvr_power_is_idle`, `function pvr_watchdog_kccb_stalled`, `function pvr_watchdog_worker`, `function pvr_watchdog_init`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.