diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c index 4fc8f76918e4..1ab4a88e4fa0 100644 --- a/drivers/devfreq/arm-memlat-mon.c +++ b/drivers/devfreq/arm-memlat-mon.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2022, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "arm-memlat-mon: " fmt @@ -126,6 +126,7 @@ struct memlat_mon { * @mons: All of the memlat_mon structs representing * the different voters who share this cpu_grp. * @mons_lock: A lock used to protect the @mons. + * @init_mons_lock: A lock used to protect the @mons in probe routine. */ struct memlat_cpu_grp { cpumask_t cpus; @@ -143,6 +144,7 @@ struct memlat_cpu_grp { unsigned int num_active_mons; struct memlat_mon *mons; struct mutex mons_lock; + struct mutex init_mons_lock; spinlock_t mon_active_lock; }; @@ -517,11 +519,15 @@ static int memlat_event_hotplug_going_down(unsigned int cpu) return ret; } +/* + * Note: We must be holding cpus_read_lock() before calling this function + * since we are using cpuslocked version of function inside it + */ static int memlat_event_cpu_hp_init(void) { int ret = 0; - ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN, "MEMLAT_EVENT", memlat_event_hotplug_coming_up, memlat_event_hotplug_going_down); @@ -851,6 +857,7 @@ static int memlat_cpu_grp_probe(struct platform_device *pdev) return -ENOMEM; mutex_init(&cpu_grp->mons_lock); + mutex_init(&cpu_grp->init_mons_lock); spin_lock_init(&cpu_grp->mon_active_lock); cpu_grp->update_ms = DEFAULT_UPDATE_MS; @@ -886,7 +893,7 @@ static int memlat_mon_probe(struct platform_device *pdev, bool is_compute) return -ENODEV; } - mutex_lock(&cpu_grp->mons_lock); + mutex_lock(&cpu_grp->init_mons_lock); mon = &cpu_grp->mons[cpu_grp->num_inited_mons]; spin_lock_irqsave(&cpu_grp->mon_active_lock, flags); mon->is_active = false; @@ -1003,7 +1010,7 @@ static int memlat_mon_probe(struct platform_device *pdev, bool is_compute) cpu_grp->num_inited_mons++; unlock_out: - mutex_unlock(&cpu_grp->mons_lock); + mutex_unlock(&cpu_grp->init_mons_lock); return ret; } diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 88afaed2cb61..81709add4b0e 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -70,28 +70,28 @@ static struct devfreq *find_device_devfreq(struct device *dev) return ERR_PTR(-ENODEV); } -static unsigned long find_available_min_freq(struct devfreq *devfreq) +static long find_available_min_freq(struct devfreq *devfreq) { struct dev_pm_opp *opp; - unsigned long min_freq = 0; + long min_freq = 0; opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &min_freq); if (IS_ERR(opp)) - min_freq = 0; + min_freq = PTR_ERR(opp); else dev_pm_opp_put(opp); return min_freq; } -static unsigned long find_available_max_freq(struct devfreq *devfreq) +static long find_available_max_freq(struct devfreq *devfreq) { struct dev_pm_opp *opp; - unsigned long max_freq = ULONG_MAX; + long max_freq = LONG_MAX; opp = dev_pm_opp_find_freq_floor(devfreq->dev.parent, &max_freq); if (IS_ERR(opp)) - max_freq = 0; + max_freq = PTR_ERR(opp); else dev_pm_opp_put(opp); @@ -318,7 +318,7 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq, devfreq->previous_freq = new_freq; - if (devfreq->suspend_freq) + if (devfreq->suspend_freq >= devfreq->scaling_min_freq) devfreq->resume_freq = new_freq; return err; @@ -552,18 +552,23 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, { struct devfreq *devfreq = container_of(nb, struct devfreq, nb); int err = -EINVAL; + long freq; mutex_lock(&devfreq->lock); - devfreq->scaling_min_freq = find_available_min_freq(devfreq); - if (!devfreq->scaling_min_freq) + freq = find_available_min_freq(devfreq); + if (freq < 0) { + devfreq->scaling_min_freq = 0; goto out; + } + devfreq->scaling_min_freq = freq; - devfreq->scaling_max_freq = find_available_max_freq(devfreq); - if (!devfreq->scaling_max_freq) { + freq = find_available_max_freq(devfreq); + if (freq < 0) { devfreq->scaling_max_freq = ULONG_MAX; goto out; } + devfreq->scaling_max_freq = freq; err = update_devfreq(devfreq); @@ -616,6 +621,7 @@ struct devfreq *devfreq_add_device(struct device *dev, struct devfreq *devfreq; struct devfreq_governor *governor; int err = 0; + long freq; if (!dev || !profile || !governor_name) { dev_err(dev, "%s: Invalid parameters.\n", __func__); @@ -660,21 +666,21 @@ struct devfreq *devfreq_add_device(struct device *dev, mutex_lock(&devfreq->lock); } - devfreq->scaling_min_freq = find_available_min_freq(devfreq); - if (!devfreq->scaling_min_freq) { + freq = find_available_min_freq(devfreq); + if (freq < 0) { mutex_unlock(&devfreq->lock); err = -EINVAL; goto err_dev; } - devfreq->min_freq = devfreq->scaling_min_freq; + devfreq->min_freq = devfreq->scaling_min_freq = freq; - devfreq->scaling_max_freq = find_available_max_freq(devfreq); - if (!devfreq->scaling_max_freq) { + freq = find_available_max_freq(devfreq); + if (freq < 0) { mutex_unlock(&devfreq->lock); err = -EINVAL; goto err_dev; } - devfreq->max_freq = devfreq->scaling_max_freq; + devfreq->max_freq = devfreq->scaling_max_freq = freq; devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev); atomic_set(&devfreq->suspend_count, 0); @@ -906,7 +912,7 @@ int devfreq_suspend_device(struct devfreq *devfreq) return ret; } - if (devfreq->suspend_freq) { + if (devfreq->suspend_freq >= devfreq->scaling_min_freq) { mutex_lock(&devfreq->lock); ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0); mutex_unlock(&devfreq->lock); diff --git a/drivers/devfreq/governor_bw_hwmon.c b/drivers/devfreq/governor_bw_hwmon.c index 2acdb0a3fe5a..261b40843ff3 100644 --- a/drivers/devfreq/governor_bw_hwmon.c +++ b/drivers/devfreq/governor_bw_hwmon.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "bw-hwmon: " fmt @@ -80,6 +80,8 @@ static DEFINE_MUTEX(list_lock); static int use_cnt; static DEFINE_MUTEX(state_lock); +static DEFINE_MUTEX(event_handle_lock); + #define show_attr(name) \ static ssize_t name##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -865,7 +867,7 @@ static int devfreq_bw_hwmon_ev_handler(struct devfreq *df, struct hwmon_node *node; struct bw_hwmon *hw; - mutex_lock(&state_lock); + mutex_lock(&event_handle_lock); switch (event) { case DEVFREQ_GOV_START: @@ -939,7 +941,7 @@ static int devfreq_bw_hwmon_ev_handler(struct devfreq *df, } out: - mutex_unlock(&state_lock); + mutex_unlock(&event_handle_lock); return ret; } diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 3a898033c178..a37aa033ed98 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1743,6 +1743,12 @@ static int adreno_pm_suspend(struct device *dev) status = ops->pm_suspend(adreno_dev); mutex_unlock(&device->mutex); + if (status) + return status; + + kthread_flush_worker(device->events_worker); + flush_workqueue(kgsl_driver.mem_workqueue); + return status; } diff --git a/drivers/gpu/msm/adreno_a6xx_rpmh.c b/drivers/gpu/msm/adreno_a6xx_rpmh.c index 0594304d64ee..c7a4b3297e45 100644 --- a/drivers/gpu/msm/adreno_a6xx_rpmh.c +++ b/drivers/gpu/msm/adreno_a6xx_rpmh.c @@ -120,6 +120,7 @@ static void tcs_cmd_data(struct bcm *bcms, int count, u32 ab, u32 ib, u32 *data) { int i; + u64 total_width; for (i = 0; i < count; i++) { bool valid = true; @@ -145,8 +146,11 @@ static void tcs_cmd_data(struct bcm *bcms, int count, u32 ab, u32 ib, /* Multiple the bandwidth by the width of the connection */ avg = ((u64) ab) * bcms[i].width; + total_width = bcms[i].buswidth * bcms[i].channels; + /* And then divide by the total width across channels */ - do_div(avg, bcms[i].buswidth * bcms[i].channels); + if (total_width) + do_div(avg, (u32) total_width); peak = ((u64) ib) * bcms[i].width; do_div(peak, bcms[i].buswidth); diff --git a/drivers/gpu/msm/governor_gpubw_mon.c b/drivers/gpu/msm/governor_gpubw_mon.c index fabcd56b3776..af437abf107e 100644 --- a/drivers/gpu/msm/governor_gpubw_mon.c +++ b/drivers/gpu/msm/governor_gpubw_mon.c @@ -101,7 +101,7 @@ static int devfreq_gpubw_get_target(struct devfreq *df, int act_level; int norm_max_cycles; int norm_cycles; - int wait_active_percent; + int wait_active_percent = 0; int gpu_percent; /* * Normalized AB should at max usage be the gpu_bimc frequency in MHz. @@ -132,8 +132,9 @@ static int devfreq_gpubw_get_target(struct devfreq *df, (unsigned int) priv->bus.total_time; norm_cycles = (unsigned int)(priv->bus.ram_time + priv->bus.ram_wait) / (unsigned int) priv->bus.total_time; - wait_active_percent = (100 * (unsigned int)priv->bus.ram_wait) / - (unsigned int) priv->bus.ram_time; + if (priv->bus.ram_time) + wait_active_percent = (100 * (unsigned int)priv->bus.ram_wait) / + (unsigned int) priv->bus.ram_time; gpu_percent = (100 * (unsigned int)priv->bus.gpu_time) / (unsigned int) priv->bus.total_time; diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 0699fdadade3..328ea61b46a8 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -686,11 +686,11 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, if (id == -ENOSPC) { /* * Before declaring that there are no contexts left try - * flushing the event workqueue just in case there are + * flushing the event worker just in case there are * detached contexts waiting to finish */ - flush_workqueue(device->events_wq); + kthread_flush_worker(device->events_worker); id = _kgsl_get_context_id(device); } @@ -4526,15 +4526,16 @@ int kgsl_device_platform_probe(struct kgsl_device *device) device->pwrctrl.interrupt_num = status; disable_irq(device->pwrctrl.interrupt_num); - device->events_wq = alloc_workqueue("kgsl-events", - WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS | WQ_HIGHPRI, 0); + device->events_worker = kthread_create_worker(0, "kgsl-events"); - if (!device->events_wq) { - dev_err(device->dev, "Failed to allocate events workqueue\n"); - status = -ENOMEM; + if (IS_ERR(device->events_worker)) { + status = PTR_ERR(device->events_worker); + dev_err(device->dev, "Failed to create events worker ret=%d\n", status); goto error_pwrctrl_close; } + sched_set_fifo(device->events_worker->task); + /* This can return -EPROBE_DEFER */ status = kgsl_mmu_probe(device); if (status != 0) @@ -4559,10 +4560,8 @@ int kgsl_device_platform_probe(struct kgsl_device *device) return 0; error_pwrctrl_close: - if (device->events_wq) { - destroy_workqueue(device->events_wq); - device->events_wq = NULL; - } + if (!IS_ERR(device->events_worker)) + kthread_destroy_worker(device->events_worker); kgsl_pwrctrl_close(device); error: @@ -4572,10 +4571,7 @@ error: void kgsl_device_platform_remove(struct kgsl_device *device) { - if (device->events_wq) { - destroy_workqueue(device->events_wq); - device->events_wq = NULL; - } + kthread_destroy_worker(device->events_worker); kgsl_device_snapshot_close(device); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 4698aacf94cf..e86051f9aa57 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -295,7 +295,7 @@ typedef void (*kgsl_event_func)(struct kgsl_device *, struct kgsl_event_group *, * @priv: Private data passed to the callback function * @node: List node for the kgsl_event_group list * @created: Jiffies when the event was created - * @work: Work struct for dispatching the callback + * @work: kthread_work struct for dispatching the callback * @result: KGSL event result type to pass to the callback * group: The event group this event belongs to */ @@ -307,7 +307,7 @@ struct kgsl_event { void *priv; struct list_head node; unsigned int created; - struct work_struct work; + struct kthread_work work; int result; struct kgsl_event_group *group; }; diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 3d3cfdab5128..0b4a6c01d1d0 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __KGSL_DEVICE_H #define __KGSL_DEVICE_H @@ -293,7 +294,7 @@ struct kgsl_device { struct kgsl_pwrscale pwrscale; int reset_counter; /* Track how many GPU core resets have occurred */ - struct workqueue_struct *events_wq; + struct kthread_worker *events_worker; /* Number of active contexts seen globally for this device */ int active_context_count; diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c index 891c662ea339..674a3dc13e2c 100644 --- a/drivers/gpu/msm/kgsl_events.c +++ b/drivers/gpu/msm/kgsl_events.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -21,17 +22,17 @@ static inline void signal_event(struct kgsl_device *device, { list_del(&event->node); event->result = result; - queue_work(device->events_wq, &event->work); + kthread_queue_work(device->events_worker, &event->work); } /** * _kgsl_event_worker() - Work handler for processing GPU event callbacks - * @work: Pointer to the work_struct for the event + * @work: Pointer to the kthread_work for the event * - * Each event callback has its own work struct and is run on a event specific - * workqeuue. This is the worker that queues up the event callback function. + * Each event callback has its own kthread_work struct and is run on a event specific + * worker thread. This is the worker that queues up the event callback function. */ -static void _kgsl_event_worker(struct work_struct *work) +static void _kgsl_event_worker(struct kthread_work *work) { struct kgsl_event *event = container_of(work, struct kgsl_event, work); int id = KGSL_CONTEXT_ID(event->context); @@ -268,7 +269,7 @@ int kgsl_add_event(struct kgsl_device *device, struct kgsl_event_group *group, event->created = jiffies; event->group = group; - INIT_WORK(&event->work, _kgsl_event_worker); + kthread_init_work(&event->work, _kgsl_event_worker); trace_kgsl_register_event(KGSL_CONTEXT_ID(context), timestamp, func); @@ -283,7 +284,7 @@ int kgsl_add_event(struct kgsl_device *device, struct kgsl_event_group *group, if (timestamp_cmp(retired, timestamp) >= 0) { event->result = KGSL_EVENT_RETIRED; - queue_work(device->events_wq, &event->work); + kthread_queue_work(device->events_worker, &event->work); spin_unlock(&group->lock); return 0; } diff --git a/scripts/as-version.sh b/scripts/as-version.sh index 1a21495e9ff0..532270bd4b7e 100755 --- a/scripts/as-version.sh +++ b/scripts/as-version.sh @@ -51,12 +51,9 @@ set -- $(LC_ALL=C "$@" -Wa,--version -c -x assembler /dev/null -o /dev/null 2>/d IFS=' ' set -- $1 -min_tool_version=$(dirname $0)/min-tool-version.sh - if [ "$1" = GNU -a "$2" = assembler ]; then shift $(($# - 1)) version=$1 - min_version=$($min_tool_version binutils) name=GNU else echo "$orig_args: unknown assembler invoked" >&2 @@ -68,15 +65,5 @@ fi version=${version%-*} cversion=$(get_canonical_version $version) -min_cversion=$(get_canonical_version $min_version) - -if [ "$cversion" -lt "$min_cversion" ]; then - echo >&2 "***" - echo >&2 "*** Assembler is too old." - echo >&2 "*** Your $name assembler version: $version" - echo >&2 "*** Minimum $name assembler version: $min_version" - echo >&2 "***" - exit 1 -fi echo $name $cversion diff --git a/techpack/display/msm/dsi/dsi_display.c b/techpack/display/msm/dsi/dsi_display.c index 57b892d32810..51c6376b6a17 100644 --- a/techpack/display/msm/dsi/dsi_display.c +++ b/techpack/display/msm/dsi/dsi_display.c @@ -7836,8 +7836,10 @@ exit: rc = 0; error: - if (rc) + if (rc) { kfree(display->modes); + display->modes = NULL; + } mutex_unlock(&display->display_lock); return rc; diff --git a/techpack/display/msm/sde/sde_crtc.h b/techpack/display/msm/sde/sde_crtc.h index 75fb998ed06d..3a9e4b68eb0b 100644 --- a/techpack/display/msm/sde/sde_crtc.h +++ b/techpack/display/msm/sde/sde_crtc.h @@ -519,7 +519,8 @@ static inline int sde_crtc_get_mixer_width(struct sde_crtc *sde_crtc, if (cstate->num_ds_enabled) mixer_width = cstate->ds_cfg[0].lm_width; else - mixer_width = mode->hdisplay / sde_crtc->num_mixers; + mixer_width = sde_crtc->num_mixers ? + mode->hdisplay / sde_crtc->num_mixers : mode->hdisplay; return mixer_width; } diff --git a/techpack/display/rotator/sde_rotator_r3.c b/techpack/display/rotator/sde_rotator_r3.c index b1e2f15a4b84..f36c0ce6ce7c 100644 --- a/techpack/display/rotator/sde_rotator_r3.c +++ b/techpack/display/rotator/sde_rotator_r3.c @@ -1419,14 +1419,14 @@ static void sde_hw_rotator_vbif_rt_setting(void) for (j = 0; j < MAX_XIN; j++) { reg_high = ((mdata->vbif_xin_id[j] & 0x8) >> 3) * 4 + (i * 8); - reg_shift = mdata->vbif_xin_id[j] * 4; + reg_shift = (mdata->vbif_xin_id[j] & 0x7) * 4; reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_NRT_VBIF_QOS_RP_REMAP_000 + reg_high); reg_val_lvl = SDE_VBIF_READ(mdata, MMSS_VBIF_NRT_VBIF_QOS_LVL_REMAP_000 + reg_high); - mask = 0x7 << (mdata->vbif_xin_id[j] * 4); + mask = 0x7 << reg_shift; vbif_qos = mdata->vbif_nrt_qos[i];