Merge pull request #819 from kwilczynski/feature/update-kernel-releases
Update Linux kernel release to v7.2.8-2 for base and BORE kernels
This commit is contained in:
524 files changed
+147294
-88760
No files matched your search
@@ -1,5 +1,4 @@
|
||||
diff --git a/kernel/fork.c b/kernel/fork.c
|
||||
index f0e2e131a9a5..7b611da9a27a 100644
|
||||
--- a/kernel/fork.c
|
||||
+++ b/kernel/fork.c
|
||||
@@ -127,6 +127,12 @@
|
||||
@@ -15,7 +14,7 @@ index f0e2e131a9a5..7b611da9a27a 100644
|
||||
/*
|
||||
* Minimum number of threads to boot the kernel
|
||||
*/
|
||||
@@ -2093,6 +2099,11 @@ __latent_entropy struct task_struct *copy_process(
|
||||
@@ -2092,6 +2098,11 @@ __latent_entropy struct task_struct *copy_process(
|
||||
return ERR_PTR(-EPERM);
|
||||
}
|
||||
|
||||
@@ -27,7 +26,7 @@ index f0e2e131a9a5..7b611da9a27a 100644
|
||||
/*
|
||||
* Force any signals received before this point to be delivered
|
||||
* before the fork happens. Collect up signals sent to multiple
|
||||
@@ -3163,6 +3174,10 @@ static int check_unshare_flags(unsigned long unshare_flags)
|
||||
@@ -3165,6 +3176,10 @@ static int check_unshare_flags(unsigned long unshare_flags)
|
||||
if (!current_is_single_threaded())
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -38,7 +37,7 @@ index f0e2e131a9a5..7b611da9a27a 100644
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3398,6 +3413,15 @@ static const struct ctl_table fork_sysctl_table[] = {
|
||||
@@ -3400,6 +3415,15 @@ static const struct ctl_table fork_sysctl_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = sysctl_max_threads,
|
||||
},
|
||||
|
||||
Binary file not shown.
@@ -177,7 +177,7 @@ diff --git a/kernel/fork.c b/kernel/fork.c
|
||||
#include <trace/events/sched.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
@@ -2441,6 +2445,11 @@ __latent_entropy struct task_struct *copy_process(
|
||||
@@ -2443,6 +2447,11 @@ __latent_entropy struct task_struct *copy_process(
|
||||
p->start_time = ktime_get_ns();
|
||||
p->start_boottime = ktime_get_boottime_ns();
|
||||
|
||||
@@ -189,7 +189,7 @@ diff --git a/kernel/fork.c b/kernel/fork.c
|
||||
/*
|
||||
* Make it visible to the rest of the system, but dont wake it up yet.
|
||||
* Need tasklist lock for parent etc handling!
|
||||
@@ -2526,7 +2535,11 @@ __latent_entropy struct task_struct *copy_process(
|
||||
@@ -2528,7 +2537,11 @@ __latent_entropy struct task_struct *copy_process(
|
||||
p->real_parent->signal->is_child_subreaper;
|
||||
if (clone_flags & CLONE_AUTOREAP)
|
||||
p->signal->autoreap = 1;
|
||||
@@ -749,7 +749,7 @@ diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
struct load_weight lw;
|
||||
|
||||
if (task_has_idle_policy(p)) {
|
||||
@@ -8975,6 +8983,10 @@ void __init sched_init(void)
|
||||
@@ -8989,6 +8997,10 @@ void __init sched_init(void)
|
||||
BUG_ON(!sched_class_above(&ext_sched_class, &idle_sched_class));
|
||||
#endif
|
||||
|
||||
@@ -934,7 +934,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
|
||||
void __init sched_init_granularity(void)
|
||||
{
|
||||
@@ -1083,7 +1108,11 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
|
||||
@@ -1093,7 +1118,11 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
|
||||
*/
|
||||
static inline void set_protect_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)
|
||||
{
|
||||
@@ -946,7 +946,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
u64 vprot = se->deadline;
|
||||
|
||||
if (sched_feat(RUN_TO_PARITY))
|
||||
@@ -1160,8 +1189,17 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq, bool protect)
|
||||
@@ -1170,8 +1199,17 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq, bool protect)
|
||||
if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr)))
|
||||
curr = NULL;
|
||||
|
||||
@@ -966,7 +966,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
|
||||
/* Pick the leftmost entity if it's eligible */
|
||||
if (se && entity_eligible(cfs_rq, se)) {
|
||||
@@ -1217,6 +1255,7 @@ struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
|
||||
@@ -1227,6 +1265,7 @@ struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
|
||||
/**************************************************************
|
||||
* Scheduling class statistics methods:
|
||||
*/
|
||||
@@ -974,7 +974,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
int sched_update_scaling(void)
|
||||
{
|
||||
unsigned int factor = get_update_sysctl_factor();
|
||||
@@ -1228,6 +1267,7 @@ int sched_update_scaling(void)
|
||||
@@ -1238,6 +1277,7 @@ int sched_update_scaling(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -982,7 +982,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
|
||||
static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se);
|
||||
|
||||
@@ -1971,6 +2011,38 @@ static void account_llc_dequeue(struct rq *rq, struct task_struct *p) {}
|
||||
@@ -1979,6 +2019,38 @@ static void account_llc_dequeue(struct rq *rq, struct task_struct *p) {}
|
||||
|
||||
#endif /* CONFIG_SCHED_CACHE */
|
||||
|
||||
@@ -1021,7 +1021,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
/*
|
||||
* Used by other classes to account runtime.
|
||||
*/
|
||||
@@ -2006,6 +2078,11 @@ static void update_curr(struct cfs_rq *cfs_rq)
|
||||
@@ -2014,6 +2086,11 @@ static void update_curr(struct cfs_rq *cfs_rq)
|
||||
resched = update_deadline(cfs_rq, curr);
|
||||
|
||||
if (entity_is_task(curr)) {
|
||||
@@ -1033,7 +1033,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
/*
|
||||
* If the fair_server is active, we need to account for the
|
||||
* fair_server time whether or not the task is running on
|
||||
@@ -4663,8 +4740,8 @@ rescale_entity(struct sched_entity *se, unsigned long weight, bool rel_vprot)
|
||||
@@ -4671,8 +4748,8 @@ rescale_entity(struct sched_entity *se, unsigned long weight, bool rel_vprot)
|
||||
se->vprot = div64_long(se->vprot * old_weight, weight);
|
||||
}
|
||||
|
||||
@@ -1044,7 +1044,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
{
|
||||
bool curr = cfs_rq->curr == se;
|
||||
bool rel_vprot = false;
|
||||
@@ -5967,13 +6044,12 @@ void __setparam_fair(struct task_struct *p, const struct sched_attr *attr)
|
||||
@@ -5976,13 +6053,12 @@ void __setparam_fair(struct task_struct *p, const struct sched_attr *attr)
|
||||
static void
|
||||
place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
|
||||
{
|
||||
@@ -1059,7 +1059,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
|
||||
/*
|
||||
* Due to how V is constructed as the weighted average of entities,
|
||||
@@ -6085,7 +6161,18 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
|
||||
@@ -6094,7 +6170,18 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
|
||||
se->rel_deadline = 0;
|
||||
return;
|
||||
}
|
||||
@@ -1079,7 +1079,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
/*
|
||||
* When joining the competition; the existing tasks will be,
|
||||
* on average, halfway through their slice, as such start tasks
|
||||
@@ -6094,6 +6181,9 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
|
||||
@@ -6103,6 +6190,9 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
|
||||
if (sched_feat(PLACE_DEADLINE_INITIAL) && (flags & ENQUEUE_INITIAL))
|
||||
vslice /= 2;
|
||||
|
||||
@@ -1089,7 +1089,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
/*
|
||||
* EEVDF: vd_i = ve_i + r_i/w_i
|
||||
*/
|
||||
@@ -6104,7 +6194,7 @@ static void check_enqueue_throttle(struct cfs_rq *cfs_rq);
|
||||
@@ -6113,7 +6203,7 @@ static void check_enqueue_throttle(struct cfs_rq *cfs_rq);
|
||||
static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq);
|
||||
|
||||
static void
|
||||
@@ -1098,7 +1098,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
|
||||
static void
|
||||
enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
|
||||
@@ -7767,7 +7857,7 @@ static int choose_idle_cpu(int cpu, struct task_struct *p)
|
||||
@@ -7776,7 +7866,7 @@ static int choose_idle_cpu(int cpu, struct task_struct *p)
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1107,7 +1107,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
{
|
||||
struct cfs_rq *cfs_rq = cfs_rq_of(se);
|
||||
|
||||
@@ -7785,7 +7875,13 @@ requeue_delayed_entity(struct sched_entity *se)
|
||||
@@ -7794,7 +7884,13 @@ requeue_delayed_entity(struct sched_entity *se)
|
||||
cfs_rq->nr_queued--;
|
||||
if (se != cfs_rq->curr)
|
||||
__dequeue_entity(cfs_rq, se);
|
||||
@@ -1122,7 +1122,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
if (se != cfs_rq->curr)
|
||||
__enqueue_entity(cfs_rq, se);
|
||||
cfs_rq->nr_queued++;
|
||||
@@ -7824,7 +7920,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
||||
@@ -7833,7 +7929,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
||||
util_est_enqueue(&rq->cfs, p);
|
||||
|
||||
if (flags & ENQUEUE_DELAYED) {
|
||||
@@ -1131,7 +1131,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7842,7 +7938,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
||||
@@ -7851,7 +7947,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
||||
for_each_sched_entity(se) {
|
||||
if (se->on_rq) {
|
||||
if (se->sched_delayed)
|
||||
@@ -1140,7 +1140,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
break;
|
||||
}
|
||||
cfs_rq = cfs_rq_of(se);
|
||||
@@ -8045,6 +8141,15 @@ static bool dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
||||
@@ -8054,6 +8150,15 @@ static bool dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
||||
if (!p->se.sched_delayed)
|
||||
util_est_dequeue(&rq->cfs, p);
|
||||
|
||||
@@ -1156,7 +1156,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
if (dequeue_entities(rq, &p->se, flags) < 0)
|
||||
return false;
|
||||
|
||||
@@ -9850,6 +9955,18 @@ static void wakeup_preempt_fair(struct rq *rq, struct task_struct *p, int wake_f
|
||||
@@ -9860,6 +9965,18 @@ static void wakeup_preempt_fair(struct rq *rq, struct task_struct *p, int wake_f
|
||||
goto pick;
|
||||
}
|
||||
|
||||
@@ -1175,7 +1175,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
/*
|
||||
* Ignore wakee preemption on WF_FORK as it is less likely that
|
||||
* there is shared data as exec often follow fork. Do not
|
||||
@@ -10020,16 +10137,25 @@ static void yield_task_fair(struct rq *rq)
|
||||
@@ -10030,16 +10147,25 @@ static void yield_task_fair(struct rq *rq)
|
||||
/*
|
||||
* Are we the only task in the tree?
|
||||
*/
|
||||
@@ -1201,7 +1201,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
/*
|
||||
* Tell update_rq_clock() that we've just updated,
|
||||
* so we don't do microscopic update in schedule()
|
||||
@@ -15010,6 +15136,9 @@ static void switched_to_fair(struct rq *rq, struct task_struct *p)
|
||||
@@ -15022,6 +15148,9 @@ static void switched_to_fair(struct rq *rq, struct task_struct *p)
|
||||
WARN_ON_ONCE(p->se.sched_delayed);
|
||||
|
||||
attach_task_cfs_rq(p);
|
||||
|
||||
Binary file not shown.
@@ -22,19 +22,6 @@ diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable
|
||||
typedef struct page *pgtable_t;
|
||||
|
||||
extern pteval_t __supported_pte_mask;
|
||||
diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h
|
||||
--- a/arch/x86/include/asm/pkeys.h
|
||||
+++ b/arch/x86/include/asm/pkeys.h
|
||||
@@ -88,6 +88,9 @@ int mm_pkey_alloc(struct mm_struct *mm)
|
||||
u16 all_pkeys_mask = ((1U << arch_max_pkey()) - 1);
|
||||
int ret;
|
||||
|
||||
+ if (!arch_pkeys_enabled())
|
||||
+ return -1;
|
||||
+
|
||||
/*
|
||||
* Are we out of pkeys? We must handle this specially
|
||||
* because ffz() behavior is undefined if there are no
|
||||
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
|
||||
--- a/arch/x86/include/asm/tlbflush.h
|
||||
+++ b/arch/x86/include/asm/tlbflush.h
|
||||
@@ -168,35 +155,7 @@ diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
|
||||
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
--- a/arch/x86/mm/pat/set_memory.c
|
||||
+++ b/arch/x86/mm/pat/set_memory.c
|
||||
@@ -62,18 +62,18 @@ enum cpa_warn {
|
||||
static const int cpa_warn_level = CPA_PROTECT;
|
||||
|
||||
/*
|
||||
- * Serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings)
|
||||
- * using cpa_lock. So that we don't allow any other cpu, with stale large tlb
|
||||
- * entries change the page attribute in parallel to some other cpu
|
||||
- * splitting a large page entry along with changing the attribute.
|
||||
+ * Serialize cpa() using cpa_lock so that we don't allow any other cpu, with
|
||||
+ * stale large tlb entries, to change the page attribute in parallel to some
|
||||
+ * other cpu splitting a large page entry along with changing the attribute.
|
||||
*/
|
||||
static DEFINE_SPINLOCK(cpa_lock);
|
||||
|
||||
-#define CPA_FLUSHTLB 1
|
||||
-#define CPA_ARRAY 2
|
||||
-#define CPA_PAGES_ARRAY 4
|
||||
-#define CPA_NO_CHECK_ALIAS 8 /* Do not search for aliases */
|
||||
-#define CPA_COLLAPSE 16 /* try to collapse large pages */
|
||||
+#define CPA_FLUSHTLB 0x01
|
||||
+#define CPA_ARRAY 0x02
|
||||
+#define CPA_PAGES_ARRAY 0x04
|
||||
+#define CPA_NO_CHECK_ALIAS 0x08 /* Do not search for aliases */
|
||||
+#define CPA_COLLAPSE 0x10 /* try to collapse large pages */
|
||||
+#define CPA_DEBUG_PAGEALLOC 0x20
|
||||
|
||||
static inline pgprot_t cachemode2pgprot(enum page_cache_mode pcm)
|
||||
{
|
||||
@@ -86,9 +86,8 @@ static unsigned long direct_pages_count[PG_LEVEL_NUM];
|
||||
@@ -88,9 +88,8 @@ static unsigned long direct_pages_count[PG_LEVEL_NUM];
|
||||
void update_page_count(int level, unsigned long pages)
|
||||
{
|
||||
/* Protect against CPA */
|
||||
@@ -207,16 +166,37 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
}
|
||||
|
||||
static void split_page_count(int level)
|
||||
@@ -418,6 +417,8 @@ static void cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
@@ -420,7 +419,7 @@ static void __cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
int collapsed = 0;
|
||||
int i;
|
||||
|
||||
- spin_lock(&cpa_lock);
|
||||
+ guard(spinlock)(&cpa_lock);
|
||||
+
|
||||
|
||||
if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
|
||||
for (i = 0; i < cpa->numpages; i++)
|
||||
collapsed += collapse_large_pages(__cpa_addr(cpa, i),
|
||||
@@ -888,24 +889,23 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
|
||||
@@ -435,10 +434,8 @@ static void __cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
collapsed += collapse_large_pages(addr, &pgtables);
|
||||
}
|
||||
|
||||
- if (!collapsed) {
|
||||
- spin_unlock(&cpa_lock);
|
||||
+ if (!collapsed)
|
||||
return;
|
||||
- }
|
||||
|
||||
flush_tlb_all();
|
||||
|
||||
@@ -454,8 +451,6 @@ static void __cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
else
|
||||
pagetable_free(ptdesc);
|
||||
}
|
||||
-
|
||||
- spin_unlock(&cpa_lock);
|
||||
}
|
||||
|
||||
static void cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
@@ -916,24 +911,23 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
|
||||
{
|
||||
/* change init_mm */
|
||||
set_pte_atomic(kpte, pte);
|
||||
@@ -246,7 +226,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
}
|
||||
|
||||
static pgprot_t pgprot_clear_protnone_bits(pgprot_t prot)
|
||||
@@ -1075,16 +1075,11 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
|
||||
@@ -1103,16 +1097,11 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
|
||||
static int should_split_large_page(pte_t *kpte, unsigned long address,
|
||||
struct cpa_data *cpa)
|
||||
{
|
||||
@@ -265,7 +245,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
}
|
||||
|
||||
static void split_set_pte(struct cpa_data *cpa, pte_t *pte, unsigned long pfn,
|
||||
@@ -1135,16 +1130,14 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
@@ -1162,16 +1151,14 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
bool nx, rw;
|
||||
pte_t *tmp;
|
||||
|
||||
@@ -284,7 +264,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
|
||||
paravirt_alloc_pte(&init_mm, page_to_pfn(base));
|
||||
|
||||
@@ -1177,7 +1170,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
@@ -1204,7 +1191,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -292,7 +272,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1225,7 +1217,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
@@ -1252,7 +1238,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
* just split large page entry.
|
||||
*/
|
||||
flush_tlb_all();
|
||||
@@ -300,21 +280,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1235,11 +1226,9 @@ static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
|
||||
{
|
||||
struct ptdesc *ptdesc;
|
||||
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_unlock(&cpa_lock);
|
||||
+ spin_unlock(&cpa_lock);
|
||||
ptdesc = pagetable_alloc(GFP_KERNEL, 0);
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_lock(&cpa_lock);
|
||||
+ spin_lock(&cpa_lock);
|
||||
if (!ptdesc)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1298,11 +1287,11 @@ static int collapse_pmd_page(pmd_t *pmd, unsigned long addr,
|
||||
@@ -1327,11 +1312,11 @@ static int collapse_pmd_page(pmd_t *pmd, unsigned long addr,
|
||||
list_add(&page_ptdesc(pmd_page(old_pmd))->pt_list, pgtables);
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_32)) {
|
||||
@@ -329,7 +295,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
p4d_t *p4d = p4d_offset(pgd, addr);
|
||||
pud_t *pud = pud_offset(p4d, addr);
|
||||
pmd_t *pmd = pmd_offset(pud, addr);
|
||||
@@ -1376,7 +1365,7 @@ static int collapse_pud_page(pud_t *pud, unsigned long addr,
|
||||
@@ -1405,7 +1390,7 @@ static int collapse_pud_page(pud_t *pud, unsigned long addr,
|
||||
*/
|
||||
static int collapse_large_pages(unsigned long addr, struct list_head *pgtables)
|
||||
{
|
||||
@@ -338,7 +304,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
pgd_t *pgd;
|
||||
p4d_t *p4d;
|
||||
pud_t *pud;
|
||||
@@ -1384,26 +1373,24 @@ static int collapse_large_pages(unsigned long addr, struct list_head *pgtables)
|
||||
@@ -1413,26 +1398,24 @@ static int collapse_large_pages(unsigned long addr, struct list_head *pgtables)
|
||||
|
||||
addr &= PMD_MASK;
|
||||
|
||||
@@ -370,153 +336,6 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
return collapsed;
|
||||
}
|
||||
|
||||
@@ -2004,6 +1991,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int primary)
|
||||
{
|
||||
unsigned long numpages = cpa->numpages;
|
||||
unsigned long rempages = numpages;
|
||||
+ bool lock = true;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
@@ -2013,6 +2001,29 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int primary)
|
||||
!cpa->force_split)
|
||||
return ret;
|
||||
|
||||
+ /*
|
||||
+ * DEBUG_PAGEALLOC is special; it is called from any context the
|
||||
+ * page-allocator is, which violates the normal cpa_lock locking
|
||||
+ * rules.
|
||||
+ *
|
||||
+ * However, since it is part of the page-allocator, things are still
|
||||
+ * properly serialized by the page-allocator locking and the fact that
|
||||
+ * when a page is owned by the page-allocator, it isn't owned by
|
||||
+ * anybody else. That is, you *SHOULD NOT* be calling cpa() on memory
|
||||
+ * that isn't allocated.
|
||||
+ *
|
||||
+ * Additionally, DEBUG_PAGEALLOC ensures (per probe_page_size_mask())
|
||||
+ * that the kernel mapping is 4k pages, therefore there are no large
|
||||
+ * pages to split/collapse.
|
||||
+ *
|
||||
+ * Furthermore, the page-allocator strictly manages pages that
|
||||
+ * *exist*, avoiding pgd_lock.
|
||||
+ *
|
||||
+ * Therefore, it is safe to not take cpa_lock.
|
||||
+ */
|
||||
+ if (debug_pagealloc_enabled() && (cpa->flags & CPA_DEBUG_PAGEALLOC))
|
||||
+ lock = false;
|
||||
+
|
||||
while (rempages) {
|
||||
/*
|
||||
* Store the remaining nr of pages for the large page
|
||||
@@ -2023,11 +2034,12 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int primary)
|
||||
if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY))
|
||||
cpa->numpages = 1;
|
||||
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_lock(&cpa_lock);
|
||||
- ret = __change_page_attr(cpa, primary);
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_unlock(&cpa_lock);
|
||||
+ if (lock) {
|
||||
+ guard(spinlock)(&cpa_lock);
|
||||
+ ret = __change_page_attr(cpa, primary);
|
||||
+ } else {
|
||||
+ ret = __change_page_attr(cpa, primary);
|
||||
+ }
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -2606,7 +2618,7 @@ int set_pages_rw(struct page *page, int numpages)
|
||||
return set_memory_rw(addr, numpages);
|
||||
}
|
||||
|
||||
-static int __set_pages_p(struct page *page, int numpages)
|
||||
+static int __set_pages_p(struct page *page, int numpages, unsigned int cpa_flags)
|
||||
{
|
||||
unsigned long tempaddr = (unsigned long) page_address(page);
|
||||
struct cpa_data cpa = { .vaddr = &tempaddr,
|
||||
@@ -2614,7 +2626,7 @@ static int __set_pages_p(struct page *page, int numpages)
|
||||
.numpages = numpages,
|
||||
.mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
|
||||
.mask_clr = __pgprot(0),
|
||||
- .flags = CPA_NO_CHECK_ALIAS };
|
||||
+ .flags = CPA_NO_CHECK_ALIAS | cpa_flags };
|
||||
|
||||
/*
|
||||
* No alias checking needed for setting present flag. otherwise,
|
||||
@@ -2625,7 +2637,7 @@ static int __set_pages_p(struct page *page, int numpages)
|
||||
return __change_page_attr_set_clr(&cpa, 1);
|
||||
}
|
||||
|
||||
-static int __set_pages_np(struct page *page, int numpages)
|
||||
+static int __set_pages_np(struct page *page, int numpages, unsigned int cpa_flags)
|
||||
{
|
||||
unsigned long tempaddr = (unsigned long) page_address(page);
|
||||
struct cpa_data cpa = { .vaddr = &tempaddr,
|
||||
@@ -2633,7 +2645,7 @@ static int __set_pages_np(struct page *page, int numpages)
|
||||
.numpages = numpages,
|
||||
.mask_set = __pgprot(0),
|
||||
.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY),
|
||||
- .flags = CPA_NO_CHECK_ALIAS };
|
||||
+ .flags = CPA_NO_CHECK_ALIAS | cpa_flags };
|
||||
|
||||
/*
|
||||
* No alias checking needed for setting not present flag. otherwise,
|
||||
@@ -2646,20 +2658,20 @@ static int __set_pages_np(struct page *page, int numpages)
|
||||
|
||||
int set_direct_map_invalid_noflush(struct page *page)
|
||||
{
|
||||
- return __set_pages_np(page, 1);
|
||||
+ return __set_pages_np(page, 1, 0);
|
||||
}
|
||||
|
||||
int set_direct_map_default_noflush(struct page *page)
|
||||
{
|
||||
- return __set_pages_p(page, 1);
|
||||
+ return __set_pages_p(page, 1, 0);
|
||||
}
|
||||
|
||||
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
|
||||
{
|
||||
if (valid)
|
||||
- return __set_pages_p(page, nr);
|
||||
+ return __set_pages_p(page, nr, 0);
|
||||
|
||||
- return __set_pages_np(page, nr);
|
||||
+ return __set_pages_np(page, nr, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
@@ -2678,15 +2690,23 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
* and hence no memory allocations during large page split.
|
||||
*/
|
||||
if (enable)
|
||||
- __set_pages_p(page, numpages);
|
||||
+ __set_pages_p(page, numpages, CPA_DEBUG_PAGEALLOC);
|
||||
else
|
||||
- __set_pages_np(page, numpages);
|
||||
+ __set_pages_np(page, numpages, CPA_DEBUG_PAGEALLOC);
|
||||
|
||||
/*
|
||||
- * We should perform an IPI and flush all tlbs,
|
||||
- * but that can deadlock->flush only current cpu.
|
||||
- * Preemption needs to be disabled around __flush_tlb_all() due to
|
||||
- * CR3 reload in __native_flush_tlb().
|
||||
+ * We should perform an IPI and flush all tlbs, but that can
|
||||
+ * deadlock, settle for a local flush.
|
||||
+ *
|
||||
+ * Not doing a global TLB flush means that remote CPUs will retain
|
||||
+ * stale TLB entries. In case of P->NP (on free) this means the remote
|
||||
+ * CPUs will not take the faults, making the debug scheme less
|
||||
+ * reliable. On the NP->P (on alloc) this means the remote CPUs can
|
||||
+ * take a spurious fault. However spurious_kernel_fault() will observe
|
||||
+ * *_present() and fix it up.
|
||||
+ *
|
||||
+ * Preemption needs to be disabled around __flush_tlb_all() due to CR3
|
||||
+ * reload in __native_flush_tlb().
|
||||
*/
|
||||
preempt_disable();
|
||||
__flush_tlb_all();
|
||||
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
|
||||
--- a/arch/x86/mm/pgtable.c
|
||||
+++ b/arch/x86/mm/pgtable.c
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
--- a/kernel/sched/fair.c
|
||||
+++ b/kernel/sched/fair.c
|
||||
@@ -13464,12 +13464,15 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq,
|
||||
@@ -13476,12 +13476,15 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq,
|
||||
* still unbalanced. ld_moved simply stays zero, so it is
|
||||
* correctly treated as an imbalance.
|
||||
*/
|
||||
|
||||
Binary file not shown.
@@ -1,23 +0,0 @@
|
||||
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -3751,11 +3751,17 @@ static inline void ttwu_do_wakeup(struct task_struct *p)
|
||||
|
||||
void update_rq_avg_idle(struct rq *rq)
|
||||
{
|
||||
- u64 delta = rq_clock(rq) - rq->idle_stamp;
|
||||
- u64 max = 2*rq->max_idle_balance_cost;
|
||||
+ u64 idle_stamp = rq->idle_stamp;
|
||||
+ u64 delta, max;
|
||||
+
|
||||
+ if (!idle_stamp)
|
||||
+ return;
|
||||
+
|
||||
+ delta = rq_clock(rq) - idle_stamp;
|
||||
|
||||
update_avg(&rq->avg_idle, delta);
|
||||
|
||||
+ max = 2 * rq->max_idle_balance_cost;
|
||||
if (rq->avg_idle > max)
|
||||
rq->avg_idle = max;
|
||||
rq->idle_stamp = 0;
|
||||
Binary file not shown.
@@ -212,7 +212,7 @@ diff --git a/include/linux/vtime.h b/include/linux/vtime.h
|
||||
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -5099,7 +5099,7 @@ static inline void prepare_task(struct task_struct *next)
|
||||
@@ -5106,7 +5106,7 @@ static inline void prepare_task(struct task_struct *next)
|
||||
WRITE_ONCE(next->on_cpu, 1);
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
{
|
||||
/*
|
||||
* This must be the very last reference to @prev from this CPU. After
|
||||
@@ -5143,7 +5143,7 @@ static void zap_balance_callbacks(struct rq *rq)
|
||||
@@ -5150,7 +5150,7 @@ static void zap_balance_callbacks(struct rq *rq)
|
||||
rq->balance_callback = found ? &balance_push_callback : NULL;
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
{
|
||||
void (*func)(struct rq *rq);
|
||||
struct balance_callback *next;
|
||||
@@ -5178,7 +5178,7 @@ struct balance_callback balance_push_callback = {
|
||||
@@ -5185,7 +5185,7 @@ struct balance_callback balance_push_callback = {
|
||||
.func = balance_push,
|
||||
};
|
||||
|
||||
@@ -239,7 +239,7 @@ diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
__splice_balance_callbacks(struct rq *rq, bool split)
|
||||
{
|
||||
struct balance_callback *head = rq->balance_callback;
|
||||
@@ -5252,7 +5252,7 @@ prepare_lock_switch(struct rq *rq, struct task_struct *next, struct rq_flags *rf
|
||||
@@ -5259,7 +5259,7 @@ prepare_lock_switch(struct rq *rq, struct task_struct *next, struct rq_flags *rf
|
||||
__acquire(__rq_lockp(this_rq()));
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
__releases(__rq_lockp(rq))
|
||||
{
|
||||
/*
|
||||
@@ -5286,7 +5286,7 @@ static inline void kmap_local_sched_out(void)
|
||||
@@ -5293,7 +5293,7 @@ static inline void kmap_local_sched_out(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
{
|
||||
#ifdef CONFIG_KMAP_LOCAL
|
||||
if (unlikely(current->kmap_ctrl.idx))
|
||||
@@ -5340,7 +5340,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
|
||||
@@ -5347,7 +5347,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
|
||||
* past. 'prev == current' is still correct but we need to recalculate this_rq
|
||||
* because prev may have moved to another CPU.
|
||||
*/
|
||||
|
||||
Binary file not shown.
@@ -1,21 +1,7 @@
|
||||
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
|
||||
--- a/kernel/sched/deadline.c
|
||||
+++ b/kernel/sched/deadline.c
|
||||
@@ -3026,8 +3026,8 @@ static struct task_struct *pick_next_pushable_dl_task(struct rq *rq)
|
||||
next_node = rb_first_cached(&rq->dl.pushable_dl_tasks_root);
|
||||
while (next_node) {
|
||||
i = __node_2_pdl(next_node);
|
||||
- /* make sure task isn't on_cpu (possible with proxy-exec) */
|
||||
- if (!task_on_cpu(rq, i)) {
|
||||
+ /* skip tasks that cannot be migrated */
|
||||
+ if (!task_on_cpu(rq, i) && !is_migration_disabled(i)) {
|
||||
p = i;
|
||||
break;
|
||||
}
|
||||
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
--- a/kernel/sched/fair.c
|
||||
+++ b/kernel/sched/fair.c
|
||||
@@ -10691,17 +10691,40 @@ static enum llc_mig can_migrate_llc(int src_cpu, int dst_cpu,
|
||||
@@ -10701,17 +10701,40 @@ static enum llc_mig can_migrate_llc(int src_cpu, int dst_cpu,
|
||||
return mig_llc;
|
||||
}
|
||||
|
||||
@@ -58,7 +44,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
mm = p->mm;
|
||||
if (!mm)
|
||||
return mig_unrestricted;
|
||||
@@ -10758,6 +10781,14 @@ alb_break_llc(struct lb_env *env)
|
||||
@@ -10768,6 +10791,14 @@ alb_break_llc(struct lb_env *env)
|
||||
unsigned long util = 0;
|
||||
struct task_struct *cur;
|
||||
|
||||
@@ -73,7 +59,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
if (env->src_rq->nr_running <= 1)
|
||||
return true;
|
||||
|
||||
@@ -10765,7 +10796,8 @@ alb_break_llc(struct lb_env *env)
|
||||
@@ -10775,7 +10806,8 @@ alb_break_llc(struct lb_env *env)
|
||||
if (cur && cur->sched_class == &fair_sched_class)
|
||||
util = task_util(cur);
|
||||
|
||||
@@ -83,7 +69,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
util, false) == mig_forbid)
|
||||
return true;
|
||||
}
|
||||
@@ -10805,8 +10837,7 @@ static bool migrate_degrades_llc(struct task_struct *p, struct lb_env *env)
|
||||
@@ -10815,8 +10847,7 @@ static bool migrate_degrades_llc(struct task_struct *p, struct lb_env *env)
|
||||
READ_ONCE(p->preferred_llc) != llc_id(env->dst_cpu))
|
||||
return true;
|
||||
|
||||
@@ -93,7 +79,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -11869,6 +11900,15 @@ static inline bool llc_balance(struct lb_env *env, struct sg_lb_stats *sgs,
|
||||
@@ -11879,6 +11910,15 @@ static inline bool llc_balance(struct lb_env *env, struct sg_lb_stats *sgs,
|
||||
if (env->sd->flags & SD_SHARE_LLC)
|
||||
return false;
|
||||
|
||||
@@ -109,17 +95,3 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
/*
|
||||
* Skip cache aware tagging if nr_balanced_failed is sufficiently high.
|
||||
* Threshold of cache_nice_tries is set to 1 higher than nr_balance_failed
|
||||
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
|
||||
--- a/kernel/sched/rt.c
|
||||
+++ b/kernel/sched/rt.c
|
||||
@@ -1871,8 +1871,8 @@ static struct task_struct *pick_next_pushable_task(struct rq *rq)
|
||||
return NULL;
|
||||
|
||||
plist_for_each_entry(i, head, pushable_tasks) {
|
||||
- /* make sure task isn't on_cpu (possible with proxy-exec) */
|
||||
- if (!task_on_cpu(rq, i)) {
|
||||
+ /* skip tasks that cannot be migrated */
|
||||
+ if (!task_on_cpu(rq, i) && !is_migration_disabled(i)) {
|
||||
p = i;
|
||||
break;
|
||||
}
|
||||
Binary file not shown.
@@ -1,24 +0,0 @@
|
||||
diff --git a/arch/x86/kernel/itmt.c b/arch/x86/kernel/itmt.c
|
||||
--- a/arch/x86/kernel/itmt.c
|
||||
+++ b/arch/x86/kernel/itmt.c
|
||||
@@ -110,18 +110,14 @@ int sched_set_itmt_support(void)
|
||||
arch_debugfs_dir,
|
||||
&sysctl_sched_itmt_enabled,
|
||||
&dfs_sched_itmt_fops);
|
||||
- if (IS_ERR_OR_NULL(dfs_sched_itmt)) {
|
||||
+ if (IS_ERR(dfs_sched_itmt))
|
||||
dfs_sched_itmt = NULL;
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
|
||||
dfs_sched_core_prio = debugfs_create_file("sched_core_priority", 0644,
|
||||
arch_debugfs_dir, NULL,
|
||||
&sched_core_priority_fops);
|
||||
- if (IS_ERR_OR_NULL(dfs_sched_core_prio)) {
|
||||
+ if (IS_ERR(dfs_sched_core_prio))
|
||||
dfs_sched_core_prio = NULL;
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
|
||||
sched_itmt_capable = true;
|
||||
|
||||
Binary file not shown.
@@ -14,22 +14,22 @@ diff --git a/include/linux/sched/sd_flags.h b/include/linux/sched/sd_flags.h
|
||||
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
--- a/kernel/sched/fair.c
|
||||
+++ b/kernel/sched/fair.c
|
||||
@@ -12028,10 +12028,25 @@ static inline void update_sg_lb_stats(struct lb_env *env,
|
||||
@@ -12038,12 +12038,25 @@ static inline void update_sg_lb_stats(struct lb_env *env,
|
||||
continue;
|
||||
|
||||
if (sd_flags & SD_ASYM_CPUCAPACITY) {
|
||||
- /* Check for a misfit task on the cpu */
|
||||
- if (sgs->group_misfit_task_load < rq->misfit_task_load) {
|
||||
- sgs->group_misfit_task_load = rq->misfit_task_load;
|
||||
- *sg_overloaded = 1;
|
||||
-
|
||||
+ if (rq->misfit_task_load) {
|
||||
+ /*
|
||||
+ * Always mark the root domain overloaded so big
|
||||
+ * CPUs can pick up misfit tasks via newly idle
|
||||
+ * balance.
|
||||
+ */
|
||||
+ if (balancing_at_rd)
|
||||
+ *sg_overloaded = 1;
|
||||
if (balancing_at_rd)
|
||||
*sg_overloaded = 1;
|
||||
+
|
||||
+ /*
|
||||
+ * Only account misfit load if @dst_cpu can
|
||||
@@ -44,43 +44,7 @@ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
}
|
||||
} else if (env->idle && sched_reduced_capacity(rq, env->sd)) {
|
||||
/* Check for a task running on a CPU with reduced capacity */
|
||||
@@ -12110,6 +12125,17 @@ static bool update_sd_pick_busiest(struct lb_env *env,
|
||||
sds->local_stat.group_type != group_has_spare))
|
||||
return false;
|
||||
|
||||
+ /*
|
||||
+ * Candidate sg has no more than one task per CPU and has higher
|
||||
+ * per-CPU capacity. Migrating tasks to less capable CPUs may harm
|
||||
+ * throughput. Maximize throughput, power/energy consequences are not
|
||||
+ * considered.
|
||||
+ */
|
||||
+ if ((env->sd->flags & SD_ASYM_CPUCAPACITY) &&
|
||||
+ (sgs->group_type <= group_fully_busy) &&
|
||||
+ (capacity_greater(sg->sgc->min_capacity, capacity_of(env->dst_cpu))))
|
||||
+ return false;
|
||||
+
|
||||
if (sgs->group_type > busiest->group_type)
|
||||
return true;
|
||||
|
||||
@@ -12216,17 +12242,6 @@ static bool update_sd_pick_busiest(struct lb_env *env,
|
||||
break;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Candidate sg has no more than one task per CPU and has higher
|
||||
- * per-CPU capacity. Migrating tasks to less capable CPUs may harm
|
||||
- * throughput. Maximize throughput, power/energy consequences are not
|
||||
- * considered.
|
||||
- */
|
||||
- if ((env->sd->flags & SD_ASYM_CPUCAPACITY) &&
|
||||
- (sgs->group_type <= group_fully_busy) &&
|
||||
- (capacity_greater(sg->sgc->min_capacity, capacity_of(env->dst_cpu))))
|
||||
- return false;
|
||||
-
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13144,9 +13159,24 @@ static struct rq *sched_balance_find_src_rq(struct lb_env *env,
|
||||
@@ -13156,9 +13169,24 @@ static struct rq *sched_balance_find_src_rq(struct lb_env *env,
|
||||
* average load.
|
||||
*/
|
||||
if (env->sd->flags & SD_ASYM_CPUCAPACITY &&
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
--- a/kernel/sched/fair.c
|
||||
+++ b/kernel/sched/fair.c
|
||||
@@ -14050,29 +14050,62 @@ static inline int on_null_domain(struct rq *rq)
|
||||
@@ -14060,29 +14060,62 @@ static inline int on_null_domain(struct rq *rq)
|
||||
*/
|
||||
static inline int find_new_ilb(void)
|
||||
{
|
||||
|
||||
Binary file not shown.
@@ -1,61 +0,0 @@
|
||||
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
|
||||
--- a/drivers/idle/intel_idle.c
|
||||
+++ b/drivers/idle/intel_idle.c
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/moduleparam.h>
|
||||
+#include <linux/pm_qos.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <asm/cpuid/api.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
@@ -2697,6 +2698,9 @@ static void __init cmdline_table_adjust(struct cpuidle_driver *drv)
|
||||
pr_info("Failed to adjust C-states with data from 'intel_idle.table'\n");
|
||||
}
|
||||
|
||||
+#define INTEL_IDLE_INIT_QOS 20
|
||||
+static struct pm_qos_request qos_req __initdata;
|
||||
+
|
||||
static int __init intel_idle_init(void)
|
||||
{
|
||||
const struct x86_cpu_id *id;
|
||||
@@ -2766,6 +2770,13 @@ static int __init intel_idle_init(void)
|
||||
if (retval)
|
||||
pr_warn("failed to initialized sysfs");
|
||||
|
||||
+ /*
|
||||
+ * Some platforms, in particular the Intel S1200BTL motherboard, have a
|
||||
+ * problem with using package idle states too early, so prevent that
|
||||
+ * from taking place until the device_initcall() phase is over.
|
||||
+ */
|
||||
+ cpu_latency_qos_add_request(&qos_req, INTEL_IDLE_INIT_QOS);
|
||||
+
|
||||
retval = cpuidle_register_driver(&intel_idle_driver);
|
||||
if (retval) {
|
||||
struct cpuidle_driver *drv = cpuidle_get_driver();
|
||||
@@ -2790,6 +2801,9 @@ static int __init intel_idle_init(void)
|
||||
intel_idle_cpuidle_devices_uninit();
|
||||
cpuidle_unregister_driver(&intel_idle_driver);
|
||||
init_driver_fail:
|
||||
+ if (cpu_latency_qos_request_active((&qos_req)))
|
||||
+ cpu_latency_qos_remove_request(&qos_req);
|
||||
+
|
||||
intel_idle_sysfs_uninit();
|
||||
free_percpu(intel_idle_cpuidle_devices);
|
||||
return retval;
|
||||
@@ -2797,6 +2811,15 @@ static int __init intel_idle_init(void)
|
||||
}
|
||||
subsys_initcall_sync(intel_idle_init);
|
||||
|
||||
+static int __init intel_idle_init_complete(void)
|
||||
+{
|
||||
+ if (cpu_latency_qos_request_active((&qos_req)))
|
||||
+ cpu_latency_qos_remove_request(&qos_req);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+device_initcall_sync(intel_idle_init_complete);
|
||||
+
|
||||
/*
|
||||
* We are not really modular, but we used to support that. Meaning we also
|
||||
* support "intel_idle.max_cstate=..." at boot and also a read-only export of
|
||||
Binary file not shown.
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -1,480 +0,0 @@
|
||||
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -782,6 +782,7 @@ static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
|
||||
static void amd_pstate_adjust_perf(struct cpufreq_policy *policy,
|
||||
unsigned long _min_perf,
|
||||
unsigned long target_perf,
|
||||
+ unsigned long _max_perf,
|
||||
unsigned long capacity)
|
||||
{
|
||||
u8 max_perf, min_perf, des_perf, cap_perf;
|
||||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
|
||||
--- a/drivers/cpufreq/cpufreq.c
|
||||
+++ b/drivers/cpufreq/cpufreq.c
|
||||
@@ -2225,14 +2225,17 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch);
|
||||
* @policy: cpufreq policy object of the target CPU.
|
||||
* @min_perf: Minimum (required) performance level (units of @capacity).
|
||||
* @target_perf: Target (desired) performance level (units of @capacity).
|
||||
+ * @max_perf: Maximum (allowed) performance level (units of @capacity).
|
||||
* @capacity: Capacity of the target CPU.
|
||||
*
|
||||
- * Carry out a fast performance level switch of @cpu without sleeping.
|
||||
+ * Carry out a fast performance level adjustment for the CPU represented by
|
||||
+ * @policy without sleeping.
|
||||
*
|
||||
* The driver's ->adjust_perf() callback invoked by this function must be
|
||||
- * suitable for being called from within RCU-sched read-side critical sections
|
||||
- * and it is expected to select a suitable performance level equal to or above
|
||||
- * @min_perf and preferably equal to or below @target_perf.
|
||||
+ * suitable for calling from within RCU-sched read-side critical sections and
|
||||
+ * it is expected to program the processor to select suitable performance
|
||||
+ * levels between @min_perf and @max_perf inclusive and preferably close to
|
||||
+ * @target_perf going forward for the CPU represented by @policy.
|
||||
*
|
||||
* This function must not be called if policy->fast_switch_enabled is unset.
|
||||
*
|
||||
@@ -2244,9 +2247,10 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch);
|
||||
void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy,
|
||||
unsigned long min_perf,
|
||||
unsigned long target_perf,
|
||||
+ unsigned long max_perf,
|
||||
unsigned long capacity)
|
||||
{
|
||||
- cpufreq_driver->adjust_perf(policy, min_perf, target_perf, capacity);
|
||||
+ cpufreq_driver->adjust_perf(policy, min_perf, target_perf, max_perf, capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
|
||||
--- a/drivers/cpufreq/intel_pstate.c
|
||||
+++ b/drivers/cpufreq/intel_pstate.c
|
||||
@@ -299,7 +299,6 @@ struct pstate_funcs {
|
||||
static struct pstate_funcs pstate_funcs __read_mostly;
|
||||
|
||||
static bool hwp_active __ro_after_init;
|
||||
-static int hwp_mode_bdw __ro_after_init;
|
||||
static bool per_cpu_limits __ro_after_init;
|
||||
static bool hwp_forced __ro_after_init;
|
||||
static bool hwp_boost __read_mostly;
|
||||
@@ -587,21 +586,14 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
|
||||
|
||||
hwp_is_hybrid = true;
|
||||
|
||||
- cpu->pstate.turbo_freq = rounddown(cpu->pstate.turbo_pstate * scaling,
|
||||
- perf_ctl_scaling);
|
||||
- cpu->pstate.max_freq = rounddown(cpu->pstate.max_pstate * scaling,
|
||||
- perf_ctl_scaling);
|
||||
-
|
||||
freq = perf_ctl_max_phys * perf_ctl_scaling;
|
||||
cpu->pstate.max_pstate_physical = intel_pstate_freq_to_hwp(cpu, freq);
|
||||
|
||||
- freq = cpu->pstate.min_pstate * perf_ctl_scaling;
|
||||
- cpu->pstate.min_freq = freq;
|
||||
/*
|
||||
* Cast the min P-state value retrieved via pstate_funcs.get_min() to
|
||||
* the effective range of HWP performance levels.
|
||||
*/
|
||||
- cpu->pstate.min_pstate = intel_pstate_freq_to_hwp(cpu, freq);
|
||||
+ cpu->pstate.min_pstate = intel_pstate_freq_to_hwp(cpu, cpu->pstate.min_freq);
|
||||
}
|
||||
|
||||
static bool turbo_is_disabled(void)
|
||||
@@ -979,12 +971,10 @@ static int hybrid_get_cost(struct device *dev, unsigned long freq,
|
||||
* capacity. Similarly, P-cores start to be populated when E-cores are
|
||||
* utilized above 60% of the capacity.
|
||||
*/
|
||||
- if (hybrid_get_cpu_type(dev->id) == INTEL_CPU_TYPE_ATOM) {
|
||||
- if (hybrid_has_l3(dev->id)) /* E-core */
|
||||
- *cost += 1;
|
||||
- } else { /* P-core */
|
||||
+ if (hybrid_get_cpu_type(dev->id) == INTEL_CPU_TYPE_CORE) /* P-core */
|
||||
*cost += 2;
|
||||
- }
|
||||
+ else if (hybrid_has_l3(dev->id)) /* E-core */
|
||||
+ *cost += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1185,6 +1175,22 @@ static bool hybrid_clear_max_perf_cpu(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void intel_pstate_update_freq_limits(struct cpudata *cpu)
|
||||
+{
|
||||
+ int scaling = cpu->pstate.scaling;
|
||||
+ unsigned int turbo_freq = cpu->pstate.turbo_pstate * scaling;
|
||||
+ unsigned int max_freq = cpu->pstate.max_pstate * scaling;
|
||||
+ int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
|
||||
+
|
||||
+ if (scaling != perf_ctl_scaling) {
|
||||
+ turbo_freq = rounddown(turbo_freq, perf_ctl_scaling);
|
||||
+ max_freq = rounddown(max_freq, perf_ctl_scaling);
|
||||
+ }
|
||||
+
|
||||
+ cpu->pstate.turbo_freq = turbo_freq;
|
||||
+ cpu->pstate.max_freq = max_freq;
|
||||
+}
|
||||
+
|
||||
static void __intel_pstate_get_hwp_cap(struct cpudata *cpu)
|
||||
{
|
||||
u64 cap;
|
||||
@@ -1197,20 +1203,8 @@ static void __intel_pstate_get_hwp_cap(struct cpudata *cpu)
|
||||
|
||||
static void intel_pstate_get_hwp_cap(struct cpudata *cpu)
|
||||
{
|
||||
- int scaling = cpu->pstate.scaling;
|
||||
-
|
||||
__intel_pstate_get_hwp_cap(cpu);
|
||||
-
|
||||
- cpu->pstate.max_freq = cpu->pstate.max_pstate * scaling;
|
||||
- cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * scaling;
|
||||
- if (scaling != cpu->pstate.perf_ctl_scaling) {
|
||||
- int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
|
||||
-
|
||||
- cpu->pstate.max_freq = rounddown(cpu->pstate.max_freq,
|
||||
- perf_ctl_scaling);
|
||||
- cpu->pstate.turbo_freq = rounddown(cpu->pstate.turbo_freq,
|
||||
- perf_ctl_scaling);
|
||||
- }
|
||||
+ intel_pstate_update_freq_limits(cpu);
|
||||
}
|
||||
|
||||
static void hybrid_update_capacity(struct cpudata *cpu)
|
||||
@@ -2299,33 +2293,16 @@ static int hwp_get_cpu_scaling(int cpu)
|
||||
return intel_pstate_cppc_get_scaling(cpu);
|
||||
}
|
||||
|
||||
-static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
|
||||
-{
|
||||
- trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
|
||||
- cpu->pstate.current_pstate = pstate;
|
||||
- /*
|
||||
- * Generally, there is no guarantee that this code will always run on
|
||||
- * the CPU being updated, so force the register update to run on the
|
||||
- * right CPU.
|
||||
- */
|
||||
- wrmsrq_on_cpu(cpu->cpu, MSR_IA32_PERF_CTL,
|
||||
- pstate_funcs.get_val(cpu, pstate));
|
||||
-}
|
||||
-
|
||||
-static void intel_pstate_set_min_pstate(struct cpudata *cpu)
|
||||
-{
|
||||
- intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
|
||||
-}
|
||||
-
|
||||
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
|
||||
{
|
||||
int perf_ctl_scaling = pstate_funcs.get_scaling();
|
||||
|
||||
cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical(cpu->cpu);
|
||||
cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu);
|
||||
+ cpu->pstate.min_freq = cpu->pstate.min_pstate * perf_ctl_scaling;
|
||||
cpu->pstate.perf_ctl_scaling = perf_ctl_scaling;
|
||||
|
||||
- if (hwp_active && !hwp_mode_bdw) {
|
||||
+ if (hwp_active) {
|
||||
__intel_pstate_get_hwp_cap(cpu);
|
||||
|
||||
if (pstate_funcs.get_cpu_scaling) {
|
||||
@@ -2345,19 +2322,13 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
|
||||
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu);
|
||||
}
|
||||
|
||||
- if (cpu->pstate.scaling == perf_ctl_scaling) {
|
||||
- cpu->pstate.min_freq = cpu->pstate.min_pstate * perf_ctl_scaling;
|
||||
- cpu->pstate.max_freq = cpu->pstate.max_pstate * perf_ctl_scaling;
|
||||
- cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * perf_ctl_scaling;
|
||||
- }
|
||||
+ intel_pstate_update_freq_limits(cpu);
|
||||
|
||||
if (pstate_funcs.get_aperf_mperf_shift)
|
||||
cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
|
||||
|
||||
if (pstate_funcs.get_vid)
|
||||
pstate_funcs.get_vid(cpu);
|
||||
-
|
||||
- intel_pstate_set_min_pstate(cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2884,8 +2855,22 @@ static void intel_pstate_update_perf_limits(struct cpudata *cpu,
|
||||
cpu->min_perf_ratio);
|
||||
}
|
||||
|
||||
+static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
|
||||
+{
|
||||
+ trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
|
||||
+ cpu->pstate.current_pstate = pstate;
|
||||
+ /*
|
||||
+ * Generally, there is no guarantee that this code will always run on
|
||||
+ * the CPU being updated, so force the register update to run on the
|
||||
+ * right CPU.
|
||||
+ */
|
||||
+ wrmsrq_on_cpu(cpu->cpu, MSR_IA32_PERF_CTL,
|
||||
+ pstate_funcs.get_val(cpu, pstate));
|
||||
+}
|
||||
+
|
||||
static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
||||
{
|
||||
+ unsigned int freq = policy->min;
|
||||
struct cpudata *cpu;
|
||||
|
||||
if (!policy->cpuinfo.max_freq)
|
||||
@@ -2901,7 +2886,23 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
||||
|
||||
intel_pstate_update_perf_limits(cpu, policy->min, policy->max);
|
||||
|
||||
- if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
|
||||
+ if (hwp_active) {
|
||||
+ /*
|
||||
+ * The active mode only requires an update util hook if HWP
|
||||
+ * boost is used and the policy is not "performance".
|
||||
+ */
|
||||
+ if (hwp_boost && cpu->policy != CPUFREQ_POLICY_PERFORMANCE) {
|
||||
+ intel_pstate_set_update_util_hook(policy->cpu);
|
||||
+ } else {
|
||||
+ intel_pstate_clear_update_util_hook(policy->cpu);
|
||||
+ if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
|
||||
+ freq = cpu->max_perf_ratio * cpu->pstate.scaling;
|
||||
+ if (cpu->pstate.scaling != cpu->pstate.perf_ctl_scaling)
|
||||
+ freq = rounddown(freq, cpu->pstate.perf_ctl_scaling);
|
||||
+ }
|
||||
+ }
|
||||
+ intel_pstate_hwp_set(policy->cpu);
|
||||
+ } else if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
|
||||
int pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio);
|
||||
|
||||
/*
|
||||
@@ -2910,25 +2911,17 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
||||
*/
|
||||
intel_pstate_clear_update_util_hook(policy->cpu);
|
||||
intel_pstate_set_pstate(cpu, pstate);
|
||||
+ freq = pstate * cpu->pstate.scaling;
|
||||
} else {
|
||||
intel_pstate_set_update_util_hook(policy->cpu);
|
||||
}
|
||||
-
|
||||
- if (hwp_active) {
|
||||
- /*
|
||||
- * When hwp_boost was active before and dynamically it
|
||||
- * was turned off, in that case we need to clear the
|
||||
- * update util hook.
|
||||
- */
|
||||
- if (!hwp_boost)
|
||||
- intel_pstate_clear_update_util_hook(policy->cpu);
|
||||
- intel_pstate_hwp_set(policy->cpu);
|
||||
- }
|
||||
/*
|
||||
- * policy->cur is never updated with the intel_pstate driver, but it
|
||||
- * is used as a stale frequency value. So, keep it within limits.
|
||||
+ * policy->cur is never updated in the intel_pstate driver, but it is
|
||||
+ * used as a stale frequency value, so set it to reflect the actual
|
||||
+ * requested P-state in the "performance" policy case and to the min
|
||||
+ * otherwise.
|
||||
*/
|
||||
- policy->cur = policy->min;
|
||||
+ policy->cur = freq;
|
||||
|
||||
mutex_unlock(&intel_pstate_limits_lock);
|
||||
|
||||
@@ -2971,6 +2964,11 @@ static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void intel_pstate_set_min_pstate(struct cpudata *cpu)
|
||||
+{
|
||||
+ intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
|
||||
+}
|
||||
+
|
||||
static int intel_cpufreq_cpu_offline(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpudata *cpu = all_cpu_data[policy->cpu];
|
||||
@@ -3063,6 +3061,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
||||
static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int ret = __intel_pstate_cpu_init(policy);
|
||||
+ struct cpudata *cpu;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -3073,11 +3072,11 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
||||
*/
|
||||
policy->policy = CPUFREQ_POLICY_POWERSAVE;
|
||||
|
||||
- if (hwp_active) {
|
||||
- struct cpudata *cpu = all_cpu_data[policy->cpu];
|
||||
-
|
||||
+ cpu = all_cpu_data[policy->cpu];
|
||||
+ if (hwp_active)
|
||||
cpu->epp_cached = intel_pstate_get_epp(cpu, 0);
|
||||
- }
|
||||
+ else
|
||||
+ intel_pstate_set_min_pstate(cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3243,6 +3242,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
|
||||
static void intel_cpufreq_adjust_perf(struct cpufreq_policy *policy,
|
||||
unsigned long min_perf,
|
||||
unsigned long target_perf,
|
||||
+ unsigned long max_perf,
|
||||
unsigned long capacity)
|
||||
{
|
||||
struct cpudata *cpu = all_cpu_data[policy->cpu];
|
||||
@@ -3273,7 +3273,13 @@ static void intel_cpufreq_adjust_perf(struct cpufreq_policy *policy,
|
||||
if (min_pstate > cpu->max_perf_ratio)
|
||||
min_pstate = cpu->max_perf_ratio;
|
||||
|
||||
- max_pstate = min(cap_pstate, cpu->max_perf_ratio);
|
||||
+ max_pstate = cap_pstate;
|
||||
+ if (max_perf < capacity)
|
||||
+ max_pstate = DIV_ROUND_UP(cap_pstate * max_perf, capacity);
|
||||
+
|
||||
+ if (max_pstate > cpu->max_perf_ratio)
|
||||
+ max_pstate = cpu->max_perf_ratio;
|
||||
+
|
||||
if (max_pstate < min_pstate)
|
||||
max_pstate = min_pstate;
|
||||
|
||||
@@ -3301,8 +3307,6 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
return ret;
|
||||
|
||||
policy->cpuinfo.transition_latency = INTEL_CPUFREQ_TRANSITION_LATENCY;
|
||||
- /* This reflects the intel_pstate_get_cpu_pstates() setting. */
|
||||
- policy->cur = policy->cpuinfo.min_freq;
|
||||
|
||||
req = kzalloc_objs(*req, 2);
|
||||
if (!req) {
|
||||
@@ -3323,9 +3327,15 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
WRITE_ONCE(cpu->hwp_req_cached, value);
|
||||
|
||||
cpu->epp_cached = intel_pstate_get_epp(cpu, value);
|
||||
+
|
||||
+ intel_cpufreq_hwp_update(cpu, cpu->pstate.min_pstate,
|
||||
+ cpu->pstate.max_pstate,
|
||||
+ cpu->pstate.min_pstate, false);
|
||||
} else {
|
||||
policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY;
|
||||
+ intel_pstate_set_min_pstate(cpu);
|
||||
}
|
||||
+ policy->cur = policy->cpuinfo.min_freq;
|
||||
|
||||
freq = DIV_ROUND_UP(cpu->pstate.turbo_freq * global.min_perf_pct, 100);
|
||||
|
||||
@@ -3676,14 +3686,14 @@ static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
|
||||
static inline void intel_pstate_request_control_from_smm(void) {}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
-#define INTEL_PSTATE_HWP_BROADWELL 0x01
|
||||
+#define INTEL_PSTATE_HWP_NOT_HYBRID 0x01
|
||||
|
||||
#define X86_MATCH_HWP(vfm, hwp_mode) \
|
||||
X86_MATCH_VFM_FEATURE(vfm, X86_FEATURE_HWP, hwp_mode)
|
||||
|
||||
static const struct x86_cpu_id hwp_support_ids[] __initconst = {
|
||||
- X86_MATCH_HWP(INTEL_BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL),
|
||||
- X86_MATCH_HWP(INTEL_BROADWELL_D, INTEL_PSTATE_HWP_BROADWELL),
|
||||
+ X86_MATCH_HWP(INTEL_BROADWELL_X, INTEL_PSTATE_HWP_NOT_HYBRID),
|
||||
+ X86_MATCH_HWP(INTEL_BROADWELL_D, INTEL_PSTATE_HWP_NOT_HYBRID),
|
||||
X86_MATCH_HWP(INTEL_ANY, 0),
|
||||
{}
|
||||
};
|
||||
@@ -3808,7 +3818,6 @@ static int __init intel_pstate_init(void)
|
||||
|
||||
if (!no_hwp) {
|
||||
hwp_active = true;
|
||||
- hwp_mode_bdw = id->driver_data;
|
||||
intel_pstate.attr = hwp_cpufreq_attrs;
|
||||
intel_cpufreq.attr = hwp_cpufreq_attrs;
|
||||
intel_cpufreq.flags |= CPUFREQ_NEED_UPDATE_LIMITS;
|
||||
@@ -3816,7 +3825,8 @@ static int __init intel_pstate_init(void)
|
||||
if (!default_driver)
|
||||
default_driver = &intel_pstate;
|
||||
|
||||
- pstate_funcs.get_cpu_scaling = hwp_get_cpu_scaling;
|
||||
+ if (!id->driver_data)
|
||||
+ pstate_funcs.get_cpu_scaling = hwp_get_cpu_scaling;
|
||||
|
||||
goto hwp_cpu_matched;
|
||||
}
|
||||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -379,6 +379,7 @@ struct cpufreq_driver {
|
||||
void (*adjust_perf)(struct cpufreq_policy *policy,
|
||||
unsigned long min_perf,
|
||||
unsigned long target_perf,
|
||||
+ unsigned long max_perf,
|
||||
unsigned long capacity);
|
||||
|
||||
/*
|
||||
@@ -624,6 +625,7 @@ unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
|
||||
void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy,
|
||||
unsigned long min_perf,
|
||||
unsigned long target_perf,
|
||||
+ unsigned long max_perf,
|
||||
unsigned long capacity);
|
||||
bool cpufreq_driver_has_adjust_perf(void);
|
||||
int cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
|
||||
--- a/kernel/sched/cpufreq_schedutil.c
|
||||
+++ b/kernel/sched/cpufreq_schedutil.c
|
||||
@@ -50,6 +50,7 @@ struct sugov_cpu {
|
||||
|
||||
unsigned long util;
|
||||
unsigned long bw_min;
|
||||
+ unsigned long bw_max;
|
||||
|
||||
/* The field below is for single-CPU policies only: */
|
||||
#ifdef CONFIG_NO_HZ_COMMON
|
||||
@@ -243,6 +244,7 @@ static void sugov_get_util(struct sugov_cpu *sg_cpu, unsigned long boost)
|
||||
util = effective_cpu_util(sg_cpu->cpu, util, &min, &max);
|
||||
util = max(util, boost);
|
||||
sg_cpu->bw_min = min;
|
||||
+ sg_cpu->bw_max = max;
|
||||
sg_cpu->util = sugov_effective_cpu_perf(sg_cpu->cpu, util, min, max);
|
||||
}
|
||||
|
||||
@@ -495,7 +497,7 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time,
|
||||
sg_cpu->util = prev_util;
|
||||
|
||||
cpufreq_driver_adjust_perf(sg_policy->policy, sg_cpu->bw_min,
|
||||
- sg_cpu->util, max_cap);
|
||||
+ sg_cpu->util, sg_cpu->bw_max, max_cap);
|
||||
|
||||
sg_policy->need_freq_update = false;
|
||||
sg_policy->last_freq_update_time = time;
|
||||
diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs
|
||||
--- a/rust/kernel/cpufreq.rs
|
||||
+++ b/rust/kernel/cpufreq.rs
|
||||
@@ -792,7 +792,13 @@ fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 {
|
||||
}
|
||||
|
||||
/// Driver's `adjust_perf` callback.
|
||||
- fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) {
|
||||
+ fn adjust_perf(
|
||||
+ _policy: &mut Policy,
|
||||
+ _min_perf: usize,
|
||||
+ _target_perf: usize,
|
||||
+ _max_perf: usize,
|
||||
+ _capacity: usize,
|
||||
+ ) {
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
@@ -1263,12 +1269,13 @@ impl<T: Driver> Registration<T> {
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
min_perf: c_ulong,
|
||||
target_perf: c_ulong,
|
||||
+ max_perf: c_ulong,
|
||||
capacity: c_ulong,
|
||||
) {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
let policy = unsafe { Policy::from_raw_mut(ptr) };
|
||||
- T::adjust_perf(policy, min_perf, target_perf, capacity);
|
||||
+ T::adjust_perf(policy, min_perf, target_perf, max_perf, capacity);
|
||||
}
|
||||
|
||||
/// Driver's `get_intermediate` callback.
|
||||
Binary file not shown.
@@ -1,127 +0,0 @@
|
||||
diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c
|
||||
--- a/drivers/cpufreq/amd-pstate-ut.c
|
||||
+++ b/drivers/cpufreq/amd-pstate-ut.c
|
||||
@@ -560,6 +560,11 @@ static int amd_pstate_ut_check_freq_attrs(u32 index)
|
||||
static int __init amd_pstate_ut_init(void)
|
||||
{
|
||||
u32 i = 0, arr_size = ARRAY_SIZE(amd_pstate_ut_cases);
|
||||
+ enum amd_pstate_mode mode = amd_pstate_get_status();
|
||||
+
|
||||
+ /* don't test if no running amd-pstate driver */
|
||||
+ if (mode == AMD_PSTATE_UNDEFINED || mode == AMD_PSTATE_DISABLE)
|
||||
+ return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < arr_size; i++) {
|
||||
int ret;
|
||||
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -199,7 +199,7 @@ static inline int get_mode_idx_from_str(const char *str, size_t size)
|
||||
|
||||
static DEFINE_MUTEX(amd_pstate_driver_lock);
|
||||
|
||||
-static u8 msr_get_epp(struct amd_cpudata *cpudata)
|
||||
+static int msr_get_epp(struct amd_cpudata *cpudata)
|
||||
{
|
||||
u64 value;
|
||||
int ret;
|
||||
@@ -215,12 +215,12 @@ static u8 msr_get_epp(struct amd_cpudata *cpudata)
|
||||
|
||||
DEFINE_STATIC_CALL(amd_pstate_get_epp, msr_get_epp);
|
||||
|
||||
-static inline s16 amd_pstate_get_epp(struct amd_cpudata *cpudata)
|
||||
+static inline int amd_pstate_get_epp(struct amd_cpudata *cpudata)
|
||||
{
|
||||
return static_call(amd_pstate_get_epp)(cpudata);
|
||||
}
|
||||
|
||||
-static u8 shmem_get_epp(struct amd_cpudata *cpudata)
|
||||
+static int shmem_get_epp(struct amd_cpudata *cpudata)
|
||||
{
|
||||
u64 epp;
|
||||
int ret;
|
||||
@@ -526,9 +526,6 @@ static int shmem_init_perf(struct amd_cpudata *cpudata)
|
||||
WRITE_ONCE(cpudata->perf, perf);
|
||||
WRITE_ONCE(cpudata->prefcore_ranking, cppc_perf.highest_perf);
|
||||
|
||||
- if (cppc_state == AMD_PSTATE_ACTIVE)
|
||||
- return 0;
|
||||
-
|
||||
ret = cppc_get_auto_sel(cpudata->cpu, &auto_sel);
|
||||
if (ret) {
|
||||
pr_warn("failed to get auto_sel, ret: %d\n", ret);
|
||||
@@ -1174,6 +1171,9 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
|
||||
if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
|
||||
return 0;
|
||||
|
||||
+ if (!policy)
|
||||
+ return NOTIFY_OK;
|
||||
+
|
||||
epp = amd_pstate_get_balanced_epp(policy);
|
||||
|
||||
ret = amd_pstate_set_epp(policy, epp);
|
||||
@@ -1209,6 +1209,9 @@ static int amd_pstate_profile_set(struct device *dev,
|
||||
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
|
||||
int ret;
|
||||
|
||||
+ if (!policy)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
switch (profile) {
|
||||
case PLATFORM_PROFILE_LOW_POWER:
|
||||
ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE);
|
||||
@@ -1877,6 +1880,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
||||
struct amd_cpudata *cpudata;
|
||||
union perf_cached perf;
|
||||
struct device *dev;
|
||||
+ int default_epp;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -1925,6 +1929,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->boost_supported = READ_ONCE(cpudata->boost_supported);
|
||||
|
||||
+ /* Fetch the firmware programmed default EPP value */
|
||||
+ default_epp = amd_pstate_get_epp(cpudata);
|
||||
+ if (default_epp < 0) {
|
||||
+ ret = default_epp;
|
||||
+ goto free_cpudata1;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Set the policy to provide a valid fallback value in case
|
||||
* the default cpufreq governor is neither powersave nor performance.
|
||||
@@ -1932,7 +1943,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
||||
if (amd_pstate_acpi_pm_profile_server() ||
|
||||
amd_pstate_acpi_pm_profile_undefined()) {
|
||||
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
|
||||
- cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
|
||||
+ cpudata->epp_default_ac = cpudata->epp_default_dc = default_epp;
|
||||
cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE;
|
||||
} else {
|
||||
policy->policy = CPUFREQ_POLICY_POWERSAVE;
|
||||
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
|
||||
--- a/drivers/cpufreq/amd-pstate.h
|
||||
+++ b/drivers/cpufreq/amd-pstate.h
|
||||
@@ -32,6 +32,7 @@
|
||||
* @min_limit_perf: Cached value of the performance corresponding to policy->min
|
||||
* @max_limit_perf: Cached value of the performance corresponding to policy->max
|
||||
* @bios_min_perf: Cached perf value corresponding to the "Requested CPU Min Frequency" BIOS option
|
||||
+ * @val: Raw 64-bit value for atomic access via READ_ONCE()/WRITE_ONCE()
|
||||
*/
|
||||
union perf_cached {
|
||||
struct {
|
||||
@@ -89,7 +90,12 @@ struct amd_aperf_mperf {
|
||||
* @epp_default_ac: Default EPP value for AC power source
|
||||
* @epp_default_dc: Default EPP value for DC power source
|
||||
* @dynamic_epp: Whether dynamic EPP is enabled
|
||||
+ * @raw_epp: Whether the last EPP write was a raw numeric value rather than a
|
||||
+ * named preference
|
||||
* @power_nb: Notifier block for power events
|
||||
+ * @current_profile: Currently selected platform profile option
|
||||
+ * @ppdev: Device registered with the platform profile handler
|
||||
+ * @profile_name: Name under which @ppdev is registered
|
||||
*
|
||||
* The amd_cpudata is key private data for each CPU thread in AMD P-State, and
|
||||
* represents all the attributes and goals that AMD P-State requests at runtime.
|
||||
Binary file not shown.
@@ -0,0 +1,104 @@
|
||||
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
|
||||
--- a/drivers/opp/core.c
|
||||
+++ b/drivers/opp/core.c
|
||||
@@ -453,8 +453,8 @@ int dev_pm_opp_get_opp_count(struct device *dev)
|
||||
_find_opp_table(dev);
|
||||
|
||||
if (IS_ERR(opp_table)) {
|
||||
- dev_dbg(dev, "%s: OPP table not found (%ld)\n",
|
||||
- __func__, PTR_ERR(opp_table));
|
||||
+ dev_dbg(dev, "%s: OPP table not found (%pe)\n",
|
||||
+ __func__, opp_table);
|
||||
return PTR_ERR(opp_table);
|
||||
}
|
||||
|
||||
@@ -611,8 +611,8 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
|
||||
_find_opp_table(dev);
|
||||
|
||||
if (IS_ERR(opp_table)) {
|
||||
- dev_err(dev, "%s: OPP table not found (%ld)\n", __func__,
|
||||
- PTR_ERR(opp_table));
|
||||
+ dev_err(dev, "%s: OPP table not found (%pe)\n", __func__,
|
||||
+ opp_table);
|
||||
return ERR_CAST(opp_table);
|
||||
}
|
||||
|
||||
@@ -722,8 +722,8 @@ struct dev_pm_opp *dev_pm_opp_find_key_exact(struct device *dev,
|
||||
struct opp_table *opp_table __free(put_opp_table) = _find_opp_table(dev);
|
||||
|
||||
if (IS_ERR(opp_table)) {
|
||||
- dev_err(dev, "%s: OPP table not found (%ld)\n", __func__,
|
||||
- PTR_ERR(opp_table));
|
||||
+ dev_err(dev, "%s: OPP table not found (%pe)\n", __func__,
|
||||
+ opp_table);
|
||||
return ERR_CAST(opp_table);
|
||||
}
|
||||
|
||||
@@ -1036,8 +1036,8 @@ static int _set_opp_voltage(struct device *dev, struct regulator *reg,
|
||||
|
||||
/* Regulator not available for device */
|
||||
if (IS_ERR(reg)) {
|
||||
- dev_dbg(dev, "%s: regulator not available: %ld\n", __func__,
|
||||
- PTR_ERR(reg));
|
||||
+ dev_dbg(dev, "%s: regulator not available: %pe\n", __func__,
|
||||
+ reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1448,8 +1448,8 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
|
||||
temp_freq = freq;
|
||||
opp = _find_freq_ceil(opp_table, &temp_freq);
|
||||
if (IS_ERR(opp)) {
|
||||
- dev_err(dev, "%s: failed to find OPP for freq %lu (%ld)\n",
|
||||
- __func__, freq, PTR_ERR(opp));
|
||||
+ dev_err(dev, "%s: failed to find OPP for freq %lu (%pe)\n",
|
||||
+ __func__, freq, opp);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
@@ -1581,6 +1581,8 @@ static struct opp_table *_update_opp_table_clk(struct device *dev,
|
||||
struct opp_table *opp_table,
|
||||
bool getclk)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
/*
|
||||
* Return early if we don't need to get clk or we have already done it
|
||||
* earlier.
|
||||
@@ -1607,9 +1609,9 @@ static struct opp_table *_update_opp_table_clk(struct device *dev,
|
||||
opp_table->clk = clk_get_optional(dev, NULL);
|
||||
|
||||
if (IS_ERR(opp_table->clk)) {
|
||||
+ ret = dev_err_probe(dev, PTR_ERR(opp_table->clk), "Couldn't find clock\n");
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
- dev_err_probe(dev, PTR_ERR(opp_table->clk), "Couldn't find clock\n");
|
||||
- return ERR_CAST(opp_table->clk);
|
||||
+ return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (opp_table->clk)
|
||||
@@ -2869,8 +2871,8 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
|
||||
struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp;
|
||||
|
||||
if (IS_ERR(opp_table)) {
|
||||
- dev_warn(dev, "%s: Device OPP not found (%ld)\n", __func__,
|
||||
- PTR_ERR(opp_table));
|
||||
+ dev_warn(dev, "%s: Device OPP not found (%pe)\n", __func__,
|
||||
+ opp_table);
|
||||
return PTR_ERR(opp_table);
|
||||
}
|
||||
|
||||
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
|
||||
--- a/drivers/opp/of.c
|
||||
+++ b/drivers/opp/of.c
|
||||
@@ -1345,8 +1345,8 @@ int of_get_required_opp_performance_state(struct device_node *np, int index)
|
||||
_find_table_of_opp_np(required_np);
|
||||
|
||||
if (IS_ERR(opp_table)) {
|
||||
- pr_err("%s: Failed to find required OPP table %pOF: %ld\n",
|
||||
- __func__, np, PTR_ERR(opp_table));
|
||||
+ pr_err("%s: Failed to find required OPP table %pOF: %pe\n",
|
||||
+ __func__, np, opp_table);
|
||||
return PTR_ERR(opp_table);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,18 +0,0 @@
|
||||
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1929,12 +1929,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->boost_supported = READ_ONCE(cpudata->boost_supported);
|
||||
|
||||
- /* Fetch the firmware programmed default EPP value */
|
||||
+ /* Cache the firmware programmed EPP */
|
||||
default_epp = amd_pstate_get_epp(cpudata);
|
||||
if (default_epp < 0) {
|
||||
ret = default_epp;
|
||||
goto free_cpudata1;
|
||||
}
|
||||
+ FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &cpudata->cppc_req_cached, default_epp);
|
||||
|
||||
/*
|
||||
* Set the policy to provide a valid fallback value in case
|
||||
Binary file not shown.
@@ -0,0 +1,54 @@
|
||||
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
|
||||
--- a/kernel/power/hibernate.c
|
||||
+++ b/kernel/power/hibernate.c
|
||||
@@ -408,9 +408,18 @@ int hibernation_snapshot(int platform_mode)
|
||||
if (error)
|
||||
goto Close;
|
||||
|
||||
+ error = dpm_prepare(PMSG_FREEZE);
|
||||
+ if (error)
|
||||
+ goto Complete;
|
||||
+
|
||||
+ /* Preallocate image memory before freezing kernel threads and shutting down devices. */
|
||||
+ error = hibernate_preallocate_memory();
|
||||
+ if (error)
|
||||
+ goto Complete;
|
||||
+
|
||||
error = freeze_kernel_threads();
|
||||
if (error)
|
||||
- goto Close;
|
||||
+ goto Cleanup;
|
||||
|
||||
if (hibernation_test(TEST_FREEZER)) {
|
||||
|
||||
@@ -422,15 +431,6 @@ int hibernation_snapshot(int platform_mode)
|
||||
goto Thaw;
|
||||
}
|
||||
|
||||
- error = dpm_prepare(PMSG_FREEZE);
|
||||
- if (error)
|
||||
- goto Complete;
|
||||
-
|
||||
- /* Preallocate image memory before shutting down devices. */
|
||||
- error = hibernate_preallocate_memory();
|
||||
- if (error)
|
||||
- goto Complete;
|
||||
-
|
||||
console_suspend_all();
|
||||
pm_restrict_gfp_mask();
|
||||
|
||||
@@ -464,10 +464,12 @@ int hibernation_snapshot(int platform_mode)
|
||||
platform_end(platform_mode);
|
||||
return error;
|
||||
|
||||
- Complete:
|
||||
- dpm_complete(PMSG_RECOVER);
|
||||
Thaw:
|
||||
thaw_kernel_threads();
|
||||
+ Cleanup:
|
||||
+ swsusp_free();
|
||||
+ Complete:
|
||||
+ dpm_complete(PMSG_RECOVER);
|
||||
goto Close;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,61 @@
|
||||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
|
||||
--- a/drivers/cpufreq/cpufreq.c
|
||||
+++ b/drivers/cpufreq/cpufreq.c
|
||||
@@ -2590,8 +2590,8 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
|
||||
|
||||
cpu = cpumask_first(policy->related_cpus);
|
||||
max_freq = arch_scale_freq_ref(cpu);
|
||||
- if (!max_freq)
|
||||
- max_freq = policy->cpuinfo.max_freq;
|
||||
+ if (!max_freq && cpufreq_driver->scale_freq_ref)
|
||||
+ max_freq = cpufreq_driver->scale_freq_ref(policy);
|
||||
|
||||
capped_freq = policy->max;
|
||||
|
||||
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
|
||||
--- a/drivers/cpufreq/intel_pstate.c
|
||||
+++ b/drivers/cpufreq/intel_pstate.c
|
||||
@@ -1175,6 +1175,14 @@ static bool hybrid_clear_max_perf_cpu(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static unsigned int intel_pstate_scale_freq_ref(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ if (READ_ONCE(all_cpu_data[policy->cpu]->capacity_perf))
|
||||
+ return policy->cpuinfo.max_freq;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void intel_pstate_update_freq_limits(struct cpudata *cpu)
|
||||
{
|
||||
int scaling = cpu->pstate.scaling;
|
||||
@@ -3092,6 +3100,7 @@ static struct cpufreq_driver intel_pstate = {
|
||||
.offline = intel_pstate_cpu_offline,
|
||||
.online = intel_pstate_cpu_online,
|
||||
.update_limits = intel_pstate_update_limits,
|
||||
+ .scale_freq_ref = intel_pstate_scale_freq_ref,
|
||||
.name = "intel_pstate",
|
||||
};
|
||||
|
||||
@@ -3415,6 +3424,7 @@ static struct cpufreq_driver intel_cpufreq = {
|
||||
.suspend = intel_cpufreq_suspend,
|
||||
.resume = intel_pstate_resume,
|
||||
.update_limits = intel_pstate_update_limits,
|
||||
+ .scale_freq_ref = intel_pstate_scale_freq_ref,
|
||||
.name = "intel_cpufreq",
|
||||
};
|
||||
|
||||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -420,6 +420,9 @@ struct cpufreq_driver {
|
||||
/* Will be called after the driver is fully initialized */
|
||||
void (*ready)(struct cpufreq_policy *policy);
|
||||
|
||||
+ /* Return the capacity reference frequency for policy. */
|
||||
+ unsigned int (*scale_freq_ref)(struct cpufreq_policy *policy);
|
||||
+
|
||||
struct freq_attr **attr;
|
||||
|
||||
/* platform specific boost support code */
|
||||
Binary file not shown.
@@ -278,25 +278,7 @@ diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
|
||||
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
|
||||
--- a/include/linux/memcontrol.h
|
||||
+++ b/include/linux/memcontrol.h
|
||||
@@ -270,10 +270,15 @@ struct mem_cgroup {
|
||||
#endif
|
||||
int kmemcg_id;
|
||||
|
||||
- struct memcg_vmstats_percpu __percpu *vmstats_percpu;
|
||||
-
|
||||
#ifdef CONFIG_CGROUP_WRITEBACK
|
||||
struct list_head cgwb_list;
|
||||
+#endif
|
||||
+
|
||||
+ /* Keep the hot per-CPU stats pointer away from memory event counters. */
|
||||
+ struct memcg_vmstats_percpu __percpu *vmstats_percpu
|
||||
+ ____cacheline_aligned_in_smp;
|
||||
+
|
||||
+#ifdef CONFIG_CGROUP_WRITEBACK
|
||||
struct wb_domain cgwb_domain;
|
||||
struct memcg_cgwb_frn cgwb_frn[MEMCG_CGWB_FRN_CNT];
|
||||
#endif
|
||||
@@ -947,6 +952,8 @@ unsigned long memcg_page_state_output(struct mem_cgroup *memcg, int item);
|
||||
@@ -952,6 +952,8 @@ unsigned long memcg_page_state_output(struct mem_cgroup *memcg, int item);
|
||||
bool memcg_stat_item_valid(int idx);
|
||||
bool memcg_vm_event_item_valid(enum vm_event_item idx);
|
||||
unsigned long lruvec_page_state(struct lruvec *lruvec, enum node_stat_item idx);
|
||||
@@ -305,7 +287,7 @@ diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
|
||||
unsigned long lruvec_page_state_local(struct lruvec *lruvec,
|
||||
enum node_stat_item idx);
|
||||
|
||||
@@ -1399,6 +1406,12 @@ static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
|
||||
@@ -1404,6 +1406,12 @@ static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
|
||||
return node_page_state(lruvec_pgdat(lruvec), idx);
|
||||
}
|
||||
|
||||
@@ -576,66 +558,6 @@ diff --git a/lib/maple_tree.c b/lib/maple_tree.c
|
||||
return wr_slot_store;
|
||||
|
||||
return wr_node_store;
|
||||
@@ -3793,35 +3825,40 @@ int mas_alloc_cyclic(struct ma_state *mas, unsigned long *startp,
|
||||
void *entry, unsigned long range_lo, unsigned long range_hi,
|
||||
unsigned long *next, gfp_t gfp)
|
||||
{
|
||||
- unsigned long min = range_lo;
|
||||
- int ret = 0;
|
||||
+ int ret;
|
||||
+ unsigned long min;
|
||||
+
|
||||
+ min = range_lo;
|
||||
+ do {
|
||||
+ range_lo = max(min, *next);
|
||||
+ ret = mas_empty_area(mas, range_lo, range_hi, 1);
|
||||
+ if (ret < 0 && range_lo > min) {
|
||||
+ mas_reset(mas);
|
||||
+ ret = mas_empty_area(mas, min, range_hi, 1);
|
||||
+ if (ret == 0)
|
||||
+ ret = 1;
|
||||
+ }
|
||||
+ if (ret < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ mas_insert(mas, entry);
|
||||
+ } while (mas_nomem(mas, gfp));
|
||||
+
|
||||
+ if (mas_is_err(mas)) {
|
||||
+ ret = xa_err(mas->node);
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- range_lo = max(min, *next);
|
||||
- ret = mas_empty_area(mas, range_lo, range_hi, 1);
|
||||
if ((mas->tree->ma_flags & MT_FLAGS_ALLOC_WRAPPED) && ret == 0) {
|
||||
mas->tree->ma_flags &= ~MT_FLAGS_ALLOC_WRAPPED;
|
||||
ret = 1;
|
||||
}
|
||||
- if (ret < 0 && range_lo > min) {
|
||||
- mas_reset(mas);
|
||||
- ret = mas_empty_area(mas, min, range_hi, 1);
|
||||
- if (ret == 0)
|
||||
- ret = 1;
|
||||
- }
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
-
|
||||
- do {
|
||||
- mas_insert(mas, entry);
|
||||
- } while (mas_nomem(mas, gfp));
|
||||
- if (mas_is_err(mas))
|
||||
- return xa_err(mas->node);
|
||||
-
|
||||
*startp = mas->index;
|
||||
*next = *startp + 1;
|
||||
if (*next == 0)
|
||||
mas->tree->ma_flags |= MT_FLAGS_ALLOC_WRAPPED;
|
||||
|
||||
+out:
|
||||
mas_destroy(mas);
|
||||
return ret;
|
||||
}
|
||||
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
|
||||
--- a/mm/khugepaged.c
|
||||
+++ b/mm/khugepaged.c
|
||||
@@ -898,24 +820,7 @@ diff --git a/mm/swap.c b/mm/swap.c
|
||||
static void lru_activate(struct lruvec *lruvec, struct folio *folio)
|
||||
{
|
||||
long nr_pages = folio_nr_pages(folio);
|
||||
@@ -1153,7 +1086,16 @@ static void lruvec_reparent_lru(struct lruvec *child_lruvec,
|
||||
for_each_managed_zone_pgdat(zone, NODE_DATA(nid), zid, MAX_NR_ZONES - 1) {
|
||||
unsigned long size = mem_cgroup_get_zone_lru_size(child_lruvec, lru, zid);
|
||||
|
||||
+ if (!size)
|
||||
+ continue;
|
||||
+
|
||||
+ /*
|
||||
+ * The folios are accounted to the parent from now on, so the
|
||||
+ * size has to be moved, not just copied. Leaving it behind
|
||||
+ * makes the dying child describe folios it no longer owns.
|
||||
+ */
|
||||
mem_cgroup_update_lru_size(parent_lruvec, lru, zid, size);
|
||||
+ mem_cgroup_update_lru_size(child_lruvec, lru, zid, -(long)size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1164,8 +1106,6 @@ void lru_reparent_memcg(struct mem_cgroup *memcg, struct mem_cgroup *parent, int
|
||||
@@ -1173,8 +1106,6 @@ void lru_reparent_memcg(struct mem_cgroup *memcg, struct mem_cgroup *parent, int
|
||||
|
||||
child_lruvec = mem_cgroup_lruvec(memcg, NODE_DATA(nid));
|
||||
parent_lruvec = mem_cgroup_lruvec(parent, NODE_DATA(nid));
|
||||
@@ -1129,20 +1034,7 @@ diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
pte_t *pte = pvmw->pte;
|
||||
unsigned long addr = pvmw->address;
|
||||
struct vm_area_struct *vma = pvmw->vma;
|
||||
@@ -4571,7 +4629,12 @@ void lru_gen_reparent_memcg(struct mem_cgroup *memcg, struct mem_cgroup *parent,
|
||||
for_each_managed_zone_pgdat(zone, NODE_DATA(nid), zid, MAX_NR_ZONES - 1) {
|
||||
unsigned long size = mem_cgroup_get_zone_lru_size(child_lruvec, lru, zid);
|
||||
|
||||
+ if (!size)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Move the accounting, do not duplicate it. */
|
||||
mem_cgroup_update_lru_size(parent_lruvec, lru, zid, size);
|
||||
+ mem_cgroup_update_lru_size(child_lruvec, lru, zid, -(long)size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4814,7 +4877,8 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
@@ -4819,7 +4877,8 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
struct reclaim_stat stat;
|
||||
struct lru_gen_mm_walk *walk;
|
||||
int scanned, reclaimed;
|
||||
@@ -1152,7 +1044,7 @@ diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
bool skip_retry = false;
|
||||
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
|
||||
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
||||
@@ -4826,6 +4890,7 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
@@ -4831,6 +4890,7 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
|
||||
scanned = isolate_folios(nr_to_scan, lruvec, sc, swappiness,
|
||||
&list, &isolated, &type, &type_scanned);
|
||||
@@ -1160,7 +1052,7 @@ diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
|
||||
/* Scanning may have emptied the oldest gen, flush it */
|
||||
if (scanned)
|
||||
@@ -4838,6 +4903,7 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
@@ -4843,6 +4903,7 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
retry:
|
||||
reclaimed = shrink_folio_list(&list, pgdat, sc, &stat, false, memcg);
|
||||
sc->nr_reclaimed += reclaimed;
|
||||
@@ -1168,7 +1060,7 @@ diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
/* Retry pass is only meant for clean folios without new isolation */
|
||||
if (isolated)
|
||||
handle_reclaim_writeback(isolated, pgdat, sc, &stat);
|
||||
@@ -4887,6 +4953,10 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
@@ -4892,6 +4953,10 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
|
||||
goto retry;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,35 @@
|
||||
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
|
||||
--- a/mm/pgtable-generic.c
|
||||
+++ b/mm/pgtable-generic.c
|
||||
@@ -438,12 +438,30 @@ static void kernel_pgtable_work_func(struct work_struct *work)
|
||||
__pagetable_free(pt);
|
||||
}
|
||||
|
||||
+static void schedule_kernel_pgtable_free(void)
|
||||
+{
|
||||
+ schedule_work(&kernel_pgtable_work.work);
|
||||
+}
|
||||
+
|
||||
void pagetable_free_kernel(struct ptdesc *pt)
|
||||
{
|
||||
spin_lock(&kernel_pgtable_work.lock);
|
||||
list_add(&pt->pt_list, &kernel_pgtable_work.list);
|
||||
spin_unlock(&kernel_pgtable_work.lock);
|
||||
|
||||
- schedule_work(&kernel_pgtable_work.work);
|
||||
+ /*
|
||||
+ * The workqueue may not exist yet while the system is booting.
|
||||
+ * kernel_pgtable_drain_early() schedules the work once it does.
|
||||
+ */
|
||||
+ if (system_state != SYSTEM_BOOTING)
|
||||
+ schedule_kernel_pgtable_free();
|
||||
}
|
||||
+
|
||||
+static int __init kernel_pgtable_drain_early(void)
|
||||
+{
|
||||
+ /* Free the kernel page tables queued while booting. */
|
||||
+ schedule_kernel_pgtable_free();
|
||||
+ return 0;
|
||||
+}
|
||||
+core_initcall(kernel_pgtable_drain_early);
|
||||
#endif
|
||||
BIN
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
|
||||
--- a/arch/x86/include/asm/pgtable.h
|
||||
+++ b/arch/x86/include/asm/pgtable.h
|
||||
@@ -806,7 +806,7 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
||||
pmdval_t val = pmd_val(pmd), oldval = val;
|
||||
pmd_t pmd_result;
|
||||
|
||||
- val &= (_HPAGE_CHG_MASK & ~_PAGE_DIRTY);
|
||||
+ val &= _HPAGE_CHG_MASK;
|
||||
val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK;
|
||||
val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK);
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -0,0 +1,92 @@
|
||||
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
|
||||
--- a/fs/btrfs/dev-replace.c
|
||||
+++ b/fs/btrfs/dev-replace.c
|
||||
@@ -627,7 +627,7 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
|
||||
|
||||
ret = mark_block_group_to_copy(fs_info, src_device);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto leave;
|
||||
|
||||
down_write(&dev_replace->rwsem);
|
||||
dev_replace->replace_task = current;
|
||||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
|
||||
--- a/fs/btrfs/ioctl.c
|
||||
+++ b/fs/btrfs/ioctl.c
|
||||
@@ -384,6 +384,7 @@ int btrfs_fileattr_set(struct mnt_idmap *idmap,
|
||||
inode_flags &= ~BTRFS_INODE_COMPRESS;
|
||||
inode_flags |= BTRFS_INODE_NOCOMPRESS;
|
||||
} else if (fsflags & FS_COMPR_FL) {
|
||||
+ enum btrfs_compression_type comp_type;
|
||||
|
||||
if (IS_SWAPFILE(&inode->vfs_inode))
|
||||
return -ETXTBSY;
|
||||
@@ -391,9 +392,23 @@ int btrfs_fileattr_set(struct mnt_idmap *idmap,
|
||||
inode_flags |= BTRFS_INODE_COMPRESS;
|
||||
inode_flags &= ~BTRFS_INODE_NOCOMPRESS;
|
||||
|
||||
- comp = btrfs_compress_type2str(fs_info->compress_type);
|
||||
- if (!comp || comp[0] == 0)
|
||||
- comp = btrfs_compress_type2str(BTRFS_COMPRESS_ZLIB);
|
||||
+ /*
|
||||
+ * Keep the algorithm recorded in the compression property,
|
||||
+ * otherwise changing an unrelated attribute would reset it to
|
||||
+ * the mount default, since FS_IOC_SETFLAGS callers write back
|
||||
+ * the whole flag set they got from FS_IOC_GETFLAGS and that
|
||||
+ * includes FS_COMPR_FL for any inode carrying the property.
|
||||
+ *
|
||||
+ * Inodes with the compress flag set but no property keep using
|
||||
+ * the mount default, so they behave as before.
|
||||
+ */
|
||||
+ if (inode->prop_compress)
|
||||
+ comp_type = inode->prop_compress;
|
||||
+ else if (fs_info->compress_type)
|
||||
+ comp_type = fs_info->compress_type;
|
||||
+ else
|
||||
+ comp_type = BTRFS_COMPRESS_ZLIB;
|
||||
+ comp = btrfs_compress_type2str(comp_type);
|
||||
} else {
|
||||
inode_flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
|
||||
}
|
||||
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
|
||||
--- a/fs/btrfs/send.c
|
||||
+++ b/fs/btrfs/send.c
|
||||
@@ -6417,6 +6417,13 @@ static int process_extent(struct send_ctx *sctx,
|
||||
|
||||
if (S_ISLNK(sctx->cur_inode_mode))
|
||||
return 0;
|
||||
+ if (unlikely(!S_ISREG(sctx->cur_inode_mode))) {
|
||||
+ btrfs_crit(sctx->send_root->fs_info,
|
||||
+ "send: extent for non-regular inode %llu root %llu mode 0%llo",
|
||||
+ key->objectid, btrfs_root_id(sctx->send_root),
|
||||
+ sctx->cur_inode_mode & S_IFMT);
|
||||
+ return -EUCLEAN;
|
||||
+ }
|
||||
|
||||
if (sctx->parent_root && !sctx->cur_inode_new) {
|
||||
ret = is_extent_unchanged(sctx, path, key);
|
||||
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
|
||||
--- a/fs/btrfs/zoned.c
|
||||
+++ b/fs/btrfs/zoned.c
|
||||
@@ -2710,6 +2710,7 @@ int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 leng
|
||||
{
|
||||
struct btrfs_block_group *block_group;
|
||||
u64 min_alloc_bytes;
|
||||
+ int ret = 0;
|
||||
|
||||
if (!btrfs_is_zoned(fs_info))
|
||||
return 0;
|
||||
@@ -2729,11 +2730,11 @@ int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 leng
|
||||
block_group->start + block_group->zone_capacity)
|
||||
goto out;
|
||||
|
||||
- do_zone_finish(block_group, true);
|
||||
+ ret = do_zone_finish(block_group, true);
|
||||
|
||||
out:
|
||||
btrfs_put_block_group(block_group);
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static void btrfs_zone_finish_endio_workfn(struct work_struct *work)
|
||||
Binary file not shown.
@@ -1,386 +0,0 @@
|
||||
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
|
||||
--- a/fs/btrfs/dev-replace.c
|
||||
+++ b/fs/btrfs/dev-replace.c
|
||||
@@ -626,7 +626,7 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
|
||||
|
||||
ret = mark_block_group_to_copy(fs_info, src_device);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto leave;
|
||||
|
||||
down_write(&dev_replace->rwsem);
|
||||
dev_replace->replace_task = current;
|
||||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
||||
--- a/fs/btrfs/inode.c
|
||||
+++ b/fs/btrfs/inode.c
|
||||
@@ -3436,6 +3436,9 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
|
||||
*/
|
||||
btrfs_remove_ordered_extent(ordered_extent);
|
||||
|
||||
+ /* Cleanup any remaining biocs attached to the OE. */
|
||||
+ btrfs_cleanup_ordered_bioc_list(ordered_extent);
|
||||
+
|
||||
/* once for us */
|
||||
btrfs_put_ordered_extent(ordered_extent);
|
||||
/* once for the tree */
|
||||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
|
||||
--- a/fs/btrfs/ioctl.c
|
||||
+++ b/fs/btrfs/ioctl.c
|
||||
@@ -384,6 +384,7 @@ int btrfs_fileattr_set(struct mnt_idmap *idmap,
|
||||
inode_flags &= ~BTRFS_INODE_COMPRESS;
|
||||
inode_flags |= BTRFS_INODE_NOCOMPRESS;
|
||||
} else if (fsflags & FS_COMPR_FL) {
|
||||
+ enum btrfs_compression_type comp_type;
|
||||
|
||||
if (IS_SWAPFILE(&inode->vfs_inode))
|
||||
return -ETXTBSY;
|
||||
@@ -391,9 +392,23 @@ int btrfs_fileattr_set(struct mnt_idmap *idmap,
|
||||
inode_flags |= BTRFS_INODE_COMPRESS;
|
||||
inode_flags &= ~BTRFS_INODE_NOCOMPRESS;
|
||||
|
||||
- comp = btrfs_compress_type2str(fs_info->compress_type);
|
||||
- if (!comp || comp[0] == 0)
|
||||
- comp = btrfs_compress_type2str(BTRFS_COMPRESS_ZLIB);
|
||||
+ /*
|
||||
+ * Keep the algorithm recorded in the compression property,
|
||||
+ * otherwise changing an unrelated attribute would reset it to
|
||||
+ * the mount default, since FS_IOC_SETFLAGS callers write back
|
||||
+ * the whole flag set they got from FS_IOC_GETFLAGS and that
|
||||
+ * includes FS_COMPR_FL for any inode carrying the property.
|
||||
+ *
|
||||
+ * Inodes with the compress flag set but no property keep using
|
||||
+ * the mount default, so they behave as before.
|
||||
+ */
|
||||
+ if (inode->prop_compress)
|
||||
+ comp_type = inode->prop_compress;
|
||||
+ else if (fs_info->compress_type)
|
||||
+ comp_type = fs_info->compress_type;
|
||||
+ else
|
||||
+ comp_type = BTRFS_COMPRESS_ZLIB;
|
||||
+ comp = btrfs_compress_type2str(comp_type);
|
||||
} else {
|
||||
inode_flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
|
||||
}
|
||||
diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
|
||||
--- a/fs/btrfs/raid-stripe-tree.c
|
||||
+++ b/fs/btrfs/raid-stripe-tree.c
|
||||
@@ -310,8 +310,10 @@ static int update_raid_extent_item(struct btrfs_trans_handle *trans,
|
||||
|
||||
ret = btrfs_search_slot(trans, trans->fs_info->stripe_root, key, path,
|
||||
0, 1);
|
||||
- if (ret)
|
||||
- return (ret == 1 ? ret : -EINVAL);
|
||||
+ if (ret > 0)
|
||||
+ ret = -ENOENT;
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
leaf = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
@@ -337,7 +339,6 @@ int btrfs_insert_one_raid_extent(struct btrfs_trans_handle *trans,
|
||||
stripe_extent = kzalloc(item_size, GFP_NOFS);
|
||||
if (unlikely(!stripe_extent)) {
|
||||
btrfs_abort_transaction(trans, -ENOMEM);
|
||||
- btrfs_end_transaction(trans);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -374,7 +375,7 @@ int btrfs_insert_raid_extent(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_ordered_extent *ordered_extent)
|
||||
{
|
||||
struct btrfs_io_context *bioc;
|
||||
- int ret;
|
||||
+ int ret = 0;
|
||||
|
||||
if (!btrfs_fs_incompat(trans->fs_info, RAID_STRIPE_TREE))
|
||||
return 0;
|
||||
@@ -382,17 +383,23 @@ int btrfs_insert_raid_extent(struct btrfs_trans_handle *trans,
|
||||
list_for_each_entry(bioc, &ordered_extent->bioc_list, rst_ordered_entry) {
|
||||
ret = btrfs_insert_one_raid_extent(trans, bioc);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ break;
|
||||
}
|
||||
|
||||
- while (!list_empty(&ordered_extent->bioc_list)) {
|
||||
- bioc = list_first_entry(&ordered_extent->bioc_list,
|
||||
+ btrfs_cleanup_ordered_bioc_list(ordered_extent);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void btrfs_cleanup_ordered_bioc_list(struct btrfs_ordered_extent *ordered)
|
||||
+{
|
||||
+ while (!list_empty(&ordered->bioc_list)) {
|
||||
+ struct btrfs_io_context *bioc;
|
||||
+
|
||||
+ bioc = list_first_entry(&ordered->bioc_list,
|
||||
typeof(*bioc), rst_ordered_entry);
|
||||
list_del(&bioc->rst_ordered_entry);
|
||||
btrfs_put_bioc(bioc);
|
||||
}
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
int btrfs_get_raid_extent_offset(struct btrfs_fs_info *fs_info,
|
||||
diff --git a/fs/btrfs/raid-stripe-tree.h b/fs/btrfs/raid-stripe-tree.h
|
||||
--- a/fs/btrfs/raid-stripe-tree.h
|
||||
+++ b/fs/btrfs/raid-stripe-tree.h
|
||||
@@ -28,6 +28,7 @@ int btrfs_get_raid_extent_offset(struct btrfs_fs_info *fs_info,
|
||||
u32 stripe_index, struct btrfs_io_stripe *stripe);
|
||||
int btrfs_insert_raid_extent(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_ordered_extent *ordered_extent);
|
||||
+void btrfs_cleanup_ordered_bioc_list(struct btrfs_ordered_extent *ordered);
|
||||
|
||||
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
|
||||
int btrfs_insert_one_raid_extent(struct btrfs_trans_handle *trans,
|
||||
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
|
||||
--- a/fs/btrfs/scrub.c
|
||||
+++ b/fs/btrfs/scrub.c
|
||||
@@ -1023,6 +1023,10 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
|
||||
|
||||
skip:
|
||||
for_each_set_bit(sector_nr, &extent_bitmap, stripe->nr_sectors) {
|
||||
+ const u64 sector_logical = stripe->logical +
|
||||
+ ((u64)sector_nr << fs_info->sectorsize_bits);
|
||||
+ const u64 sector_physical = physical +
|
||||
+ ((u64)sector_nr << fs_info->sectorsize_bits);
|
||||
bool repaired = false;
|
||||
|
||||
if (scrub_bitmap_test_bit_is_metadata(stripe, sector_nr)) {
|
||||
@@ -1051,12 +1055,12 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
|
||||
if (dev) {
|
||||
btrfs_err_rl(fs_info,
|
||||
"scrub: fixed up error at logical %llu on dev %s physical %llu",
|
||||
- stripe->logical, btrfs_dev_name(dev),
|
||||
- physical);
|
||||
+ sector_logical, btrfs_dev_name(dev),
|
||||
+ sector_physical);
|
||||
} else {
|
||||
btrfs_err_rl(fs_info,
|
||||
"scrub: fixed up error at logical %llu on mirror %u",
|
||||
- stripe->logical, stripe->mirror_num);
|
||||
+ sector_logical, stripe->mirror_num);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1065,30 +1069,30 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
|
||||
if (dev) {
|
||||
btrfs_err_rl(fs_info,
|
||||
"scrub: unable to fixup (regular) error at logical %llu on dev %s physical %llu",
|
||||
- stripe->logical, btrfs_dev_name(dev),
|
||||
- physical);
|
||||
+ sector_logical, btrfs_dev_name(dev),
|
||||
+ sector_physical);
|
||||
} else {
|
||||
btrfs_err_rl(fs_info,
|
||||
"scrub: unable to fixup (regular) error at logical %llu on mirror %u",
|
||||
- stripe->logical, stripe->mirror_num);
|
||||
+ sector_logical, stripe->mirror_num);
|
||||
}
|
||||
|
||||
if (scrub_bitmap_test_bit_io_error(stripe, sector_nr))
|
||||
if (__ratelimit(&rs) && dev)
|
||||
scrub_print_common_warning("i/o error", dev, false,
|
||||
- stripe->logical, physical);
|
||||
+ sector_logical, sector_physical);
|
||||
if (scrub_bitmap_test_bit_csum_error(stripe, sector_nr))
|
||||
if (__ratelimit(&rs) && dev)
|
||||
scrub_print_common_warning("checksum error", dev, false,
|
||||
- stripe->logical, physical);
|
||||
+ sector_logical, sector_physical);
|
||||
if (scrub_bitmap_test_bit_meta_error(stripe, sector_nr))
|
||||
if (__ratelimit(&rs) && dev)
|
||||
scrub_print_common_warning("header error", dev, false,
|
||||
- stripe->logical, physical);
|
||||
+ sector_logical, sector_physical);
|
||||
if (scrub_bitmap_test_bit_meta_gen_error(stripe, sector_nr))
|
||||
if (__ratelimit(&rs) && dev)
|
||||
scrub_print_common_warning("generation error", dev, false,
|
||||
- stripe->logical, physical);
|
||||
+ sector_logical, sector_physical);
|
||||
}
|
||||
|
||||
/* Update the device stats. */
|
||||
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
|
||||
--- a/fs/btrfs/send.c
|
||||
+++ b/fs/btrfs/send.c
|
||||
@@ -2065,7 +2065,7 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
|
||||
|
||||
ret = is_inode_existent(sctx, dir, dir_gen, NULL, &parent_root_dir_gen);
|
||||
if (ret <= 0)
|
||||
- return 0;
|
||||
+ return ret;
|
||||
|
||||
/*
|
||||
* If we have a parent root we need to verify that the parent dir was
|
||||
@@ -6417,6 +6417,13 @@ static int process_extent(struct send_ctx *sctx,
|
||||
|
||||
if (S_ISLNK(sctx->cur_inode_mode))
|
||||
return 0;
|
||||
+ if (unlikely(!S_ISREG(sctx->cur_inode_mode))) {
|
||||
+ btrfs_crit(sctx->send_root->fs_info,
|
||||
+ "send: extent for non-regular inode %llu root %llu mode 0%llo",
|
||||
+ key->objectid, btrfs_root_id(sctx->send_root),
|
||||
+ sctx->cur_inode_mode & S_IFMT);
|
||||
+ return -EUCLEAN;
|
||||
+ }
|
||||
|
||||
if (sctx->parent_root && !sctx->cur_inode_new) {
|
||||
ret = is_extent_unchanged(sctx, path, key);
|
||||
diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
|
||||
--- a/fs/btrfs/tests/extent-io-tests.c
|
||||
+++ b/fs/btrfs/tests/extent-io-tests.c
|
||||
@@ -133,14 +133,14 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
|
||||
if (IS_ERR(root)) {
|
||||
test_std_err(TEST_ALLOC_ROOT);
|
||||
ret = PTR_ERR(root);
|
||||
- goto out;
|
||||
+ goto out_root_info;
|
||||
}
|
||||
|
||||
inode = btrfs_new_test_inode();
|
||||
if (!inode) {
|
||||
test_std_err(TEST_ALLOC_INODE);
|
||||
ret = -ENOMEM;
|
||||
- goto out;
|
||||
+ goto out_root_info;
|
||||
}
|
||||
tmp = &BTRFS_I(inode)->io_tree;
|
||||
BTRFS_I(inode)->root = root;
|
||||
@@ -333,6 +333,7 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
|
||||
process_page_range(inode, 0, total_dirty - 1,
|
||||
PROCESS_UNLOCK | PROCESS_RELEASE);
|
||||
iput(inode);
|
||||
+out_root_info:
|
||||
btrfs_free_dummy_root(root);
|
||||
btrfs_free_dummy_fs_info(fs_info);
|
||||
return ret;
|
||||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
|
||||
--- a/fs/btrfs/transaction.c
|
||||
+++ b/fs/btrfs/transaction.c
|
||||
@@ -458,8 +458,19 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
|
||||
* through btrfs_record_root_in_trans without having to take the
|
||||
* lock. smp_wmb() makes sure that all the writes above are
|
||||
* done before we pop in the zero below
|
||||
+ *
|
||||
+ * If @force is true, it means the call is from
|
||||
+ * qgroup_account_snapshot(), which only requires radix tree
|
||||
+ * tracking.
|
||||
+ * We should not force reloc root creation here, as the root
|
||||
+ * may have already been modified, and in that case
|
||||
+ * root->commit_root has already been dropped.
|
||||
+ *
|
||||
+ * Using that commit root will cause the reloc root to refer
|
||||
+ * to a deleted extent, causing extent tree corruption.
|
||||
*/
|
||||
- ret = btrfs_init_reloc_root(trans, root);
|
||||
+ if (!force)
|
||||
+ ret = btrfs_init_reloc_root(trans, root);
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(BTRFS_ROOT_IN_TRANS_SETUP, &root->state);
|
||||
}
|
||||
@@ -2583,6 +2594,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
|
||||
ret = btrfs_write_and_wait_transaction(trans);
|
||||
if (unlikely(ret)) {
|
||||
btrfs_err(fs_info, "error while writing out transaction: %pe", ERR_PTR(ret));
|
||||
+ /*
|
||||
+ * Abort before releasing tree_log_mutex, so a log sync waiting
|
||||
+ * on it sees the fs error and skips writing super_for_commit
|
||||
+ * for this failed transaction. See btrfs_sync_log().
|
||||
+ */
|
||||
+ btrfs_abort_transaction(trans, ret);
|
||||
mutex_unlock(&fs_info->tree_log_mutex);
|
||||
goto scrub_continue;
|
||||
}
|
||||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
|
||||
--- a/fs/btrfs/volumes.c
|
||||
+++ b/fs/btrfs/volumes.c
|
||||
@@ -3035,7 +3035,11 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
|
||||
error_sysfs:
|
||||
btrfs_sysfs_remove_device(device);
|
||||
mutex_lock(&fs_info->fs_devices->device_list_mutex);
|
||||
+ if (seeding_dev)
|
||||
+ btrfs_assign_next_active_device(device, seed_devices->latest_dev);
|
||||
mutex_lock(&fs_info->chunk_mutex);
|
||||
+ if (!list_empty(&device->post_commit_list))
|
||||
+ list_del_init(&device->post_commit_list);
|
||||
list_del_rcu(&device->dev_list);
|
||||
list_del(&device->dev_alloc_list);
|
||||
fs_info->fs_devices->num_devices--;
|
||||
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
|
||||
--- a/fs/btrfs/zoned.c
|
||||
+++ b/fs/btrfs/zoned.c
|
||||
@@ -2626,16 +2626,13 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
|
||||
down_read(&dev_replace->rwsem);
|
||||
map = block_group->physical_map;
|
||||
for (i = 0; i < map->num_stripes; i++) {
|
||||
-
|
||||
ret = call_zone_finish(block_group, &map->stripes[i]);
|
||||
- if (ret) {
|
||||
- up_read(&dev_replace->rwsem);
|
||||
- return ret;
|
||||
- }
|
||||
+ if (ret)
|
||||
+ break;
|
||||
}
|
||||
up_read(&dev_replace->rwsem);
|
||||
|
||||
- if (!fully_written)
|
||||
+ if (!ret && !fully_written)
|
||||
btrfs_dec_block_group_ro(block_group);
|
||||
|
||||
spin_lock(&fs_info->zone_active_bgs_lock);
|
||||
@@ -2648,7 +2645,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
|
||||
|
||||
clear_and_wake_up_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
int btrfs_zone_finish(struct btrfs_block_group *block_group)
|
||||
@@ -2713,6 +2710,7 @@ int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 leng
|
||||
{
|
||||
struct btrfs_block_group *block_group;
|
||||
u64 min_alloc_bytes;
|
||||
+ int ret = 0;
|
||||
|
||||
if (!btrfs_is_zoned(fs_info))
|
||||
return 0;
|
||||
@@ -2732,11 +2730,11 @@ int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 leng
|
||||
block_group->start + block_group->zone_capacity)
|
||||
goto out;
|
||||
|
||||
- do_zone_finish(block_group, true);
|
||||
+ ret = do_zone_finish(block_group, true);
|
||||
|
||||
out:
|
||||
btrfs_put_block_group(block_group);
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static void btrfs_zone_finish_endio_workfn(struct work_struct *work)
|
||||
diff --git a/fs/btrfs/zstd.c b/fs/btrfs/zstd.c
|
||||
--- a/fs/btrfs/zstd.c
|
||||
+++ b/fs/btrfs/zstd.c
|
||||
@@ -307,8 +307,17 @@ struct list_head *zstd_get_workspace(struct btrfs_fs_info *fs_info, int level)
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
prepare_to_wait(&zwsm->wait, &wait, TASK_UNINTERRUPTIBLE);
|
||||
- schedule();
|
||||
+ /*
|
||||
+ * Re-check after being queued: zstd_put_workspace() only wakes
|
||||
+ * a queue that already has a sleeper, so a workspace returned
|
||||
+ * since the failed allocation woke nobody.
|
||||
+ */
|
||||
+ ws = zstd_find_workspace(fs_info, level);
|
||||
+ if (!ws)
|
||||
+ schedule();
|
||||
finish_wait(&zwsm->wait, &wait);
|
||||
+ if (ws)
|
||||
+ return ws;
|
||||
|
||||
goto again;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,97 @@
|
||||
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
|
||||
--- a/fs/btrfs/block-group.c
|
||||
+++ b/fs/btrfs/block-group.c
|
||||
@@ -3074,6 +3074,18 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Ensure the corresponding space_info object is created and
|
||||
+ * assigned to our block group. We want our bg to be added to the rbtree
|
||||
+ * with its ->space_info set.
|
||||
+ *
|
||||
+ * On a zoned filesystem btrfs_add_new_free_space() ends up in
|
||||
+ * __btrfs_add_free_space_zoned(), which dereferences
|
||||
+ * block_group->space_info, so it has to be set beforehand.
|
||||
+ */
|
||||
+ cache->space_info = space_info;
|
||||
+ ASSERT(cache->space_info);
|
||||
+
|
||||
ret = btrfs_add_new_free_space(cache, chunk_offset, chunk_offset + size, NULL);
|
||||
btrfs_free_excluded_extents(cache);
|
||||
if (ret) {
|
||||
@@ -3081,14 +3093,6 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Ensure the corresponding space_info object is created and
|
||||
- * assigned to our block group. We want our bg to be added to the rbtree
|
||||
- * with its ->space_info set.
|
||||
- */
|
||||
- cache->space_info = space_info;
|
||||
- ASSERT(cache->space_info);
|
||||
-
|
||||
ret = btrfs_add_block_group_cache(cache);
|
||||
if (ret) {
|
||||
btrfs_remove_free_space_cache(cache);
|
||||
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
|
||||
--- a/fs/btrfs/tree-checker.c
|
||||
+++ b/fs/btrfs/tree-checker.c
|
||||
@@ -1909,6 +1909,16 @@ static int check_inode_ref(struct extent_buffer *leaf,
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
+ if (unlikely(btrfs_is_fstree(btrfs_header_owner(leaf)) &&
|
||||
+ (key->offset < BTRFS_FIRST_FREE_OBJECTID ||
|
||||
+ key->offset > BTRFS_LAST_FREE_OBJECTID))) {
|
||||
+ inode_ref_err(leaf, slot,
|
||||
+ "invalid offset for ref key, have %llu expect [%llu, %lld]",
|
||||
+ key->offset, BTRFS_FIRST_FREE_OBJECTID,
|
||||
+ BTRFS_LAST_FREE_OBJECTID);
|
||||
+ return -EUCLEAN;
|
||||
+ }
|
||||
+
|
||||
ptr = btrfs_item_ptr_offset(leaf, slot);
|
||||
end = ptr + btrfs_item_size(leaf, slot);
|
||||
while (ptr < end) {
|
||||
@@ -1952,12 +1962,14 @@ static int check_inode_extref(struct extent_buffer *leaf,
|
||||
{
|
||||
unsigned long ptr = btrfs_item_ptr_offset(leaf, slot);
|
||||
unsigned long end = ptr + btrfs_item_size(leaf, slot);
|
||||
+ const bool is_fstree = btrfs_is_fstree(btrfs_header_owner(leaf));
|
||||
|
||||
if (unlikely(!check_prev_ino(leaf, key, slot, prev_key)))
|
||||
return -EUCLEAN;
|
||||
|
||||
while (ptr < end) {
|
||||
struct btrfs_inode_extref *extref = (struct btrfs_inode_extref *)ptr;
|
||||
+ u64 parent;
|
||||
u16 namelen;
|
||||
|
||||
if (unlikely(ptr + sizeof(*extref) > end)) {
|
||||
@@ -1967,7 +1979,24 @@ static int check_inode_extref(struct extent_buffer *leaf,
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
+ parent = btrfs_inode_extref_parent(leaf, extref);
|
||||
+ if (unlikely(is_fstree && (parent < BTRFS_FIRST_FREE_OBJECTID ||
|
||||
+ parent > BTRFS_LAST_FREE_OBJECTID))) {
|
||||
+ inode_ref_err(leaf, slot,
|
||||
+ "invalid parent for extref key, have %llu expect [%llu, %lld]",
|
||||
+ parent, BTRFS_FIRST_FREE_OBJECTID,
|
||||
+ BTRFS_LAST_FREE_OBJECTID);
|
||||
+ return -EUCLEAN;
|
||||
+ }
|
||||
+
|
||||
namelen = btrfs_inode_extref_name_len(leaf, extref);
|
||||
+ if (unlikely(namelen == 0 || namelen > BTRFS_NAME_LEN)) {
|
||||
+ inode_ref_err(leaf, slot,
|
||||
+ "invalid inode extref name length, has %u expect [1, %u]",
|
||||
+ namelen, BTRFS_NAME_LEN);
|
||||
+ return -EUCLEAN;
|
||||
+ }
|
||||
+
|
||||
if (unlikely(ptr + sizeof(*extref) + namelen > end)) {
|
||||
inode_ref_err(leaf, slot,
|
||||
"inode extref overflow, ptr %lu end %lu namelen %u",
|
||||
Binary file not shown.
@@ -0,0 +1,77 @@
|
||||
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
|
||||
--- a/fs/btrfs/tree-checker.c
|
||||
+++ b/fs/btrfs/tree-checker.c
|
||||
@@ -2306,7 +2306,7 @@ static int check_free_space_extent(struct extent_buffer *leaf, struct btrfs_key
|
||||
|
||||
if (unlikely(btrfs_item_size(leaf, slot) != 0)) {
|
||||
generic_err(leaf, slot,
|
||||
- "invalid item size for free space info, has %u expect 0",
|
||||
+ "invalid item size for free space extent, has %u expect 0",
|
||||
btrfs_item_size(leaf, slot));
|
||||
return -EUCLEAN;
|
||||
}
|
||||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
|
||||
--- a/fs/btrfs/volumes.c
|
||||
+++ b/fs/btrfs/volumes.c
|
||||
@@ -740,6 +740,36 @@ const u8 *btrfs_sb_fsid_ptr(const struct btrfs_super_block *sb)
|
||||
return has_metadata_uuid ? sb->metadata_uuid : sb->fsid;
|
||||
}
|
||||
|
||||
+static bool should_rename_device(const struct btrfs_device *dev)
|
||||
+{
|
||||
+ bool ret;
|
||||
+ const char *old_name;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ old_name = rcu_dereference(dev->name);
|
||||
+ /*
|
||||
+ * For systems booted without an initramfs, the rootfs has the device
|
||||
+ * name "/dev/root".
|
||||
+ *
|
||||
+ * Although using btrfs without an initramfs is not recommended (if a
|
||||
+ * new device is added to the rootfs, the system can no longer boot, as
|
||||
+ * there is no way to register all devices), there is still a minority
|
||||
+ * of users doing this.
|
||||
+ *
|
||||
+ * And after the system is up, a later device scan on the real block
|
||||
+ * device file will never get this device's name updated, as the
|
||||
+ * device->devt is still the same.
|
||||
+ *
|
||||
+ * Here we add one and only one exception for "/dev/root", to allow the
|
||||
+ * device name to be updated even if the new path points to the same
|
||||
+ * block device.
|
||||
+ */
|
||||
+ ret = (strcmp(old_name, "/dev/root") == 0);
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Add new device to list of registered devices
|
||||
*
|
||||
@@ -860,7 +890,8 @@ static noinline struct btrfs_device *device_list_add(const char *path,
|
||||
MAJOR(path_devt), MINOR(path_devt),
|
||||
current->comm, task_pid_nr(current));
|
||||
|
||||
- } else if (!device->name || device->devt != path_devt) {
|
||||
+ } else if (!device->name || device->devt != path_devt ||
|
||||
+ should_rename_device(device)) {
|
||||
const char *old_name;
|
||||
|
||||
/*
|
||||
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
|
||||
--- a/fs/btrfs/zoned.c
|
||||
+++ b/fs/btrfs/zoned.c
|
||||
@@ -2688,6 +2688,11 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
|
||||
|
||||
switch (flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
|
||||
case 0: /* single */
|
||||
+ case BTRFS_BLOCK_GROUP_RAID0:
|
||||
+ case BTRFS_BLOCK_GROUP_RAID1:
|
||||
+ case BTRFS_BLOCK_GROUP_RAID1C3:
|
||||
+ case BTRFS_BLOCK_GROUP_RAID1C4:
|
||||
+ case BTRFS_BLOCK_GROUP_RAID10:
|
||||
ret = (atomic_read(&zinfo->active_zones_left) >= (1 + reserved));
|
||||
break;
|
||||
case BTRFS_BLOCK_GROUP_DUP:
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
|
||||
--- a/fs/fuse/dir.c
|
||||
+++ b/fs/fuse/dir.c
|
||||
@@ -2280,6 +2280,9 @@ int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
@@ -2289,6 +2289,9 @@ int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
*/
|
||||
if ((is_truncate || !is_wb) &&
|
||||
S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
|
||||
@@ -28,7 +28,7 @@ diff --git a/fs/fuse/file.c b/fs/fuse/file.c
|
||||
if (inode->i_size < pos + iov_iter_count(ii))
|
||||
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
|
||||
|
||||
@@ -2908,6 +2912,11 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
|
||||
@@ -2909,6 +2913,11 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
|
||||
|
||||
/* we could have extended the file */
|
||||
if (!(mode & FALLOC_FL_KEEP_SIZE)) {
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
--- a/fs/fuse/dev.c
|
||||
+++ b/fs/fuse/dev.c
|
||||
@@ -216,10 +216,13 @@ EXPORT_SYMBOL_GPL(fuse_req_hash);
|
||||
@@ -213,10 +213,13 @@ EXPORT_SYMBOL_GPL(fuse_req_hash);
|
||||
/*
|
||||
* A new request is available, wake fiq->waitq
|
||||
*/
|
||||
@@ -17,7 +17,7 @@ diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
|
||||
spin_unlock(&fiq->lock);
|
||||
}
|
||||
@@ -236,7 +239,7 @@ void fuse_dev_queue_forget(struct fuse_iqueue *fiq,
|
||||
@@ -233,7 +236,7 @@ void fuse_dev_queue_forget(struct fuse_iqueue *fiq,
|
||||
if (fiq->connected) {
|
||||
fiq->forget_list_tail->next = forget;
|
||||
fiq->forget_list_tail = forget;
|
||||
@@ -26,7 +26,7 @@ diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
} else {
|
||||
kfree(forget);
|
||||
spin_unlock(&fiq->lock);
|
||||
@@ -258,7 +261,7 @@ void fuse_dev_queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
|
||||
@@ -255,7 +258,7 @@ void fuse_dev_queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
|
||||
list_del_init(&req->intr_entry);
|
||||
spin_unlock(&fiq->lock);
|
||||
} else {
|
||||
@@ -35,7 +35,7 @@ diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
}
|
||||
} else {
|
||||
spin_unlock(&fiq->lock);
|
||||
@@ -288,11 +291,13 @@ EXPORT_SYMBOL_GPL(fuse_request_assign_unique);
|
||||
@@ -285,11 +288,13 @@ EXPORT_SYMBOL_GPL(fuse_request_assign_unique);
|
||||
|
||||
static void fuse_dev_queue_req(struct fuse_iqueue *fiq, struct fuse_req *req)
|
||||
{
|
||||
@@ -50,7 +50,7 @@ diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
} else {
|
||||
spin_unlock(&fiq->lock);
|
||||
req->out.h.error = -ENOTCONN;
|
||||
@@ -755,6 +760,11 @@ static void __fuse_request_send(struct fuse_req *req)
|
||||
@@ -752,6 +757,11 @@ static void __fuse_request_send(struct fuse_req *req)
|
||||
/* acquire extra reference, since request is still needed after
|
||||
fuse_request_end() */
|
||||
__fuse_get_request(req);
|
||||
@@ -62,7 +62,7 @@ diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
fuse_send_one(fiq, req);
|
||||
|
||||
request_wait_answer(req);
|
||||
@@ -1809,7 +1819,7 @@ void fuse_chan_resend(struct fuse_chan *fch)
|
||||
@@ -1806,7 +1816,7 @@ void fuse_chan_resend(struct fuse_chan *fch)
|
||||
}
|
||||
/* iq and pq requests are both oldest to newest */
|
||||
list_splice(&to_queue, &fiq->pending);
|
||||
@@ -94,7 +94,7 @@ diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h
|
||||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
|
||||
--- a/fs/fuse/inode.c
|
||||
+++ b/fs/fuse/inode.c
|
||||
@@ -1417,6 +1417,7 @@ static void process_init_reply(struct fuse_args *args, int error)
|
||||
@@ -1420,6 +1420,7 @@ static void process_init_reply(struct fuse_args *args, int error)
|
||||
|
||||
fm->sb->s_bdi->ra_pages =
|
||||
min(fm->sb->s_bdi->ra_pages, ra_pages);
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
--- a/fs/fuse/dev.c
|
||||
+++ b/fs/fuse/dev.c
|
||||
@@ -409,7 +409,8 @@ void fuse_chan_max_background_set(struct fuse_chan *fch, unsigned int val)
|
||||
@@ -406,7 +406,8 @@ void fuse_chan_max_background_set(struct fuse_chan *fch, unsigned int val)
|
||||
fch->max_background = val;
|
||||
fch->blocked = fch->num_background >= fch->max_background;
|
||||
if (!fch->blocked)
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,119 @@
|
||||
diff --git a/fs/internal.h b/fs/internal.h
|
||||
--- a/fs/internal.h
|
||||
+++ b/fs/internal.h
|
||||
@@ -204,6 +204,7 @@ int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
|
||||
int flag);
|
||||
int chown_common(const struct path *path, uid_t user, gid_t group);
|
||||
extern int vfs_open(const struct path *, struct file *);
|
||||
+int vfs_open_consume(struct path *, struct file *);
|
||||
|
||||
/*
|
||||
* inode.c
|
||||
diff --git a/fs/namei.c b/fs/namei.c
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -4652,6 +4652,7 @@ static const char *open_last_lookups(struct nameidata *nd,
|
||||
static int do_open(struct nameidata *nd,
|
||||
struct file *file, const struct open_flags *op)
|
||||
{
|
||||
+ struct vfsmount *mnt;
|
||||
struct mnt_idmap *idmap;
|
||||
int open_flag = op->open_flag;
|
||||
bool do_truncate;
|
||||
@@ -4693,11 +4694,17 @@ static int do_open(struct nameidata *nd,
|
||||
error = mnt_want_write(nd->path.mnt);
|
||||
if (error)
|
||||
return error;
|
||||
+ /*
|
||||
+ * A dedicated reference is needed because after the call to
|
||||
+ * vfs_open_consume() we no longer own the reference in nd->path.mnt
|
||||
+ * while we need to undo write acess below.
|
||||
+ */
|
||||
+ mnt = mntget(nd->path.mnt);
|
||||
do_truncate = true;
|
||||
}
|
||||
error = may_open(idmap, &nd->path, acc_mode, open_flag);
|
||||
if (!error && !(file->f_mode & FMODE_OPENED))
|
||||
- error = vfs_open(&nd->path, file);
|
||||
+ error = vfs_open_consume(&nd->path, file);
|
||||
if (!error)
|
||||
error = security_file_post_open(file, op->acc_mode);
|
||||
if (!error && do_truncate)
|
||||
@@ -4706,8 +4713,10 @@ static int do_open(struct nameidata *nd,
|
||||
WARN_ON(1);
|
||||
error = -EINVAL;
|
||||
}
|
||||
- if (do_truncate)
|
||||
- mnt_drop_write(nd->path.mnt);
|
||||
+ if (do_truncate) {
|
||||
+ mnt_drop_write(mnt);
|
||||
+ mntput(mnt);
|
||||
+ }
|
||||
return error;
|
||||
}
|
||||
|
||||
diff --git a/fs/open.c b/fs/open.c
|
||||
--- a/fs/open.c
|
||||
+++ b/fs/open.c
|
||||
@@ -882,6 +882,11 @@ static inline int file_get_write_access(struct file *f)
|
||||
return error;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Populate struct file
|
||||
+ *
|
||||
+ * NOTE: it assumes f_path is populated and consumes the caller's reference.
|
||||
+ */
|
||||
static int do_dentry_open(struct file *f,
|
||||
int (*open)(struct inode *, struct file *))
|
||||
{
|
||||
@@ -889,7 +894,6 @@ static int do_dentry_open(struct file *f,
|
||||
struct inode *inode = f->f_path.dentry->d_inode;
|
||||
int error;
|
||||
|
||||
- path_get(&f->f_path);
|
||||
f->f_inode = inode;
|
||||
f->f_mapping = inode->i_mapping;
|
||||
f->f_wb_err = filemap_sample_wb_err(f->f_mapping);
|
||||
@@ -1006,6 +1010,7 @@ int finish_open(struct file *file, struct dentry *dentry,
|
||||
BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */
|
||||
|
||||
file->__f_path.dentry = dentry;
|
||||
+ path_get(&file->f_path);
|
||||
return do_dentry_open(file, open);
|
||||
}
|
||||
EXPORT_SYMBOL(finish_open);
|
||||
@@ -1049,6 +1054,7 @@ int vfs_open(const struct path *path, struct file *file)
|
||||
int ret;
|
||||
|
||||
file->__f_path = *path;
|
||||
+ path_get(&file->f_path);
|
||||
ret = do_dentry_open(file, NULL);
|
||||
if (!ret) {
|
||||
/*
|
||||
@@ -1061,6 +1067,25 @@ int vfs_open(const struct path *path, struct file *file)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * vfs_open_consume - open the file at the given path and consume the reference
|
||||
+ * @path: path to open
|
||||
+ * @file: newly allocated file with f_flag initialized
|
||||
+ */
|
||||
+int vfs_open_consume(struct path *path, struct file *file)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ file->__f_path = *path;
|
||||
+ path->mnt = NULL;
|
||||
+ path->dentry = NULL;
|
||||
+ ret = do_dentry_open(file, NULL);
|
||||
+ if (!ret) {
|
||||
+ fsnotify_open(file);
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
struct file *dentry_open(const struct path *path, int flags,
|
||||
const struct cred *cred)
|
||||
{
|
||||
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
|
||||
--- a/drivers/gpu/drm/ttm/ttm_bo.c
|
||||
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
|
||||
@@ -1343,7 +1343,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
|
||||
|
||||
if (ttm_tt_is_populated(tt)) {
|
||||
ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
|
||||
- if (!ret) {
|
||||
+ if (ret > 0) {
|
||||
spin_lock(&bdev->lru_lock);
|
||||
ttm_resource_del_bulk_move_unevictable(bo->resource, bo);
|
||||
ttm_resource_move_to_lru_tail(bo->resource);
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
File renamed without changes.
File renamed without changes.
+30
-54
@@ -1,5 +1,4 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
|
||||
index c21e0c0ef0b1..e62788328bfd 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
|
||||
@@ -1780,6 +1780,7 @@ struct intel_psr {
|
||||
@@ -11,10 +10,9 @@ index c21e0c0ef0b1..e62788328bfd 100644
|
||||
|
||||
u8 io_wake_lines;
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
index beaa1d62613d..644ab9b1bee9 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
@@ -2475,6 +2475,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
|
||||
@@ -2481,6 +2481,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
cancel_work_sync(&intel_dp->psr.work);
|
||||
cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
|
||||
@@ -22,7 +20,7 @@ index beaa1d62613d..644ab9b1bee9 100644
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2506,6 +2507,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
|
||||
@@ -2512,6 +2513,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
|
||||
|
||||
cancel_work_sync(&psr->work);
|
||||
cancel_delayed_work_sync(&psr->dc3co_work);
|
||||
@@ -30,48 +28,48 @@ index beaa1d62613d..644ab9b1bee9 100644
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3539,6 +3541,17 @@ static void intel_psr_handle_irq(struct intel_dp *intel_dp)
|
||||
@@ -3545,6 +3547,17 @@ static void intel_psr_handle_irq(struct intel_dp *intel_dp)
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
|
||||
}
|
||||
|
||||
+#define PANEL_REPLAY_REENABLE_DELAY_MS 50
|
||||
+
|
||||
+static bool panel_replay_alpm_cursor_lag_workaround_enabled(struct intel_dp *intel_dp)
|
||||
+static bool panel_replay_exit_on_flush_enabled(struct intel_dp *intel_dp)
|
||||
+{
|
||||
+ return intel_dp_is_edp(intel_dp) &&
|
||||
+ intel_dp->psr.panel_replay_enabled &&
|
||||
+ intel_dp->psr.sel_update_enabled &&
|
||||
+ intel_has_dpcd_quirk(intel_dp,
|
||||
+ QUIRK_PANEL_REPLAY_ALPM_CURSOR_LAG);
|
||||
+ QUIRK_PANEL_REPLAY_EXIT_ON_FLUSH);
|
||||
+}
|
||||
+
|
||||
static void intel_psr_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_dp *intel_dp =
|
||||
@@ -3557,6 +3570,11 @@ static void intel_psr_work(struct work_struct *work)
|
||||
@@ -3563,6 +3576,11 @@ static void intel_psr_work(struct work_struct *work)
|
||||
if (intel_dp->psr.pause_counter)
|
||||
goto unlock;
|
||||
|
||||
+ /* The dedicated delayed work owns re-entry while the workaround is armed. */
|
||||
+ if (panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp) &&
|
||||
+ /* The dedicated delayed work owns re-entry while the quirk is armed. */
|
||||
+ if (panel_replay_exit_on_flush_enabled(intel_dp) &&
|
||||
+ delayed_work_pending(&intel_dp->psr.panel_replay_reenable_work))
|
||||
+ goto unlock;
|
||||
+
|
||||
/*
|
||||
* We have to make sure PSR is ready for re-enable
|
||||
* otherwise it keeps disabled until next full enable/disable cycle.
|
||||
@@ -3566,6 +3584,10 @@ static void intel_psr_work(struct work_struct *work)
|
||||
@@ -3572,6 +3590,10 @@ static void intel_psr_work(struct work_struct *work)
|
||||
if (!__psr_wait_for_idle_locked(intel_dp))
|
||||
goto unlock;
|
||||
|
||||
+ if (panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp) &&
|
||||
+ if (panel_replay_exit_on_flush_enabled(intel_dp) &&
|
||||
+ delayed_work_pending(&intel_dp->psr.panel_replay_reenable_work))
|
||||
+ goto unlock;
|
||||
+
|
||||
/*
|
||||
* The delayed work can race with an invalidate hence we need to
|
||||
* recheck. Since psr_flush first clears this and then reschedules we
|
||||
@@ -3579,6 +3601,33 @@ static void intel_psr_work(struct work_struct *work)
|
||||
@@ -3585,6 +3607,33 @@ static void intel_psr_work(struct work_struct *work)
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
|
||||
@@ -84,7 +82,7 @@ index beaa1d62613d..644ab9b1bee9 100644
|
||||
+ mutex_lock(&intel_dp->psr.lock);
|
||||
+
|
||||
+ if (!intel_dp->psr.enabled ||
|
||||
+ !panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp) ||
|
||||
+ !panel_replay_exit_on_flush_enabled(intel_dp) ||
|
||||
+ intel_dp->psr.pause_counter ||
|
||||
+ READ_ONCE(intel_dp->psr.irq_aux_error))
|
||||
+ goto unlock;
|
||||
@@ -105,25 +103,25 @@ index beaa1d62613d..644ab9b1bee9 100644
|
||||
static void intel_psr_configure_full_frame_update(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
@@ -3650,8 +3699,11 @@ void intel_psr_invalidate(struct intel_display *display,
|
||||
@@ -3656,8 +3705,11 @@ void intel_psr_invalidate(struct intel_display *display,
|
||||
INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe);
|
||||
intel_dp->psr.busy_frontbuffer_bits |= pipe_frontbuffer_bits;
|
||||
|
||||
- if (pipe_frontbuffer_bits)
|
||||
+ if (pipe_frontbuffer_bits) {
|
||||
+ if (panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp))
|
||||
+ if (panel_replay_exit_on_flush_enabled(intel_dp))
|
||||
+ cancel_delayed_work(&intel_dp->psr.panel_replay_reenable_work);
|
||||
_psr_invalidate_handle(intel_dp);
|
||||
+ }
|
||||
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
@@ -3767,6 +3819,15 @@ void intel_psr_flush(struct intel_display *display,
|
||||
@@ -3773,6 +3825,15 @@ void intel_psr_flush(struct intel_display *display,
|
||||
if (intel_dp->psr.pause_counter)
|
||||
goto unlock;
|
||||
|
||||
+ if (pipe_frontbuffer_bits &&
|
||||
+ panel_replay_alpm_cursor_lag_workaround_enabled(intel_dp)) {
|
||||
+ panel_replay_exit_on_flush_enabled(intel_dp)) {
|
||||
+ intel_psr_exit(intel_dp);
|
||||
+ mod_delayed_work(display->wq.unordered,
|
||||
+ &intel_dp->psr.panel_replay_reenable_work,
|
||||
@@ -134,7 +132,7 @@ index beaa1d62613d..644ab9b1bee9 100644
|
||||
if (origin == ORIGIN_FLIP ||
|
||||
(origin == ORIGIN_CURSOR_UPDATE &&
|
||||
!intel_dp->psr.psr2_sel_fetch_enabled)) {
|
||||
@@ -3830,6 +3891,8 @@ void intel_psr_init(struct intel_dp *intel_dp)
|
||||
@@ -3836,6 +3897,8 @@ void intel_psr_init(struct intel_dp *intel_dp)
|
||||
|
||||
INIT_WORK(&intel_dp->psr.work, intel_psr_work);
|
||||
INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, tgl_dc3co_disable_work);
|
||||
@@ -144,53 +142,31 @@ index beaa1d62613d..644ab9b1bee9 100644
|
||||
}
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
index 33245f44c0d5..dc6576016400 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
@@ -86,12 +86,13 @@ static void quirk_edp_limit_rate_hbr2(struct intel_display *display)
|
||||
drm_info(display->drm, "Applying eDP Limit rate to HBR2 quirk\n");
|
||||
}
|
||||
|
||||
-static void quirk_disable_edp_panel_replay(struct intel_dp *intel_dp)
|
||||
+static void quirk_panel_replay_alpm_cursor_lag(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
|
||||
- intel_set_dpcd_quirk(intel_dp, QUIRK_DISABLE_EDP_PANEL_REPLAY);
|
||||
- drm_info(display->drm, "Applying disable Panel Replay quirk\n");
|
||||
+ intel_set_dpcd_quirk(intel_dp, QUIRK_PANEL_REPLAY_ALPM_CURSOR_LAG);
|
||||
+ drm_info(display->drm,
|
||||
+ "Applying Panel Replay ALPM cursor lag workaround\n");
|
||||
@@ -94,6 +94,14 @@ static void quirk_disable_edp_panel_replay(struct intel_dp *intel_dp)
|
||||
drm_info(display->drm, "Applying disable Panel Replay quirk\n");
|
||||
}
|
||||
|
||||
+static void quirk_panel_replay_exit_on_flush(struct intel_dp *intel_dp)
|
||||
+{
|
||||
+ struct intel_display *display = to_intel_display(intel_dp);
|
||||
+
|
||||
+ intel_set_dpcd_quirk(intel_dp, QUIRK_PANEL_REPLAY_EXIT_ON_FLUSH);
|
||||
+ drm_info(display->drm, "Applying Panel Replay exit on flush quirk\n");
|
||||
+}
|
||||
+
|
||||
static void quirk_disable_psr2(struct intel_display *display)
|
||||
@@ -276,7 +277,7 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
.subsystem_vendor = 0x1028,
|
||||
.subsystem_device = 0x0db9,
|
||||
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
- .hook = quirk_disable_edp_panel_replay,
|
||||
+ .hook = quirk_panel_replay_alpm_cursor_lag,
|
||||
},
|
||||
/* Dell XPS 16 DA16260 */
|
||||
{
|
||||
@@ -284,7 +285,7 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
.subsystem_vendor = 0x1028,
|
||||
.subsystem_device = 0x0dba,
|
||||
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
- .hook = quirk_disable_edp_panel_replay,
|
||||
+ .hook = quirk_panel_replay_alpm_cursor_lag,
|
||||
},
|
||||
};
|
||||
|
||||
{
|
||||
intel_set_quirk(display, QUIRK_DISABLE_PSR2);
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h
|
||||
index 970a4fe52faf..50ef333b87a9 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.h
|
||||
@@ -23,6 +23,7 @@ enum intel_quirk_id {
|
||||
QUIRK_EDP_LIMIT_RATE_HBR2,
|
||||
QUIRK_DISABLE_EDP_PANEL_REPLAY,
|
||||
QUIRK_DISABLE_PSR2,
|
||||
+ QUIRK_PANEL_REPLAY_ALPM_CURSOR_LAG,
|
||||
+ QUIRK_PANEL_REPLAY_EXIT_ON_FLUSH,
|
||||
};
|
||||
|
||||
void intel_init_quirks(struct intel_display *display);
|
||||
Binary file not shown.
+12
@@ -0,0 +1,12 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
@@ -284,7 +284,7 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
.subsystem_vendor = 0x1028,
|
||||
.subsystem_device = 0x0db9,
|
||||
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
- .hook = quirk_disable_edp_panel_replay,
|
||||
+ .hook = quirk_panel_replay_exit_on_flush,
|
||||
},
|
||||
/* Dell XPS 16 DA16260 */
|
||||
{
|
||||
BIN
Binary file not shown.
+12
@@ -0,0 +1,12 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
@@ -292,7 +292,7 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
.subsystem_vendor = 0x1028,
|
||||
.subsystem_device = 0x0dba,
|
||||
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
- .hook = quirk_disable_edp_panel_replay,
|
||||
+ .hook = quirk_panel_replay_exit_on_flush,
|
||||
},
|
||||
};
|
||||
|
||||
BIN
Binary file not shown.
+28
@@ -0,0 +1,28 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
@@ -267,6 +267,9 @@ static struct intel_quirk intel_quirks[] = {
|
||||
|
||||
/* Xiaomi Book Pro 14 2026 */
|
||||
{ 0xb081, 0x1d72, 0x2424, quirk_disable_psr2 },
|
||||
+
|
||||
+ /* Dell XPS 13 DX13260 */
|
||||
+ { DEVICE_ID_ANY, 0x1028, 0x0e54, quirk_disable_psr2 },
|
||||
};
|
||||
|
||||
static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
@@ -294,6 +297,14 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
.hook = quirk_panel_replay_exit_on_flush,
|
||||
},
|
||||
+ /* Dell XPS 13 DX13260 */
|
||||
+ {
|
||||
+ .device = DEVICE_ID_ANY,
|
||||
+ .subsystem_vendor = 0x1028,
|
||||
+ .subsystem_device = 0x0e54,
|
||||
+ .sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
+ .hook = quirk_disable_edp_panel_replay,
|
||||
+ },
|
||||
};
|
||||
|
||||
void intel_init_quirks(struct intel_display *display)
|
||||
BIN
Binary file not shown.
+19
@@ -0,0 +1,19 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
@@ -305,6 +305,15 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
.hook = quirk_disable_edp_panel_replay,
|
||||
},
|
||||
+ /* Dell XPS 13 DX13260 (Wildcat Lake), sink "Bamboo" */
|
||||
+ {
|
||||
+ .device = DEVICE_ID_ANY,
|
||||
+ .subsystem_vendor = 0x1028,
|
||||
+ .subsystem_device = 0x0e53,
|
||||
+ .sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
|
||||
+ .sink_device_id = SINK_DEVICE_ID(0x42, 0x61, 0x6d, 0x62, 0x6f, 0x6f),
|
||||
+ .hook = quirk_panel_replay_exit_on_flush,
|
||||
+ },
|
||||
};
|
||||
|
||||
void intel_init_quirks(struct intel_display *display)
|
||||
BIN
Binary file not shown.
@@ -55,7 +55,7 @@ diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/dis
|
||||
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
||||
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
||||
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
||||
@@ -1937,10 +1937,10 @@ static int intel_plane_min_height(struct intel_plane *plane,
|
||||
@@ -1932,10 +1932,10 @@ static int intel_plane_min_height(struct intel_plane *plane,
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/dr
|
||||
{
|
||||
if (plane->max_width)
|
||||
return plane->max_width(fb, color_plane, rotation);
|
||||
@@ -1948,10 +1948,10 @@ static int intel_plane_max_width(struct intel_plane *plane,
|
||||
@@ -1943,10 +1943,10 @@ static int intel_plane_max_width(struct intel_plane *plane,
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,95 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
|
||||
@@ -536,7 +536,8 @@ static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb,
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
- if (!crtc_state->enable_psr2_sel_fetch)
|
||||
+ if (!crtc_state->enable_psr2_sel_fetch &&
|
||||
+ !crtc_state->clear_psr2_sel_fetch)
|
||||
return;
|
||||
|
||||
intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0);
|
||||
@@ -569,8 +570,10 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
- if (!crtc_state->enable_psr2_sel_fetch)
|
||||
+ if (!crtc_state->enable_psr2_sel_fetch) {
|
||||
+ i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
|
||||
return;
|
||||
+ }
|
||||
|
||||
if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) {
|
||||
if (crtc_state->enable_psr2_su_region_et) {
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
|
||||
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
|
||||
@@ -1177,6 +1177,8 @@ struct intel_crtc_state {
|
||||
bool has_sel_update;
|
||||
bool enable_psr2_sel_fetch;
|
||||
bool enable_psr2_su_region_et;
|
||||
+ /* Drop the stale selective fetch enable bits as selective fetch is turned off */
|
||||
+ bool clear_psr2_sel_fetch;
|
||||
bool req_psr2_sdp_prior_scanline;
|
||||
bool has_panel_replay;
|
||||
bool link_off_after_as_sdp_when_pr_active;
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
|
||||
@@ -2941,6 +2941,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
+ const struct intel_crtc_state *old_crtc_state =
|
||||
+ intel_atomic_get_old_crtc_state(state, crtc);
|
||||
struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct intel_plane_state *new_plane_state, *old_plane_state;
|
||||
struct intel_plane *plane;
|
||||
@@ -2953,6 +2955,19 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
bool full_update = false, su_area_changed;
|
||||
int i, ret;
|
||||
|
||||
+ /*
|
||||
+ * Selective fetch is not always usable, for instance it is dropped
|
||||
+ * while pipe CRC is active. The planes keep their selective fetch
|
||||
+ * enable bit set in hardware over that, and a plane disabled while
|
||||
+ * selective fetch is off never gets the bit cleared. Once selective
|
||||
+ * fetch comes back the hardware would resume fetching for a plane that
|
||||
+ * is no longer enabled and keep its DDB range reserved, so have the
|
||||
+ * plane update drop the bit for every plane of the pipe as selective
|
||||
+ * fetch is turned off.
|
||||
+ */
|
||||
+ crtc_state->clear_psr2_sel_fetch = old_crtc_state->enable_psr2_sel_fetch &&
|
||||
+ !crtc_state->enable_psr2_sel_fetch;
|
||||
+
|
||||
if (!crtc_state->enable_psr2_sel_fetch)
|
||||
return 0;
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
||||
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
||||
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
|
||||
@@ -885,7 +885,8 @@ static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb,
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
- if (!crtc_state->enable_psr2_sel_fetch)
|
||||
+ if (!crtc_state->enable_psr2_sel_fetch &&
|
||||
+ !crtc_state->clear_psr2_sel_fetch)
|
||||
return;
|
||||
|
||||
intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0);
|
||||
@@ -1634,10 +1635,8 @@ static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb,
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
- if (!crtc_state->enable_psr2_sel_fetch)
|
||||
- return;
|
||||
-
|
||||
- if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
|
||||
+ if (crtc_state->enable_psr2_sel_fetch &&
|
||||
+ drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
|
||||
intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id),
|
||||
SEL_FETCH_PLANE_CTL_ENABLE);
|
||||
else
|
||||
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
|
||||
@@ -902,9 +902,17 @@ void intel_dsb_wait_for_delayed_vblank(struct intel_atomic_state *state,
|
||||
* the hardware itself guarantees that we're SCL lines
|
||||
* away from the delayed vblank, and we won't be inside
|
||||
* the vmin safe window so this extra wait does nothing.
|
||||
+ *
|
||||
+ * Experimentally, DSB may observe a slightly stale
|
||||
+ * PIPEDSL value. When the actual scanline has just reached
|
||||
+ * safe_window_start, WAIT_DSL_OUT may complete immediately
|
||||
+ * due to the stale value.
|
||||
+ *
|
||||
+ * Shift the start back by one scanline to ensure the wait
|
||||
+ * window is entered reliably.
|
||||
*/
|
||||
intel_dsb_wait_scanline_out(state, dsb,
|
||||
- intel_vrr_safe_window_start(crtc_state),
|
||||
+ intel_vrr_safe_window_start(crtc_state) - 1,
|
||||
intel_vrr_vmin_safe_window_end(crtc_state));
|
||||
/*
|
||||
* When the push is sent during vblank it will trigger
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,42 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_display_params.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_display_params.c
|
||||
@@ -120,6 +120,10 @@ intel_display_param_named_unsafe(enable_psr, int, 0400,
|
||||
"(0=disabled, 1=enable up to PSR1, 2=enable up to PSR2) "
|
||||
"Default: -1 (use per-chip default)");
|
||||
|
||||
+intel_display_param_named_unsafe(enable_dc_balance, bool, 0400,
|
||||
+ "Enable VRR DC balance (0=disabled, 1=enabled). "
|
||||
+ "Default: 0 (disabled)");
|
||||
+
|
||||
intel_display_param_named_unsafe(enable_panel_replay, int, 0400,
|
||||
"Enable Panel Replay (0=disabled, 1=enabled). Default: -1 (use per-chip default)");
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h
|
||||
--- a/drivers/gpu/drm/i915/display/intel_display_params.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_display_params.h
|
||||
@@ -46,6 +46,7 @@ struct drm_printer;
|
||||
param(bool, enable_dp_mst, true, 0600) \
|
||||
param(int, enable_fbc, -1, 0600) \
|
||||
param(int, enable_psr, -1, 0600) \
|
||||
+ param(bool, enable_dc_balance, false, 0600) \
|
||||
param(int, enable_panel_replay, -1, 0600) \
|
||||
param(bool, psr_safest_params, false, 0400) \
|
||||
param(bool, enable_psr2_sel_fetch, true, 0400) \
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
|
||||
@@ -383,10 +383,12 @@ static bool intel_vrr_dc_balance_possible(const struct intel_crtc_state *crtc_st
|
||||
static void
|
||||
intel_vrr_dc_balance_compute_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
+ struct intel_display *display = to_intel_display(crtc_state);
|
||||
int guardband_usec, adjustment_usec;
|
||||
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
|
||||
- if (!intel_vrr_dc_balance_possible(crtc_state) || !crtc_state->vrr.enable)
|
||||
+ if (!intel_vrr_dc_balance_possible(crtc_state) ||
|
||||
+ !crtc_state->vrr.enable || !display->params.enable_dc_balance)
|
||||
return;
|
||||
|
||||
crtc_state->vrr.dc_balance.vmax = crtc_state->vrr.vmax;
|
||||
Binary file not shown.
@@ -9,7 +9,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
#include "modules/inc/mod_power.h"
|
||||
#include "modules/power/power_helpers.h"
|
||||
|
||||
@@ -10068,6 +10069,9 @@ static void update_freesync_state_on_stream(
|
||||
@@ -10088,6 +10089,9 @@ static void update_freesync_state_on_stream(
|
||||
&vrr_infopacket,
|
||||
pack_sdp_v1_3);
|
||||
|
||||
@@ -19,7 +19,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
new_crtc_state->freesync_vrr_info_changed |=
|
||||
(memcmp(&new_crtc_state->vrr_infopacket,
|
||||
&vrr_infopacket,
|
||||
@@ -10079,6 +10083,36 @@ static void update_freesync_state_on_stream(
|
||||
@@ -10099,6 +10103,36 @@ static void update_freesync_state_on_stream(
|
||||
new_stream->vrr_infopacket = vrr_infopacket;
|
||||
new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
|
||||
|
||||
@@ -56,7 +56,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
if (new_crtc_state->freesync_vrr_info_changed)
|
||||
drm_dbg_kms(adev_to_drm(adev), "VRR packet update: crtc=%u enabled=%d state=%d",
|
||||
new_crtc_state->base.crtc->base.id,
|
||||
@@ -10645,9 +10679,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
|
||||
@@ -10665,9 +10699,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
|
||||
}
|
||||
|
||||
if (acrtc_state->stream) {
|
||||
@@ -70,7 +70,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12049,6 +12086,14 @@ static void get_freesync_config_for_crtc(
|
||||
@@ -12069,6 +12106,14 @@ static void get_freesync_config_for_crtc(
|
||||
}
|
||||
out:
|
||||
new_crtc_state->freesync_config = config;
|
||||
@@ -85,7 +85,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
}
|
||||
|
||||
static void reset_freesync_config_for_crtc(
|
||||
@@ -14011,6 +14056,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
@@ -14031,6 +14076,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version))
|
||||
goto update;
|
||||
|
||||
@@ -101,7 +101,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw()
|
||||
|
||||
/* Some eDP panels only have the refresh rate range info in DisplayID */
|
||||
@@ -14036,7 +14090,9 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
@@ -14056,7 +14110,9 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
|
||||
if (i >= 0) {
|
||||
amdgpu_dm_connector->vsdb_info = vsdb_info;
|
||||
@@ -14052,6 +14108,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
@@ -14072,6 +14128,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
}
|
||||
|
||||
if (amdgpu_dm_connector->dc_link)
|
||||
@@ -14093,6 +14202,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
@@ -14113,6 +14222,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
if (dm_con_state)
|
||||
dm_con_state->freesync_capable = freesync_capable;
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
@@ -10069,7 +10069,10 @@ static void update_freesync_state_on_stream(
|
||||
@@ -10089,7 +10089,10 @@ static void update_freesync_state_on_stream(
|
||||
&vrr_infopacket,
|
||||
pack_sdp_v1_3);
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
@@ -10090,8 +10090,8 @@ static void update_freesync_state_on_stream(
|
||||
pack_sdp_v1_3);
|
||||
|
||||
/* Per HDMI 2.1, VTEM is valid on TMDS as well as FRL */
|
||||
- if (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_FRL ||
|
||||
- (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A &&
|
||||
+ if (new_stream->signal == SIGNAL_TYPE_HDMI_FRL ||
|
||||
+ (new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A &&
|
||||
aconn && aconn->base.display_info.hdmi.vrr_cap.supported))
|
||||
mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
@@ -2025,7 +2025,7 @@ static void hdmi_frl_status_polling_work(struct work_struct *work)
|
||||
if (!dc_is_hdmi_signal(dc_link->connector_signal))
|
||||
continue;
|
||||
|
||||
- if (dc_link->connector_signal != SIGNAL_TYPE_HDMI_FRL)
|
||||
+ if (dc_link->frl_link_settings.frl_link_rate == 0)
|
||||
continue;
|
||||
|
||||
link_update = dc_link_frl_poll_status_flag(dc_link);
|
||||
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
|
||||
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
|
||||
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
|
||||
@@ -882,7 +882,7 @@ static void verify_link_capability_non_destructive(struct dc_link *link)
|
||||
else
|
||||
link->verified_link_cap = dp_get_max_link_cap(link);
|
||||
} else if (dc_is_hdmi_signal(link->local_sink->sink_signal)) {
|
||||
- link->verified_link_cap = link->reported_link_cap;
|
||||
+ link->frl_verified_link_cap = link->frl_reported_link_cap;
|
||||
|
||||
if (is_hdmi_frl_in_use(link)) {
|
||||
link->local_sink->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
|
||||
Binary file not shown.
@@ -0,0 +1,26 @@
|
||||
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.c
|
||||
--- a/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.c
|
||||
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.c
|
||||
@@ -630,17 +630,17 @@ enum frl_cap_chk_result dml1_frl_cap_chk(struct frl_cap_chk_params *params)
|
||||
{
|
||||
struct frl_cap_chk_intermediates inter;
|
||||
|
||||
-#if defined (CONFIG_DRM_AMD_DC_FP)
|
||||
- if (params->compressed)
|
||||
- return dml1_frl_cap_chk_compressed(params, &inter);
|
||||
-#endif
|
||||
-
|
||||
return dml1_frl_cap_chk_inter(params, &inter);
|
||||
}
|
||||
|
||||
enum frl_cap_chk_result dml1_frl_cap_chk_inter(struct frl_cap_chk_params *params,
|
||||
struct frl_cap_chk_intermediates *inter)
|
||||
{
|
||||
+#if defined (CONFIG_DRM_AMD_DC_FP)
|
||||
+ if (params->compressed)
|
||||
+ return dml1_frl_cap_chk_compressed(params, inter);
|
||||
+#endif
|
||||
+
|
||||
return dml1_frl_cap_chk_uncompressed(params, inter);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
@@ -7096,6 +7096,11 @@ static void fill_stream_properties_from_drm_display_mode(
|
||||
@@ -7116,6 +7116,11 @@ static void fill_stream_properties_from_drm_display_mode(
|
||||
|
||||
stream->output_color_space = get_output_color_space(timing_out, connector_state);
|
||||
stream->content_type = get_output_content_type(connector_state);
|
||||
@@ -13,7 +13,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
}
|
||||
|
||||
static void fill_audio_info(struct audio_info *audio_info,
|
||||
@@ -7616,6 +7621,7 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
@@ -7636,6 +7641,7 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
struct drm_display_mode mode;
|
||||
struct drm_display_mode saved_mode;
|
||||
struct drm_display_mode *freesync_mode = NULL;
|
||||
@@ -21,7 +21,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
bool native_mode_found = false;
|
||||
bool recalculate_timing = false;
|
||||
bool scale = dm_state->scaling != RMX_OFF;
|
||||
@@ -7707,6 +7713,16 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
@@ -7727,6 +7733,16 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
@@ -7622,6 +7622,7 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
@@ -7642,6 +7642,7 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
struct drm_display_mode saved_mode;
|
||||
struct drm_display_mode *freesync_mode = NULL;
|
||||
struct drm_display_mode *dsc_passthru_mode = NULL;
|
||||
@@ -9,7 +9,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
bool native_mode_found = false;
|
||||
bool recalculate_timing = false;
|
||||
bool scale = dm_state->scaling != RMX_OFF;
|
||||
@@ -7688,6 +7689,22 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
@@ -7708,6 +7709,22 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
|
||||
mode_refresh = drm_mode_vrefresh(&mode);
|
||||
|
||||
@@ -32,7 +32,7 @@ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm
|
||||
if (preferred_mode == NULL) {
|
||||
/*
|
||||
* This may not be an error, the use case is when we have no
|
||||
@@ -7713,16 +7730,6 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
@@ -7733,16 +7750,6 @@ create_stream_for_sink(struct drm_connector *connector,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,16 +0,0 @@
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
|
||||
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
|
||||
@@ -2366,8 +2366,10 @@ static void bxt_sanitize_cdclk(struct intel_display *display)
|
||||
* dividers both syncing to an active pipe, or asynchronously
|
||||
* (PIPE_NONE).
|
||||
*/
|
||||
- cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
|
||||
- cdctl |= bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
|
||||
+ if (DISPLAY_VER(display) < 30) {
|
||||
+ cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
|
||||
+ cdctl |= bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
|
||||
+ }
|
||||
|
||||
if (cdctl != expected) {
|
||||
if (DISPLAY_VER(display) < 20) {
|
||||
Loaded 100 of 524 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user