void amdgpu_xcp_release_sched(struct amdgpu_device *adev,
struct amdgpu_ctx_entity *entity)
{
- struct drm_gpu_scheduler *sched =
- container_of(entity->entity.rq, typeof(*sched), rq);
+ struct amdgpu_xcp_mgr *xcp_mgr = adev->xcp_mgr;
+ struct drm_gpu_scheduler *sched;
- struct amdgpu_ring *ring;
- if (!adev->xcp_mgr)
+ if (!xcp_mgr)
return;
+ sched = entity->entity.rq->sched;
if (drm_sched_wqueue_ready(sched)) {
- ring = to_amdgpu_ring(entity->entity.rq->sched);
- atomic_dec(&adev->xcp_mgr->xcp[ring->xcp_id].ref_cnt);
+ struct amdgpu_ring *ring = to_amdgpu_ring(sched);
+
+ mutex_lock(&xcp_mgr->xcp_lock);
+ if (ring->xcp_id < xcp_mgr->num_xcps && xcp_mgr->xcp[ring->xcp_id].valid)
+ atomic_dec(&xcp_mgr->xcp[ring->xcp_id].ref_cnt);
+ mutex_unlock(&xcp_mgr->xcp_lock);
}
}
speed);
}
-static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
- uint32_t *current_power_limit,
- uint32_t *default_power_limit,
- uint32_t *max_power_limit,
- uint32_t *min_power_limit)
+static int smu_v14_0_2_get_ppt_limit(struct smu_context *smu,
+ enum smu_ppt_limit_type limit_type,
+ uint32_t *ppt_limit)
{
- struct smu_table_context *table_context = &smu->smu_table;
- struct smu_14_0_2_powerplay_table *powerplay_table =
- table_context->power_play_table;
- PPTable_t *pptable = table_context->driver_pptable;
- CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
- uint32_t pp_limit = smu->adev->pm.ac_power ?
- skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
- skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
- uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
- uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
- uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
- int16_t od_percent_upper = 0, od_percent_lower = 0;
+ OverDriveTableExternal_t od_table;
int ret;
- if (current_power_limit) {
- ret = smu_v14_0_get_current_power_limit(smu, current_power_limit);
- if (ret)
- *current_power_limit = pp_limit;
- }
+ if (limit_type != SMU_PPT_LIMIT_PPT0)
+ return -EOPNOTSUPP;
- if (default_power_limit)
- *default_power_limit = pp_limit;
-
- if (powerplay_table) {
- if (smu->od_enabled &&
- smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
- od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt;
- od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
- } else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
- od_percent_upper = 0;
- od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
- }
- }
+ ret = smu_v14_0_get_ppt_limit(smu, limit_type, ppt_limit);
+ if (ret)
+ return ret;
- dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
- od_percent_upper, od_percent_lower, pp_limit);
+ ret = smu_v14_0_2_get_overdrive_table(smu, &od_table);
+ if (ret)
+ return ret;
- if (max_power_limit) {
- *max_power_limit = max_limit * (100 + od_percent_upper);
- *max_power_limit /= 100;
- }
+ if (od_table.OverDriveTable.Ppt > 0)
+ *ppt_limit = *ppt_limit *
+ (100 + od_table.OverDriveTable.Ppt) / 100;
- if (min_power_limit) {
- *min_power_limit = min_limit * (100 + od_percent_lower);
- *min_power_limit /= 100;
- }
+ return 0;
+}
+
+static int smu_v14_0_2_init_ppt_limits(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_14_0_2_powerplay_table *powerplay_table =
+ table_context->power_play_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
+ int16_t od_percent_upper = 0, od_percent_lower = 0;
- uint32_t pp_limit, msg_limit, min_limit, max_limit;
- int i;
-
- if (powerplay_table &&
- smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
- od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt;
- od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
- }
-
- for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
- pp_limit = i == SMU_POWER_SOURCE_AC ?
- skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
- skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
- msg_limit = pptable->SkuTable.MsgLimits.Power
- [PPT_THROTTLER_PPT0][i];
- min_limit = min(pp_limit, msg_limit);
- max_limit = max(pp_limit, msg_limit);
-
- smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
- pp_limit;
- smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max = max_limit;
- smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min =
- min_limit * (100 + od_percent_lower) / 100;
- smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
- max_limit * (100 + od_percent_upper) / 100;
- smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min =
- smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min;
- }
-
- smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
++ uint32_t pp_limit, msg_limit, min_limit, max_limit;
++ int i;
++
++ if (powerplay_table &&
++ smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
++ od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt;
++ od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
++ }
++
++ for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT; i++) {
++ pp_limit = i == SMU_POWER_SOURCE_AC ?
++ skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
++ skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
++ msg_limit = pptable->SkuTable.MsgLimits.Power
++ [PPT_THROTTLER_PPT0][i];
++ min_limit = min(pp_limit, msg_limit);
++ max_limit = max(pp_limit, msg_limit);
++
++ smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].default_value =
++ pp_limit;
++ smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].max = max_limit;
++ smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min =
++ min_limit * (100 + od_percent_lower) / 100;
++ smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_max =
++ max_limit * (100 + od_percent_upper) / 100;
++ smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].od_min =
++ smu->ppt_limits.range[i][SMU_PPT_LIMIT_PPT0].min;
++ }
++
++ smu->ppt_limits.supported_mask |= BIT(SMU_PPT_LIMIT_PPT0);
return 0;
}
uint32_t *value)
{
struct smu_table_context *smu_table = &smu->smu_table;
+ SMU_15_0_0_MetricsInfo_t *metrics_info =
+ (SMU_15_0_0_MetricsInfo_t *)smu_table->metrics_table;
+ int ret;
- SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
- int ret = 0;
+ if (member >= ARRAY_SIZE(metrics_info->avg_metric))
+ return -EINVAL;
- ret = smu_v15_0_0_get_metrics_table(smu, NULL, false);
- if (ret)
+ ret = smu_v15_0_0_get_metrics_table(smu, metrics_info);
+ if (ret < 0)
return ret;
- if (ret == 0 &&
- metrics_info->metrics[metrics_info->active_idx].IOD.AccumulationCounter !=
- metrics_info->metrics[!metrics_info->active_idx].IOD.AccumulationCounter) {
- /* New sample: active_idx already points to the latest sample. */
- smu_v15_0_0_compute_all_metrics(metrics_info->avg_metric,
- &metrics_info->metrics[!metrics_info->active_idx],
- &metrics_info->metrics[metrics_info->active_idx]);
- switch (member) {
- case METRICS_AVERAGE_GFXCLK:
- *value = metrics->GfxclkFrequency;
- break;
- case METRICS_AVERAGE_SOCCLK:
- *value = metrics->SocclkFrequency;
- break;
- case METRICS_AVERAGE_VCLK:
- *value = metrics->VclkFrequency;
- break;
- case METRICS_AVERAGE_DCLK:
- *value = 0;
- break;
- case METRICS_AVERAGE_UCLK:
- *value = metrics->MemclkFrequency;
- break;
- case METRICS_AVERAGE_FCLK:
- *value = metrics->FclkFrequency;
- break;
- case METRICS_AVERAGE_VPECLK:
- *value = metrics->VpeclkFrequency;
- break;
- case METRICS_AVERAGE_NPUCLK:
- *value = metrics->NpuclkFrequency;
- break;
- case METRICS_AVERAGE_GFXACTIVITY:
- if ((smu->smc_fw_version > 0x5d4600))
- *value = metrics->GfxActivity;
- else
- *value = metrics->GfxActivity / 100;
- break;
- case METRICS_AVERAGE_VCNACTIVITY:
- *value = metrics->VcnActivity / 100;
- break;
- case METRICS_AVERAGE_SOCKETPOWER:
- case METRICS_CURR_SOCKETPOWER:
- *value = metrics->SocketPower;
- break;
- case METRICS_TEMPERATURE_EDGE:
- *value = metrics->GfxTemperature / 100 *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- break;
- case METRICS_TEMPERATURE_HOTSPOT:
- *value = metrics->SocTemperature / 100 *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
- break;
- case METRICS_THROTTLER_RESIDENCY_PROCHOT:
- *value = metrics->ThrottleResidency_PROCHOT;
- break;
- case METRICS_THROTTLER_RESIDENCY_SPL:
- *value = metrics->ThrottleResidency_SPL;
- break;
- case METRICS_THROTTLER_RESIDENCY_FPPT:
- *value = metrics->ThrottleResidency_FPPT;
- break;
- case METRICS_THROTTLER_RESIDENCY_SPPT:
- *value = metrics->ThrottleResidency_SPPT;
- break;
- case METRICS_THROTTLER_RESIDENCY_THM_SOC:
- *value = metrics->ThrottleResidency_THM_SOC;
- break;
- case METRICS_VOLTAGE_VDDGFX:
- *value = 0;
- break;
- case METRICS_VOLTAGE_VDDSOC:
- *value = 0;
- break;
- case METRICS_SS_APU_SHARE:
- /* return the percentage of APU power with respect to APU's power limit.
- * percentage is reported, this isn't boost value. Smartshift power
- * boost/shift is only when the percentage is more than 100.
- */
- if (metrics->StapmOpnLimit > 0)
- *value = (metrics->ApuPower * 100) / metrics->StapmOpnLimit;
- else
- *value = 0;
- break;
- case METRICS_SS_DGPU_SHARE:
- /* return the percentage of dGPU power with respect to dGPU's power limit.
- * percentage is reported, this isn't boost value. Smartshift power
- * boost/shift is only when the percentage is more than 100.
- */
- if ((metrics->dGpuPower > 0) &&
- (metrics->StapmCurrentLimit > metrics->StapmOpnLimit))
- *value = (metrics->dGpuPower * 100) /
- (metrics->StapmCurrentLimit - metrics->StapmOpnLimit);
- else
- *value = 0;
- break;
- default:
- *value = UINT_MAX;
- break;
-- }
++ if (ret == 0 &&
++ metrics_info->metrics[metrics_info->active_idx].IOD.AccumulationCounter !=
++ metrics_info->metrics[!metrics_info->active_idx].IOD.AccumulationCounter) {
++ /* New sample: active_idx already points to the latest sample. */
++ smu_v15_0_0_compute_all_metrics(metrics_info->avg_metric,
++ &metrics_info->metrics[!metrics_info->active_idx],
++ &metrics_info->metrics[metrics_info->active_idx]);
++ }
- return ret;
+ *value = metrics_info->avg_metric[member];
+
+ return 0;
}
static int smu_v15_0_0_read_sensor(struct smu_context *smu,
static const struct drm_bridge_funcs display_connector_bridge_funcs = {
.attach = display_connector_attach,
+ .destroy = display_connector_destroy,
.detect = display_connector_bridge_detect,
+ .hpd_enable = display_connector_hpd_enable,
+ .hpd_disable = display_connector_hpd_disable,
.edid_read = display_connector_edid_read,
.atomic_get_output_bus_fmts = display_connector_get_output_bus_fmts,
.atomic_get_input_bus_fmts = display_connector_get_input_bus_fmts,
const struct drm_sched_init_args sched_args = {
.ops = &pvr_queue_sched_ops,
.submit_wq = pvr_dev->sched_wq,
+ .num_rqs = 1,
.credit_limit = 64 * 1024,
.hang_limit = 1,
- .timeout = msecs_to_jiffies(500),
+ .timeout = msecs_to_jiffies(SCHED_TIMEOUT_PERIOD),
.timeout_wq = pvr_dev->sched_wq,
.name = "pvr-queue",
.dev = pvr_dev->base.dev,
struct task_struct *last_user;
long ret = timeout;
- if (!entity->rq)
- return 0;
-
+ sched = entity->rq->sched;
/*
* The client will not queue more jobs during this fini - consume
* existing queued ones, or discard them on SIGKILL.
sizeof(indirect_csd.wg_uniform_offsets));
info->indirect = drm_gem_object_lookup(file_priv, indirect_csd.indirect);
+ if (!info->indirect)
+ return -ENOENT;
- return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,
- &info->job, &info->clean_job,
- NULL, &info->acquire_ctx);
+ return 0;
}
/* Get data for the query timestamp job submission. */
{
iounmap(addr);
}
+ #endif /* CONFIG_HAS_IOMEM */
+__rust_helper void rust_helper_memcpy_fromio(void *dst,
+ const volatile void __iomem *src,
+ size_t count)
+{
+ memcpy_fromio(dst, src, count);
+}
+
+__rust_helper void rust_helper_memcpy_toio(volatile void __iomem *dst,
+ const void *src, size_t count)
+{
+ memcpy_toio(dst, src, count);
+}
+
__rust_helper u8 rust_helper_readb(const void __iomem *addr)
{
return readb(addr);
//!
//! C header: [`include/asm-generic/io.h`](srctree/include/asm-generic/io.h)
+use core::{
+ marker::PhantomData,
+ mem::MaybeUninit, //
+};
+
use crate::{
bindings,
- prelude::*, //
+ prelude::*,
+ ptr::{
+ Alignment,
+ KnownSize, //
+ }, //
};
+ #[cfg(CONFIG_HAS_IOMEM)]
pub mod mem;
pub mod poll;
pub mod register;