From: Weijie Gao Date: Wed, 3 Jan 2024 17:47:10 +0000 (+0800) Subject: generic: 6.6: drop backport patches X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=8c3892b1d79aa0901154e31644b9e6f0446023f4;p=openwrt%2Fstaging%2Fneocturne.git generic: 6.6: drop backport patches Drop all backport patches that are now included in kernel 6.6. Signed-off-by: Weijie Gao --- diff --git a/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch b/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch deleted file mode 100644 index fe32acc985..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch +++ /dev/null @@ -1,352 +0,0 @@ -From 8c20e2eb5f2a0175b774134685e4d7bd93e85ff8 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:18:59 -0700 -Subject: [PATCH 01/19] UPSTREAM: mm: multi-gen LRU: rename lru_gen_struct to - lru_gen_folio - -Patch series "mm: multi-gen LRU: memcg LRU", v3. - -Overview -======== - -An memcg LRU is a per-node LRU of memcgs. It is also an LRU of LRUs, -since each node and memcg combination has an LRU of folios (see -mem_cgroup_lruvec()). - -Its goal is to improve the scalability of global reclaim, which is -critical to system-wide memory overcommit in data centers. Note that -memcg reclaim is currently out of scope. - -Its memory bloat is a pointer to each lruvec and negligible to each -pglist_data. In terms of traversing memcgs during global reclaim, it -improves the best-case complexity from O(n) to O(1) and does not affect -the worst-case complexity O(n). Therefore, on average, it has a sublinear -complexity in contrast to the current linear complexity. - -The basic structure of an memcg LRU can be understood by an analogy to -the active/inactive LRU (of folios): -1. It has the young and the old (generations), i.e., the counterparts - to the active and the inactive; -2. The increment of max_seq triggers promotion, i.e., the counterpart - to activation; -3. Other events trigger similar operations, e.g., offlining an memcg - triggers demotion, i.e., the counterpart to deactivation. - -In terms of global reclaim, it has two distinct features: -1. Sharding, which allows each thread to start at a random memcg (in - the old generation) and improves parallelism; -2. Eventual fairness, which allows direct reclaim to bail out at will - and reduces latency without affecting fairness over some time. - -The commit message in patch 6 details the workflow: -https://lore.kernel.org/r/20221222041905.2431096-7-yuzhao@google.com/ - -The following is a simple test to quickly verify its effectiveness. - - Test design: - 1. Create multiple memcgs. - 2. Each memcg contains a job (fio). - 3. All jobs access the same amount of memory randomly. - 4. The system does not experience global memory pressure. - 5. Periodically write to the root memory.reclaim. - - Desired outcome: - 1. All memcgs have similar pgsteal counts, i.e., stddev(pgsteal) - over mean(pgsteal) is close to 0%. - 2. The total pgsteal is close to the total requested through - memory.reclaim, i.e., sum(pgsteal) over sum(requested) is close - to 100%. - - Actual outcome [1]: - MGLRU off MGLRU on - stddev(pgsteal) / mean(pgsteal) 75% 20% - sum(pgsteal) / sum(requested) 425% 95% - - #################################################################### - MEMCGS=128 - - for ((memcg = 0; memcg < $MEMCGS; memcg++)); do - mkdir /sys/fs/cgroup/memcg$memcg - done - - start() { - echo $BASHPID > /sys/fs/cgroup/memcg$memcg/cgroup.procs - - fio -name=memcg$memcg --numjobs=1 --ioengine=mmap \ - --filename=/dev/zero --size=1920M --rw=randrw \ - --rate=64m,64m --random_distribution=random \ - --fadvise_hint=0 --time_based --runtime=10h \ - --group_reporting --minimal - } - - for ((memcg = 0; memcg < $MEMCGS; memcg++)); do - start & - done - - sleep 600 - - for ((i = 0; i < 600; i++)); do - echo 256m >/sys/fs/cgroup/memory.reclaim - sleep 6 - done - - for ((memcg = 0; memcg < $MEMCGS; memcg++)); do - grep "pgsteal " /sys/fs/cgroup/memcg$memcg/memory.stat - done - #################################################################### - -[1]: This was obtained from running the above script (touches less - than 256GB memory) on an EPYC 7B13 with 512GB DRAM for over an - hour. - -This patch (of 8): - -The new name lru_gen_folio will be more distinct from the coming -lru_gen_memcg. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-1-yuzhao@google.com -Link: https://lkml.kernel.org/r/20221222041905.2431096-2-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -Cc: Mike Rapoport -Cc: Roman Gushchin -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit 391655fe08d1f942359a11148aa9aaf3f99d6d6f) -Change-Id: I7df67e0e2435ba28f10eaa57d28d98b61a9210a6 -Signed-off-by: T.J. Mercier ---- - include/linux/mm_inline.h | 4 ++-- - include/linux/mmzone.h | 6 +++--- - mm/vmscan.c | 34 +++++++++++++++++----------------- - mm/workingset.c | 4 ++-- - 4 files changed, 24 insertions(+), 24 deletions(-) - ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -178,7 +178,7 @@ static inline void lru_gen_update_size(s - int zone = folio_zonenum(folio); - int delta = folio_nr_pages(folio); - enum lru_list lru = type * LRU_INACTIVE_FILE; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE(old_gen != -1 && old_gen >= MAX_NR_GENS); - VM_WARN_ON_ONCE(new_gen != -1 && new_gen >= MAX_NR_GENS); -@@ -224,7 +224,7 @@ static inline bool lru_gen_add_folio(str - int gen = folio_lru_gen(folio); - int type = folio_is_file_lru(folio); - int zone = folio_zonenum(folio); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE_FOLIO(gen != -1, folio); - ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -404,7 +404,7 @@ enum { - * The number of pages in each generation is eventually consistent and therefore - * can be transiently negative when reset_batch_size() is pending. - */ --struct lru_gen_struct { -+struct lru_gen_folio { - /* the aging increments the youngest generation number */ - unsigned long max_seq; - /* the eviction increments the oldest generation numbers */ -@@ -461,7 +461,7 @@ struct lru_gen_mm_state { - struct lru_gen_mm_walk { - /* the lruvec under reclaim */ - struct lruvec *lruvec; -- /* unstable max_seq from lru_gen_struct */ -+ /* unstable max_seq from lru_gen_folio */ - unsigned long max_seq; - /* the next address within an mm to scan */ - unsigned long next_addr; -@@ -524,7 +524,7 @@ struct lruvec { - unsigned long flags; - #ifdef CONFIG_LRU_GEN - /* evictable pages divided into generations */ -- struct lru_gen_struct lrugen; -+ struct lru_gen_folio lrugen; - /* to concurrently iterate lru_gen_mm_list */ - struct lru_gen_mm_state mm_state; - #endif ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3190,7 +3190,7 @@ static int get_nr_gens(struct lruvec *lr - - static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) - { -- /* see the comment on lru_gen_struct */ -+ /* see the comment on lru_gen_folio */ - return get_nr_gens(lruvec, LRU_GEN_FILE) >= MIN_NR_GENS && - get_nr_gens(lruvec, LRU_GEN_FILE) <= get_nr_gens(lruvec, LRU_GEN_ANON) && - get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; -@@ -3596,7 +3596,7 @@ struct ctrl_pos { - static void read_ctrl_pos(struct lruvec *lruvec, int type, int tier, int gain, - struct ctrl_pos *pos) - { -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - int hist = lru_hist_from_seq(lrugen->min_seq[type]); - - pos->refaulted = lrugen->avg_refaulted[type][tier] + -@@ -3611,7 +3611,7 @@ static void read_ctrl_pos(struct lruvec - static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover) - { - int hist, tier; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - bool clear = carryover ? NR_HIST_GENS == 1 : NR_HIST_GENS > 1; - unsigned long seq = carryover ? lrugen->min_seq[type] : lrugen->max_seq + 1; - -@@ -3688,7 +3688,7 @@ static int folio_update_gen(struct folio - static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool reclaiming) - { - int type = folio_is_file_lru(folio); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); - unsigned long new_flags, old_flags = READ_ONCE(folio->flags); - -@@ -3733,7 +3733,7 @@ static void update_batch_size(struct lru - static void reset_batch_size(struct lruvec *lruvec, struct lru_gen_mm_walk *walk) - { - int gen, type, zone; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - walk->batched = 0; - -@@ -4250,7 +4250,7 @@ static bool inc_min_seq(struct lruvec *l - { - int zone; - int remaining = MAX_LRU_BATCH; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); - - if (type == LRU_GEN_ANON && !can_swap) -@@ -4286,7 +4286,7 @@ static bool try_to_inc_min_seq(struct lr - { - int gen, type, zone; - bool success = false; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - DEFINE_MIN_SEQ(lruvec); - - VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); -@@ -4307,7 +4307,7 @@ next: - ; - } - -- /* see the comment on lru_gen_struct */ -+ /* see the comment on lru_gen_folio */ - if (can_swap) { - min_seq[LRU_GEN_ANON] = min(min_seq[LRU_GEN_ANON], min_seq[LRU_GEN_FILE]); - min_seq[LRU_GEN_FILE] = max(min_seq[LRU_GEN_ANON], lrugen->min_seq[LRU_GEN_FILE]); -@@ -4329,7 +4329,7 @@ static void inc_max_seq(struct lruvec *l - { - int prev, next; - int type, zone; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - restart: - spin_lock_irq(&lruvec->lru_lock); -@@ -4389,7 +4389,7 @@ static bool try_to_inc_max_seq(struct lr - bool success; - struct lru_gen_mm_walk *walk; - struct mm_struct *mm = NULL; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE(max_seq > READ_ONCE(lrugen->max_seq)); - -@@ -4454,7 +4454,7 @@ static bool should_run_aging(struct lruv - unsigned long old = 0; - unsigned long young = 0; - unsigned long total = 0; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - - for (type = !can_swap; type < ANON_AND_FILE; type++) { -@@ -4740,7 +4740,7 @@ static bool sort_folio(struct lruvec *lr - int delta = folio_nr_pages(folio); - int refs = folio_lru_refs(folio); - int tier = lru_tier_from_refs(refs); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE_FOLIO(gen >= MAX_NR_GENS, folio); - -@@ -4848,7 +4848,7 @@ static int scan_folios(struct lruvec *lr - int scanned = 0; - int isolated = 0; - int remaining = MAX_LRU_BATCH; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - - VM_WARN_ON_ONCE(!list_empty(list)); -@@ -5249,7 +5249,7 @@ done: - - static bool __maybe_unused state_is_valid(struct lruvec *lruvec) - { -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - if (lrugen->enabled) { - enum lru_list lru; -@@ -5531,7 +5531,7 @@ static void lru_gen_seq_show_full(struct - int i; - int type, tier; - int hist = lru_hist_from_seq(seq); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - for (tier = 0; tier < MAX_NR_TIERS; tier++) { - seq_printf(m, " %10d", tier); -@@ -5581,7 +5581,7 @@ static int lru_gen_seq_show(struct seq_f - unsigned long seq; - bool full = !debugfs_real_fops(m->file)->write; - struct lruvec *lruvec = v; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - int nid = lruvec_pgdat(lruvec)->node_id; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); -@@ -5835,7 +5835,7 @@ void lru_gen_init_lruvec(struct lruvec * - { - int i; - int gen, type, zone; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - lrugen->max_seq = MIN_NR_GENS + 1; - lrugen->enabled = lru_gen_enabled(); ---- a/mm/workingset.c -+++ b/mm/workingset.c -@@ -223,7 +223,7 @@ static void *lru_gen_eviction(struct fol - unsigned long token; - unsigned long min_seq; - struct lruvec *lruvec; -- struct lru_gen_struct *lrugen; -+ struct lru_gen_folio *lrugen; - int type = folio_is_file_lru(folio); - int delta = folio_nr_pages(folio); - int refs = folio_lru_refs(folio); -@@ -252,7 +252,7 @@ static void lru_gen_refault(struct folio - unsigned long token; - unsigned long min_seq; - struct lruvec *lruvec; -- struct lru_gen_struct *lrugen; -+ struct lru_gen_folio *lrugen; - struct mem_cgroup *memcg; - struct pglist_data *pgdat; - int type = folio_is_file_lru(folio); diff --git a/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch b/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch deleted file mode 100644 index e5ad78b61d..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch +++ /dev/null @@ -1,192 +0,0 @@ -From 14f9a7a15f3d1af351f30e0438fd747b7ac253b0 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:01 -0700 -Subject: [PATCH 03/19] UPSTREAM: mm: multi-gen LRU: remove eviction fairness - safeguard - -Recall that the eviction consumes the oldest generation: first it -bucket-sorts folios whose gen counters were updated by the aging and -reclaims the rest; then it increments lrugen->min_seq. - -The current eviction fairness safeguard for global reclaim has a -dilemma: when there are multiple eligible memcgs, should it continue -or stop upon meeting the reclaim goal? If it continues, it overshoots -and increases direct reclaim latency; if it stops, it loses fairness -between memcgs it has taken memory away from and those it has yet to. - -With memcg LRU, the eviction, while ensuring eventual fairness, will -stop upon meeting its goal. Therefore the current eviction fairness -safeguard for global reclaim will not be needed. - -Note that memcg LRU only applies to global reclaim. For memcg reclaim, -the eviction will continue, even if it is overshooting. This becomes -unconditional due to code simplification. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-4-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -Cc: Mike Rapoport -Cc: Roman Gushchin -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit a579086c99ed70cc4bfc104348dbe3dd8f2787e6) -Change-Id: I08ac1b3c90e29cafd0566785aaa4bcdb5db7d22c -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 81 +++++++++++++++-------------------------------------- - 1 file changed, 23 insertions(+), 58 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -448,6 +448,11 @@ static bool cgroup_reclaim(struct scan_c - return sc->target_mem_cgroup; - } - -+static bool global_reclaim(struct scan_control *sc) -+{ -+ return !sc->target_mem_cgroup || mem_cgroup_is_root(sc->target_mem_cgroup); -+} -+ - /** - * writeback_throttling_sane - is the usual dirty throttling mechanism available? - * @sc: scan_control in question -@@ -498,6 +503,11 @@ static bool cgroup_reclaim(struct scan_c - return false; - } - -+static bool global_reclaim(struct scan_control *sc) -+{ -+ return true; -+} -+ - static bool writeback_throttling_sane(struct scan_control *sc) - { - return true; -@@ -5005,8 +5015,7 @@ static int isolate_folios(struct lruvec - return scanned; - } - --static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness, -- bool *need_swapping) -+static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness) - { - int type; - int scanned; -@@ -5095,9 +5104,6 @@ retry: - goto retry; - } - -- if (need_swapping && type == LRU_GEN_ANON) -- *need_swapping = true; -- - return scanned; - } - -@@ -5136,67 +5142,26 @@ done: - return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; - } - --static bool should_abort_scan(struct lruvec *lruvec, unsigned long seq, -- struct scan_control *sc, bool need_swapping) -+static unsigned long get_nr_to_reclaim(struct scan_control *sc) - { -- int i; -- DEFINE_MAX_SEQ(lruvec); -- -- if (!current_is_kswapd()) { -- /* age each memcg at most once to ensure fairness */ -- if (max_seq - seq > 1) -- return true; -- -- /* over-swapping can increase allocation latency */ -- if (sc->nr_reclaimed >= sc->nr_to_reclaim && need_swapping) -- return true; -- -- /* give this thread a chance to exit and free its memory */ -- if (fatal_signal_pending(current)) { -- sc->nr_reclaimed += MIN_LRU_BATCH; -- return true; -- } -- -- if (cgroup_reclaim(sc)) -- return false; -- } else if (sc->nr_reclaimed - sc->last_reclaimed < sc->nr_to_reclaim) -- return false; -- -- /* keep scanning at low priorities to ensure fairness */ -- if (sc->priority > DEF_PRIORITY - 2) -- return false; -- -- /* -- * A minimum amount of work was done under global memory pressure. For -- * kswapd, it may be overshooting. For direct reclaim, the allocation -- * may succeed if all suitable zones are somewhat safe. In either case, -- * it's better to stop now, and restart later if necessary. -- */ -- for (i = 0; i <= sc->reclaim_idx; i++) { -- unsigned long wmark; -- struct zone *zone = lruvec_pgdat(lruvec)->node_zones + i; -- -- if (!managed_zone(zone)) -- continue; -- -- wmark = current_is_kswapd() ? high_wmark_pages(zone) : low_wmark_pages(zone); -- if (wmark > zone_page_state(zone, NR_FREE_PAGES)) -- return false; -- } -+ /* don't abort memcg reclaim to ensure fairness */ -+ if (!global_reclaim(sc)) -+ return -1; - -- sc->nr_reclaimed += MIN_LRU_BATCH; -+ /* discount the previous progress for kswapd */ -+ if (current_is_kswapd()) -+ return sc->nr_to_reclaim + sc->last_reclaimed; - -- return true; -+ return max(sc->nr_to_reclaim, compact_gap(sc->order)); - } - - static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) - { - struct blk_plug plug; - bool need_aging = false; -- bool need_swapping = false; - unsigned long scanned = 0; - unsigned long reclaimed = sc->nr_reclaimed; -- DEFINE_MAX_SEQ(lruvec); -+ unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - - lru_add_drain(); - -@@ -5220,7 +5185,7 @@ static void lru_gen_shrink_lruvec(struct - if (!nr_to_scan) - goto done; - -- delta = evict_folios(lruvec, sc, swappiness, &need_swapping); -+ delta = evict_folios(lruvec, sc, swappiness); - if (!delta) - goto done; - -@@ -5228,7 +5193,7 @@ static void lru_gen_shrink_lruvec(struct - if (scanned >= nr_to_scan) - break; - -- if (should_abort_scan(lruvec, max_seq, sc, need_swapping)) -+ if (sc->nr_reclaimed >= nr_to_reclaim) - break; - - cond_resched(); -@@ -5678,7 +5643,7 @@ static int run_eviction(struct lruvec *l - if (sc->nr_reclaimed >= nr_to_reclaim) - return 0; - -- if (!evict_folios(lruvec, sc, swappiness, NULL)) -+ if (!evict_folios(lruvec, sc, swappiness)) - return 0; - - cond_resched(); diff --git a/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch b/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch deleted file mode 100644 index cb349abcdb..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch +++ /dev/null @@ -1,294 +0,0 @@ -From f3c93d2e37a3c56593d7ccf4f4bcf1b58426fdd8 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:02 -0700 -Subject: [PATCH 04/19] BACKPORT: mm: multi-gen LRU: remove aging fairness - safeguard - -Recall that the aging produces the youngest generation: first it scans -for accessed folios and updates their gen counters; then it increments -lrugen->max_seq. - -The current aging fairness safeguard for kswapd uses two passes to -ensure the fairness to multiple eligible memcgs. On the first pass, -which is shared with the eviction, it checks whether all eligible -memcgs are low on cold folios. If so, it requires a second pass, on -which it ages all those memcgs at the same time. - -With memcg LRU, the aging, while ensuring eventual fairness, will run -when necessary. Therefore the current aging fairness safeguard for -kswapd will not be needed. - -Note that memcg LRU only applies to global reclaim. For memcg reclaim, -the aging can be unfair to different memcgs, i.e., their -lrugen->max_seq can be incremented at different paces. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-5-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -Cc: Mike Rapoport -Cc: Roman Gushchin -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit 7348cc91821b0cb24dfb00e578047f68299a50ab) -[TJ: Resolved conflicts with older function signatures for -min_cgroup_below_min / min_cgroup_below_low] -Change-Id: I6e36ecfbaaefbc0a56d9a9d5d7cbe404ed7f57a5 -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 126 ++++++++++++++++++++++++---------------------------- - 1 file changed, 59 insertions(+), 67 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -136,7 +136,6 @@ struct scan_control { - - #ifdef CONFIG_LRU_GEN - /* help kswapd make better choices among multiple memcgs */ -- unsigned int memcgs_need_aging:1; - unsigned long last_reclaimed; - #endif - -@@ -4457,7 +4456,7 @@ done: - return true; - } - --static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsigned long *min_seq, -+static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, - struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) - { - int gen, type, zone; -@@ -4466,6 +4465,13 @@ static bool should_run_aging(struct lruv - unsigned long total = 0; - struct lru_gen_folio *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ DEFINE_MIN_SEQ(lruvec); -+ -+ /* whether this lruvec is completely out of cold folios */ -+ if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { -+ *nr_to_scan = 0; -+ return true; -+ } - - for (type = !can_swap; type < ANON_AND_FILE; type++) { - unsigned long seq; -@@ -4494,8 +4500,6 @@ static bool should_run_aging(struct lruv - * stalls when the number of generations reaches MIN_NR_GENS. Hence, the - * ideal number of generations is MIN_NR_GENS+1. - */ -- if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) -- return true; - if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) - return false; - -@@ -4514,40 +4518,54 @@ static bool should_run_aging(struct lruv - return false; - } - --static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned long min_ttl) -+static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) - { -- bool need_aging; -- unsigned long nr_to_scan; -- int swappiness = get_swappiness(lruvec, sc); -+ int gen, type, zone; -+ unsigned long total = 0; -+ bool can_swap = get_swappiness(lruvec, sc); -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); - DEFINE_MIN_SEQ(lruvec); - -- VM_WARN_ON_ONCE(sc->memcg_low_reclaim); -+ for (type = !can_swap; type < ANON_AND_FILE; type++) { -+ unsigned long seq; - -- mem_cgroup_calculate_protection(NULL, memcg); -+ for (seq = min_seq[type]; seq <= max_seq; seq++) { -+ gen = lru_gen_from_seq(seq); - -- if (mem_cgroup_below_min(memcg)) -- return false; -+ for (zone = 0; zone < MAX_NR_ZONES; zone++) -+ total += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); -+ } -+ } - -- need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); -+ /* whether the size is big enough to be helpful */ -+ return mem_cgroup_online(memcg) ? (total >> sc->priority) : total; -+} - -- if (min_ttl) { -- int gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); -- unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); -+static bool lruvec_is_reclaimable(struct lruvec *lruvec, struct scan_control *sc, -+ unsigned long min_ttl) -+{ -+ int gen; -+ unsigned long birth; -+ struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ DEFINE_MIN_SEQ(lruvec); - -- if (time_is_after_jiffies(birth + min_ttl)) -- return false; -+ VM_WARN_ON_ONCE(sc->memcg_low_reclaim); - -- /* the size is likely too small to be helpful */ -- if (!nr_to_scan && sc->priority != DEF_PRIORITY) -- return false; -- } -+ /* see the comment on lru_gen_folio */ -+ gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); -+ birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); - -- if (need_aging) -- try_to_inc_max_seq(lruvec, max_seq, sc, swappiness, false); -+ if (time_is_after_jiffies(birth + min_ttl)) -+ return false; - -- return true; -+ if (!lruvec_is_sizable(lruvec, sc)) -+ return false; -+ -+ mem_cgroup_calculate_protection(NULL, memcg); -+ -+ return !mem_cgroup_below_min(memcg); - } - - /* to protect the working set of the last N jiffies */ -@@ -4556,46 +4574,32 @@ static unsigned long lru_gen_min_ttl __r - static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) - { - struct mem_cgroup *memcg; -- bool success = false; - unsigned long min_ttl = READ_ONCE(lru_gen_min_ttl); - - VM_WARN_ON_ONCE(!current_is_kswapd()); - - sc->last_reclaimed = sc->nr_reclaimed; - -- /* -- * To reduce the chance of going into the aging path, which can be -- * costly, optimistically skip it if the flag below was cleared in the -- * eviction path. This improves the overall performance when multiple -- * memcgs are available. -- */ -- if (!sc->memcgs_need_aging) { -- sc->memcgs_need_aging = true; -+ /* check the order to exclude compaction-induced reclaim */ -+ if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) - return; -- } -- -- set_mm_walk(pgdat); - - memcg = mem_cgroup_iter(NULL, NULL, NULL); - do { - struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat); - -- if (age_lruvec(lruvec, sc, min_ttl)) -- success = true; -+ if (lruvec_is_reclaimable(lruvec, sc, min_ttl)) { -+ mem_cgroup_iter_break(NULL, memcg); -+ return; -+ } - - cond_resched(); - } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); - -- clear_mm_walk(); -- -- /* check the order to exclude compaction-induced reclaim */ -- if (success || !min_ttl || sc->order) -- return; -- - /* - * The main goal is to OOM kill if every generation from all memcgs is - * younger than min_ttl. However, another possibility is all memcgs are -- * either below min or empty. -+ * either too small or below min. - */ - if (mutex_trylock(&oom_lock)) { - struct oom_control oc = { -@@ -5113,33 +5117,27 @@ retry: - * reclaim. - */ - static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, -- bool can_swap, bool *need_aging) -+ bool can_swap) - { - unsigned long nr_to_scan; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); -- DEFINE_MIN_SEQ(lruvec); - - if (mem_cgroup_below_min(memcg) || - (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim)) - return 0; - -- *need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); -- if (!*need_aging) -+ if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan)) - return nr_to_scan; - - /* skip the aging path at the default priority */ - if (sc->priority == DEF_PRIORITY) -- goto done; -+ return nr_to_scan; - -- /* leave the work to lru_gen_age_node() */ -- if (current_is_kswapd()) -- return 0; -+ try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false); - -- if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false)) -- return nr_to_scan; --done: -- return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; -+ /* skip this lruvec as it's low on cold folios */ -+ return 0; - } - - static unsigned long get_nr_to_reclaim(struct scan_control *sc) -@@ -5158,9 +5156,7 @@ static unsigned long get_nr_to_reclaim(s - static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) - { - struct blk_plug plug; -- bool need_aging = false; - unsigned long scanned = 0; -- unsigned long reclaimed = sc->nr_reclaimed; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - - lru_add_drain(); -@@ -5181,13 +5177,13 @@ static void lru_gen_shrink_lruvec(struct - else - swappiness = 0; - -- nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness, &need_aging); -+ nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); - if (!nr_to_scan) -- goto done; -+ break; - - delta = evict_folios(lruvec, sc, swappiness); - if (!delta) -- goto done; -+ break; - - scanned += delta; - if (scanned >= nr_to_scan) -@@ -5199,10 +5195,6 @@ static void lru_gen_shrink_lruvec(struct - cond_resched(); - } - -- /* see the comment in lru_gen_age_node() */ -- if (sc->nr_reclaimed - reclaimed >= MIN_LRU_BATCH && !need_aging) -- sc->memcgs_need_aging = false; --done: - clear_mm_walk(); - - blk_finish_plug(&plug); diff --git a/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch b/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch deleted file mode 100644 index 42caab7c37..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch +++ /dev/null @@ -1,166 +0,0 @@ -From eca3858631e0cbad2ca6e40f788892749428e4cb Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:03 -0700 -Subject: [PATCH 05/19] UPSTREAM: mm: multi-gen LRU: shuffle should_run_aging() - -Move should_run_aging() next to its only caller left. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-6-yuzhao@google.com -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -Cc: Mike Rapoport -Cc: Roman Gushchin -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit 77d4459a4a1a472b7309e475f962dda87d950abd) -Signed-off-by: T.J. Mercier -Change-Id: I3b0383fe16b93a783b4d8c0b3a0b325160392576 -Signed-off-by: Yu Zhao -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 124 ++++++++++++++++++++++++++-------------------------- - 1 file changed, 62 insertions(+), 62 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4456,68 +4456,6 @@ done: - return true; - } - --static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, -- struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) --{ -- int gen, type, zone; -- unsigned long old = 0; -- unsigned long young = 0; -- unsigned long total = 0; -- struct lru_gen_folio *lrugen = &lruvec->lrugen; -- struct mem_cgroup *memcg = lruvec_memcg(lruvec); -- DEFINE_MIN_SEQ(lruvec); -- -- /* whether this lruvec is completely out of cold folios */ -- if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { -- *nr_to_scan = 0; -- return true; -- } -- -- for (type = !can_swap; type < ANON_AND_FILE; type++) { -- unsigned long seq; -- -- for (seq = min_seq[type]; seq <= max_seq; seq++) { -- unsigned long size = 0; -- -- gen = lru_gen_from_seq(seq); -- -- for (zone = 0; zone < MAX_NR_ZONES; zone++) -- size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); -- -- total += size; -- if (seq == max_seq) -- young += size; -- else if (seq + MIN_NR_GENS == max_seq) -- old += size; -- } -- } -- -- /* try to scrape all its memory if this memcg was deleted */ -- *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; -- -- /* -- * The aging tries to be lazy to reduce the overhead, while the eviction -- * stalls when the number of generations reaches MIN_NR_GENS. Hence, the -- * ideal number of generations is MIN_NR_GENS+1. -- */ -- if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) -- return false; -- -- /* -- * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) -- * of the total number of pages for each generation. A reasonable range -- * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The -- * aging cares about the upper bound of hot pages, while the eviction -- * cares about the lower bound of cold pages. -- */ -- if (young * MIN_NR_GENS > total) -- return true; -- if (old * (MIN_NR_GENS + 2) < total) -- return true; -- -- return false; --} -- - static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) - { - int gen, type, zone; -@@ -5111,6 +5049,68 @@ retry: - return scanned; - } - -+static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, -+ struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) -+{ -+ int gen, type, zone; -+ unsigned long old = 0; -+ unsigned long young = 0; -+ unsigned long total = 0; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; -+ struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ DEFINE_MIN_SEQ(lruvec); -+ -+ /* whether this lruvec is completely out of cold folios */ -+ if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { -+ *nr_to_scan = 0; -+ return true; -+ } -+ -+ for (type = !can_swap; type < ANON_AND_FILE; type++) { -+ unsigned long seq; -+ -+ for (seq = min_seq[type]; seq <= max_seq; seq++) { -+ unsigned long size = 0; -+ -+ gen = lru_gen_from_seq(seq); -+ -+ for (zone = 0; zone < MAX_NR_ZONES; zone++) -+ size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); -+ -+ total += size; -+ if (seq == max_seq) -+ young += size; -+ else if (seq + MIN_NR_GENS == max_seq) -+ old += size; -+ } -+ } -+ -+ /* try to scrape all its memory if this memcg was deleted */ -+ *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; -+ -+ /* -+ * The aging tries to be lazy to reduce the overhead, while the eviction -+ * stalls when the number of generations reaches MIN_NR_GENS. Hence, the -+ * ideal number of generations is MIN_NR_GENS+1. -+ */ -+ if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) -+ return false; -+ -+ /* -+ * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) -+ * of the total number of pages for each generation. A reasonable range -+ * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The -+ * aging cares about the upper bound of hot pages, while the eviction -+ * cares about the lower bound of cold pages. -+ */ -+ if (young * MIN_NR_GENS > total) -+ return true; -+ if (old * (MIN_NR_GENS + 2) < total) -+ return true; -+ -+ return false; -+} -+ - /* - * For future optimizations: - * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg diff --git a/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch b/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch deleted file mode 100644 index 99ec42fe48..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch +++ /dev/null @@ -1,876 +0,0 @@ -From 8ee8571e47aa75221e5fbd4c9c7802fc4244c346 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:04 -0700 -Subject: [PATCH 06/19] BACKPORT: mm: multi-gen LRU: per-node lru_gen_folio - lists - -For each node, memcgs are divided into two generations: the old and -the young. For each generation, memcgs are randomly sharded into -multiple bins to improve scalability. For each bin, an RCU hlist_nulls -is virtually divided into three segments: the head, the tail and the -default. - -An onlining memcg is added to the tail of a random bin in the old -generation. The eviction starts at the head of a random bin in the old -generation. The per-node memcg generation counter, whose reminder (mod -2) indexes the old generation, is incremented when all its bins become -empty. - -There are four operations: -1. MEMCG_LRU_HEAD, which moves an memcg to the head of a random bin in - its current generation (old or young) and updates its "seg" to - "head"; -2. MEMCG_LRU_TAIL, which moves an memcg to the tail of a random bin in - its current generation (old or young) and updates its "seg" to - "tail"; -3. MEMCG_LRU_OLD, which moves an memcg to the head of a random bin in - the old generation, updates its "gen" to "old" and resets its "seg" - to "default"; -4. MEMCG_LRU_YOUNG, which moves an memcg to the tail of a random bin - in the young generation, updates its "gen" to "young" and resets - its "seg" to "default". - -The events that trigger the above operations are: -1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD; -2. The first attempt to reclaim an memcg below low, which triggers - MEMCG_LRU_TAIL; -3. The first attempt to reclaim an memcg below reclaimable size - threshold, which triggers MEMCG_LRU_TAIL; -4. The second attempt to reclaim an memcg below reclaimable size - threshold, which triggers MEMCG_LRU_YOUNG; -5. Attempting to reclaim an memcg below min, which triggers - MEMCG_LRU_YOUNG; -6. Finishing the aging on the eviction path, which triggers - MEMCG_LRU_YOUNG; -7. Offlining an memcg, which triggers MEMCG_LRU_OLD. - -Note that memcg LRU only applies to global reclaim, and the -round-robin incrementing of their max_seq counters ensures the -eventual fairness to all eligible memcgs. For memcg reclaim, it still -relies on mem_cgroup_iter(). - -Link: https://lkml.kernel.org/r/20221222041905.2431096-7-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -Cc: Mike Rapoport -Cc: Roman Gushchin -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit e4dde56cd208674ce899b47589f263499e5b8cdc) -[TJ: Resolved conflicts with older function signatures for -min_cgroup_below_min / min_cgroup_below_low and includes] -Change-Id: Idc8a0f635e035d72dd911f807d1224cb47cbd655 -Signed-off-by: T.J. Mercier ---- - include/linux/memcontrol.h | 10 + - include/linux/mm_inline.h | 17 ++ - include/linux/mmzone.h | 117 +++++++++++- - mm/memcontrol.c | 16 ++ - mm/page_alloc.c | 1 + - mm/vmscan.c | 374 +++++++++++++++++++++++++++++++++---- - 6 files changed, 500 insertions(+), 35 deletions(-) - ---- a/include/linux/memcontrol.h -+++ b/include/linux/memcontrol.h -@@ -795,6 +795,11 @@ static inline void obj_cgroup_put(struct - percpu_ref_put(&objcg->refcnt); - } - -+static inline bool mem_cgroup_tryget(struct mem_cgroup *memcg) -+{ -+ return !memcg || css_tryget(&memcg->css); -+} -+ - static inline void mem_cgroup_put(struct mem_cgroup *memcg) - { - if (memcg) -@@ -1295,6 +1300,11 @@ static inline void obj_cgroup_put(struct - { - } - -+static inline bool mem_cgroup_tryget(struct mem_cgroup *memcg) -+{ -+ return true; -+} -+ - static inline void mem_cgroup_put(struct mem_cgroup *memcg) - { - } ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -122,6 +122,18 @@ static inline bool lru_gen_in_fault(void - return current->in_lru_fault; - } - -+#ifdef CONFIG_MEMCG -+static inline int lru_gen_memcg_seg(struct lruvec *lruvec) -+{ -+ return READ_ONCE(lruvec->lrugen.seg); -+} -+#else -+static inline int lru_gen_memcg_seg(struct lruvec *lruvec) -+{ -+ return 0; -+} -+#endif -+ - static inline int lru_gen_from_seq(unsigned long seq) - { - return seq % MAX_NR_GENS; -@@ -302,6 +314,11 @@ static inline bool lru_gen_in_fault(void - return false; - } - -+static inline int lru_gen_memcg_seg(struct lruvec *lruvec) -+{ -+ return 0; -+} -+ - static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, bool reclaiming) - { - return false; ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -7,6 +7,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -367,6 +368,15 @@ struct page_vma_mapped_walk; - #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) - #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) - -+/* see the comment on MEMCG_NR_GENS */ -+enum { -+ MEMCG_LRU_NOP, -+ MEMCG_LRU_HEAD, -+ MEMCG_LRU_TAIL, -+ MEMCG_LRU_OLD, -+ MEMCG_LRU_YOUNG, -+}; -+ - #ifdef CONFIG_LRU_GEN - - enum { -@@ -426,6 +436,14 @@ struct lru_gen_folio { - atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; - /* whether the multi-gen LRU is enabled */ - bool enabled; -+#ifdef CONFIG_MEMCG -+ /* the memcg generation this lru_gen_folio belongs to */ -+ u8 gen; -+ /* the list segment this lru_gen_folio belongs to */ -+ u8 seg; -+ /* per-node lru_gen_folio list for global reclaim */ -+ struct hlist_nulls_node list; -+#endif - }; - - enum { -@@ -479,12 +497,87 @@ void lru_gen_init_lruvec(struct lruvec * - void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); - - #ifdef CONFIG_MEMCG -+ -+/* -+ * For each node, memcgs are divided into two generations: the old and the -+ * young. For each generation, memcgs are randomly sharded into multiple bins -+ * to improve scalability. For each bin, the hlist_nulls is virtually divided -+ * into three segments: the head, the tail and the default. -+ * -+ * An onlining memcg is added to the tail of a random bin in the old generation. -+ * The eviction starts at the head of a random bin in the old generation. The -+ * per-node memcg generation counter, whose reminder (mod MEMCG_NR_GENS) indexes -+ * the old generation, is incremented when all its bins become empty. -+ * -+ * There are four operations: -+ * 1. MEMCG_LRU_HEAD, which moves an memcg to the head of a random bin in its -+ * current generation (old or young) and updates its "seg" to "head"; -+ * 2. MEMCG_LRU_TAIL, which moves an memcg to the tail of a random bin in its -+ * current generation (old or young) and updates its "seg" to "tail"; -+ * 3. MEMCG_LRU_OLD, which moves an memcg to the head of a random bin in the old -+ * generation, updates its "gen" to "old" and resets its "seg" to "default"; -+ * 4. MEMCG_LRU_YOUNG, which moves an memcg to the tail of a random bin in the -+ * young generation, updates its "gen" to "young" and resets its "seg" to -+ * "default". -+ * -+ * The events that trigger the above operations are: -+ * 1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD; -+ * 2. The first attempt to reclaim an memcg below low, which triggers -+ * MEMCG_LRU_TAIL; -+ * 3. The first attempt to reclaim an memcg below reclaimable size threshold, -+ * which triggers MEMCG_LRU_TAIL; -+ * 4. The second attempt to reclaim an memcg below reclaimable size threshold, -+ * which triggers MEMCG_LRU_YOUNG; -+ * 5. Attempting to reclaim an memcg below min, which triggers MEMCG_LRU_YOUNG; -+ * 6. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG; -+ * 7. Offlining an memcg, which triggers MEMCG_LRU_OLD. -+ * -+ * Note that memcg LRU only applies to global reclaim, and the round-robin -+ * incrementing of their max_seq counters ensures the eventual fairness to all -+ * eligible memcgs. For memcg reclaim, it still relies on mem_cgroup_iter(). -+ */ -+#define MEMCG_NR_GENS 2 -+#define MEMCG_NR_BINS 8 -+ -+struct lru_gen_memcg { -+ /* the per-node memcg generation counter */ -+ unsigned long seq; -+ /* each memcg has one lru_gen_folio per node */ -+ unsigned long nr_memcgs[MEMCG_NR_GENS]; -+ /* per-node lru_gen_folio list for global reclaim */ -+ struct hlist_nulls_head fifo[MEMCG_NR_GENS][MEMCG_NR_BINS]; -+ /* protects the above */ -+ spinlock_t lock; -+}; -+ -+void lru_gen_init_pgdat(struct pglist_data *pgdat); -+ - void lru_gen_init_memcg(struct mem_cgroup *memcg); - void lru_gen_exit_memcg(struct mem_cgroup *memcg); --#endif -+void lru_gen_online_memcg(struct mem_cgroup *memcg); -+void lru_gen_offline_memcg(struct mem_cgroup *memcg); -+void lru_gen_release_memcg(struct mem_cgroup *memcg); -+void lru_gen_rotate_memcg(struct lruvec *lruvec, int op); -+ -+#else /* !CONFIG_MEMCG */ -+ -+#define MEMCG_NR_GENS 1 -+ -+struct lru_gen_memcg { -+}; -+ -+static inline void lru_gen_init_pgdat(struct pglist_data *pgdat) -+{ -+} -+ -+#endif /* CONFIG_MEMCG */ - - #else /* !CONFIG_LRU_GEN */ - -+static inline void lru_gen_init_pgdat(struct pglist_data *pgdat) -+{ -+} -+ - static inline void lru_gen_init_lruvec(struct lruvec *lruvec) - { - } -@@ -494,6 +587,7 @@ static inline void lru_gen_look_around(s - } - - #ifdef CONFIG_MEMCG -+ - static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) - { - } -@@ -501,7 +595,24 @@ static inline void lru_gen_init_memcg(st - static inline void lru_gen_exit_memcg(struct mem_cgroup *memcg) - { - } --#endif -+ -+static inline void lru_gen_online_memcg(struct mem_cgroup *memcg) -+{ -+} -+ -+static inline void lru_gen_offline_memcg(struct mem_cgroup *memcg) -+{ -+} -+ -+static inline void lru_gen_release_memcg(struct mem_cgroup *memcg) -+{ -+} -+ -+static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) -+{ -+} -+ -+#endif /* CONFIG_MEMCG */ - - #endif /* CONFIG_LRU_GEN */ - -@@ -1219,6 +1330,8 @@ typedef struct pglist_data { - #ifdef CONFIG_LRU_GEN - /* kswap mm walk data */ - struct lru_gen_mm_walk mm_walk; -+ /* lru_gen_folio list */ -+ struct lru_gen_memcg memcg_lru; - #endif - - CACHELINE_PADDING(_pad2_); ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -477,6 +477,16 @@ static void mem_cgroup_update_tree(struc - struct mem_cgroup_per_node *mz; - struct mem_cgroup_tree_per_node *mctz; - -+ if (lru_gen_enabled()) { -+ struct lruvec *lruvec = &memcg->nodeinfo[nid]->lruvec; -+ -+ /* see the comment on MEMCG_NR_GENS */ -+ if (soft_limit_excess(memcg) && lru_gen_memcg_seg(lruvec) != MEMCG_LRU_HEAD) -+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_HEAD); -+ -+ return; -+ } -+ - mctz = soft_limit_tree.rb_tree_per_node[nid]; - if (!mctz) - return; -@@ -3524,6 +3534,9 @@ unsigned long mem_cgroup_soft_limit_recl - struct mem_cgroup_tree_per_node *mctz; - unsigned long excess; - -+ if (lru_gen_enabled()) -+ return 0; -+ - if (order > 0) - return 0; - -@@ -5387,6 +5400,7 @@ static int mem_cgroup_css_online(struct - if (unlikely(mem_cgroup_is_root(memcg))) - queue_delayed_work(system_unbound_wq, &stats_flush_dwork, - 2UL*HZ); -+ lru_gen_online_memcg(memcg); - return 0; - offline_kmem: - memcg_offline_kmem(memcg); -@@ -5418,6 +5432,7 @@ static void mem_cgroup_css_offline(struc - memcg_offline_kmem(memcg); - reparent_shrinker_deferred(memcg); - wb_memcg_offline(memcg); -+ lru_gen_offline_memcg(memcg); - - drain_all_stock(memcg); - -@@ -5429,6 +5444,7 @@ static void mem_cgroup_css_released(stru - struct mem_cgroup *memcg = mem_cgroup_from_css(css); - - invalidate_reclaim_iterators(memcg); -+ lru_gen_release_memcg(memcg); - } - - static void mem_cgroup_css_free(struct cgroup_subsys_state *css) ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -7943,6 +7943,7 @@ static void __init free_area_init_node(i - pgdat_set_deferred_range(pgdat); - - free_area_init_core(pgdat); -+ lru_gen_init_pgdat(pgdat); - } - - static void __init free_area_init_memoryless_node(int nid) ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -54,6 +54,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -134,11 +136,6 @@ struct scan_control { - /* Always discard instead of demoting to lower tier memory */ - unsigned int no_demotion:1; - --#ifdef CONFIG_LRU_GEN -- /* help kswapd make better choices among multiple memcgs */ -- unsigned long last_reclaimed; --#endif -- - /* Allocation order */ - s8 order; - -@@ -3160,6 +3157,9 @@ DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_ca - for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ - for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) - -+#define get_memcg_gen(seq) ((seq) % MEMCG_NR_GENS) -+#define get_memcg_bin(bin) ((bin) % MEMCG_NR_BINS) -+ - static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid) - { - struct pglist_data *pgdat = NODE_DATA(nid); -@@ -4442,8 +4442,7 @@ done: - if (sc->priority <= DEF_PRIORITY - 2) - wait_event_killable(lruvec->mm_state.wait, - max_seq < READ_ONCE(lrugen->max_seq)); -- -- return max_seq < READ_ONCE(lrugen->max_seq); -+ return false; - } - - VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); -@@ -4516,8 +4515,6 @@ static void lru_gen_age_node(struct pgli - - VM_WARN_ON_ONCE(!current_is_kswapd()); - -- sc->last_reclaimed = sc->nr_reclaimed; -- - /* check the order to exclude compaction-induced reclaim */ - if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) - return; -@@ -5116,8 +5113,7 @@ static bool should_run_aging(struct lruv - * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg - * reclaim. - */ --static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, -- bool can_swap) -+static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool can_swap) - { - unsigned long nr_to_scan; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); -@@ -5134,10 +5130,8 @@ static unsigned long get_nr_to_scan(stru - if (sc->priority == DEF_PRIORITY) - return nr_to_scan; - -- try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false); -- - /* skip this lruvec as it's low on cold folios */ -- return 0; -+ return try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false) ? -1 : 0; - } - - static unsigned long get_nr_to_reclaim(struct scan_control *sc) -@@ -5146,29 +5140,18 @@ static unsigned long get_nr_to_reclaim(s - if (!global_reclaim(sc)) - return -1; - -- /* discount the previous progress for kswapd */ -- if (current_is_kswapd()) -- return sc->nr_to_reclaim + sc->last_reclaimed; -- - return max(sc->nr_to_reclaim, compact_gap(sc->order)); - } - --static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -+static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) - { -- struct blk_plug plug; -+ long nr_to_scan; - unsigned long scanned = 0; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - -- lru_add_drain(); -- -- blk_start_plug(&plug); -- -- set_mm_walk(lruvec_pgdat(lruvec)); -- - while (true) { - int delta; - int swappiness; -- unsigned long nr_to_scan; - - if (sc->may_swap) - swappiness = get_swappiness(lruvec, sc); -@@ -5178,7 +5161,7 @@ static void lru_gen_shrink_lruvec(struct - swappiness = 0; - - nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); -- if (!nr_to_scan) -+ if (nr_to_scan <= 0) - break; - - delta = evict_folios(lruvec, sc, swappiness); -@@ -5195,10 +5178,251 @@ static void lru_gen_shrink_lruvec(struct - cond_resched(); - } - -+ /* whether try_to_inc_max_seq() was successful */ -+ return nr_to_scan < 0; -+} -+ -+static int shrink_one(struct lruvec *lruvec, struct scan_control *sc) -+{ -+ bool success; -+ unsigned long scanned = sc->nr_scanned; -+ unsigned long reclaimed = sc->nr_reclaimed; -+ int seg = lru_gen_memcg_seg(lruvec); -+ struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ struct pglist_data *pgdat = lruvec_pgdat(lruvec); -+ -+ /* see the comment on MEMCG_NR_GENS */ -+ if (!lruvec_is_sizable(lruvec, sc)) -+ return seg != MEMCG_LRU_TAIL ? MEMCG_LRU_TAIL : MEMCG_LRU_YOUNG; -+ -+ mem_cgroup_calculate_protection(NULL, memcg); -+ -+ if (mem_cgroup_below_min(memcg)) -+ return MEMCG_LRU_YOUNG; -+ -+ if (mem_cgroup_below_low(memcg)) { -+ /* see the comment on MEMCG_NR_GENS */ -+ if (seg != MEMCG_LRU_TAIL) -+ return MEMCG_LRU_TAIL; -+ -+ memcg_memory_event(memcg, MEMCG_LOW); -+ } -+ -+ success = try_to_shrink_lruvec(lruvec, sc); -+ -+ shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, sc->priority); -+ -+ if (!sc->proactive) -+ vmpressure(sc->gfp_mask, memcg, false, sc->nr_scanned - scanned, -+ sc->nr_reclaimed - reclaimed); -+ -+ sc->nr_reclaimed += current->reclaim_state->reclaimed_slab; -+ current->reclaim_state->reclaimed_slab = 0; -+ -+ return success ? MEMCG_LRU_YOUNG : 0; -+} -+ -+#ifdef CONFIG_MEMCG -+ -+static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ int gen; -+ int bin; -+ int first_bin; -+ struct lruvec *lruvec; -+ struct lru_gen_folio *lrugen; -+ const struct hlist_nulls_node *pos; -+ int op = 0; -+ struct mem_cgroup *memcg = NULL; -+ unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); -+ -+ bin = first_bin = get_random_u32_below(MEMCG_NR_BINS); -+restart: -+ gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq)); -+ -+ rcu_read_lock(); -+ -+ hlist_nulls_for_each_entry_rcu(lrugen, pos, &pgdat->memcg_lru.fifo[gen][bin], list) { -+ if (op) -+ lru_gen_rotate_memcg(lruvec, op); -+ -+ mem_cgroup_put(memcg); -+ -+ lruvec = container_of(lrugen, struct lruvec, lrugen); -+ memcg = lruvec_memcg(lruvec); -+ -+ if (!mem_cgroup_tryget(memcg)) { -+ op = 0; -+ memcg = NULL; -+ continue; -+ } -+ -+ rcu_read_unlock(); -+ -+ op = shrink_one(lruvec, sc); -+ -+ if (sc->nr_reclaimed >= nr_to_reclaim) -+ goto success; -+ -+ rcu_read_lock(); -+ } -+ -+ rcu_read_unlock(); -+ -+ /* restart if raced with lru_gen_rotate_memcg() */ -+ if (gen != get_nulls_value(pos)) -+ goto restart; -+ -+ /* try the rest of the bins of the current generation */ -+ bin = get_memcg_bin(bin + 1); -+ if (bin != first_bin) -+ goto restart; -+success: -+ if (op) -+ lru_gen_rotate_memcg(lruvec, op); -+ -+ mem_cgroup_put(memcg); -+} -+ -+static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -+{ -+ struct blk_plug plug; -+ -+ VM_WARN_ON_ONCE(global_reclaim(sc)); -+ -+ lru_add_drain(); -+ -+ blk_start_plug(&plug); -+ -+ set_mm_walk(lruvec_pgdat(lruvec)); -+ -+ if (try_to_shrink_lruvec(lruvec, sc)) -+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); -+ -+ clear_mm_walk(); -+ -+ blk_finish_plug(&plug); -+} -+ -+#else /* !CONFIG_MEMCG */ -+ -+static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ BUILD_BUG(); -+} -+ -+static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -+{ -+ BUILD_BUG(); -+} -+ -+#endif -+ -+static void set_initial_priority(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ int priority; -+ unsigned long reclaimable; -+ struct lruvec *lruvec = mem_cgroup_lruvec(NULL, pgdat); -+ -+ if (sc->priority != DEF_PRIORITY || sc->nr_to_reclaim < MIN_LRU_BATCH) -+ return; -+ /* -+ * Determine the initial priority based on ((total / MEMCG_NR_GENS) >> -+ * priority) * reclaimed_to_scanned_ratio = nr_to_reclaim, where the -+ * estimated reclaimed_to_scanned_ratio = inactive / total. -+ */ -+ reclaimable = node_page_state(pgdat, NR_INACTIVE_FILE); -+ if (get_swappiness(lruvec, sc)) -+ reclaimable += node_page_state(pgdat, NR_INACTIVE_ANON); -+ -+ reclaimable /= MEMCG_NR_GENS; -+ -+ /* round down reclaimable and round up sc->nr_to_reclaim */ -+ priority = fls_long(reclaimable) - 1 - fls_long(sc->nr_to_reclaim - 1); -+ -+ sc->priority = clamp(priority, 0, DEF_PRIORITY); -+} -+ -+static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ struct blk_plug plug; -+ unsigned long reclaimed = sc->nr_reclaimed; -+ -+ VM_WARN_ON_ONCE(!global_reclaim(sc)); -+ -+ lru_add_drain(); -+ -+ blk_start_plug(&plug); -+ -+ set_mm_walk(pgdat); -+ -+ set_initial_priority(pgdat, sc); -+ -+ if (current_is_kswapd()) -+ sc->nr_reclaimed = 0; -+ -+ if (mem_cgroup_disabled()) -+ shrink_one(&pgdat->__lruvec, sc); -+ else -+ shrink_many(pgdat, sc); -+ -+ if (current_is_kswapd()) -+ sc->nr_reclaimed += reclaimed; -+ - clear_mm_walk(); - - blk_finish_plug(&plug); -+ -+ /* kswapd should never fail */ -+ pgdat->kswapd_failures = 0; -+} -+ -+#ifdef CONFIG_MEMCG -+void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) -+{ -+ int seg; -+ int old, new; -+ int bin = get_random_u32_below(MEMCG_NR_BINS); -+ struct pglist_data *pgdat = lruvec_pgdat(lruvec); -+ -+ spin_lock(&pgdat->memcg_lru.lock); -+ -+ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); -+ -+ seg = 0; -+ new = old = lruvec->lrugen.gen; -+ -+ /* see the comment on MEMCG_NR_GENS */ -+ if (op == MEMCG_LRU_HEAD) -+ seg = MEMCG_LRU_HEAD; -+ else if (op == MEMCG_LRU_TAIL) -+ seg = MEMCG_LRU_TAIL; -+ else if (op == MEMCG_LRU_OLD) -+ new = get_memcg_gen(pgdat->memcg_lru.seq); -+ else if (op == MEMCG_LRU_YOUNG) -+ new = get_memcg_gen(pgdat->memcg_lru.seq + 1); -+ else -+ VM_WARN_ON_ONCE(true); -+ -+ hlist_nulls_del_rcu(&lruvec->lrugen.list); -+ -+ if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD) -+ hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); -+ else -+ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); -+ -+ pgdat->memcg_lru.nr_memcgs[old]--; -+ pgdat->memcg_lru.nr_memcgs[new]++; -+ -+ lruvec->lrugen.gen = new; -+ WRITE_ONCE(lruvec->lrugen.seg, seg); -+ -+ if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq)) -+ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); -+ -+ spin_unlock(&pgdat->memcg_lru.lock); - } -+#endif - - /****************************************************************************** - * state change -@@ -5656,11 +5880,11 @@ static int run_cmd(char cmd, int memcg_i - - if (!mem_cgroup_disabled()) { - rcu_read_lock(); -+ - memcg = mem_cgroup_from_id(memcg_id); --#ifdef CONFIG_MEMCG -- if (memcg && !css_tryget(&memcg->css)) -+ if (!mem_cgroup_tryget(memcg)) - memcg = NULL; --#endif -+ - rcu_read_unlock(); - - if (!memcg) -@@ -5808,6 +6032,19 @@ void lru_gen_init_lruvec(struct lruvec * - } - - #ifdef CONFIG_MEMCG -+ -+void lru_gen_init_pgdat(struct pglist_data *pgdat) -+{ -+ int i, j; -+ -+ spin_lock_init(&pgdat->memcg_lru.lock); -+ -+ for (i = 0; i < MEMCG_NR_GENS; i++) { -+ for (j = 0; j < MEMCG_NR_BINS; j++) -+ INIT_HLIST_NULLS_HEAD(&pgdat->memcg_lru.fifo[i][j], i); -+ } -+} -+ - void lru_gen_init_memcg(struct mem_cgroup *memcg) - { - INIT_LIST_HEAD(&memcg->mm_list.fifo); -@@ -5831,7 +6068,69 @@ void lru_gen_exit_memcg(struct mem_cgrou - } - } - } --#endif -+ -+void lru_gen_online_memcg(struct mem_cgroup *memcg) -+{ -+ int gen; -+ int nid; -+ int bin = get_random_u32_below(MEMCG_NR_BINS); -+ -+ for_each_node(nid) { -+ struct pglist_data *pgdat = NODE_DATA(nid); -+ struct lruvec *lruvec = get_lruvec(memcg, nid); -+ -+ spin_lock(&pgdat->memcg_lru.lock); -+ -+ VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list)); -+ -+ gen = get_memcg_gen(pgdat->memcg_lru.seq); -+ -+ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]); -+ pgdat->memcg_lru.nr_memcgs[gen]++; -+ -+ lruvec->lrugen.gen = gen; -+ -+ spin_unlock(&pgdat->memcg_lru.lock); -+ } -+} -+ -+void lru_gen_offline_memcg(struct mem_cgroup *memcg) -+{ -+ int nid; -+ -+ for_each_node(nid) { -+ struct lruvec *lruvec = get_lruvec(memcg, nid); -+ -+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD); -+ } -+} -+ -+void lru_gen_release_memcg(struct mem_cgroup *memcg) -+{ -+ int gen; -+ int nid; -+ -+ for_each_node(nid) { -+ struct pglist_data *pgdat = NODE_DATA(nid); -+ struct lruvec *lruvec = get_lruvec(memcg, nid); -+ -+ spin_lock(&pgdat->memcg_lru.lock); -+ -+ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); -+ -+ gen = lruvec->lrugen.gen; -+ -+ hlist_nulls_del_rcu(&lruvec->lrugen.list); -+ pgdat->memcg_lru.nr_memcgs[gen]--; -+ -+ if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq)) -+ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); -+ -+ spin_unlock(&pgdat->memcg_lru.lock); -+ } -+} -+ -+#endif /* CONFIG_MEMCG */ - - static int __init init_lru_gen(void) - { -@@ -5858,6 +6157,10 @@ static void lru_gen_shrink_lruvec(struct - { - } - -+static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+} -+ - #endif /* CONFIG_LRU_GEN */ - - static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -@@ -5871,7 +6174,7 @@ static void shrink_lruvec(struct lruvec - bool proportional_reclaim; - struct blk_plug plug; - -- if (lru_gen_enabled()) { -+ if (lru_gen_enabled() && !global_reclaim(sc)) { - lru_gen_shrink_lruvec(lruvec, sc); - return; - } -@@ -6114,6 +6417,11 @@ static void shrink_node(pg_data_t *pgdat - struct lruvec *target_lruvec; - bool reclaimable = false; - -+ if (lru_gen_enabled() && global_reclaim(sc)) { -+ lru_gen_shrink_node(pgdat, sc); -+ return; -+ } -+ - target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat); - - again: diff --git a/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch b/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch deleted file mode 100644 index d60ddb9dcc..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 11b14ee8cbbbebd8204609076a9327a1171cd253 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:05 -0700 -Subject: [PATCH 07/19] BACKPORT: mm: multi-gen LRU: clarify scan_control flags - -Among the flags in scan_control: -1. sc->may_swap, which indicates swap constraint due to memsw.max, is - supported as usual. -2. sc->proactive, which indicates reclaim by memory.reclaim, may not - opportunistically skip the aging path, since it is considered less - latency sensitive. -3. !(sc->gfp_mask & __GFP_IO), which indicates IO constraint, lowers - swappiness to prioritize file LRU, since clean file folios are more - likely to exist. -4. sc->may_writepage and sc->may_unmap, which indicates opportunistic - reclaim, are rejected, since unmapped clean folios are already - prioritized. Scanning for more of them is likely futile and can - cause high reclaim latency when there is a large number of memcgs. - -The rest are handled by the existing code. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-8-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -Cc: Mike Rapoport -Cc: Roman Gushchin -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit e9d4e1ee788097484606c32122f146d802a9c5fb) -[TJ: Resolved conflict with older function signature for min_cgroup_below_min, and over -cdded861182142ac4488a4d64c571107aeb77f53 ("ANDROID: MGLRU: Don't skip anon reclaim if swap low")] -Change-Id: Ic2e779eaf4e91a3921831b4e2fa10c740dc59d50 -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 55 +++++++++++++++++++++++++++-------------------------- - 1 file changed, 28 insertions(+), 27 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3185,6 +3185,9 @@ static int get_swappiness(struct lruvec - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - struct pglist_data *pgdat = lruvec_pgdat(lruvec); - -+ if (!sc->may_swap) -+ return 0; -+ - if (!can_demote(pgdat->node_id, sc) && - mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) - return 0; -@@ -4223,7 +4226,7 @@ static void walk_mm(struct lruvec *lruve - } while (err == -EAGAIN); - } - --static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat) -+static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat, bool force_alloc) - { - struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; - -@@ -4231,7 +4234,7 @@ static struct lru_gen_mm_walk *set_mm_wa - VM_WARN_ON_ONCE(walk); - - walk = &pgdat->mm_walk; -- } else if (!pgdat && !walk) { -+ } else if (!walk && force_alloc) { - VM_WARN_ON_ONCE(current_is_kswapd()); - - walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); -@@ -4419,7 +4422,7 @@ static bool try_to_inc_max_seq(struct lr - goto done; - } - -- walk = set_mm_walk(NULL); -+ walk = set_mm_walk(NULL, true); - if (!walk) { - success = iterate_mm_list_nowalk(lruvec, max_seq); - goto done; -@@ -4488,8 +4491,6 @@ static bool lruvec_is_reclaimable(struct - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MIN_SEQ(lruvec); - -- VM_WARN_ON_ONCE(sc->memcg_low_reclaim); -- - /* see the comment on lru_gen_folio */ - gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); - birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); -@@ -4753,12 +4754,8 @@ static bool isolate_folio(struct lruvec - { - bool success; - -- /* unmapping inhibited */ -- if (!sc->may_unmap && folio_mapped(folio)) -- return false; -- - /* swapping inhibited */ -- if (!(sc->may_writepage && (sc->gfp_mask & __GFP_IO)) && -+ if (!(sc->gfp_mask & __GFP_IO) && - (folio_test_dirty(folio) || - (folio_test_anon(folio) && !folio_test_swapcache(folio)))) - return false; -@@ -4857,9 +4854,8 @@ static int scan_folios(struct lruvec *lr - __count_vm_events(PGSCAN_ANON + type, isolated); - - /* -- * There might not be eligible pages due to reclaim_idx, may_unmap and -- * may_writepage. Check the remaining to prevent livelock if it's not -- * making progress. -+ * There might not be eligible folios due to reclaim_idx. Check the -+ * remaining to prevent livelock if it's not making progress. - */ - return isolated || !remaining ? scanned : 0; - } -@@ -5119,8 +5115,7 @@ static long get_nr_to_scan(struct lruvec - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); - -- if (mem_cgroup_below_min(memcg) || -- (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim)) -+ if (mem_cgroup_below_min(memcg)) - return 0; - - if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan)) -@@ -5148,17 +5143,14 @@ static bool try_to_shrink_lruvec(struct - long nr_to_scan; - unsigned long scanned = 0; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); -+ int swappiness = get_swappiness(lruvec, sc); -+ -+ /* clean file folios are more likely to exist */ -+ if (swappiness && !(sc->gfp_mask & __GFP_IO)) -+ swappiness = 1; - - while (true) { - int delta; -- int swappiness; -- -- if (sc->may_swap) -- swappiness = get_swappiness(lruvec, sc); -- else if (!cgroup_reclaim(sc) && get_swappiness(lruvec, sc)) -- swappiness = 1; -- else -- swappiness = 0; - - nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); - if (nr_to_scan <= 0) -@@ -5289,12 +5281,13 @@ static void lru_gen_shrink_lruvec(struct - struct blk_plug plug; - - VM_WARN_ON_ONCE(global_reclaim(sc)); -+ VM_WARN_ON_ONCE(!sc->may_writepage || !sc->may_unmap); - - lru_add_drain(); - - blk_start_plug(&plug); - -- set_mm_walk(lruvec_pgdat(lruvec)); -+ set_mm_walk(NULL, sc->proactive); - - if (try_to_shrink_lruvec(lruvec, sc)) - lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); -@@ -5350,11 +5343,19 @@ static void lru_gen_shrink_node(struct p - - VM_WARN_ON_ONCE(!global_reclaim(sc)); - -+ /* -+ * Unmapped clean folios are already prioritized. Scanning for more of -+ * them is likely futile and can cause high reclaim latency when there -+ * is a large number of memcgs. -+ */ -+ if (!sc->may_writepage || !sc->may_unmap) -+ goto done; -+ - lru_add_drain(); - - blk_start_plug(&plug); - -- set_mm_walk(pgdat); -+ set_mm_walk(pgdat, sc->proactive); - - set_initial_priority(pgdat, sc); - -@@ -5372,7 +5373,7 @@ static void lru_gen_shrink_node(struct p - clear_mm_walk(); - - blk_finish_plug(&plug); -- -+done: - /* kswapd should never fail */ - pgdat->kswapd_failures = 0; - } -@@ -5944,7 +5945,7 @@ static ssize_t lru_gen_seq_write(struct - set_task_reclaim_state(current, &sc.reclaim_state); - flags = memalloc_noreclaim_save(); - blk_start_plug(&plug); -- if (!set_mm_walk(NULL)) { -+ if (!set_mm_walk(NULL, true)) { - err = -ENOMEM; - goto done; - } diff --git a/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch b/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch deleted file mode 100644 index 3cbc84f8b8..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 25887d48dff860751a06caa4188bfaf6bfb6e4b2 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:06 -0700 -Subject: [PATCH 08/19] UPSTREAM: mm: multi-gen LRU: simplify - arch_has_hw_pte_young() check - -Scanning page tables when hardware does not set the accessed bit has -no real use cases. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-9-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -Cc: Mike Rapoport -Cc: Roman Gushchin -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit f386e9314025ea99dae639ed2032560a92081430) -Change-Id: I84d97ab665b4e3bb862a9bc7d72f50dea7191a6b -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4417,7 +4417,7 @@ static bool try_to_inc_max_seq(struct lr - * handful of PTEs. Spreading the work out over a period of time usually - * is less efficient, but it avoids bursty page faults. - */ -- if (!force_scan && !(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { -+ if (!arch_has_hw_pte_young() || !get_cap(LRU_GEN_MM_WALK)) { - success = iterate_mm_list_nowalk(lruvec, max_seq); - goto done; - } diff --git a/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch b/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch deleted file mode 100644 index c1ad1c538e..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 620b0ee94455e48d124414cd06d8a53f69fb6453 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Mon, 13 Feb 2023 00:53:22 -0700 -Subject: [PATCH 09/19] UPSTREAM: mm: multi-gen LRU: avoid futile retries - -Recall that the per-node memcg LRU has two generations and they alternate -when the last memcg (of a given node) is moved from one to the other. -Each generation is also sharded into multiple bins to improve scalability. -A reclaimer starts with a random bin (in the old generation) and, if it -fails, it will retry, i.e., to try the rest of the bins. - -If a reclaimer fails with the last memcg, it should move this memcg to the -young generation first, which causes the generations to alternate, and -then retry. Otherwise, the retries will be futile because all other bins -are empty. - -Link: https://lkml.kernel.org/r/20230213075322.1416966-1-yuzhao@google.com -Fixes: e4dde56cd208 ("mm: multi-gen LRU: per-node lru_gen_folio lists") -Signed-off-by: Yu Zhao -Reported-by: T.J. Mercier -Signed-off-by: Andrew Morton -Bug: 274865848 -(cherry picked from commit 9f550d78b40da21b4da515db4c37d8d7b12aa1a6) -Change-Id: Ie92535676b005ec9e7987632b742fdde8d54436f -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 25 +++++++++++++++---------- - 1 file changed, 15 insertions(+), 10 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -5218,18 +5218,20 @@ static int shrink_one(struct lruvec *lru - - static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) - { -+ int op; - int gen; - int bin; - int first_bin; - struct lruvec *lruvec; - struct lru_gen_folio *lrugen; -+ struct mem_cgroup *memcg; - const struct hlist_nulls_node *pos; -- int op = 0; -- struct mem_cgroup *memcg = NULL; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - - bin = first_bin = get_random_u32_below(MEMCG_NR_BINS); - restart: -+ op = 0; -+ memcg = NULL; - gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq)); - - rcu_read_lock(); -@@ -5253,14 +5255,22 @@ restart: - - op = shrink_one(lruvec, sc); - -- if (sc->nr_reclaimed >= nr_to_reclaim) -- goto success; -- - rcu_read_lock(); -+ -+ if (sc->nr_reclaimed >= nr_to_reclaim) -+ break; - } - - rcu_read_unlock(); - -+ if (op) -+ lru_gen_rotate_memcg(lruvec, op); -+ -+ mem_cgroup_put(memcg); -+ -+ if (sc->nr_reclaimed >= nr_to_reclaim) -+ return; -+ - /* restart if raced with lru_gen_rotate_memcg() */ - if (gen != get_nulls_value(pos)) - goto restart; -@@ -5269,11 +5279,6 @@ restart: - bin = get_memcg_bin(bin + 1); - if (bin != first_bin) - goto restart; --success: -- if (op) -- lru_gen_rotate_memcg(lruvec, op); -- -- mem_cgroup_put(memcg); - } - - static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) diff --git a/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch b/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch deleted file mode 100644 index 67fe4f96ec..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 70d216c71ff5c5b17dd1da6294f97b91fb6aba7a Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Fri, 30 Dec 2022 14:52:51 -0700 -Subject: [PATCH 10/19] UPSTREAM: mm: add vma_has_recency() - -Add vma_has_recency() to indicate whether a VMA may exhibit temporal -locality that the LRU algorithm relies on. - -This function returns false for VMAs marked by VM_SEQ_READ or -VM_RAND_READ. While the former flag indicates linear access, i.e., a -special case of spatial locality, both flags indicate a lack of temporal -locality, i.e., the reuse of an area within a relatively small duration. - -"Recency" is chosen over "locality" to avoid confusion between temporal -and spatial localities. - -Before this patch, the active/inactive LRU only ignored the accessed bit -from VMAs marked by VM_SEQ_READ. After this patch, the active/inactive -LRU and MGLRU share the same logic: they both ignore the accessed bit if -vma_has_recency() returns false. - -For the active/inactive LRU, the following fio test showed a [6, 8]% -increase in IOPS when randomly accessing mapped files under memory -pressure. - - kb=$(awk '/MemTotal/ { print $2 }' /proc/meminfo) - kb=$((kb - 8*1024*1024)) - - modprobe brd rd_nr=1 rd_size=$kb - dd if=/dev/zero of=/dev/ram0 bs=1M - - mkfs.ext4 /dev/ram0 - mount /dev/ram0 /mnt/ - swapoff -a - - fio --name=test --directory=/mnt/ --ioengine=mmap --numjobs=8 \ - --size=8G --rw=randrw --time_based --runtime=10m \ - --group_reporting - -The discussion that led to this patch is here [1]. Additional test -results are available in that thread. - -[1] https://lore.kernel.org/r/Y31s%2FK8T85jh05wH@google.com/ - -Link: https://lkml.kernel.org/r/20221230215252.2628425-1-yuzhao@google.com -Change-Id: I291dcb795197659e40e46539cd32b857677c34ad -Signed-off-by: Yu Zhao -Cc: Alexander Viro -Cc: Andrea Righi -Cc: Johannes Weiner -Cc: Michael Larabel -Signed-off-by: Andrew Morton -(cherry picked from commit 8788f6781486769d9598dcaedc3fe0eb12fc3e59) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - include/linux/mm_inline.h | 8 ++++++++ - mm/memory.c | 7 +++---- - mm/rmap.c | 42 +++++++++++++++++---------------------- - mm/vmscan.c | 5 ++++- - 4 files changed, 33 insertions(+), 29 deletions(-) - ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -600,4 +600,12 @@ pte_install_uffd_wp_if_needed(struct vm_ - #endif - } - -+static inline bool vma_has_recency(struct vm_area_struct *vma) -+{ -+ if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)) -+ return false; -+ -+ return true; -+} -+ - #endif ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1445,8 +1445,7 @@ again: - force_flush = 1; - set_page_dirty(page); - } -- if (pte_young(ptent) && -- likely(!(vma->vm_flags & VM_SEQ_READ))) -+ if (pte_young(ptent) && likely(vma_has_recency(vma))) - mark_page_accessed(page); - } - rss[mm_counter(page)]--; -@@ -5219,8 +5218,8 @@ static inline void mm_account_fault(stru - #ifdef CONFIG_LRU_GEN - static void lru_gen_enter_fault(struct vm_area_struct *vma) - { -- /* the LRU algorithm doesn't apply to sequential or random reads */ -- current->in_lru_fault = !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)); -+ /* the LRU algorithm only applies to accesses with recency */ -+ current->in_lru_fault = vma_has_recency(vma); - } - - static void lru_gen_exit_fault(void) ---- a/mm/rmap.c -+++ b/mm/rmap.c -@@ -823,25 +823,14 @@ static bool folio_referenced_one(struct - } - - if (pvmw.pte) { -- if (lru_gen_enabled() && pte_young(*pvmw.pte) && -- !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ))) { -+ if (lru_gen_enabled() && pte_young(*pvmw.pte)) { - lru_gen_look_around(&pvmw); - referenced++; - } - - if (ptep_clear_flush_young_notify(vma, address, -- pvmw.pte)) { -- /* -- * Don't treat a reference through -- * a sequentially read mapping as such. -- * If the folio has been used in another mapping, -- * we will catch it; if this other mapping is -- * already gone, the unmap path will have set -- * the referenced flag or activated the folio. -- */ -- if (likely(!(vma->vm_flags & VM_SEQ_READ))) -- referenced++; -- } -+ pvmw.pte)) -+ referenced++; - } else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) { - if (pmdp_clear_flush_young_notify(vma, address, - pvmw.pmd)) -@@ -875,7 +864,20 @@ static bool invalid_folio_referenced_vma - struct folio_referenced_arg *pra = arg; - struct mem_cgroup *memcg = pra->memcg; - -- if (!mm_match_cgroup(vma->vm_mm, memcg)) -+ /* -+ * Ignore references from this mapping if it has no recency. If the -+ * folio has been used in another mapping, we will catch it; if this -+ * other mapping is already gone, the unmap path will have set the -+ * referenced flag or activated the folio in zap_pte_range(). -+ */ -+ if (!vma_has_recency(vma)) -+ return true; -+ -+ /* -+ * If we are reclaiming on behalf of a cgroup, skip counting on behalf -+ * of references from different cgroups. -+ */ -+ if (memcg && !mm_match_cgroup(vma->vm_mm, memcg)) - return true; - - return false; -@@ -906,6 +908,7 @@ int folio_referenced(struct folio *folio - .arg = (void *)&pra, - .anon_lock = folio_lock_anon_vma_read, - .try_lock = true, -+ .invalid_vma = invalid_folio_referenced_vma, - }; - - *vm_flags = 0; -@@ -921,15 +924,6 @@ int folio_referenced(struct folio *folio - return 1; - } - -- /* -- * If we are reclaiming on behalf of a cgroup, skip -- * counting on behalf of references from different -- * cgroups -- */ -- if (memcg) { -- rwc.invalid_vma = invalid_folio_referenced_vma; -- } -- - rmap_walk(folio, &rwc); - *vm_flags = pra.vm_flags; - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3778,7 +3778,10 @@ static int should_skip_vma(unsigned long - if (is_vm_hugetlb_page(vma)) - return true; - -- if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL | VM_SEQ_READ | VM_RAND_READ)) -+ if (!vma_has_recency(vma)) -+ return true; -+ -+ if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) - return true; - - if (vma == get_gate_vma(vma->vm_mm)) diff --git a/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch b/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch deleted file mode 100644 index f9c39be920..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 9ca4e437a24dfc4ec6c362f319eb9850b9eca497 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Fri, 30 Dec 2022 14:52:52 -0700 -Subject: [PATCH 11/19] UPSTREAM: mm: support POSIX_FADV_NOREUSE - -This patch adds POSIX_FADV_NOREUSE to vma_has_recency() so that the LRU -algorithm can ignore access to mapped files marked by this flag. - -The advantages of POSIX_FADV_NOREUSE are: -1. Unlike MADV_SEQUENTIAL and MADV_RANDOM, it does not alter the - default readahead behavior. -2. Unlike MADV_SEQUENTIAL and MADV_RANDOM, it does not split VMAs and - therefore does not take mmap_lock. -3. Unlike MADV_COLD, setting it has a negligible cost, regardless of - how many pages it affects. - -Its limitations are: -1. Like POSIX_FADV_RANDOM and POSIX_FADV_SEQUENTIAL, it currently does - not support range. IOW, its scope is the entire file. -2. It currently does not ignore access through file descriptors. - Specifically, for the active/inactive LRU, given a file page shared - by two users and one of them having set POSIX_FADV_NOREUSE on the - file, this page will be activated upon the second user accessing - it. This corner case can be covered by checking POSIX_FADV_NOREUSE - before calling folio_mark_accessed() on the read path. But it is - considered not worth the effort. - -There have been a few attempts to support POSIX_FADV_NOREUSE, e.g., [1]. -This time the goal is to fill a niche: a few desktop applications, e.g., -large file transferring and video encoding/decoding, want fast file -streaming with mmap() rather than direct IO. Among those applications, an -SVT-AV1 regression was reported when running with MGLRU [2]. The -following test can reproduce that regression. - - kb=$(awk '/MemTotal/ { print $2 }' /proc/meminfo) - kb=$((kb - 8*1024*1024)) - - modprobe brd rd_nr=1 rd_size=$kb - dd if=/dev/zero of=/dev/ram0 bs=1M - - mkfs.ext4 /dev/ram0 - mount /dev/ram0 /mnt/ - swapoff -a - - fallocate -l 8G /mnt/swapfile - mkswap /mnt/swapfile - swapon /mnt/swapfile - - wget http://ultravideo.cs.tut.fi/video/Bosphorus_3840x2160_120fps_420_8bit_YUV_Y4M.7z - 7z e -o/mnt/ Bosphorus_3840x2160_120fps_420_8bit_YUV_Y4M.7z - SvtAv1EncApp --preset 12 -w 3840 -h 2160 \ - -i /mnt/Bosphorus_3840x2160.y4m - -For MGLRU, the following change showed a [9-11]% increase in FPS, -which makes it on par with the active/inactive LRU. - - patch Source/App/EncApp/EbAppMain.c < #include - 35d35 - < #include /* _O_BINARY */ - 117a118 - > posix_fadvise(config->mmap.fd, 0, 0, POSIX_FADV_NOREUSE); - EOF - -[1] https://lore.kernel.org/r/1308923350-7932-1-git-send-email-andrea@betterlinux.com/ -[2] https://openbenchmarking.org/result/2209259-PTS-MGLRU8GB57 - -Link: https://lkml.kernel.org/r/20221230215252.2628425-2-yuzhao@google.com -Change-Id: I0b7f5f971d78014ea1ba44cee6a8ec902a4330d0 -Signed-off-by: Yu Zhao -Cc: Alexander Viro -Cc: Andrea Righi -Cc: Johannes Weiner -Cc: Michael Larabel -Signed-off-by: Andrew Morton -(cherry picked from commit 17e810229cb3068b692fa078bd9b3a6527e0866a) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - include/linux/fs.h | 2 ++ - include/linux/mm_inline.h | 3 +++ - mm/fadvise.c | 5 ++++- - 3 files changed, 9 insertions(+), 1 deletion(-) - ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -166,6 +166,8 @@ typedef int (dio_iodone_t)(struct kiocb - /* File supports DIRECT IO */ - #define FMODE_CAN_ODIRECT ((__force fmode_t)0x400000) - -+#define FMODE_NOREUSE ((__force fmode_t)0x800000) -+ - /* File was opened by fanotify and shouldn't generate fanotify events */ - #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) - ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -605,6 +605,9 @@ static inline bool vma_has_recency(struc - if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)) - return false; - -+ if (vma->vm_file && (vma->vm_file->f_mode & FMODE_NOREUSE)) -+ return false; -+ - return true; - } - ---- a/mm/fadvise.c -+++ b/mm/fadvise.c -@@ -80,7 +80,7 @@ int generic_fadvise(struct file *file, l - case POSIX_FADV_NORMAL: - file->f_ra.ra_pages = bdi->ra_pages; - spin_lock(&file->f_lock); -- file->f_mode &= ~FMODE_RANDOM; -+ file->f_mode &= ~(FMODE_RANDOM | FMODE_NOREUSE); - spin_unlock(&file->f_lock); - break; - case POSIX_FADV_RANDOM: -@@ -107,6 +107,9 @@ int generic_fadvise(struct file *file, l - force_page_cache_readahead(mapping, file, start_index, nrpages); - break; - case POSIX_FADV_NOREUSE: -+ spin_lock(&file->f_lock); -+ file->f_mode |= FMODE_NOREUSE; -+ spin_unlock(&file->f_lock); - break; - case POSIX_FADV_DONTNEED: - __filemap_fdatawrite_range(mapping, offset, endbyte, diff --git a/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch b/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch deleted file mode 100644 index bac2e3e344..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 1b5e4c317d80f4826eceb3781702d18d06b14394 Mon Sep 17 00:00:00 2001 -From: "T.J. Alumbaugh" -Date: Wed, 18 Jan 2023 00:18:21 +0000 -Subject: [PATCH 12/19] UPSTREAM: mm: multi-gen LRU: section for working set - protection - -Patch series "mm: multi-gen LRU: improve". - -This patch series improves a few MGLRU functions, collects related -functions, and adds additional documentation. - -This patch (of 7): - -Add a section for working set protection in the code and the design doc. -The admin doc already contains its usage. - -Link: https://lkml.kernel.org/r/20230118001827.1040870-1-talumbau@google.com -Link: https://lkml.kernel.org/r/20230118001827.1040870-2-talumbau@google.com -Change-Id: I65599075fd42951db7739a2ab7cee78516e157b3 -Signed-off-by: T.J. Alumbaugh -Cc: Yu Zhao -Signed-off-by: Andrew Morton -(cherry picked from commit 7b8144e63d84716f16a1b929e0c7e03ae5c4d5c1) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - Documentation/mm/multigen_lru.rst | 15 +++++++++++++++ - mm/vmscan.c | 4 ++++ - 2 files changed, 19 insertions(+) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -141,6 +141,21 @@ loop has detected outlying refaults from - this end, the feedback loop uses the first tier as the baseline, for - the reason stated earlier. - -+Working set protection -+---------------------- -+Each generation is timestamped at birth. If ``lru_gen_min_ttl`` is -+set, an ``lruvec`` is protected from the eviction when its oldest -+generation was born within ``lru_gen_min_ttl`` milliseconds. In other -+words, it prevents the working set of ``lru_gen_min_ttl`` milliseconds -+from getting evicted. The OOM killer is triggered if this working set -+cannot be kept in memory. -+ -+This time-based approach has the following advantages: -+ -+1. It is easier to configure because it is agnostic to applications -+ and memory sizes. -+2. It is more reliable because it is directly wired to the OOM killer. -+ - Summary - ------- - The multi-gen LRU can be disassembled into the following parts: ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4461,6 +4461,10 @@ done: - return true; - } - -+/****************************************************************************** -+ * working set protection -+ ******************************************************************************/ -+ - static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) - { - int gen, type, zone; diff --git a/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch b/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch deleted file mode 100644 index c28a1c5d5b..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 5ddf9d53d375e42af49b744bd7c2f8247c6bce15 Mon Sep 17 00:00:00 2001 -From: "T.J. Alumbaugh" -Date: Wed, 18 Jan 2023 00:18:22 +0000 -Subject: [PATCH 13/19] UPSTREAM: mm: multi-gen LRU: section for rmap/PT walk - feedback - -Add a section for lru_gen_look_around() in the code and the design doc. - -Link: https://lkml.kernel.org/r/20230118001827.1040870-3-talumbau@google.com -Change-Id: I5097af63f61b3b69ec2abee6cdbdc33c296df213 -Signed-off-by: T.J. Alumbaugh -Cc: Yu Zhao -Signed-off-by: Andrew Morton -(cherry picked from commit db19a43d9b3a8876552f00f656008206ef9a5efa) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - Documentation/mm/multigen_lru.rst | 14 ++++++++++++++ - mm/vmscan.c | 4 ++++ - 2 files changed, 18 insertions(+) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -156,6 +156,20 @@ This time-based approach has the followi - and memory sizes. - 2. It is more reliable because it is directly wired to the OOM killer. - -+Rmap/PT walk feedback -+--------------------- -+Searching the rmap for PTEs mapping each page on an LRU list (to test -+and clear the accessed bit) can be expensive because pages from -+different VMAs (PA space) are not cache friendly to the rmap (VA -+space). For workloads mostly using mapped pages, searching the rmap -+can incur the highest CPU cost in the reclaim path. -+ -+``lru_gen_look_around()`` exploits spatial locality to reduce the -+trips into the rmap. It scans the adjacent PTEs of a young PTE and -+promotes hot pages. If the scan was done cacheline efficiently, it -+adds the PMD entry pointing to the PTE table to the Bloom filter. This -+forms a feedback loop between the eviction and the aging. -+ - Summary - ------- - The multi-gen LRU can be disassembled into the following parts: ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4555,6 +4555,10 @@ static void lru_gen_age_node(struct pgli - } - } - -+/****************************************************************************** -+ * rmap/PT walk feedback -+ ******************************************************************************/ -+ - /* - * This function exploits spatial locality when shrink_folio_list() walks the - * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. If diff --git a/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch b/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch deleted file mode 100644 index a7dfb5ffe7..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch +++ /dev/null @@ -1,243 +0,0 @@ -From 397624e12244ec038f51cb1f178ccb7a2ec562e5 Mon Sep 17 00:00:00 2001 -From: "T.J. Alumbaugh" -Date: Wed, 18 Jan 2023 00:18:23 +0000 -Subject: [PATCH 14/19] UPSTREAM: mm: multi-gen LRU: section for Bloom filters - -Move Bloom filters code into a dedicated section. Improve the design doc -to explain Bloom filter usage and connection between aging and eviction in -their use. - -Link: https://lkml.kernel.org/r/20230118001827.1040870-4-talumbau@google.com -Change-Id: I73e866f687c1ed9f5c8538086aa39408b79897db -Signed-off-by: T.J. Alumbaugh -Cc: Yu Zhao -Signed-off-by: Andrew Morton -(cherry picked from commit ccbbbb85945d8f0255aa9dbc1b617017e2294f2c) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - Documentation/mm/multigen_lru.rst | 16 +++ - mm/vmscan.c | 180 +++++++++++++++--------------- - 2 files changed, 108 insertions(+), 88 deletions(-) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -170,6 +170,22 @@ promotes hot pages. If the scan was done - adds the PMD entry pointing to the PTE table to the Bloom filter. This - forms a feedback loop between the eviction and the aging. - -+Bloom Filters -+------------- -+Bloom filters are a space and memory efficient data structure for set -+membership test, i.e., test if an element is not in the set or may be -+in the set. -+ -+In the eviction path, specifically, in ``lru_gen_look_around()``, if a -+PMD has a sufficient number of hot pages, its address is placed in the -+filter. In the aging path, set membership means that the PTE range -+will be scanned for young pages. -+ -+Note that Bloom filters are probabilistic on set membership. If a test -+is false positive, the cost is an additional scan of a range of PTEs, -+which may yield hot pages anyway. Parameters of the filter itself can -+control the false positive rate in the limit. -+ - Summary - ------- - The multi-gen LRU can be disassembled into the following parts: ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3209,6 +3209,98 @@ static bool __maybe_unused seq_is_valid( - } - - /****************************************************************************** -+ * Bloom filters -+ ******************************************************************************/ -+ -+/* -+ * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when -+ * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of -+ * bits in a bitmap, k is the number of hash functions and n is the number of -+ * inserted items. -+ * -+ * Page table walkers use one of the two filters to reduce their search space. -+ * To get rid of non-leaf entries that no longer have enough leaf entries, the -+ * aging uses the double-buffering technique to flip to the other filter each -+ * time it produces a new generation. For non-leaf entries that have enough -+ * leaf entries, the aging carries them over to the next generation in -+ * walk_pmd_range(); the eviction also report them when walking the rmap -+ * in lru_gen_look_around(). -+ * -+ * For future optimizations: -+ * 1. It's not necessary to keep both filters all the time. The spare one can be -+ * freed after the RCU grace period and reallocated if needed again. -+ * 2. And when reallocating, it's worth scaling its size according to the number -+ * of inserted entries in the other filter, to reduce the memory overhead on -+ * small systems and false positives on large systems. -+ * 3. Jenkins' hash function is an alternative to Knuth's. -+ */ -+#define BLOOM_FILTER_SHIFT 15 -+ -+static inline int filter_gen_from_seq(unsigned long seq) -+{ -+ return seq % NR_BLOOM_FILTERS; -+} -+ -+static void get_item_key(void *item, int *key) -+{ -+ u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2); -+ -+ BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32)); -+ -+ key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1); -+ key[1] = hash >> BLOOM_FILTER_SHIFT; -+} -+ -+static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) -+{ -+ int key[2]; -+ unsigned long *filter; -+ int gen = filter_gen_from_seq(seq); -+ -+ filter = READ_ONCE(lruvec->mm_state.filters[gen]); -+ if (!filter) -+ return true; -+ -+ get_item_key(item, key); -+ -+ return test_bit(key[0], filter) && test_bit(key[1], filter); -+} -+ -+static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) -+{ -+ int key[2]; -+ unsigned long *filter; -+ int gen = filter_gen_from_seq(seq); -+ -+ filter = READ_ONCE(lruvec->mm_state.filters[gen]); -+ if (!filter) -+ return; -+ -+ get_item_key(item, key); -+ -+ if (!test_bit(key[0], filter)) -+ set_bit(key[0], filter); -+ if (!test_bit(key[1], filter)) -+ set_bit(key[1], filter); -+} -+ -+static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq) -+{ -+ unsigned long *filter; -+ int gen = filter_gen_from_seq(seq); -+ -+ filter = lruvec->mm_state.filters[gen]; -+ if (filter) { -+ bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT)); -+ return; -+ } -+ -+ filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT), -+ __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); -+ WRITE_ONCE(lruvec->mm_state.filters[gen], filter); -+} -+ -+/****************************************************************************** - * mm_struct list - ******************************************************************************/ - -@@ -3333,94 +3425,6 @@ void lru_gen_migrate_mm(struct mm_struct - } - #endif - --/* -- * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when -- * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of -- * bits in a bitmap, k is the number of hash functions and n is the number of -- * inserted items. -- * -- * Page table walkers use one of the two filters to reduce their search space. -- * To get rid of non-leaf entries that no longer have enough leaf entries, the -- * aging uses the double-buffering technique to flip to the other filter each -- * time it produces a new generation. For non-leaf entries that have enough -- * leaf entries, the aging carries them over to the next generation in -- * walk_pmd_range(); the eviction also report them when walking the rmap -- * in lru_gen_look_around(). -- * -- * For future optimizations: -- * 1. It's not necessary to keep both filters all the time. The spare one can be -- * freed after the RCU grace period and reallocated if needed again. -- * 2. And when reallocating, it's worth scaling its size according to the number -- * of inserted entries in the other filter, to reduce the memory overhead on -- * small systems and false positives on large systems. -- * 3. Jenkins' hash function is an alternative to Knuth's. -- */ --#define BLOOM_FILTER_SHIFT 15 -- --static inline int filter_gen_from_seq(unsigned long seq) --{ -- return seq % NR_BLOOM_FILTERS; --} -- --static void get_item_key(void *item, int *key) --{ -- u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2); -- -- BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32)); -- -- key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1); -- key[1] = hash >> BLOOM_FILTER_SHIFT; --} -- --static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq) --{ -- unsigned long *filter; -- int gen = filter_gen_from_seq(seq); -- -- filter = lruvec->mm_state.filters[gen]; -- if (filter) { -- bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT)); -- return; -- } -- -- filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT), -- __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); -- WRITE_ONCE(lruvec->mm_state.filters[gen], filter); --} -- --static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) --{ -- int key[2]; -- unsigned long *filter; -- int gen = filter_gen_from_seq(seq); -- -- filter = READ_ONCE(lruvec->mm_state.filters[gen]); -- if (!filter) -- return; -- -- get_item_key(item, key); -- -- if (!test_bit(key[0], filter)) -- set_bit(key[0], filter); -- if (!test_bit(key[1], filter)) -- set_bit(key[1], filter); --} -- --static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) --{ -- int key[2]; -- unsigned long *filter; -- int gen = filter_gen_from_seq(seq); -- -- filter = READ_ONCE(lruvec->mm_state.filters[gen]); -- if (!filter) -- return true; -- -- get_item_key(item, key); -- -- return test_bit(key[0], filter) && test_bit(key[1], filter); --} -- - static void reset_mm_stats(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, bool last) - { - int i; diff --git a/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch b/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch deleted file mode 100644 index 101a0a3757..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch +++ /dev/null @@ -1,427 +0,0 @@ -From 48c916b812652f9453be5bd45a703728926d41ca Mon Sep 17 00:00:00 2001 -From: "T.J. Alumbaugh" -Date: Wed, 18 Jan 2023 00:18:24 +0000 -Subject: [PATCH 15/19] UPSTREAM: mm: multi-gen LRU: section for memcg LRU - -Move memcg LRU code into a dedicated section. Improve the design doc to -outline its architecture. - -Link: https://lkml.kernel.org/r/20230118001827.1040870-5-talumbau@google.com -Change-Id: Id252e420cff7a858acb098cf2b3642da5c40f602 -Signed-off-by: T.J. Alumbaugh -Cc: Yu Zhao -Signed-off-by: Andrew Morton -(cherry picked from commit 36c7b4db7c942ae9e1b111f0c6b468c8b2e33842) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - Documentation/mm/multigen_lru.rst | 33 +++- - include/linux/mm_inline.h | 17 -- - include/linux/mmzone.h | 13 +- - mm/memcontrol.c | 8 +- - mm/vmscan.c | 250 +++++++++++++++++------------- - 5 files changed, 178 insertions(+), 143 deletions(-) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -186,9 +186,40 @@ is false positive, the cost is an additi - which may yield hot pages anyway. Parameters of the filter itself can - control the false positive rate in the limit. - -+Memcg LRU -+--------- -+An memcg LRU is a per-node LRU of memcgs. It is also an LRU of LRUs, -+since each node and memcg combination has an LRU of folios (see -+``mem_cgroup_lruvec()``). Its goal is to improve the scalability of -+global reclaim, which is critical to system-wide memory overcommit in -+data centers. Note that memcg LRU only applies to global reclaim. -+ -+The basic structure of an memcg LRU can be understood by an analogy to -+the active/inactive LRU (of folios): -+ -+1. It has the young and the old (generations), i.e., the counterparts -+ to the active and the inactive; -+2. The increment of ``max_seq`` triggers promotion, i.e., the -+ counterpart to activation; -+3. Other events trigger similar operations, e.g., offlining an memcg -+ triggers demotion, i.e., the counterpart to deactivation. -+ -+In terms of global reclaim, it has two distinct features: -+ -+1. Sharding, which allows each thread to start at a random memcg (in -+ the old generation) and improves parallelism; -+2. Eventual fairness, which allows direct reclaim to bail out at will -+ and reduces latency without affecting fairness over some time. -+ -+In terms of traversing memcgs during global reclaim, it improves the -+best-case complexity from O(n) to O(1) and does not affect the -+worst-case complexity O(n). Therefore, on average, it has a sublinear -+complexity. -+ - Summary - ------- --The multi-gen LRU can be disassembled into the following parts: -+The multi-gen LRU (of folios) can be disassembled into the following -+parts: - - * Generations - * Rmap walks ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -122,18 +122,6 @@ static inline bool lru_gen_in_fault(void - return current->in_lru_fault; - } - --#ifdef CONFIG_MEMCG --static inline int lru_gen_memcg_seg(struct lruvec *lruvec) --{ -- return READ_ONCE(lruvec->lrugen.seg); --} --#else --static inline int lru_gen_memcg_seg(struct lruvec *lruvec) --{ -- return 0; --} --#endif -- - static inline int lru_gen_from_seq(unsigned long seq) - { - return seq % MAX_NR_GENS; -@@ -314,11 +302,6 @@ static inline bool lru_gen_in_fault(void - return false; - } - --static inline int lru_gen_memcg_seg(struct lruvec *lruvec) --{ -- return 0; --} -- - static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, bool reclaiming) - { - return false; ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -368,15 +368,6 @@ struct page_vma_mapped_walk; - #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) - #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) - --/* see the comment on MEMCG_NR_GENS */ --enum { -- MEMCG_LRU_NOP, -- MEMCG_LRU_HEAD, -- MEMCG_LRU_TAIL, -- MEMCG_LRU_OLD, -- MEMCG_LRU_YOUNG, --}; -- - #ifdef CONFIG_LRU_GEN - - enum { -@@ -557,7 +548,7 @@ void lru_gen_exit_memcg(struct mem_cgrou - void lru_gen_online_memcg(struct mem_cgroup *memcg); - void lru_gen_offline_memcg(struct mem_cgroup *memcg); - void lru_gen_release_memcg(struct mem_cgroup *memcg); --void lru_gen_rotate_memcg(struct lruvec *lruvec, int op); -+void lru_gen_soft_reclaim(struct lruvec *lruvec); - - #else /* !CONFIG_MEMCG */ - -@@ -608,7 +599,7 @@ static inline void lru_gen_release_memcg - { - } - --static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) -+static inline void lru_gen_soft_reclaim(struct lruvec *lruvec) - { - } - ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -478,12 +478,8 @@ static void mem_cgroup_update_tree(struc - struct mem_cgroup_tree_per_node *mctz; - - if (lru_gen_enabled()) { -- struct lruvec *lruvec = &memcg->nodeinfo[nid]->lruvec; -- -- /* see the comment on MEMCG_NR_GENS */ -- if (soft_limit_excess(memcg) && lru_gen_memcg_seg(lruvec) != MEMCG_LRU_HEAD) -- lru_gen_rotate_memcg(lruvec, MEMCG_LRU_HEAD); -- -+ if (soft_limit_excess(memcg)) -+ lru_gen_soft_reclaim(&memcg->nodeinfo[nid]->lruvec); - return; - } - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4692,6 +4692,148 @@ void lru_gen_look_around(struct page_vma - } - - /****************************************************************************** -+ * memcg LRU -+ ******************************************************************************/ -+ -+/* see the comment on MEMCG_NR_GENS */ -+enum { -+ MEMCG_LRU_NOP, -+ MEMCG_LRU_HEAD, -+ MEMCG_LRU_TAIL, -+ MEMCG_LRU_OLD, -+ MEMCG_LRU_YOUNG, -+}; -+ -+#ifdef CONFIG_MEMCG -+ -+static int lru_gen_memcg_seg(struct lruvec *lruvec) -+{ -+ return READ_ONCE(lruvec->lrugen.seg); -+} -+ -+static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) -+{ -+ int seg; -+ int old, new; -+ int bin = get_random_u32_below(MEMCG_NR_BINS); -+ struct pglist_data *pgdat = lruvec_pgdat(lruvec); -+ -+ spin_lock(&pgdat->memcg_lru.lock); -+ -+ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); -+ -+ seg = 0; -+ new = old = lruvec->lrugen.gen; -+ -+ /* see the comment on MEMCG_NR_GENS */ -+ if (op == MEMCG_LRU_HEAD) -+ seg = MEMCG_LRU_HEAD; -+ else if (op == MEMCG_LRU_TAIL) -+ seg = MEMCG_LRU_TAIL; -+ else if (op == MEMCG_LRU_OLD) -+ new = get_memcg_gen(pgdat->memcg_lru.seq); -+ else if (op == MEMCG_LRU_YOUNG) -+ new = get_memcg_gen(pgdat->memcg_lru.seq + 1); -+ else -+ VM_WARN_ON_ONCE(true); -+ -+ hlist_nulls_del_rcu(&lruvec->lrugen.list); -+ -+ if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD) -+ hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); -+ else -+ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); -+ -+ pgdat->memcg_lru.nr_memcgs[old]--; -+ pgdat->memcg_lru.nr_memcgs[new]++; -+ -+ lruvec->lrugen.gen = new; -+ WRITE_ONCE(lruvec->lrugen.seg, seg); -+ -+ if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq)) -+ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); -+ -+ spin_unlock(&pgdat->memcg_lru.lock); -+} -+ -+void lru_gen_online_memcg(struct mem_cgroup *memcg) -+{ -+ int gen; -+ int nid; -+ int bin = get_random_u32_below(MEMCG_NR_BINS); -+ -+ for_each_node(nid) { -+ struct pglist_data *pgdat = NODE_DATA(nid); -+ struct lruvec *lruvec = get_lruvec(memcg, nid); -+ -+ spin_lock(&pgdat->memcg_lru.lock); -+ -+ VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list)); -+ -+ gen = get_memcg_gen(pgdat->memcg_lru.seq); -+ -+ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]); -+ pgdat->memcg_lru.nr_memcgs[gen]++; -+ -+ lruvec->lrugen.gen = gen; -+ -+ spin_unlock(&pgdat->memcg_lru.lock); -+ } -+} -+ -+void lru_gen_offline_memcg(struct mem_cgroup *memcg) -+{ -+ int nid; -+ -+ for_each_node(nid) { -+ struct lruvec *lruvec = get_lruvec(memcg, nid); -+ -+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD); -+ } -+} -+ -+void lru_gen_release_memcg(struct mem_cgroup *memcg) -+{ -+ int gen; -+ int nid; -+ -+ for_each_node(nid) { -+ struct pglist_data *pgdat = NODE_DATA(nid); -+ struct lruvec *lruvec = get_lruvec(memcg, nid); -+ -+ spin_lock(&pgdat->memcg_lru.lock); -+ -+ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); -+ -+ gen = lruvec->lrugen.gen; -+ -+ hlist_nulls_del_rcu(&lruvec->lrugen.list); -+ pgdat->memcg_lru.nr_memcgs[gen]--; -+ -+ if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq)) -+ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); -+ -+ spin_unlock(&pgdat->memcg_lru.lock); -+ } -+} -+ -+void lru_gen_soft_reclaim(struct lruvec *lruvec) -+{ -+ /* see the comment on MEMCG_NR_GENS */ -+ if (lru_gen_memcg_seg(lruvec) != MEMCG_LRU_HEAD) -+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_HEAD); -+} -+ -+#else /* !CONFIG_MEMCG */ -+ -+static int lru_gen_memcg_seg(struct lruvec *lruvec) -+{ -+ return 0; -+} -+ -+#endif -+ -+/****************************************************************************** - * the eviction - ******************************************************************************/ - -@@ -5398,53 +5540,6 @@ done: - pgdat->kswapd_failures = 0; - } - --#ifdef CONFIG_MEMCG --void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) --{ -- int seg; -- int old, new; -- int bin = get_random_u32_below(MEMCG_NR_BINS); -- struct pglist_data *pgdat = lruvec_pgdat(lruvec); -- -- spin_lock(&pgdat->memcg_lru.lock); -- -- VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); -- -- seg = 0; -- new = old = lruvec->lrugen.gen; -- -- /* see the comment on MEMCG_NR_GENS */ -- if (op == MEMCG_LRU_HEAD) -- seg = MEMCG_LRU_HEAD; -- else if (op == MEMCG_LRU_TAIL) -- seg = MEMCG_LRU_TAIL; -- else if (op == MEMCG_LRU_OLD) -- new = get_memcg_gen(pgdat->memcg_lru.seq); -- else if (op == MEMCG_LRU_YOUNG) -- new = get_memcg_gen(pgdat->memcg_lru.seq + 1); -- else -- VM_WARN_ON_ONCE(true); -- -- hlist_nulls_del_rcu(&lruvec->lrugen.list); -- -- if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD) -- hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); -- else -- hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); -- -- pgdat->memcg_lru.nr_memcgs[old]--; -- pgdat->memcg_lru.nr_memcgs[new]++; -- -- lruvec->lrugen.gen = new; -- WRITE_ONCE(lruvec->lrugen.seg, seg); -- -- if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq)) -- WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); -- -- spin_unlock(&pgdat->memcg_lru.lock); --} --#endif -- - /****************************************************************************** - * state change - ******************************************************************************/ -@@ -6090,67 +6185,6 @@ void lru_gen_exit_memcg(struct mem_cgrou - } - } - --void lru_gen_online_memcg(struct mem_cgroup *memcg) --{ -- int gen; -- int nid; -- int bin = get_random_u32_below(MEMCG_NR_BINS); -- -- for_each_node(nid) { -- struct pglist_data *pgdat = NODE_DATA(nid); -- struct lruvec *lruvec = get_lruvec(memcg, nid); -- -- spin_lock(&pgdat->memcg_lru.lock); -- -- VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list)); -- -- gen = get_memcg_gen(pgdat->memcg_lru.seq); -- -- hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]); -- pgdat->memcg_lru.nr_memcgs[gen]++; -- -- lruvec->lrugen.gen = gen; -- -- spin_unlock(&pgdat->memcg_lru.lock); -- } --} -- --void lru_gen_offline_memcg(struct mem_cgroup *memcg) --{ -- int nid; -- -- for_each_node(nid) { -- struct lruvec *lruvec = get_lruvec(memcg, nid); -- -- lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD); -- } --} -- --void lru_gen_release_memcg(struct mem_cgroup *memcg) --{ -- int gen; -- int nid; -- -- for_each_node(nid) { -- struct pglist_data *pgdat = NODE_DATA(nid); -- struct lruvec *lruvec = get_lruvec(memcg, nid); -- -- spin_lock(&pgdat->memcg_lru.lock); -- -- VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); -- -- gen = lruvec->lrugen.gen; -- -- hlist_nulls_del_rcu(&lruvec->lrugen.list); -- pgdat->memcg_lru.nr_memcgs[gen]--; -- -- if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq)) -- WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); -- -- spin_unlock(&pgdat->memcg_lru.lock); -- } --} -- - #endif /* CONFIG_MEMCG */ - - static int __init init_lru_gen(void) diff --git a/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch b/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch deleted file mode 100644 index 1ee766f861..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch +++ /dev/null @@ -1,40 +0,0 @@ -From bec433f29537652ed054148edfd7e2183ddcf7c3 Mon Sep 17 00:00:00 2001 -From: "T.J. Alumbaugh" -Date: Wed, 18 Jan 2023 00:18:25 +0000 -Subject: [PATCH 16/19] UPSTREAM: mm: multi-gen LRU: improve - lru_gen_exit_memcg() - -Add warnings and poison ->next. - -Link: https://lkml.kernel.org/r/20230118001827.1040870-6-talumbau@google.com -Change-Id: I53de9e04c1ae941e122b33cd45d2bbb5f34aae0c -Signed-off-by: T.J. Alumbaugh -Cc: Yu Zhao -Signed-off-by: Andrew Morton -(cherry picked from commit 37cc99979d04cca677c0ad5c0acd1149ec165d1b) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -6172,12 +6172,17 @@ void lru_gen_exit_memcg(struct mem_cgrou - int i; - int nid; - -+ VM_WARN_ON_ONCE(!list_empty(&memcg->mm_list.fifo)); -+ - for_each_node(nid) { - struct lruvec *lruvec = get_lruvec(memcg, nid); - -+ VM_WARN_ON_ONCE(lruvec->mm_state.nr_walkers); - VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, - sizeof(lruvec->lrugen.nr_pages))); - -+ lruvec->lrugen.list.next = LIST_POISON1; -+ - for (i = 0; i < NR_BLOOM_FILTERS; i++) { - bitmap_free(lruvec->mm_state.filters[i]); - lruvec->mm_state.filters[i] = NULL; diff --git a/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch b/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch deleted file mode 100644 index 2273977dc9..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch +++ /dev/null @@ -1,135 +0,0 @@ -From fc0e3b06e0f19917b7ecad7967a72f61d4743644 Mon Sep 17 00:00:00 2001 -From: "T.J. Alumbaugh" -Date: Wed, 18 Jan 2023 00:18:26 +0000 -Subject: [PATCH 17/19] UPSTREAM: mm: multi-gen LRU: improve walk_pmd_range() - -Improve readability of walk_pmd_range() and walk_pmd_range_locked(). - -Link: https://lkml.kernel.org/r/20230118001827.1040870-7-talumbau@google.com -Change-Id: Ia084fbf53fe989673b7804ca8ca520af12d7d52a -Signed-off-by: T.J. Alumbaugh -Cc: Yu Zhao -Signed-off-by: Andrew Morton -(cherry picked from commit b5ff4133617d0eced35b685da0bd0929dd9fabb7) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 40 ++++++++++++++++++++-------------------- - 1 file changed, 20 insertions(+), 20 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3980,8 +3980,8 @@ restart: - } - - #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) --static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, -- struct mm_walk *args, unsigned long *bitmap, unsigned long *start) -+static void walk_pmd_range_locked(pud_t *pud, unsigned long addr, struct vm_area_struct *vma, -+ struct mm_walk *args, unsigned long *bitmap, unsigned long *first) - { - int i; - pmd_t *pmd; -@@ -3994,18 +3994,19 @@ static void walk_pmd_range_locked(pud_t - VM_WARN_ON_ONCE(pud_leaf(*pud)); - - /* try to batch at most 1+MIN_LRU_BATCH+1 entries */ -- if (*start == -1) { -- *start = next; -+ if (*first == -1) { -+ *first = addr; -+ bitmap_zero(bitmap, MIN_LRU_BATCH); - return; - } - -- i = next == -1 ? 0 : pmd_index(next) - pmd_index(*start); -+ i = addr == -1 ? 0 : pmd_index(addr) - pmd_index(*first); - if (i && i <= MIN_LRU_BATCH) { - __set_bit(i - 1, bitmap); - return; - } - -- pmd = pmd_offset(pud, *start); -+ pmd = pmd_offset(pud, *first); - - ptl = pmd_lockptr(args->mm, pmd); - if (!spin_trylock(ptl)) -@@ -4016,15 +4017,16 @@ static void walk_pmd_range_locked(pud_t - do { - unsigned long pfn; - struct folio *folio; -- unsigned long addr = i ? (*start & PMD_MASK) + i * PMD_SIZE : *start; -+ -+ /* don't round down the first address */ -+ addr = i ? (*first & PMD_MASK) + i * PMD_SIZE : *first; - - pfn = get_pmd_pfn(pmd[i], vma, addr); - if (pfn == -1) - goto next; - - if (!pmd_trans_huge(pmd[i])) { -- if (arch_has_hw_nonleaf_pmd_young() && -- get_cap(LRU_GEN_NONLEAF_YOUNG)) -+ if (arch_has_hw_nonleaf_pmd_young() && get_cap(LRU_GEN_NONLEAF_YOUNG)) - pmdp_test_and_clear_young(vma, addr, pmd + i); - goto next; - } -@@ -4053,12 +4055,11 @@ next: - arch_leave_lazy_mmu_mode(); - spin_unlock(ptl); - done: -- *start = -1; -- bitmap_zero(bitmap, MIN_LRU_BATCH); -+ *first = -1; - } - #else --static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, -- struct mm_walk *args, unsigned long *bitmap, unsigned long *start) -+static void walk_pmd_range_locked(pud_t *pud, unsigned long addr, struct vm_area_struct *vma, -+ struct mm_walk *args, unsigned long *bitmap, unsigned long *first) - { - } - #endif -@@ -4071,9 +4072,9 @@ static void walk_pmd_range(pud_t *pud, u - unsigned long next; - unsigned long addr; - struct vm_area_struct *vma; -- unsigned long pos = -1; -+ unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)]; -+ unsigned long first = -1; - struct lru_gen_mm_walk *walk = args->private; -- unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; - - VM_WARN_ON_ONCE(pud_leaf(*pud)); - -@@ -4115,18 +4116,17 @@ restart: - if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat)) - continue; - -- walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); -+ walk_pmd_range_locked(pud, addr, vma, args, bitmap, &first); - continue; - } - #endif - walk->mm_stats[MM_NONLEAF_TOTAL]++; - -- if (arch_has_hw_nonleaf_pmd_young() && -- get_cap(LRU_GEN_NONLEAF_YOUNG)) { -+ if (arch_has_hw_nonleaf_pmd_young() && get_cap(LRU_GEN_NONLEAF_YOUNG)) { - if (!pmd_young(val)) - continue; - -- walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); -+ walk_pmd_range_locked(pud, addr, vma, args, bitmap, &first); - } - - if (!walk->force_scan && !test_bloom_filter(walk->lruvec, walk->max_seq, pmd + i)) -@@ -4143,7 +4143,7 @@ restart: - update_bloom_filter(walk->lruvec, walk->max_seq + 1, pmd + i); - } - -- walk_pmd_range_locked(pud, -1, vma, args, bitmap, &pos); -+ walk_pmd_range_locked(pud, -1, vma, args, bitmap, &first); - - if (i < PTRS_PER_PMD && get_next_vma(PUD_MASK, PMD_SIZE, args, &start, &end)) - goto restart; diff --git a/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch b/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch deleted file mode 100644 index 856199574a..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch +++ /dev/null @@ -1,148 +0,0 @@ -From e604c3ccb4dfbdde2467fccef9bb36170a392695 Mon Sep 17 00:00:00 2001 -From: "T.J. Alumbaugh" -Date: Wed, 18 Jan 2023 00:18:27 +0000 -Subject: [PATCH 18/19] UPSTREAM: mm: multi-gen LRU: simplify - lru_gen_look_around() - -Update the folio generation in place with or without -current->reclaim_state->mm_walk. The LRU lock is held for longer, if -mm_walk is NULL and the number of folios to update is more than -PAGEVEC_SIZE. - -This causes a measurable regression from the LRU lock contention during a -microbencmark. But a tiny regression is not worth the complexity. - -Link: https://lkml.kernel.org/r/20230118001827.1040870-8-talumbau@google.com -Change-Id: I9ce18b4f4062e6c1c13c98ece9422478eb8e1846 -Signed-off-by: T.J. Alumbaugh -Cc: Yu Zhao -Signed-off-by: Andrew Morton -(cherry picked from commit abf086721a2f1e6897c57796f7268df1b194c750) -Bug: 274865848 -Signed-off-by: T.J. Mercier ---- - mm/vmscan.c | 73 +++++++++++++++++------------------------------------ - 1 file changed, 23 insertions(+), 50 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4573,13 +4573,12 @@ static void lru_gen_age_node(struct pgli - void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) - { - int i; -- pte_t *pte; - unsigned long start; - unsigned long end; -- unsigned long addr; - struct lru_gen_mm_walk *walk; - int young = 0; -- unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; -+ pte_t *pte = pvmw->pte; -+ unsigned long addr = pvmw->address; - struct folio *folio = pfn_folio(pvmw->pfn); - struct mem_cgroup *memcg = folio_memcg(folio); - struct pglist_data *pgdat = folio_pgdat(folio); -@@ -4596,25 +4595,28 @@ void lru_gen_look_around(struct page_vma - /* avoid taking the LRU lock under the PTL when possible */ - walk = current->reclaim_state ? current->reclaim_state->mm_walk : NULL; - -- start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start); -- end = min(pvmw->address | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; -+ start = max(addr & PMD_MASK, pvmw->vma->vm_start); -+ end = min(addr | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; - - if (end - start > MIN_LRU_BATCH * PAGE_SIZE) { -- if (pvmw->address - start < MIN_LRU_BATCH * PAGE_SIZE / 2) -+ if (addr - start < MIN_LRU_BATCH * PAGE_SIZE / 2) - end = start + MIN_LRU_BATCH * PAGE_SIZE; -- else if (end - pvmw->address < MIN_LRU_BATCH * PAGE_SIZE / 2) -+ else if (end - addr < MIN_LRU_BATCH * PAGE_SIZE / 2) - start = end - MIN_LRU_BATCH * PAGE_SIZE; - else { -- start = pvmw->address - MIN_LRU_BATCH * PAGE_SIZE / 2; -- end = pvmw->address + MIN_LRU_BATCH * PAGE_SIZE / 2; -+ start = addr - MIN_LRU_BATCH * PAGE_SIZE / 2; -+ end = addr + MIN_LRU_BATCH * PAGE_SIZE / 2; - } - } - -- pte = pvmw->pte - (pvmw->address - start) / PAGE_SIZE; -+ /* folio_update_gen() requires stable folio_memcg() */ -+ if (!mem_cgroup_trylock_pages(memcg)) -+ return; - -- rcu_read_lock(); - arch_enter_lazy_mmu_mode(); - -+ pte -= (addr - start) / PAGE_SIZE; -+ - for (i = 0, addr = start; addr != end; i++, addr += PAGE_SIZE) { - unsigned long pfn; - -@@ -4639,56 +4641,27 @@ void lru_gen_look_around(struct page_vma - !folio_test_swapcache(folio))) - folio_mark_dirty(folio); - -+ if (walk) { -+ old_gen = folio_update_gen(folio, new_gen); -+ if (old_gen >= 0 && old_gen != new_gen) -+ update_batch_size(walk, folio, old_gen, new_gen); -+ -+ continue; -+ } -+ - old_gen = folio_lru_gen(folio); - if (old_gen < 0) - folio_set_referenced(folio); - else if (old_gen != new_gen) -- __set_bit(i, bitmap); -+ folio_activate(folio); - } - - arch_leave_lazy_mmu_mode(); -- rcu_read_unlock(); -+ mem_cgroup_unlock_pages(); - - /* feedback from rmap walkers to page table walkers */ - if (suitable_to_scan(i, young)) - update_bloom_filter(lruvec, max_seq, pvmw->pmd); -- -- if (!walk && bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { -- for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { -- folio = pfn_folio(pte_pfn(pte[i])); -- folio_activate(folio); -- } -- return; -- } -- -- /* folio_update_gen() requires stable folio_memcg() */ -- if (!mem_cgroup_trylock_pages(memcg)) -- return; -- -- if (!walk) { -- spin_lock_irq(&lruvec->lru_lock); -- new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); -- } -- -- for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { -- folio = pfn_folio(pte_pfn(pte[i])); -- if (folio_memcg_rcu(folio) != memcg) -- continue; -- -- old_gen = folio_update_gen(folio, new_gen); -- if (old_gen < 0 || old_gen == new_gen) -- continue; -- -- if (walk) -- update_batch_size(walk, folio, old_gen, new_gen); -- else -- lru_gen_update_size(lruvec, folio, old_gen, new_gen); -- } -- -- if (!walk) -- spin_unlock_irq(&lruvec->lru_lock); -- -- mem_cgroup_unlock_pages(); - } - - /****************************************************************************** diff --git a/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch b/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch deleted file mode 100644 index 1b0459cdb9..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch +++ /dev/null @@ -1,273 +0,0 @@ -From 418038c22452df38cde519cc8c662bb15139764a Mon Sep 17 00:00:00 2001 -From: Kalesh Singh -Date: Thu, 13 Apr 2023 14:43:26 -0700 -Subject: [PATCH 19/19] mm: Multi-gen LRU: remove wait_event_killable() - -Android 14 and later default to MGLRU [1] and field telemetry showed -occasional long tail latency (>100ms) in the reclaim path. - -Tracing revealed priority inversion in the reclaim path. In -try_to_inc_max_seq(), when high priority tasks were blocked on -wait_event_killable(), the preemption of the low priority task to call -wake_up_all() caused those high priority tasks to wait longer than -necessary. In general, this problem is not different from others of its -kind, e.g., one caused by mutex_lock(). However, it is specific to MGLRU -because it introduced the new wait queue lruvec->mm_state.wait. - -The purpose of this new wait queue is to avoid the thundering herd -problem. If many direct reclaimers rush into try_to_inc_max_seq(), only -one can succeed, i.e., the one to wake up the rest, and the rest who -failed might cause premature OOM kills if they do not wait. So far there -is no evidence supporting this scenario, based on how often the wait has -been hit. And this begs the question how useful the wait queue is in -practice. - -Based on Minchan's recommendation, which is in line with his commit -6d4675e60135 ("mm: don't be stuck to rmap lock on reclaim path") and the -rest of the MGLRU code which also uses trylock when possible, remove the -wait queue. - -[1] https://android-review.googlesource.com/q/I7ed7fbfd6ef9ce10053347528125dd98c39e50bf - -Link: https://lkml.kernel.org/r/20230413214326.2147568-1-kaleshsingh@google.com -Fixes: bd74fdaea146 ("mm: multi-gen LRU: support page table walks") -Signed-off-by: Kalesh Singh -Suggested-by: Minchan Kim -Reported-by: Wei Wang -Acked-by: Yu Zhao -Cc: Minchan Kim -Cc: Jan Alexander Steffens (heftig) -Cc: Oleksandr Natalenko -Cc: Suleiman Souhlal -Cc: Suren Baghdasaryan -Signed-off-by: Andrew Morton ---- - include/linux/mmzone.h | 8 +-- - mm/vmscan.c | 112 +++++++++++++++-------------------------- - 2 files changed, 42 insertions(+), 78 deletions(-) - ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -453,18 +453,14 @@ enum { - struct lru_gen_mm_state { - /* set to max_seq after each iteration */ - unsigned long seq; -- /* where the current iteration continues (inclusive) */ -+ /* where the current iteration continues after */ - struct list_head *head; -- /* where the last iteration ended (exclusive) */ -+ /* where the last iteration ended before */ - struct list_head *tail; -- /* to wait for the last page table walker to finish */ -- struct wait_queue_head wait; - /* Bloom filters flip after each iteration */ - unsigned long *filters[NR_BLOOM_FILTERS]; - /* the mm stats for debugging */ - unsigned long stats[NR_HIST_GENS][NR_MM_STATS]; -- /* the number of concurrent page table walkers */ -- int nr_walkers; - }; - - struct lru_gen_mm_walk { ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3371,18 +3371,13 @@ void lru_gen_del_mm(struct mm_struct *mm - if (!lruvec) - continue; - -- /* where the last iteration ended (exclusive) */ -+ /* where the current iteration continues after */ -+ if (lruvec->mm_state.head == &mm->lru_gen.list) -+ lruvec->mm_state.head = lruvec->mm_state.head->prev; -+ -+ /* where the last iteration ended before */ - if (lruvec->mm_state.tail == &mm->lru_gen.list) - lruvec->mm_state.tail = lruvec->mm_state.tail->next; -- -- /* where the current iteration continues (inclusive) */ -- if (lruvec->mm_state.head != &mm->lru_gen.list) -- continue; -- -- lruvec->mm_state.head = lruvec->mm_state.head->next; -- /* the deletion ends the current iteration */ -- if (lruvec->mm_state.head == &mm_list->fifo) -- WRITE_ONCE(lruvec->mm_state.seq, lruvec->mm_state.seq + 1); - } - - list_del_init(&mm->lru_gen.list); -@@ -3478,68 +3473,54 @@ static bool iterate_mm_list(struct lruve - struct mm_struct **iter) - { - bool first = false; -- bool last = true; -+ bool last = false; - struct mm_struct *mm = NULL; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - struct lru_gen_mm_list *mm_list = get_mm_list(memcg); - struct lru_gen_mm_state *mm_state = &lruvec->mm_state; - - /* -- * There are four interesting cases for this page table walker: -- * 1. It tries to start a new iteration of mm_list with a stale max_seq; -- * there is nothing left to do. -- * 2. It's the first of the current generation, and it needs to reset -- * the Bloom filter for the next generation. -- * 3. It reaches the end of mm_list, and it needs to increment -- * mm_state->seq; the iteration is done. -- * 4. It's the last of the current generation, and it needs to reset the -- * mm stats counters for the next generation. -+ * mm_state->seq is incremented after each iteration of mm_list. There -+ * are three interesting cases for this page table walker: -+ * 1. It tries to start a new iteration with a stale max_seq: there is -+ * nothing left to do. -+ * 2. It started the next iteration: it needs to reset the Bloom filter -+ * so that a fresh set of PTE tables can be recorded. -+ * 3. It ended the current iteration: it needs to reset the mm stats -+ * counters and tell its caller to increment max_seq. - */ - spin_lock(&mm_list->lock); - - VM_WARN_ON_ONCE(mm_state->seq + 1 < walk->max_seq); -- VM_WARN_ON_ONCE(*iter && mm_state->seq > walk->max_seq); -- VM_WARN_ON_ONCE(*iter && !mm_state->nr_walkers); - -- if (walk->max_seq <= mm_state->seq) { -- if (!*iter) -- last = false; -+ if (walk->max_seq <= mm_state->seq) - goto done; -- } - -- if (!mm_state->nr_walkers) { -- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); -+ if (!mm_state->head) -+ mm_state->head = &mm_list->fifo; - -- mm_state->head = mm_list->fifo.next; -+ if (mm_state->head == &mm_list->fifo) - first = true; -- } -- -- while (!mm && mm_state->head != &mm_list->fifo) { -- mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); - -+ do { - mm_state->head = mm_state->head->next; -+ if (mm_state->head == &mm_list->fifo) { -+ WRITE_ONCE(mm_state->seq, mm_state->seq + 1); -+ last = true; -+ break; -+ } - - /* force scan for those added after the last iteration */ -- if (!mm_state->tail || mm_state->tail == &mm->lru_gen.list) { -- mm_state->tail = mm_state->head; -+ if (!mm_state->tail || mm_state->tail == mm_state->head) { -+ mm_state->tail = mm_state->head->next; - walk->force_scan = true; - } - -+ mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); - if (should_skip_mm(mm, walk)) - mm = NULL; -- } -- -- if (mm_state->head == &mm_list->fifo) -- WRITE_ONCE(mm_state->seq, mm_state->seq + 1); -+ } while (!mm); - done: -- if (*iter && !mm) -- mm_state->nr_walkers--; -- if (!*iter && mm) -- mm_state->nr_walkers++; -- -- if (mm_state->nr_walkers) -- last = false; -- - if (*iter || last) - reset_mm_stats(lruvec, walk, last); - -@@ -3567,9 +3548,9 @@ static bool iterate_mm_list_nowalk(struc - - VM_WARN_ON_ONCE(mm_state->seq + 1 < max_seq); - -- if (max_seq > mm_state->seq && !mm_state->nr_walkers) { -- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); -- -+ if (max_seq > mm_state->seq) { -+ mm_state->head = NULL; -+ mm_state->tail = NULL; - WRITE_ONCE(mm_state->seq, mm_state->seq + 1); - reset_mm_stats(lruvec, NULL, true); - success = true; -@@ -4172,10 +4153,6 @@ restart: - - walk_pmd_range(&val, addr, next, args); - -- /* a racy check to curtail the waiting time */ -- if (wq_has_sleeper(&walk->lruvec->mm_state.wait)) -- return 1; -- - if (need_resched() || walk->batched >= MAX_LRU_BATCH) { - end = (addr | ~PUD_MASK) + 1; - goto done; -@@ -4208,8 +4185,14 @@ static void walk_mm(struct lruvec *lruve - walk->next_addr = FIRST_USER_ADDRESS; - - do { -+ DEFINE_MAX_SEQ(lruvec); -+ - err = -EBUSY; - -+ /* another thread might have called inc_max_seq() */ -+ if (walk->max_seq != max_seq) -+ break; -+ - /* folio_update_gen() requires stable folio_memcg() */ - if (!mem_cgroup_trylock_pages(memcg)) - break; -@@ -4444,25 +4427,12 @@ static bool try_to_inc_max_seq(struct lr - success = iterate_mm_list(lruvec, walk, &mm); - if (mm) - walk_mm(lruvec, mm, walk); -- -- cond_resched(); - } while (mm); - done: -- if (!success) { -- if (sc->priority <= DEF_PRIORITY - 2) -- wait_event_killable(lruvec->mm_state.wait, -- max_seq < READ_ONCE(lrugen->max_seq)); -- return false; -- } -+ if (success) -+ inc_max_seq(lruvec, can_swap, force_scan); - -- VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); -- -- inc_max_seq(lruvec, can_swap, force_scan); -- /* either this sees any waiters or they will see updated max_seq */ -- if (wq_has_sleeper(&lruvec->mm_state.wait)) -- wake_up_all(&lruvec->mm_state.wait); -- -- return true; -+ return success; - } - - /****************************************************************************** -@@ -6117,7 +6087,6 @@ void lru_gen_init_lruvec(struct lruvec * - INIT_LIST_HEAD(&lrugen->folios[gen][type][zone]); - - lruvec->mm_state.seq = MIN_NR_GENS; -- init_waitqueue_head(&lruvec->mm_state.wait); - } - - #ifdef CONFIG_MEMCG -@@ -6150,7 +6119,6 @@ void lru_gen_exit_memcg(struct mem_cgrou - for_each_node(nid) { - struct lruvec *lruvec = get_lruvec(memcg, nid); - -- VM_WARN_ON_ONCE(lruvec->mm_state.nr_walkers); - VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, - sizeof(lruvec->lrugen.nr_pages))); - diff --git a/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch b/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch deleted file mode 100644 index 2e6d881fe9..0000000000 --- a/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch +++ /dev/null @@ -1,58 +0,0 @@ -From e2192de59e457aef8d1f055a452131f0b3e5d097 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Wed, 18 Jan 2023 14:26:53 +0100 -Subject: [PATCH] bitfield: add FIELD_PREP_CONST() - -Neither FIELD_PREP() nor *_encode_bits() can be used -in constant contexts (such as initializers), but we -don't want to define shift constants for all masks -just for use in initializers, and having checks that -the values fit is also useful. - -Therefore, add FIELD_PREP_CONST() which is a smaller -version of FIELD_PREP() that can only take constant -arguments and has less friendly (but not less strict) -error checks, and expands to a constant value. - -Signed-off-by: Johannes Berg -Link: https://lore.kernel.org/r/20230118142652.53f20593504b.Iaeea0aee77a6493d70e573b4aa55c91c00e01e4b@changeid -Signed-off-by: Johannes Berg ---- - include/linux/bitfield.h | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - ---- a/include/linux/bitfield.h -+++ b/include/linux/bitfield.h -@@ -115,6 +115,32 @@ - ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ - }) - -+#define __BF_CHECK_POW2(n) BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0) -+ -+/** -+ * FIELD_PREP_CONST() - prepare a constant bitfield element -+ * @_mask: shifted mask defining the field's length and position -+ * @_val: value to put in the field -+ * -+ * FIELD_PREP_CONST() masks and shifts up the value. The result should -+ * be combined with other fields of the bitfield using logical OR. -+ * -+ * Unlike FIELD_PREP() this is a constant expression and can therefore -+ * be used in initializers. Error checking is less comfortable for this -+ * version, and non-constant masks cannot be used. -+ */ -+#define FIELD_PREP_CONST(_mask, _val) \ -+ ( \ -+ /* mask must be non-zero */ \ -+ BUILD_BUG_ON_ZERO((_mask) == 0) + \ -+ /* check if value fits */ \ -+ BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \ -+ /* check if mask is contiguous */ \ -+ __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) + \ -+ /* and create the value */ \ -+ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \ -+ ) -+ - /** - * FIELD_GET() - extract a bitfield element - * @_mask: shifted mask defining the field's length and position diff --git a/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch b/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch deleted file mode 100644 index d8d0cf9555..0000000000 --- a/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 579aee9fc594af94c242068c011b0233563d4bbf Mon Sep 17 00:00:00 2001 -From: Stephen Rothwell -Date: Mon, 10 Oct 2022 16:57:21 +1100 -Subject: [PATCH] powerpc: suppress some linker warnings in recent linker - versions - -This is a follow on from commit - - 0d362be5b142 ("Makefile: link with -z noexecstack --no-warn-rwx-segments") - -for arch/powerpc/boot to address wanrings like: - - ld: warning: opal-calls.o: missing .note.GNU-stack section implies executable stack - ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker - ld: warning: arch/powerpc/boot/zImage.epapr has a LOAD segment with RWX permissions - -This fixes issue https://github.com/linuxppc/issues/issues/417 - -Signed-off-by: Stephen Rothwell -Signed-off-by: Michael Ellerman -Link: https://lore.kernel.org/r/20221010165721.106267e6@canb.auug.org.au ---- - arch/powerpc/boot/wrapper | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -215,6 +215,11 @@ ld_version() - }' - } - -+ld_is_lld() -+{ -+ ${CROSS}ld -V 2>&1 | grep -q LLD -+} -+ - # Do not include PT_INTERP segment when linking pie. Non-pie linking - # just ignores this option. - LD_VERSION=$(${CROSS}ld --version | ld_version) -@@ -223,6 +228,14 @@ if [ "$LD_VERSION" -ge "$LD_NO_DL_MIN_VE - nodl="--no-dynamic-linker" - fi - -+# suppress some warnings in recent ld versions -+nowarn="-z noexecstack" -+if ! ld_is_lld; then -+ if [ "$LD_VERSION" -ge "$(echo 2.39 | ld_version)" ]; then -+ nowarn="$nowarn --no-warn-rwx-segments" -+ fi -+fi -+ - platformo=$object/"$platform".o - lds=$object/zImage.lds - ext=strip -@@ -504,7 +517,7 @@ if [ "$platform" != "miboot" ]; then - text_start="-Ttext $link_address" - fi - #link everything -- ${CROSS}ld -m $format -T $lds $text_start $pie $nodl $rodynamic $notext -o "$ofile" $map \ -+ ${CROSS}ld -m $format -T $lds $text_start $pie $nodl $nowarn $rodynamic $notext -o "$ofile" $map \ - $platformo $tmp $object/wrapper.a - rm $tmp - fi diff --git a/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch b/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch deleted file mode 100644 index eb6be5ed00..0000000000 --- a/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 63db0cb35e1cb3b3c134906d1062f65513fdda2d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Oct 2022 10:37:09 +0200 -Subject: [PATCH] mtd: core: simplify (a bit) code find partition-matching - dynamic OF node -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -1. Don't hardcode "partition-" string twice -2. Use simpler logic & use ->name to avoid of_property_read_string() -3. Use mtd_get_of_node() helper - -Cc: Christian Marangi -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221004083710.27704-1-zajec5@gmail.com ---- - drivers/mtd/mtdcore.c | 16 +++++++--------- - 1 file changed, 7 insertions(+), 9 deletions(-) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -551,18 +551,16 @@ static void mtd_check_of_node(struct mtd - struct device_node *partitions, *parent_dn, *mtd_dn = NULL; - const char *pname, *prefix = "partition-"; - int plen, mtd_name_len, offset, prefix_len; -- struct mtd_info *parent; - bool found = false; - - /* Check if MTD already has a device node */ -- if (dev_of_node(&mtd->dev)) -+ if (mtd_get_of_node(mtd)) - return; - - /* Check if a partitions node exist */ - if (!mtd_is_partition(mtd)) - return; -- parent = mtd->parent; -- parent_dn = of_node_get(dev_of_node(&parent->dev)); -+ parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); - if (!parent_dn) - return; - -@@ -575,15 +573,15 @@ static void mtd_check_of_node(struct mtd - - /* Search if a partition is defined with the same name */ - for_each_child_of_node(partitions, mtd_dn) { -- offset = 0; -- - /* Skip partition with no/wrong prefix */ -- if (!of_node_name_prefix(mtd_dn, "partition-")) -+ if (!of_node_name_prefix(mtd_dn, prefix)) - continue; - - /* Label have priority. Check that first */ -- if (of_property_read_string(mtd_dn, "label", &pname)) { -- of_property_read_string(mtd_dn, "name", &pname); -+ if (!of_property_read_string(mtd_dn, "label", &pname)) { -+ offset = 0; -+ } else { -+ pname = mtd_dn->name; - offset = prefix_len; - } - diff --git a/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch b/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch deleted file mode 100644 index f8d3a370d4..0000000000 --- a/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch +++ /dev/null @@ -1,84 +0,0 @@ -From ddb8cefb7af288950447ca6eeeafb09977dab56f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Oct 2022 10:37:10 +0200 -Subject: [PATCH] mtd: core: try to find OF node for every MTD partition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -So far this feature was limited to the top-level "nvmem-cells" node. -There are multiple parsers creating partitions and subpartitions -dynamically. Extend that code to handle them too. - -This allows finding partition-* node for every MTD (sub)partition. - -Random example: - -partitions { - compatible = "brcm,bcm947xx-cfe-partitions"; - - partition-firmware { - compatible = "brcm,trx"; - - partition-loader { - }; - }; -}; - -Cc: Christian Marangi -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221004083710.27704-2-zajec5@gmail.com ---- - drivers/mtd/mtdcore.c | 18 ++++++------------ - 1 file changed, 6 insertions(+), 12 deletions(-) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -551,20 +551,22 @@ static void mtd_check_of_node(struct mtd - struct device_node *partitions, *parent_dn, *mtd_dn = NULL; - const char *pname, *prefix = "partition-"; - int plen, mtd_name_len, offset, prefix_len; -- bool found = false; - - /* Check if MTD already has a device node */ - if (mtd_get_of_node(mtd)) - return; - -- /* Check if a partitions node exist */ - if (!mtd_is_partition(mtd)) - return; -+ - parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); - if (!parent_dn) - return; - -- partitions = of_get_child_by_name(parent_dn, "partitions"); -+ if (mtd_is_partition(mtd->parent)) -+ partitions = of_node_get(parent_dn); -+ else -+ partitions = of_get_child_by_name(parent_dn, "partitions"); - if (!partitions) - goto exit_parent; - -@@ -588,19 +590,11 @@ static void mtd_check_of_node(struct mtd - plen = strlen(pname) - offset; - if (plen == mtd_name_len && - !strncmp(mtd->name, pname + offset, plen)) { -- found = true; -+ mtd_set_of_node(mtd, mtd_dn); - break; - } - } - -- if (!found) -- goto exit_partitions; -- -- /* Set of_node only for nvmem */ -- if (of_device_is_compatible(mtd_dn, "nvmem-cells")) -- mtd_set_of_node(mtd, mtd_dn); -- --exit_partitions: - of_node_put(partitions); - exit_parent: - of_node_put(parent_dn); diff --git a/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch b/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch deleted file mode 100644 index 5a5e11c8f7..0000000000 --- a/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 26422ac78e9d8767bd4aabfbae616b15edbf6a1b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sat, 22 Oct 2022 23:13:18 +0200 -Subject: [PATCH] mtd: core: set ROOT_DEV for partitions marked as rootfs in DT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds support for "linux,rootfs" binding that is used to mark flash -partition containing rootfs. It's useful for devices using device tree -that don't have bootloader passing root info in cmdline. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221022211318.32009-2-zajec5@gmail.com ---- - drivers/mtd/mtdcore.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -737,6 +738,17 @@ int add_mtd_device(struct mtd_info *mtd) - not->add(mtd); - - mutex_unlock(&mtd_table_mutex); -+ -+ if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL)) { -+ if (IS_BUILTIN(CONFIG_MTD)) { -+ pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); -+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); -+ } else { -+ pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", -+ mtd->index, mtd->name); -+ } -+ } -+ - /* We _know_ we aren't being removed, because - our caller is still holding us here. So none - of this try_ nonsense, and no bitching about it diff --git a/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch b/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch deleted file mode 100644 index e570564a0b..0000000000 --- a/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch +++ /dev/null @@ -1,229 +0,0 @@ -From aec4d5f5ffd0f0092bd9dc21ea90e0bc237d4b74 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sat, 15 Oct 2022 11:29:50 +0200 -Subject: [PATCH] mtd: parsers: add TP-Link SafeLoader partitions table parser -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This parser deals with most TP-Link home routers. It reads info about -partitions and registers them in the MTD subsystem. - -Example from TP-Link Archer C5 V2: - -spi-nor spi0.0: s25fl128s1 (16384 Kbytes) -15 tplink-safeloader partitions found on MTD device spi0.0 -Creating 15 MTD partitions on "spi0.0": -0x000000000000-0x000000040000 : "fs-uboot" -0x000000040000-0x000000440000 : "os-image" -0x000000440000-0x000000e40000 : "rootfs" -0x000000e40000-0x000000e40200 : "default-mac" -0x000000e40200-0x000000e40400 : "pin" -0x000000e40400-0x000000e40600 : "product-info" -0x000000e50000-0x000000e60000 : "partition-table" -0x000000e60000-0x000000e60200 : "soft-version" -0x000000e61000-0x000000e70000 : "support-list" -0x000000e70000-0x000000e80000 : "profile" -0x000000e80000-0x000000e90000 : "default-config" -0x000000e90000-0x000000ee0000 : "user-config" -0x000000ee0000-0x000000fe0000 : "log" -0x000000fe0000-0x000000ff0000 : "radio_bk" -0x000000ff0000-0x000001000000 : "radio" - -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221015092950.27467-2-zajec5@gmail.com ---- - drivers/mtd/parsers/Kconfig | 15 +++ - drivers/mtd/parsers/Makefile | 1 + - drivers/mtd/parsers/tplink_safeloader.c | 150 ++++++++++++++++++++++++ - 3 files changed, 166 insertions(+) - create mode 100644 drivers/mtd/parsers/tplink_safeloader.c - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -123,6 +123,21 @@ config MTD_AFS_PARTS - for your particular device. It won't happen automatically. The - 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. - -+config MTD_PARSER_TPLINK_SAFELOADER -+ tristate "TP-Link Safeloader partitions parser" -+ depends on MTD && (ARCH_BCM_5301X || ATH79 || SOC_MT7620 || SOC_MT7621 || COMPILE_TEST) -+ help -+ TP-Link home routers use flash partitions to store various data. Info -+ about flash space layout is stored in a partitions table using a -+ custom ASCII-based format. -+ -+ That format was first found in devices with SafeLoader bootloader and -+ was named after it. Later it was adapted to CFE and U-Boot -+ bootloaders. -+ -+ This driver reads partitions table, parses it and creates MTD -+ partitions. -+ - config MTD_PARSER_TRX - tristate "Parser for TRX format partitions" - depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || RALINK || COMPILE_TEST) ---- a/drivers/mtd/parsers/Makefile -+++ b/drivers/mtd/parsers/Makefile -@@ -10,6 +10,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += - ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o - obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o - obj-$(CONFIG_MTD_AFS_PARTS) += afs.o -+obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o - obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o - obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpart.o - obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o ---- /dev/null -+++ b/drivers/mtd/parsers/tplink_safeloader.c -@@ -0,0 +1,150 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright © 2022 Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TPLINK_SAFELOADER_DATA_OFFSET 4 -+#define TPLINK_SAFELOADER_MAX_PARTS 32 -+ -+struct safeloader_cmn_header { -+ __be32 size; -+ uint32_t unused; -+} __packed; -+ -+static void *mtd_parser_tplink_safeloader_read_table(struct mtd_info *mtd) -+{ -+ struct safeloader_cmn_header hdr; -+ struct device_node *np; -+ size_t bytes_read; -+ size_t offset; -+ size_t size; -+ char *buf; -+ int err; -+ -+ np = mtd_get_of_node(mtd); -+ if (mtd_is_partition(mtd)) -+ of_node_get(np); -+ else -+ np = of_get_child_by_name(np, "partitions"); -+ -+ if (of_property_read_u32(np, "partitions-table-offset", (u32 *)&offset)) { -+ pr_err("Failed to get partitions table offset\n"); -+ goto err_put; -+ } -+ -+ err = mtd_read(mtd, offset, sizeof(hdr), &bytes_read, (uint8_t *)&hdr); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset); -+ goto err_put; -+ } -+ -+ size = be32_to_cpu(hdr.size); -+ -+ buf = kmalloc(size + 1, GFP_KERNEL); -+ if (!buf) -+ goto err_put; -+ -+ err = mtd_read(mtd, offset + sizeof(hdr), size, &bytes_read, buf); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset + sizeof(hdr)); -+ goto err_kfree; -+ } -+ -+ buf[size] = '\0'; -+ -+ of_node_put(np); -+ -+ return buf; -+ -+err_kfree: -+ kfree(buf); -+err_put: -+ of_node_put(np); -+ return NULL; -+} -+ -+static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd, -+ const struct mtd_partition **pparts, -+ struct mtd_part_parser_data *data) -+{ -+ struct mtd_partition *parts; -+ char name[65]; -+ size_t offset; -+ size_t bytes; -+ char *buf; -+ int idx; -+ int err; -+ -+ parts = kcalloc(TPLINK_SAFELOADER_MAX_PARTS, sizeof(*parts), GFP_KERNEL); -+ if (!parts) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ buf = mtd_parser_tplink_safeloader_read_table(mtd); -+ if (!buf) { -+ err = -ENOENT; -+ goto err_out; -+ } -+ -+ for (idx = 0, offset = TPLINK_SAFELOADER_DATA_OFFSET; -+ idx < TPLINK_SAFELOADER_MAX_PARTS && -+ sscanf(buf + offset, "partition %64s base 0x%llx size 0x%llx%zn\n", -+ name, &parts[idx].offset, &parts[idx].size, &bytes) == 3; -+ idx++, offset += bytes + 1) { -+ parts[idx].name = kstrdup(name, GFP_KERNEL); -+ if (!parts[idx].name) { -+ err = -ENOMEM; -+ goto err_free; -+ } -+ } -+ -+ if (idx == TPLINK_SAFELOADER_MAX_PARTS) -+ pr_warn("Reached maximum number of partitions!\n"); -+ -+ kfree(buf); -+ -+ *pparts = parts; -+ -+ return idx; -+ -+err_free: -+ for (idx -= 1; idx >= 0; idx--) -+ kfree(parts[idx].name); -+err_out: -+ return err; -+}; -+ -+static void mtd_parser_tplink_safeloader_cleanup(const struct mtd_partition *pparts, -+ int nr_parts) -+{ -+ int i; -+ -+ for (i = 0; i < nr_parts; i++) -+ kfree(pparts[i].name); -+ -+ kfree(pparts); -+} -+ -+static const struct of_device_id mtd_parser_tplink_safeloader_of_match_table[] = { -+ { .compatible = "tplink,safeloader-partitions" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mtd_parser_tplink_safeloader_of_match_table); -+ -+static struct mtd_part_parser mtd_parser_tplink_safeloader = { -+ .parse_fn = mtd_parser_tplink_safeloader_parse, -+ .cleanup = mtd_parser_tplink_safeloader_cleanup, -+ .name = "tplink-safeloader", -+ .of_match_table = mtd_parser_tplink_safeloader_of_match_table, -+}; -+module_mtd_part_parser(mtd_parser_tplink_safeloader); -+ -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch b/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch deleted file mode 100644 index 7dbc271725..0000000000 --- a/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch +++ /dev/null @@ -1,35 +0,0 @@ -From ebed787a0becb9354f0a23620a5130cccd6c730c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 19 Jan 2023 03:45:43 +0000 -Subject: [PATCH] mtd: spinand: macronix: use scratch buffer for DMA operation - -The mx35lf1ge4ab_get_eccsr() function uses an SPI DMA operation to -read the eccsr, hence the buffer should not be on stack. Since commit -380583227c0c7f ("spi: spi-mem: Add extra sanity checks on the op param") -the kernel emmits a warning and blocks such operations. - -Use the scratch buffer to get eccsr instead of trying to directly read -into a stack-allocated variable. - -Signed-off-by: Daniel Golle -Reviewed-by: Dhruva Gole -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/Y8i85zM0u4XdM46z@makrotopia.org ---- - drivers/mtd/nand/spi/macronix.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/nand/spi/macronix.c -+++ b/drivers/mtd/nand/spi/macronix.c -@@ -83,9 +83,10 @@ static int mx35lf1ge4ab_ecc_get_status(s - * in order to avoid forcing the wear-leveling layer to move - * data around if it's not necessary. - */ -- if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr)) -+ if (mx35lf1ge4ab_get_eccsr(spinand, spinand->scratchbuf)) - return nanddev_get_ecc_conf(nand)->strength; - -+ eccsr = *spinand->scratchbuf; - if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength || - !eccsr)) - return nanddev_get_ecc_conf(nand)->strength; diff --git a/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch b/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch deleted file mode 100644 index 657404196d..0000000000 --- a/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 1ecf9e390452e73a362ea7fbde8f3f0db83de856 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 22 Dec 2022 19:33:04 +0000 -Subject: [PATCH] mtd: ubi: wire-up parent MTD device - -Wire up the device parent pointer of UBI devices to their lower MTD -device, typically an MTD partition or whole-chip device. - -The most noticeable change is that in sysfs, previously ubi devices -would be could in /sys/devices/virtual/ubi while after this change they -would be correctly attached to their parent MTD device, e.g. - -/sys/devices/platform/1100d000.spi/spi_master/spi1/spi1.0/mtd/mtd2/ubi0. - -Locating UBI devices using /sys/class/ubi/ of course still works as -well. - -Signed-off-by: Daniel Golle -Signed-off-by: Richard Weinberger ---- - drivers/mtd/ubi/build.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/mtd/ubi/build.c -+++ b/drivers/mtd/ubi/build.c -@@ -929,6 +929,7 @@ int ubi_attach_mtd_dev(struct mtd_info * - ubi->dev.release = dev_release; - ubi->dev.class = &ubi_class; - ubi->dev.groups = ubi_dev_groups; -+ ubi->dev.parent = &mtd->dev; - - ubi->mtd = mtd; - ubi->ubi_num = ubi_num; diff --git a/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch b/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch deleted file mode 100644 index 48bf986118..0000000000 --- a/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 05b8773ca33253ea562be145cf3145b05ef19f86 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 22 Dec 2022 19:33:31 +0000 -Subject: [PATCH] mtd: ubi: block: wire-up device parent - -ubiblock devices were previously only identifyable by their name, but -not connected to their parent UBI volume device e.g. in sysfs. -Properly parent ubiblock device as descendant of a UBI volume device -to reflect device model hierachy. - -Signed-off-by: Daniel Golle -Signed-off-by: Richard Weinberger ---- - drivers/mtd/ubi/block.c | 2 +- - drivers/mtd/ubi/kapi.c | 1 + - include/linux/mtd/ubi.h | 1 + - 3 files changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/ubi/block.c -+++ b/drivers/mtd/ubi/block.c -@@ -452,7 +452,7 @@ int ubiblock_create(struct ubi_volume_in - list_add_tail(&dev->list, &ubiblock_devices); - - /* Must be the last step: anyone can call file ops from now on */ -- ret = add_disk(dev->gd); -+ ret = device_add_disk(vi->dev, dev->gd, NULL); - if (ret) - goto out_destroy_wq; - ---- a/drivers/mtd/ubi/kapi.c -+++ b/drivers/mtd/ubi/kapi.c -@@ -79,6 +79,7 @@ void ubi_do_get_volume_info(struct ubi_d - vi->name_len = vol->name_len; - vi->name = vol->name; - vi->cdev = vol->cdev.dev; -+ vi->dev = &vol->dev; - } - - /** ---- a/include/linux/mtd/ubi.h -+++ b/include/linux/mtd/ubi.h -@@ -110,6 +110,7 @@ struct ubi_volume_info { - int name_len; - const char *name; - dev_t cdev; -+ struct device *dev; - }; - - /** diff --git a/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch b/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch deleted file mode 100644 index 9ddda420ac..0000000000 --- a/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 281f7a6c1a33fffcde32001bacbb4f672140fbf9 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Wed, 8 Mar 2023 09:20:21 +0100 -Subject: [PATCH] mtd: core: prepare mtd_otp_nvmem_add() to handle - -EPROBE_DEFER - -NVMEM soon will get the ability for nvmem layouts and these might -not be ready when nvmem_register() is called and thus it might -return -EPROBE_DEFER. Don't print the error message in this case. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20230308082021.870459-4-michael@walle.cc ---- - drivers/mtd/mtdcore.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -953,8 +953,8 @@ static int mtd_otp_nvmem_add(struct mtd_ - nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size, - mtd_nvmem_user_otp_reg_read); - if (IS_ERR(nvmem)) { -- dev_err(dev, "Failed to register OTP NVMEM device\n"); -- return PTR_ERR(nvmem); -+ err = PTR_ERR(nvmem); -+ goto err; - } - mtd->otp_user_nvmem = nvmem; - } -@@ -971,7 +971,6 @@ static int mtd_otp_nvmem_add(struct mtd_ - nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size, - mtd_nvmem_fact_otp_reg_read); - if (IS_ERR(nvmem)) { -- dev_err(dev, "Failed to register OTP NVMEM device\n"); - err = PTR_ERR(nvmem); - goto err; - } -@@ -983,7 +982,7 @@ static int mtd_otp_nvmem_add(struct mtd_ - - err: - nvmem_unregister(mtd->otp_user_nvmem); -- return err; -+ return dev_err_probe(dev, err, "Failed to register OTP NVMEM device\n"); - } - - /** diff --git a/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch b/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch deleted file mode 100644 index 28b7b4383e..0000000000 --- a/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 7390609b0121a1b982c5ecdfcd72dc328e5784ee Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:42 +0000 -Subject: [PATCH] net: add helper eth_addr_add() - -Add a helper to add an offset to a ethernet address. This comes in handy -if you have a base ethernet address for multiple interfaces. - -Signed-off-by: Michael Walle -Reviewed-by: Andrew Lunn -Acked-by: Jakub Kicinski -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/etherdevice.h | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/include/linux/etherdevice.h -+++ b/include/linux/etherdevice.h -@@ -508,6 +508,20 @@ static inline void eth_addr_inc(u8 *addr - } - - /** -+ * eth_addr_add() - Add (or subtract) an offset to/from the given MAC address. -+ * -+ * @offset: Offset to add. -+ * @addr: Pointer to a six-byte array containing Ethernet address to increment. -+ */ -+static inline void eth_addr_add(u8 *addr, long offset) -+{ -+ u64 u = ether_addr_to_u64(addr); -+ -+ u += offset; -+ u64_to_ether_addr(u, addr); -+} -+ -+/** - * is_etherdev_addr - Tell if given Ethernet address belongs to the device. - * @dev: Pointer to a device structure - * @addr: Pointer to a six-byte array containing the Ethernet address diff --git a/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch b/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch deleted file mode 100644 index 56e14c5c0a..0000000000 --- a/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch +++ /dev/null @@ -1,32 +0,0 @@ -From d387e34fec407f881fdf165b5d7ec128ebff362f Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 19 Sep 2023 14:47:20 +0200 -Subject: [PATCH] net: sfp: add quirk for Fiberstone GPON-ONU-34-20BI - -Fiberstone GPON-ONU-34-20B can operate at 2500base-X, but report 1.2GBd -NRZ in their EEPROM. - -The module also require the ignore tx fault fixup similar to Huawei MA5671A -as it gets disabled on error messages with serial redirection enabled. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20230919124720.8210-1-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/sfp.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -393,6 +393,11 @@ static const struct sfp_quirk sfp_quirks - SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex, - sfp_fixup_long_startup), - -+ // Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd -+ // NRZ in their EEPROM -+ SFP_QUIRK("FS", "GPON-ONU-34-20BI", sfp_quirk_2500basex, -+ sfp_fixup_ignore_tx_fault), -+ - SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp), - - // HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports diff --git a/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch b/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch deleted file mode 100644 index ff186742ba..0000000000 --- a/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch +++ /dev/null @@ -1,326 +0,0 @@ -From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 9 Jan 2023 16:30:41 +0100 -Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers - -Currently C22 and C45 transactions are mixed over a combined API calls -which make use of a special bit in the reg address to indicate if a -C45 transaction should be performed. This makes it impossible to know -if the bus driver actually supports C45. Additionally, many C22 only -drivers don't return -EOPNOTSUPP when asked to perform a C45 -transaction, they mistaking perform a C22 transaction. - -This is the first step to cleanly separate C22 from C45. To maintain -backwards compatibility until all drivers which are capable of -performing C45 are converted to this new API, the helper functions -will fall back to the older API if the new API is not -supported. Eventually this fallback will be removed. - -Signed-off-by: Andrew Lunn -Signed-off-by: Michael Walle -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++ - include/linux/mdio.h | 39 ++++---- - include/linux/phy.h | 5 + - 3 files changed, 214 insertions(+), 19 deletions(-) - ---- a/drivers/net/phy/mdio_bus.c -+++ b/drivers/net/phy/mdio_bus.c -@@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_ - EXPORT_SYMBOL_GPL(__mdiobus_modify_changed); - - /** -+ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to read -+ * -+ * Read a MDIO bus register. Caller must hold the mdio bus lock. -+ * -+ * NOTE: MUST NOT be called from interrupt context. -+ */ -+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) -+{ -+ int retval; -+ -+ lockdep_assert_held_once(&bus->mdio_lock); -+ -+ if (bus->read_c45) -+ retval = bus->read_c45(bus, addr, devad, regnum); -+ else -+ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum)); -+ -+ trace_mdio_access(bus, 1, addr, regnum, retval, retval); -+ mdiobus_stats_acct(&bus->stats[addr], true, retval); -+ -+ return retval; -+} -+EXPORT_SYMBOL(__mdiobus_c45_read); -+ -+/** -+ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * Write a MDIO bus register. Caller must hold the mdio bus lock. -+ * -+ * NOTE: MUST NOT be called from interrupt context. -+ */ -+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val) -+{ -+ int err; -+ -+ lockdep_assert_held_once(&bus->mdio_lock); -+ -+ if (bus->write_c45) -+ err = bus->write_c45(bus, addr, devad, regnum, val); -+ else -+ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum), -+ val); -+ -+ trace_mdio_access(bus, 0, addr, regnum, val, err); -+ mdiobus_stats_acct(&bus->stats[addr], false, err); -+ -+ return err; -+} -+EXPORT_SYMBOL(__mdiobus_c45_write); -+ -+/** -+ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to modify -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * Read, modify, and if any change, write the register value back to the -+ * device. Any error returns a negative number. -+ * -+ * NOTE: MUST NOT be called from interrupt context. -+ */ -+static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, -+ int devad, u32 regnum, u16 mask, -+ u16 set) -+{ -+ int new, ret; -+ -+ ret = __mdiobus_c45_read(bus, addr, devad, regnum); -+ if (ret < 0) -+ return ret; -+ -+ new = (ret & ~mask) | set; -+ if (new == ret) -+ return 0; -+ -+ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new); -+ -+ return ret < 0 ? ret : 1; -+} -+ -+/** - * mdiobus_read_nested - Nested version of the mdiobus_read function - * @bus: the mii_bus struct - * @addr: the phy address -@@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in - EXPORT_SYMBOL(mdiobus_read); - - /** -+ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to read -+ * -+ * NOTE: MUST NOT be called from interrupt context, -+ * because the bus read/write functions may wait for an interrupt -+ * to conclude the operation. -+ */ -+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) -+{ -+ int retval; -+ -+ mutex_lock(&bus->mdio_lock); -+ retval = __mdiobus_c45_read(bus, addr, devad, regnum); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return retval; -+} -+EXPORT_SYMBOL(mdiobus_c45_read); -+ -+/** - * mdiobus_write_nested - Nested version of the mdiobus_write function - * @bus: the mii_bus struct - * @addr: the phy address -@@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i - EXPORT_SYMBOL(mdiobus_write); - - /** -+ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * NOTE: MUST NOT be called from interrupt context, -+ * because the bus read/write functions may wait for an interrupt -+ * to conclude the operation. -+ */ -+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val) -+{ -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ err = __mdiobus_c45_write(bus, addr, devad, regnum, val); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err; -+} -+EXPORT_SYMBOL(mdiobus_c45_write); -+ -+/** - * mdiobus_modify - Convenience function for modifying a given mdio device - * register - * @bus: the mii_bus struct -@@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus, - EXPORT_SYMBOL_GPL(mdiobus_modify); - - /** -+ * mdiobus_c45_modify - Convenience function for modifying a given mdio device -+ * register -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ */ -+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 mask, u16 set) -+{ -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, -+ mask, set); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err < 0 ? err : 0; -+} -+EXPORT_SYMBOL_GPL(mdiobus_c45_modify); -+ -+/** - * mdiobus_modify_changed - Convenience function for modifying a given mdio - * device register and returning if it changed - * @bus: the mii_bus struct -@@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu - EXPORT_SYMBOL_GPL(mdiobus_modify_changed); - - /** -+ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio -+ * device register and returning if it changed -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ */ -+int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr, -+ u32 regnum, u16 mask, u16 set) -+{ -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed); -+ -+/** - * mdio_bus_match - determine if given MDIO driver supports the given - * MDIO device - * @dev: target MDIO device ---- a/include/linux/mdio.h -+++ b/include/linux/mdio.h -@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus, - u16 set); - int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, - u16 mask, u16 set); -+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); -+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); -+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val); -+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val); -+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 mask, u16 set); -+ -+int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, -+ u32 regnum, u16 mask, u16 set); - - static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) - { -@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32 - return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); - } - --static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, -- u16 regnum) --{ -- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); --} -- --static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, -- u16 regnum, u16 val) --{ -- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), -- val); --} -- --static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, -- u16 regnum) -+static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad, -+ u32 regnum, u16 mask, u16 set) - { -- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); -+ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum, -+ mask, set); - } - --static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, -- u16 regnum, u16 val) -+static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev, -+ int devad, u32 regnum, u16 mask, -+ u16 set) - { -- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val); -+ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad, -+ regnum, mask, set); - } - - int mdiobus_register_device(struct mdio_device *mdiodev); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -364,6 +364,11 @@ struct mii_bus { - int (*read)(struct mii_bus *bus, int addr, int regnum); - /** @write: Perform a write transfer on the bus */ - int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); -+ /** @read_c45: Perform a C45 read transfer on the bus */ -+ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum); -+ /** @write_c45: Perform a C45 write transfer on the bus */ -+ int (*write_c45)(struct mii_bus *bus, int addr, int devnum, -+ int regnum, u16 val); - /** @reset: Perform a reset of the bus */ - int (*reset)(struct mii_bus *bus); - diff --git a/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch deleted file mode 100644 index 80210e6da1..0000000000 --- a/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Fri, 11 Aug 2023 13:10:07 +0200 -Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode - -The PSGMII interface is similar to QSGMII. The main difference -is that the PSGMII interface combines five SGMII lines into a -single link while in QSGMII only four lines are combined. - -Similarly to the QSGMII, this interface mode might also needs -special handling within the MAC driver. - -It is commonly used by Qualcomm with their QCA807x PHY series and -modern WiSoC-s. - -Add definitions for the PHY layer to allow to express this type -of connection between the MAC and PHY. - -Signed-off-by: Gabor Juhos -Signed-off-by: Robert Marko -Signed-off-by: David S. Miller ---- - Documentation/networking/phy.rst | 4 ++++ - drivers/net/phy/phy-core.c | 2 ++ - drivers/net/phy/phylink.c | 3 +++ - include/linux/phy.h | 4 ++++ - 4 files changed, 13 insertions(+) - ---- a/Documentation/networking/phy.rst -+++ b/Documentation/networking/phy.rst -@@ -323,6 +323,10 @@ Some of the interface modes are describe - contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this - interface mode has different autonegotiation and only supports full duplex. - -+``PHY_INTERFACE_MODE_PSGMII`` -+ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5 -+ SGMII lines into a single link compared to 4 on QSGMII. -+ - Pause frames / flow control - =========================== - ---- a/drivers/net/phy/phy-core.c -+++ b/drivers/net/phy/phy-core.c -@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - return 4; -+ case PHY_INTERFACE_MODE_PSGMII: -+ return 5; - case PHY_INTERFACE_MODE_MAX: - WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); - return 0; ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_SGMII: -@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_SGMII: -@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy - - switch (pl->link_config.interface) { - case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_RGMII: ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -103,6 +103,7 @@ extern const int phy_10gbit_features_arr - * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface - * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface - * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax -+ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII - * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII - * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII - * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX -@@ -140,6 +141,7 @@ typedef enum { - PHY_INTERFACE_MODE_XGMII, - PHY_INTERFACE_MODE_XLGMII, - PHY_INTERFACE_MODE_MOCA, -+ PHY_INTERFACE_MODE_PSGMII, - PHY_INTERFACE_MODE_QSGMII, - PHY_INTERFACE_MODE_TRGMII, - PHY_INTERFACE_MODE_100BASEX, -@@ -247,6 +249,8 @@ static inline const char *phy_modes(phy_ - return "xlgmii"; - case PHY_INTERFACE_MODE_MOCA: - return "moca"; -+ case PHY_INTERFACE_MODE_PSGMII: -+ return "psgmii"; - case PHY_INTERFACE_MODE_QSGMII: - return "qsgmii"; - case PHY_INTERFACE_MODE_TRGMII: diff --git a/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch b/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch deleted file mode 100644 index 7cacb71b18..0000000000 --- a/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a593a2fcfdfb92cfd0ffc54bc81b07e6bfaaaf46 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Thu, 16 Mar 2023 14:08:26 +0200 -Subject: [PATCH] net: phy: at803x: Replace of_gpio.h with what indeed is used - -of_gpio.h in this driver is solely used as a proxy to other headers. -This is incorrect usage of the of_gpio.h. Replace it .h with what -indeed is used in the code. - -Signed-off-by: Andy Shevchenko -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -13,12 +13,11 @@ - #include - #include - #include --#include - #include --#include - #include - #include - #include -+#include - #include - #include - #include diff --git a/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch b/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch deleted file mode 100644 index dab4928960..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:19 +0800 -Subject: [PATCH 1/6] net: phy: at803x: support qca8081 - genphy_c45_pma_read_abilities - -qca8081 PHY supports to use genphy_c45_pma_read_abilities for -getting the PHY features supported except for the autoneg ability - -but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it -manually after calling genphy_c45_pma_read_abilities. - -Signed-off-by: Luo Jie -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 28 ++++++++++++++++++---------- - 1 file changed, 18 insertions(+), 10 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -902,15 +902,6 @@ static int at803x_get_features(struct ph - if (err) - return err; - -- if (phydev->drv->phy_id == QCA8081_PHY_ID) { -- err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); -- if (err < 0) -- return err; -- -- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, -- err & MDIO_PMA_NG_EXTABLE_2_5GBT); -- } -- - if (phydev->drv->phy_id != ATH8031_PHY_ID) - return 0; - -@@ -1996,6 +1987,23 @@ static int qca808x_cable_test_get_status - return 0; - } - -+static int qca808x_get_features(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = genphy_c45_pma_read_abilities(phydev); -+ if (ret) -+ return ret; -+ -+ /* The autoneg ability is not existed in bit3 of MMD7.1, -+ * but it is supported by qca808x PHY, so we add it here -+ * manually. -+ */ -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); -+ -+ return 0; -+} -+ - static struct phy_driver at803x_driver[] = { - { - /* Qualcomm Atheros AR8035 */ -@@ -2163,7 +2171,7 @@ static struct phy_driver at803x_driver[] - .set_tunable = at803x_set_tunable, - .set_wol = at803x_set_wol, - .get_wol = at803x_get_wol, -- .get_features = at803x_get_features, -+ .get_features = qca808x_get_features, - .config_aneg = at803x_config_aneg, - .suspend = genphy_suspend, - .resume = genphy_resume, diff --git a/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch b/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch deleted file mode 100644 index 28874068ce..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch +++ /dev/null @@ -1,73 +0,0 @@ -From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:20 +0800 -Subject: [PATCH 2/6] net: phy: at803x: merge qca8081 slave seed function - -merge the seed enablement and seed value configuration into -one function, since the random seed value is needed to be -configured when the seed is enabled. - -Signed-off-by: Luo Jie -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 29 +++++++++-------------------- - 1 file changed, 9 insertions(+), 20 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -1730,24 +1730,19 @@ static int qca808x_phy_fast_retrain_conf - return 0; - } - --static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) --{ -- u16 seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); -- -- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, -- QCA808X_MASTER_SLAVE_SEED_CFG, -- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); --} -- - static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) - { -- u16 seed_enable = 0; -+ u16 seed_value; - -- if (enable) -- seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; -+ if (!enable) -+ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, -+ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); - -+ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, -- QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); -+ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, -+ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | -+ QCA808X_MASTER_SLAVE_SEED_ENABLE); - } - - static int qca808x_config_init(struct phy_device *phydev) -@@ -1771,12 +1766,7 @@ static int qca808x_config_init(struct ph - if (ret) - return ret; - -- /* Configure lower ramdom seed to make phy linked as slave mode */ -- ret = qca808x_phy_ms_random_seed_set(phydev); -- if (ret) -- return ret; -- -- /* Enable seed */ -+ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ - ret = qca808x_phy_ms_seed_enable(phydev, true); - if (ret) - return ret; -@@ -1821,7 +1811,6 @@ static int qca808x_read_status(struct ph - if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { - qca808x_phy_ms_seed_enable(phydev, false); - } else { -- qca808x_phy_ms_random_seed_set(phydev); - qca808x_phy_ms_seed_enable(phydev, true); - } - } diff --git a/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch b/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch deleted file mode 100644 index b91d2cab30..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:21 +0800 -Subject: [PATCH 3/6] net: phy: at803x: enable qca8081 slave seed conditionally - -qca8081 is the single port PHY, the slave prefer mode is used -by default. - -if the phy master perfer mode is configured, the slave seed -configuration should not be enabled, since the slave seed -enablement is for making PHY linked as slave mode easily. - -disable slave seed if the master mode is preferred. - -Signed-off-by: Luo Jie -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- - 1 file changed, 20 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -1745,6 +1745,12 @@ static int qca808x_phy_ms_seed_enable(st - QCA808X_MASTER_SLAVE_SEED_ENABLE); - } - -+static bool qca808x_is_prefer_master(struct phy_device *phydev) -+{ -+ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || -+ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); -+} -+ - static int qca808x_config_init(struct phy_device *phydev) - { - int ret; -@@ -1766,11 +1772,17 @@ static int qca808x_config_init(struct ph - if (ret) - return ret; - -- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ -- ret = qca808x_phy_ms_seed_enable(phydev, true); -- if (ret) -+ ret = genphy_read_master_slave(phydev); -+ if (ret < 0) - return ret; - -+ if (!qca808x_is_prefer_master(phydev)) { -+ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ -+ ret = qca808x_phy_ms_seed_enable(phydev, true); -+ if (ret) -+ return ret; -+ } -+ - /* Configure adc threshold as 100mv for the link 10M */ - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, - QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); -@@ -1802,13 +1814,16 @@ static int qca808x_read_status(struct ph - phydev->interface = PHY_INTERFACE_MODE_SGMII; - } else { - /* generate seed as a lower random value to make PHY linked as SLAVE easily, -- * except for master/slave configuration fault detected. -+ * except for master/slave configuration fault detected or the master mode -+ * preferred. -+ * - * the reason for not putting this code into the function link_change_notify is - * the corner case where the link partner is also the qca8081 PHY and the seed - * value is configured as the same value, the link can't be up and no link change - * occurs. - */ -- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { -+ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || -+ qca808x_is_prefer_master(phydev)) { - qca808x_phy_ms_seed_enable(phydev, false); - } else { - qca808x_phy_ms_seed_enable(phydev, true); diff --git a/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch b/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch deleted file mode 100644 index b8db89d853..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch +++ /dev/null @@ -1,48 +0,0 @@ -From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:22 +0800 -Subject: [PATCH 4/6] net: phy: at803x: support qca8081 1G chip type - -The qca8081 1G chip version does not support 2.5 capability, which -is distinguished from qca8081 2.5G chip according to the bit0 of -register mmd7.0x901d, the 1G version chip also has the same PHY ID -as the normal qca8081 2.5G chip. - -Signed-off-by: Luo Jie -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -272,6 +272,10 @@ - #define QCA808X_CDT_STATUS_STAT_OPEN 2 - #define QCA808X_CDT_STATUS_STAT_SHORT 3 - -+/* QCA808X 1G chip type */ -+#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d -+#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) -+ - MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi"); - MODULE_LICENSE("GPL"); -@@ -2005,6 +2009,17 @@ static int qca808x_get_features(struct p - */ - linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); - -+ /* As for the qca8081 1G version chip, the 2500baseT ability is also -+ * existed in the bit0 of MMD1.21, we need to remove it manually if -+ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. -+ */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); -+ if (ret < 0) -+ return ret; -+ -+ if (QCA808X_PHY_CHIP_TYPE_1G & ret) -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch b/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch deleted file mode 100644 index b54a86e5f5..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch +++ /dev/null @@ -1,98 +0,0 @@ -From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:23 +0800 -Subject: [PATCH 5/6] net: phy: at803x: remove qca8081 1G fast retrain and - slave seed config - -The fast retrain and slave seed configs are only applicable when the 2.5G -ability is supported. - -Signed-off-by: Luo Jie -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++--------------- - 1 file changed, 32 insertions(+), 18 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -1755,6 +1755,11 @@ static bool qca808x_is_prefer_master(str - (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); - } - -+static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) -+{ -+ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); -+} -+ - static int qca808x_config_init(struct phy_device *phydev) - { - int ret; -@@ -1771,20 +1776,24 @@ static int qca808x_config_init(struct ph - if (ret) - return ret; - -- /* Config the fast retrain for the link 2500M */ -- ret = qca808x_phy_fast_retrain_config(phydev); -- if (ret) -- return ret; -- -- ret = genphy_read_master_slave(phydev); -- if (ret < 0) -- return ret; -- -- if (!qca808x_is_prefer_master(phydev)) { -- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ -- ret = qca808x_phy_ms_seed_enable(phydev, true); -+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { -+ /* Config the fast retrain for the link 2500M */ -+ ret = qca808x_phy_fast_retrain_config(phydev); - if (ret) - return ret; -+ -+ ret = genphy_read_master_slave(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (!qca808x_is_prefer_master(phydev)) { -+ /* Enable seed and configure lower ramdom seed to make phy -+ * linked as slave mode. -+ */ -+ ret = qca808x_phy_ms_seed_enable(phydev, true); -+ if (ret) -+ return ret; -+ } - } - - /* Configure adc threshold as 100mv for the link 10M */ -@@ -1826,11 +1835,13 @@ static int qca808x_read_status(struct ph - * value is configured as the same value, the link can't be up and no link change - * occurs. - */ -- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || -- qca808x_is_prefer_master(phydev)) { -- qca808x_phy_ms_seed_enable(phydev, false); -- } else { -- qca808x_phy_ms_seed_enable(phydev, true); -+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { -+ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || -+ qca808x_is_prefer_master(phydev)) { -+ qca808x_phy_ms_seed_enable(phydev, false); -+ } else { -+ qca808x_phy_ms_seed_enable(phydev, true); -+ } - } - } - -@@ -1845,7 +1856,10 @@ static int qca808x_soft_reset(struct phy - if (ret < 0) - return ret; - -- return qca808x_phy_ms_seed_enable(phydev, true); -+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) -+ ret = qca808x_phy_ms_seed_enable(phydev, true); -+ -+ return ret; - } - - static bool qca808x_cdt_fault_length_valid(int cdt_code) diff --git a/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch b/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch deleted file mode 100644 index e382cf7876..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:24 +0800 -Subject: [PATCH 6/6] net: phy: at803x: add qca8081 fifo reset on the link - changed - -The qca8081 sgmii fifo needs to be reset on link down and -released on the link up in case of any abnormal issue -such as the packet blocked on the PHY. - -Signed-off-by: Luo Jie -Reviewed-by: Andrew Lunn -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -276,6 +276,9 @@ - #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d - #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) - -+#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 -+#define QCA8081_PHY_FIFO_RSTN BIT(11) -+ - MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi"); - MODULE_LICENSE("GPL"); -@@ -2037,6 +2040,16 @@ static int qca808x_get_features(struct p - return 0; - } - -+static void qca808x_link_change_notify(struct phy_device *phydev) -+{ -+ /* Assert interface sgmii fifo on link down, deassert it on link up, -+ * the interface device address is always phy address added by 1. -+ */ -+ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, -+ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, -+ QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); -+} -+ - static struct phy_driver at803x_driver[] = { - { - /* Qualcomm Atheros AR8035 */ -@@ -2213,6 +2226,7 @@ static struct phy_driver at803x_driver[] - .soft_reset = qca808x_soft_reset, - .cable_test_start = qca808x_cable_test_start, - .cable_test_get_status = qca808x_cable_test_get_status, -+ .link_change_notify = qca808x_link_change_notify, - }, }; - - module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch b/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch deleted file mode 100644 index d56a142451..0000000000 --- a/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 4765a9722e09765866e131ec31f7b9cf4c1f4854 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:57:50 +0000 -Subject: [PATCH] net: pcs: add driver for MediaTek SGMII PCS - -The SGMII core found in several MediaTek SoCs is identical to what can -also be found in MediaTek's MT7531 Ethernet switch IC. -As this has not always been clear, both drivers developed different -implementations to deal with the PCS. -Recently Alexander Couzens pointed out this fact which lead to the -development of this shared driver. - -Add a dedicated driver, mostly by copying the code now found in the -Ethernet driver. The now redundant code will be removed by a follow-up -commit. - -Suggested-by: Alexander Couzens -Suggested-by: Russell King (Oracle) -Signed-off-by: Daniel Golle -Tested-by: Frank Wunderlich -Reviewed-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - MAINTAINERS | 8 + - drivers/net/pcs/Kconfig | 7 + - drivers/net/pcs/Makefile | 1 + - drivers/net/pcs/pcs-mtk-lynxi.c | 305 ++++++++++++++++++++++++++++++ - include/linux/pcs/pcs-mtk-lynxi.h | 13 ++ - 5 files changed, 334 insertions(+) - create mode 100644 drivers/net/pcs/pcs-mtk-lynxi.c - create mode 100644 include/linux/pcs/pcs-mtk-lynxi.h - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -12928,6 +12928,14 @@ L: netdev@vger.kernel.org - S: Maintained - F: drivers/net/ethernet/mediatek/ - -+MEDIATEK ETHERNET PCS DRIVER -+M: Alexander Couzens -+M: Daniel Golle -+L: netdev@vger.kernel.org -+S: Maintained -+F: drivers/net/pcs/pcs-mtk-lynxi.c -+F: include/linux/pcs/pcs-mtk-lynxi.h -+ - MEDIATEK I2C CONTROLLER DRIVER - M: Qii Wang - L: linux-i2c@vger.kernel.org ---- a/drivers/net/pcs/Kconfig -+++ b/drivers/net/pcs/Kconfig -@@ -32,4 +32,11 @@ config PCS_ALTERA_TSE - This module provides helper functions for the Altera Triple Speed - Ethernet SGMII PCS, that can be found on the Intel Socfpga family. - -+config PCS_MTK_LYNXI -+ tristate -+ select REGMAP -+ help -+ This module provides helpers to phylink for managing the LynxI PCS -+ which is part of MediaTek's SoC and Ethernet switch ICs. -+ - endmenu ---- a/drivers/net/pcs/Makefile -+++ b/drivers/net/pcs/Makefile -@@ -7,3 +7,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o - obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o - obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o - obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o -+obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o ---- /dev/null -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -0,0 +1,305 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018-2019 MediaTek Inc. -+/* A library for MediaTek SGMII circuit -+ * -+ * Author: Sean Wang -+ * Author: Alexander Couzens -+ * Author: Daniel Golle -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* SGMII subsystem config registers */ -+/* BMCR (low 16) BMSR (high 16) */ -+#define SGMSYS_PCS_CONTROL_1 0x0 -+#define SGMII_BMCR GENMASK(15, 0) -+#define SGMII_BMSR GENMASK(31, 16) -+ -+#define SGMSYS_PCS_DEVICE_ID 0x4 -+#define SGMII_LYNXI_DEV_ID 0x4d544950 -+ -+#define SGMSYS_PCS_ADVERTISE 0x8 -+#define SGMII_ADVERTISE GENMASK(15, 0) -+#define SGMII_LPA GENMASK(31, 16) -+ -+#define SGMSYS_PCS_SCRATCH 0x14 -+#define SGMII_DEV_VERSION GENMASK(31, 16) -+ -+/* Register to programmable link timer, the unit in 2 * 8ns */ -+#define SGMSYS_PCS_LINK_TIMER 0x18 -+#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) -+#define SGMII_LINK_TIMER_VAL(ns) FIELD_PREP(SGMII_LINK_TIMER_MASK, \ -+ ((ns) / 2 / 8)) -+ -+/* Register to control remote fault */ -+#define SGMSYS_SGMII_MODE 0x20 -+#define SGMII_IF_MODE_SGMII BIT(0) -+#define SGMII_SPEED_DUPLEX_AN BIT(1) -+#define SGMII_SPEED_MASK GENMASK(3, 2) -+#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) -+#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) -+#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) -+#define SGMII_DUPLEX_HALF BIT(4) -+#define SGMII_REMOTE_FAULT_DIS BIT(8) -+ -+/* Register to reset SGMII design */ -+#define SGMSYS_RESERVED_0 0x34 -+#define SGMII_SW_RESET BIT(0) -+ -+/* Register to set SGMII speed, ANA RG_ Control Signals III */ -+#define SGMII_PHY_SPEED_MASK GENMASK(3, 2) -+#define SGMII_PHY_SPEED_1_25G FIELD_PREP(SGMII_PHY_SPEED_MASK, 0) -+#define SGMII_PHY_SPEED_3_125G FIELD_PREP(SGMII_PHY_SPEED_MASK, 1) -+ -+/* Register to power up QPHY */ -+#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 -+#define SGMII_PHYA_PWD BIT(4) -+ -+/* Register to QPHY wrapper control */ -+#define SGMSYS_QPHY_WRAP_CTRL 0xec -+#define SGMII_PN_SWAP_MASK GENMASK(1, 0) -+#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) -+ -+/* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated -+ * data -+ * @regmap: The register map pointing at the range used to setup -+ * SGMII modes -+ * @dev: Pointer to device owning the PCS -+ * @ana_rgc3: The offset of register ANA_RGC3 relative to regmap -+ * @interface: Currently configured interface mode -+ * @pcs: Phylink PCS structure -+ * @flags: Flags indicating hardware properties -+ */ -+struct mtk_pcs_lynxi { -+ struct regmap *regmap; -+ u32 ana_rgc3; -+ phy_interface_t interface; -+ struct phylink_pcs pcs; -+ u32 flags; -+}; -+ -+static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct mtk_pcs_lynxi, pcs); -+} -+ -+static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ unsigned int bm, adv; -+ -+ /* Read the BMSR and LPA */ -+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); -+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); -+ -+ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), -+ FIELD_GET(SGMII_LPA, adv)); -+} -+ -+static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ bool mode_changed = false, changed, use_an; -+ unsigned int rgc3, sgm_mode, bmcr; -+ int advertise, link_timer; -+ -+ advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -+ advertising); -+ if (advertise < 0) -+ return advertise; -+ -+ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and -+ * we assume that fixes it's speed at bitrate = line rate (in -+ * other words, 1000Mbps or 2500Mbps). -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII) { -+ sgm_mode = SGMII_IF_MODE_SGMII; -+ if (phylink_autoneg_inband(mode)) { -+ sgm_mode |= SGMII_REMOTE_FAULT_DIS | -+ SGMII_SPEED_DUPLEX_AN; -+ use_an = true; -+ } else { -+ use_an = false; -+ } -+ } else if (phylink_autoneg_inband(mode)) { -+ /* 1000base-X or 2500base-X autoneg */ -+ sgm_mode = SGMII_REMOTE_FAULT_DIS; -+ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ advertising); -+ } else { -+ /* 1000base-X or 2500base-X without autoneg */ -+ sgm_mode = 0; -+ use_an = false; -+ } -+ -+ if (use_an) -+ bmcr = BMCR_ANENABLE; -+ else -+ bmcr = 0; -+ -+ if (mpcs->interface != interface) { -+ link_timer = phylink_get_link_timer_ns(interface); -+ if (link_timer < 0) -+ return link_timer; -+ -+ /* PHYA power down */ -+ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD); -+ -+ /* Reset SGMII PCS state */ -+ regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, -+ SGMII_SW_RESET); -+ -+ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, -+ SGMII_PN_SWAP_MASK, -+ SGMII_PN_SWAP_TX_RX); -+ -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) -+ rgc3 = SGMII_PHY_SPEED_3_125G; -+ else -+ rgc3 = SGMII_PHY_SPEED_1_25G; -+ -+ /* Configure the underlying interface speed */ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ SGMII_PHY_SPEED_MASK, rgc3); -+ -+ /* Setup the link timer */ -+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, -+ SGMII_LINK_TIMER_VAL(link_timer)); -+ -+ mpcs->interface = interface; -+ mode_changed = true; -+ } -+ -+ /* Update the advertisement, noting whether it has changed */ -+ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -+ SGMII_ADVERTISE, advertise, &changed); -+ -+ /* Update the sgmsys mode register */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -+ SGMII_IF_MODE_SGMII, sgm_mode); -+ -+ /* Update the BMCR */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ BMCR_ANENABLE, bmcr); -+ -+ /* Release PHYA power down state -+ * Only removing bit SGMII_PHYA_PWD isn't enough. -+ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which -+ * prevents SGMII from working. The SGMII still shows link but no traffic -+ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -+ * taken from a good working state of the SGMII interface. -+ * Unknown how much the QPHY needs but it is racy without a sleep. -+ * Tested on mt7622 & mt7986. -+ */ -+ usleep_range(50, 100); -+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); -+ -+ return changed || mode_changed; -+} -+ -+static void mtk_pcs_lynxi_restart_an(struct phylink_pcs *pcs) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ -+ regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); -+} -+ -+static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, int speed, -+ int duplex) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ unsigned int sgm_mode; -+ -+ if (!phylink_autoneg_inband(mode)) { -+ /* Force the speed and duplex setting */ -+ if (speed == SPEED_10) -+ sgm_mode = SGMII_SPEED_10; -+ else if (speed == SPEED_100) -+ sgm_mode = SGMII_SPEED_100; -+ else -+ sgm_mode = SGMII_SPEED_1000; -+ -+ if (duplex != DUPLEX_FULL) -+ sgm_mode |= SGMII_DUPLEX_HALF; -+ -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, -+ sgm_mode); -+ } -+} -+ -+static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { -+ .pcs_get_state = mtk_pcs_lynxi_get_state, -+ .pcs_config = mtk_pcs_lynxi_config, -+ .pcs_an_restart = mtk_pcs_lynxi_restart_an, -+ .pcs_link_up = mtk_pcs_lynxi_link_up, -+}; -+ -+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, -+ struct regmap *regmap, u32 ana_rgc3, -+ u32 flags) -+{ -+ struct mtk_pcs_lynxi *mpcs; -+ u32 id, ver; -+ int ret; -+ -+ ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); -+ if (ret < 0) -+ return NULL; -+ -+ if (id != SGMII_LYNXI_DEV_ID) { -+ dev_err(dev, "unknown PCS device id %08x\n", id); -+ return NULL; -+ } -+ -+ ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver); -+ if (ret < 0) -+ return NULL; -+ -+ ver = FIELD_GET(SGMII_DEV_VERSION, ver); -+ if (ver != 0x1) { -+ dev_err(dev, "unknown PCS device version %04x\n", ver); -+ return NULL; -+ } -+ -+ dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id, -+ ver); -+ -+ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); -+ if (!mpcs) -+ return NULL; -+ -+ mpcs->ana_rgc3 = ana_rgc3; -+ mpcs->regmap = regmap; -+ mpcs->flags = flags; -+ mpcs->pcs.ops = &mtk_pcs_lynxi_ops; -+ mpcs->pcs.poll = true; -+ mpcs->interface = PHY_INTERFACE_MODE_NA; -+ -+ return &mpcs->pcs; -+} -+EXPORT_SYMBOL(mtk_pcs_lynxi_create); -+ -+void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs) -+{ -+ if (!pcs) -+ return; -+ -+ kfree(pcs_to_mtk_pcs_lynxi(pcs)); -+} -+EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); -+ -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/include/linux/pcs/pcs-mtk-lynxi.h -@@ -0,0 +1,13 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef __LINUX_PCS_MTK_LYNXI_H -+#define __LINUX_PCS_MTK_LYNXI_H -+ -+#include -+#include -+ -+#define MTK_SGMII_FLAG_PN_SWAP BIT(0) -+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, -+ struct regmap *regmap, -+ u32 ana_rgc3, u32 flags); -+void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs); -+#endif diff --git a/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch b/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch deleted file mode 100644 index 2886123f2d..0000000000 --- a/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch +++ /dev/null @@ -1,103 +0,0 @@ -From affa013f494486079c3c5ad2d00cebc41a3d7445 Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Mon, 17 Oct 2022 16:22:36 -0400 -Subject: [PATCH 01/21] net: fman: memac: Add serdes support - -This adds support for using a serdes which has to be configured. This is -primarly in preparation for phylink conversion, which will then change the -serdes mode dynamically. - -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - .../net/ethernet/freescale/fman/fman_memac.c | 49 ++++++++++++++++++- - 1 file changed, 47 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/freescale/fman/fman_memac.c -+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - - /* PCS registers */ -@@ -324,6 +325,7 @@ struct fman_mac { - void *fm; - struct fman_rev_info fm_rev_info; - bool basex_if; -+ struct phy *serdes; - struct phy_device *pcsphy; - bool allmulti_enabled; - }; -@@ -1203,17 +1205,56 @@ int memac_initialization(struct mac_devi - } - } - -+ memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); -+ err = PTR_ERR(memac->serdes); -+ if (err == -ENODEV || err == -ENOSYS) { -+ dev_dbg(mac_dev->dev, "could not get (optional) serdes\n"); -+ memac->serdes = NULL; -+ } else if (IS_ERR(memac->serdes)) { -+ dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); -+ goto _return_fm_mac_free; -+ } else { -+ err = phy_init(memac->serdes); -+ if (err) { -+ dev_err_probe(mac_dev->dev, err, -+ "could not initialize serdes\n"); -+ goto _return_fm_mac_free; -+ } -+ -+ err = phy_power_on(memac->serdes); -+ if (err) { -+ dev_err_probe(mac_dev->dev, err, -+ "could not power on serdes\n"); -+ goto _return_phy_exit; -+ } -+ -+ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || -+ memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || -+ memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || -+ memac->phy_if == PHY_INTERFACE_MODE_QSGMII || -+ memac->phy_if == PHY_INTERFACE_MODE_XGMII) { -+ err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, -+ memac->phy_if); -+ if (err) { -+ dev_err_probe(mac_dev->dev, err, -+ "could not set serdes mode to %s\n", -+ phy_modes(memac->phy_if)); -+ goto _return_phy_power_off; -+ } -+ } -+ } -+ - if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { - struct phy_device *phy; - - err = of_phy_register_fixed_link(mac_node); - if (err) -- goto _return_fm_mac_free; -+ goto _return_phy_power_off; - - fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); - if (!fixed_link) { - err = -ENOMEM; -- goto _return_fm_mac_free; -+ goto _return_phy_power_off; - } - - mac_dev->phy_node = of_node_get(mac_node); -@@ -1242,6 +1283,10 @@ int memac_initialization(struct mac_devi - - goto _return; - -+_return_phy_power_off: -+ phy_power_off(memac->serdes); -+_return_phy_exit: -+ phy_exit(memac->serdes); - _return_fixed_link_free: - kfree(fixed_link); - _return_fm_mac_free: diff --git a/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch b/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch deleted file mode 100644 index 873debc080..0000000000 --- a/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch +++ /dev/null @@ -1,384 +0,0 @@ -From fe60e7154d3a35af975c5e6570d6ec31aab9a731 Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Mon, 17 Oct 2022 16:22:37 -0400 -Subject: [PATCH 02/21] net: fman: memac: Use lynx pcs driver - -Although not stated in the datasheet, as far as I can tell PCS for mEMACs -is a "Lynx." By reusing the existing driver, we can remove the PCS -management code from the memac driver. This requires calling some PCS -functions manually which phylink would usually do for us, but we will let -it do that soon. - -One problem is that we don't actually have a PCS for QSGMII. We pretend -that each mEMAC's MDIO bus has four QSGMII PCSs, but this is not the case. -Only the "base" mEMAC's MDIO bus has the four QSGMII PCSs. This is not an -issue yet, because we never get the PCS state. However, it will be once the -conversion to phylink is complete, since the links will appear to never -come up. To get around this, we allow specifying multiple PCSs in pcsphy. -This breaks backwards compatibility with old device trees, but only for -QSGMII. IMO this is the only reasonable way to figure out what the actual -QSGMII PCS is. - -Additionally, we now also support a separate XFI PCS. This can allow the -SerDes driver to set different addresses for the SGMII and XFI PCSs so they -can be accessed at the same time. - -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/freescale/fman/Kconfig | 3 + - .../net/ethernet/freescale/fman/fman_memac.c | 258 +++++++----------- - 2 files changed, 105 insertions(+), 156 deletions(-) - ---- a/drivers/net/ethernet/freescale/fman/Kconfig -+++ b/drivers/net/ethernet/freescale/fman/Kconfig -@@ -4,6 +4,9 @@ config FSL_FMAN - depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST - select GENERIC_ALLOCATOR - select PHYLIB -+ select PHYLINK -+ select PCS -+ select PCS_LYNX - select CRC32 - default n - help ---- a/drivers/net/ethernet/freescale/fman/fman_memac.c -+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c -@@ -11,43 +11,12 @@ - - #include - #include -+#include - #include - #include - #include - #include - --/* PCS registers */ --#define MDIO_SGMII_CR 0x00 --#define MDIO_SGMII_DEV_ABIL_SGMII 0x04 --#define MDIO_SGMII_LINK_TMR_L 0x12 --#define MDIO_SGMII_LINK_TMR_H 0x13 --#define MDIO_SGMII_IF_MODE 0x14 -- --/* SGMII Control defines */ --#define SGMII_CR_AN_EN 0x1000 --#define SGMII_CR_RESTART_AN 0x0200 --#define SGMII_CR_FD 0x0100 --#define SGMII_CR_SPEED_SEL1_1G 0x0040 --#define SGMII_CR_DEF_VAL (SGMII_CR_AN_EN | SGMII_CR_FD | \ -- SGMII_CR_SPEED_SEL1_1G) -- --/* SGMII Device Ability for SGMII defines */ --#define MDIO_SGMII_DEV_ABIL_SGMII_MODE 0x4001 --#define MDIO_SGMII_DEV_ABIL_BASEX_MODE 0x01A0 -- --/* Link timer define */ --#define LINK_TMR_L 0xa120 --#define LINK_TMR_H 0x0007 --#define LINK_TMR_L_BASEX 0xaf08 --#define LINK_TMR_H_BASEX 0x002f -- --/* SGMII IF Mode defines */ --#define IF_MODE_USE_SGMII_AN 0x0002 --#define IF_MODE_SGMII_EN 0x0001 --#define IF_MODE_SGMII_SPEED_100M 0x0004 --#define IF_MODE_SGMII_SPEED_1G 0x0008 --#define IF_MODE_SGMII_DUPLEX_HALF 0x0010 -- - /* Num of additional exact match MAC adr regs */ - #define MEMAC_NUM_OF_PADDRS 7 - -@@ -326,7 +295,9 @@ struct fman_mac { - struct fman_rev_info fm_rev_info; - bool basex_if; - struct phy *serdes; -- struct phy_device *pcsphy; -+ struct phylink_pcs *sgmii_pcs; -+ struct phylink_pcs *qsgmii_pcs; -+ struct phylink_pcs *xfi_pcs; - bool allmulti_enabled; - }; - -@@ -487,91 +458,22 @@ static u32 get_mac_addr_hash_code(u64 et - return xor_val; - } - --static void setup_sgmii_internal_phy(struct fman_mac *memac, -- struct fixed_phy_status *fixed_link) --{ -- u16 tmp_reg16; -- -- if (WARN_ON(!memac->pcsphy)) -- return; -- -- /* SGMII mode */ -- tmp_reg16 = IF_MODE_SGMII_EN; -- if (!fixed_link) -- /* AN enable */ -- tmp_reg16 |= IF_MODE_USE_SGMII_AN; -- else { -- switch (fixed_link->speed) { -- case 10: -- /* For 10M: IF_MODE[SPEED_10M] = 0 */ -- break; -- case 100: -- tmp_reg16 |= IF_MODE_SGMII_SPEED_100M; -- break; -- case 1000: -- default: -- tmp_reg16 |= IF_MODE_SGMII_SPEED_1G; -- break; -- } -- if (!fixed_link->duplex) -- tmp_reg16 |= IF_MODE_SGMII_DUPLEX_HALF; -- } -- phy_write(memac->pcsphy, MDIO_SGMII_IF_MODE, tmp_reg16); -- -- /* Device ability according to SGMII specification */ -- tmp_reg16 = MDIO_SGMII_DEV_ABIL_SGMII_MODE; -- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); -- -- /* Adjust link timer for SGMII - -- * According to Cisco SGMII specification the timer should be 1.6 ms. -- * The link_timer register is configured in units of the clock. -- * - When running as 1G SGMII, Serdes clock is 125 MHz, so -- * unit = 1 / (125*10^6 Hz) = 8 ns. -- * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40 -- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so -- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. -- * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120. -- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, -- * we always set up here a value of 2.5 SGMII. -- */ -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H); -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L); -- -- if (!fixed_link) -- /* Restart AN */ -- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; -+static void setup_sgmii_internal(struct fman_mac *memac, -+ struct phylink_pcs *pcs, -+ struct fixed_phy_status *fixed_link) -+{ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); -+ phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : -+ PHY_INTERFACE_MODE_SGMII; -+ unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; -+ -+ linkmode_set_pause(advertising, true, true); -+ pcs->ops->pcs_config(pcs, mode, iface, advertising, true); -+ if (fixed_link) -+ pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, -+ fixed_link->duplex); - else -- /* AN disabled */ -- tmp_reg16 = SGMII_CR_DEF_VAL & ~SGMII_CR_AN_EN; -- phy_write(memac->pcsphy, 0x0, tmp_reg16); --} -- --static void setup_sgmii_internal_phy_base_x(struct fman_mac *memac) --{ -- u16 tmp_reg16; -- -- /* AN Device capability */ -- tmp_reg16 = MDIO_SGMII_DEV_ABIL_BASEX_MODE; -- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); -- -- /* Adjust link timer for SGMII - -- * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms. -- * The link_timer register is configured in units of the clock. -- * - When running as 1G SGMII, Serdes clock is 125 MHz, so -- * unit = 1 / (125*10^6 Hz) = 8 ns. -- * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0 -- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so -- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. -- * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08. -- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, -- * we always set up here a value of 2.5 SGMII. -- */ -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H_BASEX); -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L_BASEX); -- -- /* Restart AN */ -- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; -- phy_write(memac->pcsphy, 0x0, tmp_reg16); -+ pcs->ops->pcs_an_restart(pcs); - } - - static int check_init_parameters(struct fman_mac *memac) -@@ -983,7 +885,6 @@ static int memac_set_exception(struct fm - static int memac_init(struct fman_mac *memac) - { - struct memac_cfg *memac_drv_param; -- u8 i; - enet_addr_t eth_addr; - bool slow_10g_if = false; - struct fixed_phy_status *fixed_link = NULL; -@@ -1036,32 +937,10 @@ static int memac_init(struct fman_mac *m - iowrite32be(reg32, &memac->regs->command_config); - } - -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) { -- /* Configure internal SGMII PHY */ -- if (memac->basex_if) -- setup_sgmii_internal_phy_base_x(memac); -- else -- setup_sgmii_internal_phy(memac, fixed_link); -- } else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { -- /* Configure 4 internal SGMII PHYs */ -- for (i = 0; i < 4; i++) { -- u8 qsmgii_phy_addr, phy_addr; -- /* QSGMII PHY address occupies 3 upper bits of 5-bit -- * phy_address; the lower 2 bits are used to extend -- * register address space and access each one of 4 -- * ports inside QSGMII. -- */ -- phy_addr = memac->pcsphy->mdio.addr; -- qsmgii_phy_addr = (u8)((phy_addr << 2) | i); -- memac->pcsphy->mdio.addr = qsmgii_phy_addr; -- if (memac->basex_if) -- setup_sgmii_internal_phy_base_x(memac); -- else -- setup_sgmii_internal_phy(memac, fixed_link); -- -- memac->pcsphy->mdio.addr = phy_addr; -- } -- } -+ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) -+ setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); -+ else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) -+ setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); - - /* Max Frame Length */ - err = fman_set_mac_max_frame(memac->fm, memac->mac_id, -@@ -1097,12 +976,25 @@ static int memac_init(struct fman_mac *m - return 0; - } - -+static void pcs_put(struct phylink_pcs *pcs) -+{ -+ struct mdio_device *mdiodev; -+ -+ if (IS_ERR_OR_NULL(pcs)) -+ return; -+ -+ mdiodev = lynx_get_mdio_device(pcs); -+ lynx_pcs_destroy(pcs); -+ mdio_device_free(mdiodev); -+} -+ - static int memac_free(struct fman_mac *memac) - { - free_init_resources(memac); - -- if (memac->pcsphy) -- put_device(&memac->pcsphy->mdio.dev); -+ pcs_put(memac->sgmii_pcs); -+ pcs_put(memac->qsgmii_pcs); -+ pcs_put(memac->xfi_pcs); - - kfree(memac->memac_drv_param); - kfree(memac); -@@ -1153,12 +1045,31 @@ static struct fman_mac *memac_config(str - return memac; - } - -+static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node, -+ int index) -+{ -+ struct device_node *node; -+ struct mdio_device *mdiodev = NULL; -+ struct phylink_pcs *pcs; -+ -+ node = of_parse_phandle(mac_node, "pcsphy-handle", index); -+ if (node && of_device_is_available(node)) -+ mdiodev = of_mdio_find_device(node); -+ of_node_put(node); -+ -+ if (!mdiodev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ pcs = lynx_pcs_create(mdiodev); -+ return pcs; -+} -+ - int memac_initialization(struct mac_device *mac_dev, - struct device_node *mac_node, - struct fman_mac_params *params) - { - int err; -- struct device_node *phy_node; -+ struct phylink_pcs *pcs; - struct fixed_phy_status *fixed_link; - struct fman_mac *memac; - -@@ -1188,23 +1099,58 @@ int memac_initialization(struct mac_devi - memac = mac_dev->fman_mac; - memac->memac_drv_param->max_frame_length = fman_get_max_frm(); - memac->memac_drv_param->reset_on_init = true; -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || -- memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { -- phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0); -- if (!phy_node) { -- pr_err("PCS PHY node is not available\n"); -- err = -EINVAL; -+ -+ err = of_property_match_string(mac_node, "pcs-handle-names", "xfi"); -+ if (err >= 0) { -+ memac->xfi_pcs = memac_pcs_create(mac_node, err); -+ if (IS_ERR(memac->xfi_pcs)) { -+ err = PTR_ERR(memac->xfi_pcs); -+ dev_err_probe(mac_dev->dev, err, "missing xfi pcs\n"); - goto _return_fm_mac_free; - } -+ } else if (err != -EINVAL && err != -ENODATA) { -+ goto _return_fm_mac_free; -+ } - -- memac->pcsphy = of_phy_find_device(phy_node); -- if (!memac->pcsphy) { -- pr_err("of_phy_find_device (PCS PHY) failed\n"); -- err = -EINVAL; -+ err = of_property_match_string(mac_node, "pcs-handle-names", "qsgmii"); -+ if (err >= 0) { -+ memac->qsgmii_pcs = memac_pcs_create(mac_node, err); -+ if (IS_ERR(memac->qsgmii_pcs)) { -+ err = PTR_ERR(memac->qsgmii_pcs); -+ dev_err_probe(mac_dev->dev, err, -+ "missing qsgmii pcs\n"); - goto _return_fm_mac_free; - } -+ } else if (err != -EINVAL && err != -ENODATA) { -+ goto _return_fm_mac_free; -+ } -+ -+ /* For compatibility, if pcs-handle-names is missing, we assume this -+ * phy is the first one in pcsphy-handle -+ */ -+ err = of_property_match_string(mac_node, "pcs-handle-names", "sgmii"); -+ if (err == -EINVAL || err == -ENODATA) -+ pcs = memac_pcs_create(mac_node, 0); -+ else if (err < 0) -+ goto _return_fm_mac_free; -+ else -+ pcs = memac_pcs_create(mac_node, err); -+ -+ if (!pcs) { -+ dev_err(mac_dev->dev, "missing pcs\n"); -+ err = -ENOENT; -+ goto _return_fm_mac_free; - } - -+ /* If err is set here, it means that pcs-handle-names was missing above -+ * (and therefore that xfi_pcs cannot be set). If we are defaulting to -+ * XGMII, assume this is for XFI. Otherwise, assume it is for SGMII. -+ */ -+ if (err && mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -+ memac->xfi_pcs = pcs; -+ else -+ memac->sgmii_pcs = pcs; -+ - memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); - err = PTR_ERR(memac->serdes); - if (err == -ENODEV || err == -ENOSYS) { diff --git a/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch b/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch deleted file mode 100644 index 63b651bb2d..0000000000 --- a/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch +++ /dev/null @@ -1,2451 +0,0 @@ -From 38e50fc3d43882a43115b4f1ca3eb88255163c5b Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Mon, 17 Oct 2022 16:22:38 -0400 -Subject: [PATCH 03/21] net: dpaa: Convert to phylink - -This converts DPAA to phylink. All macs are converted. This should work -with no device tree modifications (including those made in this series), -except for QSGMII (as noted previously). - -The mEMAC configuration is one of the tricker areas. I have tried to -capture all the restrictions across the various models. Most of the time, -we assume that if the serdes supports a mode or the phy-interface-mode -specifies it, then we support it. The only place we can't do this is -(RG)MII, since there's no serdes. In that case, we rely on a (new) -devicetree property. There are also several cases where half-duplex is -broken. Unfortunately, only a single compatible is used for the MAC, so we -have to use the board compatible instead. - -The 10GEC conversion is very straightforward, since it only supports XAUI. -There is generally nothing to configure. - -The dTSEC conversion is broadly similar to mEMAC, but is simpler because we -don't support configuring the SerDes (though this can be easily added) and -we don't have multiple PCSs. From what I can tell, there's nothing -different in the driver or documentation between SGMII and 1000BASE-X -except for the advertising. Similarly, I couldn't find anything about -2500BASE-X. In both cases, I treat them like SGMII. These modes aren't used -by any in-tree boards. Similarly, despite being mentioned in the driver, I -couldn't find any documented SoCs which supported QSGMII. I have left it -unimplemented for now. - -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/freescale/dpaa/Kconfig | 4 +- - .../net/ethernet/freescale/dpaa/dpaa_eth.c | 89 +-- - .../ethernet/freescale/dpaa/dpaa_ethtool.c | 90 +-- - drivers/net/ethernet/freescale/fman/Kconfig | 1 - - .../net/ethernet/freescale/fman/fman_dtsec.c | 458 +++++++-------- - .../net/ethernet/freescale/fman/fman_mac.h | 10 - - .../net/ethernet/freescale/fman/fman_memac.c | 547 +++++++++--------- - .../net/ethernet/freescale/fman/fman_tgec.c | 131 ++--- - drivers/net/ethernet/freescale/fman/mac.c | 168 +----- - drivers/net/ethernet/freescale/fman/mac.h | 23 +- - 10 files changed, 612 insertions(+), 909 deletions(-) - ---- a/drivers/net/ethernet/freescale/dpaa/Kconfig -+++ b/drivers/net/ethernet/freescale/dpaa/Kconfig -@@ -2,8 +2,8 @@ - menuconfig FSL_DPAA_ETH - tristate "DPAA Ethernet" - depends on FSL_DPAA && FSL_FMAN -- select PHYLIB -- select FIXED_PHY -+ select PHYLINK -+ select PCS_LYNX - help - Data Path Acceleration Architecture Ethernet driver, - supporting the Freescale QorIQ chips. ---- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c -+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c -@@ -264,8 +264,19 @@ static int dpaa_netdev_init(struct net_d - net_dev->needed_headroom = priv->tx_headroom; - net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout); - -- mac_dev->net_dev = net_dev; -+ /* The rest of the config is filled in by the mac device already */ -+ mac_dev->phylink_config.dev = &net_dev->dev; -+ mac_dev->phylink_config.type = PHYLINK_NETDEV; - mac_dev->update_speed = dpaa_eth_cgr_set_speed; -+ mac_dev->phylink = phylink_create(&mac_dev->phylink_config, -+ dev_fwnode(mac_dev->dev), -+ mac_dev->phy_if, -+ mac_dev->phylink_ops); -+ if (IS_ERR(mac_dev->phylink)) { -+ err = PTR_ERR(mac_dev->phylink); -+ dev_err_probe(dev, err, "Could not create phylink\n"); -+ return err; -+ } - - /* start without the RUNNING flag, phylib controls it later */ - netif_carrier_off(net_dev); -@@ -273,6 +284,7 @@ static int dpaa_netdev_init(struct net_d - err = register_netdev(net_dev); - if (err < 0) { - dev_err(dev, "register_netdev() = %d\n", err); -+ phylink_destroy(mac_dev->phylink); - return err; - } - -@@ -295,8 +307,7 @@ static int dpaa_stop(struct net_device * - */ - msleep(200); - -- if (mac_dev->phy_dev) -- phy_stop(mac_dev->phy_dev); -+ phylink_stop(mac_dev->phylink); - mac_dev->disable(mac_dev->fman_mac); - - for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) { -@@ -305,8 +316,7 @@ static int dpaa_stop(struct net_device * - err = error; - } - -- if (net_dev->phydev) -- phy_disconnect(net_dev->phydev); -+ phylink_disconnect_phy(mac_dev->phylink); - net_dev->phydev = NULL; - - msleep(200); -@@ -834,10 +844,10 @@ static int dpaa_eth_cgr_init(struct dpaa - - /* Set different thresholds based on the configured MAC speed. - * This may turn suboptimal if the MAC is reconfigured at another -- * speed, so MACs must call dpaa_eth_cgr_set_speed in their adjust_link -+ * speed, so MACs must call dpaa_eth_cgr_set_speed in their link_up - * callback. - */ -- if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full) -+ if (priv->mac_dev->phylink_config.mac_capabilities & MAC_10000FD) - cs_th = DPAA_CS_THRESHOLD_10G; - else - cs_th = DPAA_CS_THRESHOLD_1G; -@@ -866,7 +876,7 @@ out_error: - - static void dpaa_eth_cgr_set_speed(struct mac_device *mac_dev, int speed) - { -- struct net_device *net_dev = mac_dev->net_dev; -+ struct net_device *net_dev = to_net_dev(mac_dev->phylink_config.dev); - struct dpaa_priv *priv = netdev_priv(net_dev); - struct qm_mcc_initcgr opts = { }; - u32 cs_th; -@@ -2905,58 +2915,6 @@ static void dpaa_eth_napi_disable(struct - } - } - --static void dpaa_adjust_link(struct net_device *net_dev) --{ -- struct mac_device *mac_dev; -- struct dpaa_priv *priv; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- mac_dev->adjust_link(mac_dev); --} -- --/* The Aquantia PHYs are capable of performing rate adaptation */ --#define PHY_VEND_AQUANTIA 0x03a1b400 --#define PHY_VEND_AQUANTIA2 0x31c31c00 -- --static int dpaa_phy_init(struct net_device *net_dev) --{ -- __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; -- struct mac_device *mac_dev; -- struct phy_device *phy_dev; -- struct dpaa_priv *priv; -- u32 phy_vendor; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- -- phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, -- &dpaa_adjust_link, 0, -- mac_dev->phy_if); -- if (!phy_dev) { -- netif_err(priv, ifup, net_dev, "init_phy() failed\n"); -- return -ENODEV; -- } -- -- phy_vendor = phy_dev->drv->phy_id & GENMASK(31, 10); -- /* Unless the PHY is capable of rate adaptation */ -- if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII || -- (phy_vendor != PHY_VEND_AQUANTIA && -- phy_vendor != PHY_VEND_AQUANTIA2)) { -- /* remove any features not supported by the controller */ -- ethtool_convert_legacy_u32_to_link_mode(mask, -- mac_dev->if_support); -- linkmode_and(phy_dev->supported, phy_dev->supported, mask); -- } -- -- phy_support_asym_pause(phy_dev); -- -- mac_dev->phy_dev = phy_dev; -- net_dev->phydev = phy_dev; -- -- return 0; --} -- - static int dpaa_open(struct net_device *net_dev) - { - struct mac_device *mac_dev; -@@ -2967,7 +2925,8 @@ static int dpaa_open(struct net_device * - mac_dev = priv->mac_dev; - dpaa_eth_napi_enable(priv); - -- err = dpaa_phy_init(net_dev); -+ err = phylink_of_phy_connect(mac_dev->phylink, -+ mac_dev->dev->of_node, 0); - if (err) - goto phy_init_failed; - -@@ -2982,7 +2941,7 @@ static int dpaa_open(struct net_device * - netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err); - goto mac_start_failed; - } -- phy_start(priv->mac_dev->phy_dev); -+ phylink_start(mac_dev->phylink); - - netif_tx_start_all_queues(net_dev); - -@@ -2991,6 +2950,7 @@ static int dpaa_open(struct net_device * - mac_start_failed: - for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) - fman_port_disable(mac_dev->port[i]); -+ phylink_disconnect_phy(mac_dev->phylink); - - phy_init_failed: - dpaa_eth_napi_disable(priv); -@@ -3146,10 +3106,12 @@ static int dpaa_ts_ioctl(struct net_devi - static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd) - { - int ret = -EINVAL; -+ struct dpaa_priv *priv = netdev_priv(net_dev); - - if (cmd == SIOCGMIIREG) { - if (net_dev->phydev) -- return phy_mii_ioctl(net_dev->phydev, rq, cmd); -+ return phylink_mii_ioctl(priv->mac_dev->phylink, rq, -+ cmd); - } - - if (cmd == SIOCSHWTSTAMP) -@@ -3552,6 +3514,7 @@ static int dpaa_remove(struct platform_d - - dev_set_drvdata(dev, NULL); - unregister_netdev(net_dev); -+ phylink_destroy(priv->mac_dev->phylink); - - err = dpaa_fq_free(dev, &priv->dpaa_fq_list); - ---- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c -+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c -@@ -54,27 +54,19 @@ static char dpaa_stats_global[][ETH_GSTR - static int dpaa_get_link_ksettings(struct net_device *net_dev, - struct ethtool_link_ksettings *cmd) - { -- if (!net_dev->phydev) -- return 0; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- phy_ethtool_ksettings_get(net_dev->phydev, cmd); -- -- return 0; -+ return phylink_ethtool_ksettings_get(mac_dev->phylink, cmd); - } - - static int dpaa_set_link_ksettings(struct net_device *net_dev, - const struct ethtool_link_ksettings *cmd) - { -- int err; -- -- if (!net_dev->phydev) -- return -ENODEV; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- err = phy_ethtool_ksettings_set(net_dev->phydev, cmd); -- if (err < 0) -- netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err); -- -- return err; -+ return phylink_ethtool_ksettings_set(mac_dev->phylink, cmd); - } - - static void dpaa_get_drvinfo(struct net_device *net_dev, -@@ -99,80 +91,28 @@ static void dpaa_set_msglevel(struct net - - static int dpaa_nway_reset(struct net_device *net_dev) - { -- int err; -- -- if (!net_dev->phydev) -- return -ENODEV; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- err = 0; -- if (net_dev->phydev->autoneg) { -- err = phy_start_aneg(net_dev->phydev); -- if (err < 0) -- netdev_err(net_dev, "phy_start_aneg() = %d\n", -- err); -- } -- -- return err; -+ return phylink_ethtool_nway_reset(mac_dev->phylink); - } - - static void dpaa_get_pauseparam(struct net_device *net_dev, - struct ethtool_pauseparam *epause) - { -- struct mac_device *mac_dev; -- struct dpaa_priv *priv; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- -- if (!net_dev->phydev) -- return; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- epause->autoneg = mac_dev->autoneg_pause; -- epause->rx_pause = mac_dev->rx_pause_active; -- epause->tx_pause = mac_dev->tx_pause_active; -+ phylink_ethtool_get_pauseparam(mac_dev->phylink, epause); - } - - static int dpaa_set_pauseparam(struct net_device *net_dev, - struct ethtool_pauseparam *epause) - { -- struct mac_device *mac_dev; -- struct phy_device *phydev; -- bool rx_pause, tx_pause; -- struct dpaa_priv *priv; -- int err; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- -- phydev = net_dev->phydev; -- if (!phydev) { -- netdev_err(net_dev, "phy device not initialized\n"); -- return -ENODEV; -- } -- -- if (!phy_validate_pause(phydev, epause)) -- return -EINVAL; -- -- /* The MAC should know how to handle PAUSE frame autonegotiation before -- * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE -- * settings. -- */ -- mac_dev->autoneg_pause = !!epause->autoneg; -- mac_dev->rx_pause_req = !!epause->rx_pause; -- mac_dev->tx_pause_req = !!epause->tx_pause; -- -- /* Determine the sym/asym advertised PAUSE capabilities from the desired -- * rx/tx pause settings. -- */ -- -- phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause); -- -- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); -- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); -- if (err < 0) -- netdev_err(net_dev, "set_mac_active_pause() = %d\n", err); -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- return err; -+ return phylink_ethtool_set_pauseparam(mac_dev->phylink, epause); - } - - static int dpaa_get_sset_count(struct net_device *net_dev, int type) ---- a/drivers/net/ethernet/freescale/fman/Kconfig -+++ b/drivers/net/ethernet/freescale/fman/Kconfig -@@ -3,7 +3,6 @@ config FSL_FMAN - tristate "FMan support" - depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST - select GENERIC_ALLOCATOR -- select PHYLIB - select PHYLINK - select PCS - select PCS_LYNX ---- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - /* TBI register addresses */ - #define MII_TBICON 0x11 -@@ -29,9 +30,6 @@ - #define TBICON_CLK_SELECT 0x0020 /* Clock select */ - #define TBICON_MI_MODE 0x0010 /* GMII mode (TBI if not set) */ - --#define TBIANA_SGMII 0x4001 --#define TBIANA_1000X 0x01a0 -- - /* Interrupt Mask Register (IMASK) */ - #define DTSEC_IMASK_BREN 0x80000000 - #define DTSEC_IMASK_RXCEN 0x40000000 -@@ -92,9 +90,10 @@ - - #define DTSEC_ECNTRL_GMIIM 0x00000040 - #define DTSEC_ECNTRL_TBIM 0x00000020 --#define DTSEC_ECNTRL_SGMIIM 0x00000002 - #define DTSEC_ECNTRL_RPM 0x00000010 - #define DTSEC_ECNTRL_R100M 0x00000008 -+#define DTSEC_ECNTRL_RMM 0x00000004 -+#define DTSEC_ECNTRL_SGMIIM 0x00000002 - #define DTSEC_ECNTRL_QSGMIIM 0x00000001 - - #define TCTRL_TTSE 0x00000040 -@@ -318,7 +317,8 @@ struct fman_mac { - void *fm; - struct fman_rev_info fm_rev_info; - bool basex_if; -- struct phy_device *tbiphy; -+ struct mdio_device *tbidev; -+ struct phylink_pcs pcs; - }; - - static void set_dflts(struct dtsec_cfg *cfg) -@@ -356,56 +356,14 @@ static int init(struct dtsec_regs __iome - phy_interface_t iface, u16 iface_speed, u64 addr, - u32 exception_mask, u8 tbi_addr) - { -- bool is_rgmii, is_sgmii, is_qsgmii; - enet_addr_t eth_addr; -- u32 tmp; -+ u32 tmp = 0; - int i; - - /* Soft reset */ - iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); - iowrite32be(0, ®s->maccfg1); - -- /* dtsec_id2 */ -- tmp = ioread32be(®s->tsec_id2); -- -- /* check RGMII support */ -- if (iface == PHY_INTERFACE_MODE_RGMII || -- iface == PHY_INTERFACE_MODE_RGMII_ID || -- iface == PHY_INTERFACE_MODE_RGMII_RXID || -- iface == PHY_INTERFACE_MODE_RGMII_TXID || -- iface == PHY_INTERFACE_MODE_RMII) -- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) -- return -EINVAL; -- -- if (iface == PHY_INTERFACE_MODE_SGMII || -- iface == PHY_INTERFACE_MODE_MII) -- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) -- return -EINVAL; -- -- is_rgmii = iface == PHY_INTERFACE_MODE_RGMII || -- iface == PHY_INTERFACE_MODE_RGMII_ID || -- iface == PHY_INTERFACE_MODE_RGMII_RXID || -- iface == PHY_INTERFACE_MODE_RGMII_TXID; -- is_sgmii = iface == PHY_INTERFACE_MODE_SGMII; -- is_qsgmii = iface == PHY_INTERFACE_MODE_QSGMII; -- -- tmp = 0; -- if (is_rgmii || iface == PHY_INTERFACE_MODE_GMII) -- tmp |= DTSEC_ECNTRL_GMIIM; -- if (is_sgmii) -- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); -- if (is_qsgmii) -- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | -- DTSEC_ECNTRL_QSGMIIM); -- if (is_rgmii) -- tmp |= DTSEC_ECNTRL_RPM; -- if (iface_speed == SPEED_100) -- tmp |= DTSEC_ECNTRL_R100M; -- -- iowrite32be(tmp, ®s->ecntrl); -- -- tmp = 0; -- - if (cfg->tx_pause_time) - tmp |= cfg->tx_pause_time; - if (cfg->tx_pause_time_extd) -@@ -446,17 +404,10 @@ static int init(struct dtsec_regs __iome - - tmp = 0; - -- if (iface_speed < SPEED_1000) -- tmp |= MACCFG2_NIBBLE_MODE; -- else if (iface_speed == SPEED_1000) -- tmp |= MACCFG2_BYTE_MODE; -- - tmp |= (cfg->preamble_len << MACCFG2_PREAMBLE_LENGTH_SHIFT) & - MACCFG2_PREAMBLE_LENGTH_MASK; - if (cfg->tx_pad_crc) - tmp |= MACCFG2_PAD_CRC_EN; -- /* Full Duplex */ -- tmp |= MACCFG2_FULL_DUPLEX; - iowrite32be(tmp, ®s->maccfg2); - - tmp = (((cfg->non_back_to_back_ipg1 << -@@ -525,10 +476,6 @@ static void set_bucket(struct dtsec_regs - - static int check_init_parameters(struct fman_mac *dtsec) - { -- if (dtsec->max_speed >= SPEED_10000) { -- pr_err("1G MAC driver supports 1G or lower speeds\n"); -- return -EINVAL; -- } - if ((dtsec->dtsec_drv_param)->rx_prepend > - MAX_PACKET_ALIGNMENT) { - pr_err("packetAlignmentPadding can't be > than %d\n", -@@ -630,22 +577,10 @@ static int get_exception_flag(enum fman_ - return bit_mask; - } - --static bool is_init_done(struct dtsec_cfg *dtsec_drv_params) --{ -- /* Checks if dTSEC driver parameters were initialized */ -- if (!dtsec_drv_params) -- return true; -- -- return false; --} -- - static u16 dtsec_get_max_frame_length(struct fman_mac *dtsec) - { - struct dtsec_regs __iomem *regs = dtsec->regs; - -- if (is_init_done(dtsec->dtsec_drv_param)) -- return 0; -- - return (u16)ioread32be(®s->maxfrm); - } - -@@ -682,6 +617,7 @@ static void dtsec_isr(void *handle) - dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_COL_RET_LMT); - if (event & DTSEC_IMASK_XFUNEN) { - /* FM_TX_LOCKUP_ERRATA_DTSEC6 Errata workaround */ -+ /* FIXME: This races with the rest of the driver! */ - if (dtsec->fm_rev_info.major == 2) { - u32 tpkt1, tmp_reg1, tpkt2, tmp_reg2, i; - /* a. Write 0x00E0_0C00 to DTSEC_ID -@@ -814,6 +750,43 @@ static void free_init_resources(struct f - dtsec->unicast_addr_hash = NULL; - } - -+static struct fman_mac *pcs_to_dtsec(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct fman_mac, pcs); -+} -+ -+static void dtsec_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct fman_mac *dtsec = pcs_to_dtsec(pcs); -+ -+ phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); -+} -+ -+static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct fman_mac *dtsec = pcs_to_dtsec(pcs); -+ -+ return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, -+ advertising); -+} -+ -+static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ struct fman_mac *dtsec = pcs_to_dtsec(pcs); -+ -+ phylink_mii_c22_pcs_an_restart(dtsec->tbidev); -+} -+ -+static const struct phylink_pcs_ops dtsec_pcs_ops = { -+ .pcs_get_state = dtsec_pcs_get_state, -+ .pcs_config = dtsec_pcs_config, -+ .pcs_an_restart = dtsec_pcs_an_restart, -+}; -+ - static void graceful_start(struct fman_mac *dtsec) - { - struct dtsec_regs __iomem *regs = dtsec->regs; -@@ -854,36 +827,11 @@ static void graceful_stop(struct fman_ma - - static int dtsec_enable(struct fman_mac *dtsec) - { -- struct dtsec_regs __iomem *regs = dtsec->regs; -- u32 tmp; -- -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- /* Enable */ -- tmp = ioread32be(®s->maccfg1); -- tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; -- iowrite32be(tmp, ®s->maccfg1); -- -- /* Graceful start - clear the graceful Rx/Tx stop bit */ -- graceful_start(dtsec); -- - return 0; - } - - static void dtsec_disable(struct fman_mac *dtsec) - { -- struct dtsec_regs __iomem *regs = dtsec->regs; -- u32 tmp; -- -- WARN_ON_ONCE(!is_init_done(dtsec->dtsec_drv_param)); -- -- /* Graceful stop - Assert the graceful Rx/Tx stop bit */ -- graceful_stop(dtsec); -- -- tmp = ioread32be(®s->maccfg1); -- tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); -- iowrite32be(tmp, ®s->maccfg1); - } - - static int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, -@@ -894,11 +842,6 @@ static int dtsec_set_tx_pause_frames(str - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 ptv = 0; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- graceful_stop(dtsec); -- - if (pause_time) { - /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ - if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) { -@@ -919,8 +862,6 @@ static int dtsec_set_tx_pause_frames(str - iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, - ®s->maccfg1); - -- graceful_start(dtsec); -- - return 0; - } - -@@ -929,11 +870,6 @@ static int dtsec_accept_rx_pause_frames( - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 tmp; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- graceful_stop(dtsec); -- - tmp = ioread32be(®s->maccfg1); - if (en) - tmp |= MACCFG1_RX_FLOW; -@@ -941,17 +877,125 @@ static int dtsec_accept_rx_pause_frames( - tmp &= ~MACCFG1_RX_FLOW; - iowrite32be(tmp, ®s->maccfg1); - -+ return 0; -+} -+ -+static struct phylink_pcs *dtsec_select_pcs(struct phylink_config *config, -+ phy_interface_t iface) -+{ -+ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; -+ -+ switch (iface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return &dtsec->pcs; -+ default: -+ return NULL; -+ } -+} -+ -+static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mac_device *mac_dev = fman_config_to_mac(config); -+ struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; -+ u32 tmp; -+ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_RMII: -+ tmp = DTSEC_ECNTRL_RMM; -+ break; -+ case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; -+ break; -+ default: -+ dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", -+ phy_modes(state->interface)); -+ return; -+ } -+ -+ iowrite32be(tmp, ®s->ecntrl); -+} -+ -+static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct mac_device *mac_dev = fman_config_to_mac(config); -+ struct fman_mac *dtsec = mac_dev->fman_mac; -+ struct dtsec_regs __iomem *regs = dtsec->regs; -+ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : -+ FSL_FM_PAUSE_TIME_DISABLE; -+ u32 tmp; -+ -+ dtsec_set_tx_pause_frames(dtsec, 0, pause_time, 0); -+ dtsec_accept_rx_pause_frames(dtsec, rx_pause); -+ -+ tmp = ioread32be(®s->ecntrl); -+ if (speed == SPEED_100) -+ tmp |= DTSEC_ECNTRL_R100M; -+ else -+ tmp &= ~DTSEC_ECNTRL_R100M; -+ iowrite32be(tmp, ®s->ecntrl); -+ -+ tmp = ioread32be(®s->maccfg2); -+ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE | MACCFG2_FULL_DUPLEX); -+ if (speed >= SPEED_1000) -+ tmp |= MACCFG2_BYTE_MODE; -+ else -+ tmp |= MACCFG2_NIBBLE_MODE; -+ -+ if (duplex == DUPLEX_FULL) -+ tmp |= MACCFG2_FULL_DUPLEX; -+ -+ iowrite32be(tmp, ®s->maccfg2); -+ -+ mac_dev->update_speed(mac_dev, speed); -+ -+ /* Enable */ -+ tmp = ioread32be(®s->maccfg1); -+ tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; -+ iowrite32be(tmp, ®s->maccfg1); -+ -+ /* Graceful start - clear the graceful Rx/Tx stop bit */ - graceful_start(dtsec); -+} - -- return 0; -+static void dtsec_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; -+ struct dtsec_regs __iomem *regs = dtsec->regs; -+ u32 tmp; -+ -+ /* Graceful stop - Assert the graceful Rx/Tx stop bit */ -+ graceful_stop(dtsec); -+ -+ tmp = ioread32be(®s->maccfg1); -+ tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); -+ iowrite32be(tmp, ®s->maccfg1); - } - -+static const struct phylink_mac_ops dtsec_mac_ops = { -+ .validate = phylink_generic_validate, -+ .mac_select_pcs = dtsec_select_pcs, -+ .mac_config = dtsec_mac_config, -+ .mac_link_up = dtsec_link_up, -+ .mac_link_down = dtsec_link_down, -+}; -+ - static int dtsec_modify_mac_address(struct fman_mac *dtsec, - const enet_addr_t *enet_addr) - { -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - graceful_stop(dtsec); - - /* Initialize MAC Station Address registers (1 & 2) -@@ -975,9 +1019,6 @@ static int dtsec_add_hash_mac_address(st - u32 crc = 0xFFFFFFFF; - bool mcast, ghtx; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); -@@ -1037,9 +1078,6 @@ static int dtsec_set_allmulti(struct fma - u32 tmp; - struct dtsec_regs __iomem *regs = dtsec->regs; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->rctrl); - if (enable) - tmp |= RCTRL_MPROM; -@@ -1056,9 +1094,6 @@ static int dtsec_set_tstamp(struct fman_ - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 rctrl, tctrl; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - rctrl = ioread32be(®s->rctrl); - tctrl = ioread32be(®s->tctrl); - -@@ -1087,9 +1122,6 @@ static int dtsec_del_hash_mac_address(st - u32 crc = 0xFFFFFFFF; - bool mcast, ghtx; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); -@@ -1153,9 +1185,6 @@ static int dtsec_set_promiscuous(struct - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 tmp; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - /* Set unicast promiscuous */ - tmp = ioread32be(®s->rctrl); - if (new_val) -@@ -1177,90 +1206,12 @@ static int dtsec_set_promiscuous(struct - return 0; - } - --static int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed) --{ -- struct dtsec_regs __iomem *regs = dtsec->regs; -- u32 tmp; -- -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- graceful_stop(dtsec); -- -- tmp = ioread32be(®s->maccfg2); -- -- /* Full Duplex */ -- tmp |= MACCFG2_FULL_DUPLEX; -- -- tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); -- if (speed < SPEED_1000) -- tmp |= MACCFG2_NIBBLE_MODE; -- else if (speed == SPEED_1000) -- tmp |= MACCFG2_BYTE_MODE; -- iowrite32be(tmp, ®s->maccfg2); -- -- tmp = ioread32be(®s->ecntrl); -- if (speed == SPEED_100) -- tmp |= DTSEC_ECNTRL_R100M; -- else -- tmp &= ~DTSEC_ECNTRL_R100M; -- iowrite32be(tmp, ®s->ecntrl); -- -- graceful_start(dtsec); -- -- return 0; --} -- --static int dtsec_restart_autoneg(struct fman_mac *dtsec) --{ -- u16 tmp_reg16; -- -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- tmp_reg16 = phy_read(dtsec->tbiphy, MII_BMCR); -- -- tmp_reg16 &= ~(BMCR_SPEED100 | BMCR_SPEED1000); -- tmp_reg16 |= (BMCR_ANENABLE | BMCR_ANRESTART | -- BMCR_FULLDPLX | BMCR_SPEED1000); -- -- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); -- -- return 0; --} -- --static void adjust_link_dtsec(struct mac_device *mac_dev) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- struct fman_mac *fman_mac; -- bool rx_pause, tx_pause; -- int err; -- -- fman_mac = mac_dev->fman_mac; -- if (!phy_dev->link) { -- dtsec_restart_autoneg(fman_mac); -- -- return; -- } -- -- dtsec_adjust_link(fman_mac, phy_dev->speed); -- mac_dev->update_speed(mac_dev, phy_dev->speed); -- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); -- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); -- if (err < 0) -- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", -- err); --} -- - static int dtsec_set_exception(struct fman_mac *dtsec, - enum fman_mac_exceptions exception, bool enable) - { - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 bit_mask = 0; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) { - bit_mask = get_exception_flag(exception); - if (bit_mask) { -@@ -1310,12 +1261,9 @@ static int dtsec_init(struct fman_mac *d - { - struct dtsec_regs __iomem *regs = dtsec->regs; - struct dtsec_cfg *dtsec_drv_param; -- u16 max_frm_ln; -+ u16 max_frm_ln, tbicon; - int err; - -- if (is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - if (DEFAULT_RESET_ON_INIT && - (fman_reset_mac(dtsec->fm, dtsec->mac_id) != 0)) { - pr_err("Can't reset MAC!\n"); -@@ -1330,38 +1278,19 @@ static int dtsec_init(struct fman_mac *d - - err = init(dtsec->regs, dtsec_drv_param, dtsec->phy_if, - dtsec->max_speed, dtsec->addr, dtsec->exceptions, -- dtsec->tbiphy->mdio.addr); -+ dtsec->tbidev->addr); - if (err) { - free_init_resources(dtsec); - pr_err("DTSEC version doesn't support this i/f mode\n"); - return err; - } - -- if (dtsec->phy_if == PHY_INTERFACE_MODE_SGMII) { -- u16 tmp_reg16; -- -- /* Configure the TBI PHY Control Register */ -- tmp_reg16 = TBICON_CLK_SELECT | TBICON_SOFT_RESET; -- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); -- -- tmp_reg16 = TBICON_CLK_SELECT; -- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); -- -- tmp_reg16 = (BMCR_RESET | BMCR_ANENABLE | -- BMCR_FULLDPLX | BMCR_SPEED1000); -- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); -- -- if (dtsec->basex_if) -- tmp_reg16 = TBIANA_1000X; -- else -- tmp_reg16 = TBIANA_SGMII; -- phy_write(dtsec->tbiphy, MII_ADVERTISE, tmp_reg16); -+ /* Configure the TBI PHY Control Register */ -+ tbicon = TBICON_CLK_SELECT | TBICON_SOFT_RESET; -+ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); - -- tmp_reg16 = (BMCR_ANENABLE | BMCR_ANRESTART | -- BMCR_FULLDPLX | BMCR_SPEED1000); -- -- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); -- } -+ tbicon = TBICON_CLK_SELECT; -+ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); - - /* Max Frame Length */ - max_frm_ln = (u16)ioread32be(®s->maxfrm); -@@ -1406,6 +1335,8 @@ static int dtsec_free(struct fman_mac *d - - kfree(dtsec->dtsec_drv_param); - dtsec->dtsec_drv_param = NULL; -+ if (!IS_ERR_OR_NULL(dtsec->tbidev)) -+ put_device(&dtsec->tbidev->dev); - kfree(dtsec); - - return 0; -@@ -1434,7 +1365,6 @@ static struct fman_mac *dtsec_config(str - - dtsec->regs = mac_dev->vaddr; - dtsec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); -- dtsec->max_speed = params->max_speed; - dtsec->phy_if = mac_dev->phy_if; - dtsec->mac_id = params->mac_id; - dtsec->exceptions = (DTSEC_IMASK_BREN | -@@ -1457,7 +1387,6 @@ static struct fman_mac *dtsec_config(str - dtsec->en_tsu_err_exception = dtsec->dtsec_drv_param->ptp_exception_en; - - dtsec->fm = params->fm; -- dtsec->basex_if = params->basex_if; - - /* Save FMan revision */ - fman_get_revision(dtsec->fm, &dtsec->fm_rev_info); -@@ -1476,18 +1405,18 @@ int dtsec_initialization(struct mac_devi - int err; - struct fman_mac *dtsec; - struct device_node *phy_node; -+ unsigned long capabilities; -+ unsigned long *supported; - -+ mac_dev->phylink_ops = &dtsec_mac_ops; - mac_dev->set_promisc = dtsec_set_promiscuous; - mac_dev->change_addr = dtsec_modify_mac_address; - mac_dev->add_hash_mac_addr = dtsec_add_hash_mac_address; - mac_dev->remove_hash_mac_addr = dtsec_del_hash_mac_address; -- mac_dev->set_tx_pause = dtsec_set_tx_pause_frames; -- mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames; - mac_dev->set_exception = dtsec_set_exception; - mac_dev->set_allmulti = dtsec_set_allmulti; - mac_dev->set_tstamp = dtsec_set_tstamp; - mac_dev->set_multi = fman_set_multi; -- mac_dev->adjust_link = adjust_link_dtsec; - mac_dev->enable = dtsec_enable; - mac_dev->disable = dtsec_disable; - -@@ -1502,19 +1431,56 @@ int dtsec_initialization(struct mac_devi - dtsec->dtsec_drv_param->tx_pad_crc = true; - - phy_node = of_parse_phandle(mac_node, "tbi-handle", 0); -- if (!phy_node) { -- pr_err("TBI PHY node is not available\n"); -+ if (!phy_node || of_device_is_available(phy_node)) { -+ of_node_put(phy_node); - err = -EINVAL; -+ dev_err_probe(mac_dev->dev, err, -+ "TBI PCS node is not available\n"); - goto _return_fm_mac_free; - } - -- dtsec->tbiphy = of_phy_find_device(phy_node); -- if (!dtsec->tbiphy) { -- pr_err("of_phy_find_device (TBI PHY) failed\n"); -- err = -EINVAL; -+ dtsec->tbidev = of_mdio_find_device(phy_node); -+ of_node_put(phy_node); -+ if (!dtsec->tbidev) { -+ err = -EPROBE_DEFER; -+ dev_err_probe(mac_dev->dev, err, -+ "could not find mdiodev for PCS\n"); - goto _return_fm_mac_free; - } -- put_device(&dtsec->tbiphy->mdio.dev); -+ dtsec->pcs.ops = &dtsec_pcs_ops; -+ dtsec->pcs.poll = true; -+ -+ supported = mac_dev->phylink_config.supported_interfaces; -+ -+ /* FIXME: Can we use DTSEC_ID2_INT_FULL_OFF to determine if these are -+ * supported? If not, we can determine support via the phy if SerDes -+ * support is added. -+ */ -+ if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII || -+ mac_dev->phy_if == PHY_INTERFACE_MODE_1000BASEX) { -+ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); -+ } else if (mac_dev->phy_if == PHY_INTERFACE_MODE_2500BASEX) { -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); -+ } -+ -+ if (!(ioread32be(&dtsec->regs->tsec_id2) & DTSEC_ID2_INT_REDUCED_OFF)) { -+ phy_interface_set_rgmii(supported); -+ -+ /* DTSEC_ID2_INT_REDUCED_OFF indicates that the dTSEC supports -+ * RMII and RGMII. However, the only SoCs which support RMII -+ * are the P1017 and P1023. Avoid advertising this mode on -+ * other SoCs. This is a bit of a moot point, since there's no -+ * in-tree support for ethernet on these platforms... -+ */ -+ if (of_machine_is_compatible("fsl,P1023") || -+ of_machine_is_compatible("fsl,P1023RDB")) -+ __set_bit(PHY_INTERFACE_MODE_RMII, supported); -+ } -+ -+ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE; -+ capabilities |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; -+ mac_dev->phylink_config.mac_capabilities = capabilities; - - err = dtsec_init(dtsec); - if (err < 0) ---- a/drivers/net/ethernet/freescale/fman/fman_mac.h -+++ b/drivers/net/ethernet/freescale/fman/fman_mac.h -@@ -170,20 +170,10 @@ struct fman_mac_params { - * 0 - FM_MAX_NUM_OF_10G_MACS - */ - u8 mac_id; -- /* Note that the speed should indicate the maximum rate that -- * this MAC should support rather than the actual speed; -- */ -- u16 max_speed; - /* A handle to the FM object this port related to */ - void *fm; - fman_mac_exception_cb *event_cb; /* MDIO Events Callback Routine */ - fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */ -- /* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC -- * and phy or backplane; Note: 1000BaseX auto-negotiation relates only -- * to interface between MAC and phy/backplane, SGMII phy can still -- * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps -- */ -- bool basex_if; - }; - - struct eth_hash_t { ---- a/drivers/net/ethernet/freescale/fman/fman_memac.c -+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c -@@ -278,9 +278,6 @@ struct fman_mac { - struct memac_regs __iomem *regs; - /* MAC address of device */ - u64 addr; -- /* Ethernet physical interface */ -- phy_interface_t phy_if; -- u16 max_speed; - struct mac_device *dev_id; /* device cookie used by the exception cbs */ - fman_mac_exception_cb *exception_cb; - fman_mac_exception_cb *event_cb; -@@ -293,12 +290,12 @@ struct fman_mac { - struct memac_cfg *memac_drv_param; - void *fm; - struct fman_rev_info fm_rev_info; -- bool basex_if; - struct phy *serdes; - struct phylink_pcs *sgmii_pcs; - struct phylink_pcs *qsgmii_pcs; - struct phylink_pcs *xfi_pcs; - bool allmulti_enabled; -+ bool rgmii_no_half_duplex; - }; - - static void add_addr_in_paddr(struct memac_regs __iomem *regs, const u8 *adr, -@@ -356,7 +353,6 @@ static void set_exception(struct memac_r - } - - static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg, -- phy_interface_t phy_if, u16 speed, bool slow_10g_if, - u32 exceptions) - { - u32 tmp; -@@ -384,41 +380,6 @@ static int init(struct memac_regs __iome - iowrite32be((u32)cfg->pause_quanta, ®s->pause_quanta[0]); - iowrite32be((u32)0, ®s->pause_thresh[0]); - -- /* IF_MODE */ -- tmp = 0; -- switch (phy_if) { -- case PHY_INTERFACE_MODE_XGMII: -- tmp |= IF_MODE_10G; -- break; -- case PHY_INTERFACE_MODE_MII: -- tmp |= IF_MODE_MII; -- break; -- default: -- tmp |= IF_MODE_GMII; -- if (phy_if == PHY_INTERFACE_MODE_RGMII || -- phy_if == PHY_INTERFACE_MODE_RGMII_ID || -- phy_if == PHY_INTERFACE_MODE_RGMII_RXID || -- phy_if == PHY_INTERFACE_MODE_RGMII_TXID) -- tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; -- } -- iowrite32be(tmp, ®s->if_mode); -- -- /* TX_FIFO_SECTIONS */ -- tmp = 0; -- if (phy_if == PHY_INTERFACE_MODE_XGMII) { -- if (slow_10g_if) { -- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G | -- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); -- } else { -- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G | -- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); -- } -- } else { -- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G | -- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G); -- } -- iowrite32be(tmp, ®s->tx_fifo_sections); -- - /* clear all pending events and set-up interrupts */ - iowrite32be(0xffffffff, ®s->ievent); - set_exception(regs, exceptions, true); -@@ -458,24 +419,6 @@ static u32 get_mac_addr_hash_code(u64 et - return xor_val; - } - --static void setup_sgmii_internal(struct fman_mac *memac, -- struct phylink_pcs *pcs, -- struct fixed_phy_status *fixed_link) --{ -- __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); -- phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : -- PHY_INTERFACE_MODE_SGMII; -- unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; -- -- linkmode_set_pause(advertising, true, true); -- pcs->ops->pcs_config(pcs, mode, iface, advertising, true); -- if (fixed_link) -- pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, -- fixed_link->duplex); -- else -- pcs->ops->pcs_an_restart(pcs); --} -- - static int check_init_parameters(struct fman_mac *memac) - { - if (!memac->exception_cb) { -@@ -581,41 +524,31 @@ static void free_init_resources(struct f - memac->unicast_addr_hash = NULL; - } - --static bool is_init_done(struct memac_cfg *memac_drv_params) --{ -- /* Checks if mEMAC driver parameters were initialized */ -- if (!memac_drv_params) -- return true; -- -- return false; --} -- - static int memac_enable(struct fman_mac *memac) - { -- struct memac_regs __iomem *regs = memac->regs; -- u32 tmp; -+ int ret; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -+ ret = phy_init(memac->serdes); -+ if (ret) { -+ dev_err(memac->dev_id->dev, -+ "could not initialize serdes: %pe\n", ERR_PTR(ret)); -+ return ret; -+ } - -- tmp = ioread32be(®s->command_config); -- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -- iowrite32be(tmp, ®s->command_config); -+ ret = phy_power_on(memac->serdes); -+ if (ret) { -+ dev_err(memac->dev_id->dev, -+ "could not power on serdes: %pe\n", ERR_PTR(ret)); -+ phy_exit(memac->serdes); -+ } - -- return 0; -+ return ret; - } - - static void memac_disable(struct fman_mac *memac) -- - { -- struct memac_regs __iomem *regs = memac->regs; -- u32 tmp; -- -- WARN_ON_ONCE(!is_init_done(memac->memac_drv_param)); -- -- tmp = ioread32be(®s->command_config); -- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -- iowrite32be(tmp, ®s->command_config); -+ phy_power_off(memac->serdes); -+ phy_exit(memac->serdes); - } - - static int memac_set_promiscuous(struct fman_mac *memac, bool new_val) -@@ -623,9 +556,6 @@ static int memac_set_promiscuous(struct - struct memac_regs __iomem *regs = memac->regs; - u32 tmp; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (new_val) - tmp |= CMD_CFG_PROMIS_EN; -@@ -637,73 +567,12 @@ static int memac_set_promiscuous(struct - return 0; - } - --static int memac_adjust_link(struct fman_mac *memac, u16 speed) --{ -- struct memac_regs __iomem *regs = memac->regs; -- u32 tmp; -- -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- -- tmp = ioread32be(®s->if_mode); -- -- /* Set full duplex */ -- tmp &= ~IF_MODE_HD; -- -- if (phy_interface_mode_is_rgmii(memac->phy_if)) { -- /* Configure RGMII in manual mode */ -- tmp &= ~IF_MODE_RGMII_AUTO; -- tmp &= ~IF_MODE_RGMII_SP_MASK; -- /* Full duplex */ -- tmp |= IF_MODE_RGMII_FD; -- -- switch (speed) { -- case SPEED_1000: -- tmp |= IF_MODE_RGMII_1000; -- break; -- case SPEED_100: -- tmp |= IF_MODE_RGMII_100; -- break; -- case SPEED_10: -- tmp |= IF_MODE_RGMII_10; -- break; -- default: -- break; -- } -- } -- -- iowrite32be(tmp, ®s->if_mode); -- -- return 0; --} -- --static void adjust_link_memac(struct mac_device *mac_dev) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- struct fman_mac *fman_mac; -- bool rx_pause, tx_pause; -- int err; -- -- fman_mac = mac_dev->fman_mac; -- memac_adjust_link(fman_mac, phy_dev->speed); -- mac_dev->update_speed(mac_dev, phy_dev->speed); -- -- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); -- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); -- if (err < 0) -- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", -- err); --} -- - static int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority, - u16 pause_time, u16 thresh_time) - { - struct memac_regs __iomem *regs = memac->regs; - u32 tmp; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->tx_fifo_sections); - - GET_TX_EMPTY_DEFAULT_VALUE(tmp); -@@ -738,9 +607,6 @@ static int memac_accept_rx_pause_frames( - struct memac_regs __iomem *regs = memac->regs; - u32 tmp; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (en) - tmp &= ~CMD_CFG_PAUSE_IGNORE; -@@ -752,12 +618,175 @@ static int memac_accept_rx_pause_frames( - return 0; - } - -+static void memac_validate(struct phylink_config *config, -+ unsigned long *supported, -+ struct phylink_link_state *state) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ unsigned long caps = config->mac_capabilities; -+ -+ if (phy_interface_mode_is_rgmii(state->interface) && -+ memac->rgmii_no_half_duplex) -+ caps &= ~(MAC_10HD | MAC_100HD); -+ -+ phylink_validate_mask_caps(supported, state, caps); -+} -+ -+/** -+ * memac_if_mode() - Convert an interface mode into an IF_MODE config -+ * @interface: A phy interface mode -+ * -+ * Return: A configuration word, suitable for programming into the lower bits -+ * of %IF_MODE. -+ */ -+static u32 memac_if_mode(phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_MII: -+ return IF_MODE_MII; -+ case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ return IF_MODE_GMII | IF_MODE_RGMII; -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return IF_MODE_GMII; -+ case PHY_INTERFACE_MODE_10GBASER: -+ return IF_MODE_10G; -+ default: -+ WARN_ON_ONCE(1); -+ return 0; -+ } -+} -+ -+static struct phylink_pcs *memac_select_pcs(struct phylink_config *config, -+ phy_interface_t iface) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ -+ switch (iface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ return memac->sgmii_pcs; -+ case PHY_INTERFACE_MODE_QSGMII: -+ return memac->qsgmii_pcs; -+ case PHY_INTERFACE_MODE_10GBASER: -+ return memac->xfi_pcs; -+ default: -+ return NULL; -+ } -+} -+ -+static int memac_prepare(struct phylink_config *config, unsigned int mode, -+ phy_interface_t iface) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ -+ switch (iface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_10GBASER: -+ return phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, -+ iface); -+ default: -+ return 0; -+ } -+} -+ -+static void memac_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mac_device *mac_dev = fman_config_to_mac(config); -+ struct memac_regs __iomem *regs = mac_dev->fman_mac->regs; -+ u32 tmp = ioread32be(®s->if_mode); -+ -+ tmp &= ~(IF_MODE_MASK | IF_MODE_RGMII); -+ tmp |= memac_if_mode(state->interface); -+ if (phylink_autoneg_inband(mode)) -+ tmp |= IF_MODE_RGMII_AUTO; -+ iowrite32be(tmp, ®s->if_mode); -+} -+ -+static void memac_link_up(struct phylink_config *config, struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct mac_device *mac_dev = fman_config_to_mac(config); -+ struct fman_mac *memac = mac_dev->fman_mac; -+ struct memac_regs __iomem *regs = memac->regs; -+ u32 tmp = memac_if_mode(interface); -+ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : -+ FSL_FM_PAUSE_TIME_DISABLE; -+ -+ memac_set_tx_pause_frames(memac, 0, pause_time, 0); -+ memac_accept_rx_pause_frames(memac, rx_pause); -+ -+ if (duplex == DUPLEX_HALF) -+ tmp |= IF_MODE_HD; -+ -+ switch (speed) { -+ case SPEED_1000: -+ tmp |= IF_MODE_RGMII_1000; -+ break; -+ case SPEED_100: -+ tmp |= IF_MODE_RGMII_100; -+ break; -+ case SPEED_10: -+ tmp |= IF_MODE_RGMII_10; -+ break; -+ } -+ iowrite32be(tmp, ®s->if_mode); -+ -+ /* TODO: EEE? */ -+ -+ if (speed == SPEED_10000) { -+ if (memac->fm_rev_info.major == 6 && -+ memac->fm_rev_info.minor == 4) -+ tmp = TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G; -+ else -+ tmp = TX_FIFO_SECTIONS_TX_AVAIL_10G; -+ tmp |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G; -+ } else { -+ tmp = TX_FIFO_SECTIONS_TX_AVAIL_1G | -+ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G; -+ } -+ iowrite32be(tmp, ®s->tx_fifo_sections); -+ -+ mac_dev->update_speed(mac_dev, speed); -+ -+ tmp = ioread32be(®s->command_config); -+ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static void memac_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ struct memac_regs __iomem *regs = memac->regs; -+ u32 tmp; -+ -+ /* TODO: graceful */ -+ tmp = ioread32be(®s->command_config); -+ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static const struct phylink_mac_ops memac_mac_ops = { -+ .validate = memac_validate, -+ .mac_select_pcs = memac_select_pcs, -+ .mac_prepare = memac_prepare, -+ .mac_config = memac_mac_config, -+ .mac_link_up = memac_link_up, -+ .mac_link_down = memac_link_down, -+}; -+ - static int memac_modify_mac_address(struct fman_mac *memac, - const enet_addr_t *enet_addr) - { -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - add_addr_in_paddr(memac->regs, (const u8 *)(*enet_addr), 0); - - return 0; -@@ -771,9 +800,6 @@ static int memac_add_hash_mac_address(st - u32 hash; - u64 addr; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - if (!(addr & GROUP_ADDRESS)) { -@@ -802,9 +828,6 @@ static int memac_set_allmulti(struct fma - u32 entry; - struct memac_regs __iomem *regs = memac->regs; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - if (enable) { - for (entry = 0; entry < HASH_TABLE_SIZE; entry++) - iowrite32be(entry | HASH_CTRL_MCAST_EN, -@@ -834,9 +857,6 @@ static int memac_del_hash_mac_address(st - u32 hash; - u64 addr; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK; -@@ -864,9 +884,6 @@ static int memac_set_exception(struct fm - { - u32 bit_mask = 0; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - bit_mask = get_exception_flag(exception); - if (bit_mask) { - if (enable) -@@ -886,23 +903,15 @@ static int memac_init(struct fman_mac *m - { - struct memac_cfg *memac_drv_param; - enet_addr_t eth_addr; -- bool slow_10g_if = false; -- struct fixed_phy_status *fixed_link = NULL; - int err; - u32 reg32 = 0; - -- if (is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - err = check_init_parameters(memac); - if (err) - return err; - - memac_drv_param = memac->memac_drv_param; - -- if (memac->fm_rev_info.major == 6 && memac->fm_rev_info.minor == 4) -- slow_10g_if = true; -- - /* First, reset the MAC if desired. */ - if (memac_drv_param->reset_on_init) { - err = reset(memac->regs); -@@ -918,10 +927,7 @@ static int memac_init(struct fman_mac *m - add_addr_in_paddr(memac->regs, (const u8 *)eth_addr, 0); - } - -- fixed_link = memac_drv_param->fixed_link; -- -- init(memac->regs, memac->memac_drv_param, memac->phy_if, -- memac->max_speed, slow_10g_if, memac->exceptions); -+ init(memac->regs, memac->memac_drv_param, memac->exceptions); - - /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 errata workaround - * Exists only in FMan 6.0 and 6.3. -@@ -937,11 +943,6 @@ static int memac_init(struct fman_mac *m - iowrite32be(reg32, &memac->regs->command_config); - } - -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) -- setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); -- else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) -- setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); -- - /* Max Frame Length */ - err = fman_set_mac_max_frame(memac->fm, memac->mac_id, - memac_drv_param->max_frame_length); -@@ -970,9 +971,6 @@ static int memac_init(struct fman_mac *m - fman_register_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, - FMAN_INTR_TYPE_NORMAL, memac_exception, memac); - -- kfree(memac_drv_param); -- memac->memac_drv_param = NULL; -- - return 0; - } - -@@ -995,7 +993,6 @@ static int memac_free(struct fman_mac *m - pcs_put(memac->sgmii_pcs); - pcs_put(memac->qsgmii_pcs); - pcs_put(memac->xfi_pcs); -- - kfree(memac->memac_drv_param); - kfree(memac); - -@@ -1028,8 +1025,6 @@ static struct fman_mac *memac_config(str - memac->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); - - memac->regs = mac_dev->vaddr; -- memac->max_speed = params->max_speed; -- memac->phy_if = mac_dev->phy_if; - memac->mac_id = params->mac_id; - memac->exceptions = (MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER | - MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI); -@@ -1037,7 +1032,6 @@ static struct fman_mac *memac_config(str - memac->event_cb = params->event_cb; - memac->dev_id = mac_dev; - memac->fm = params->fm; -- memac->basex_if = params->basex_if; - - /* Save FMan revision */ - fman_get_revision(memac->fm, &memac->fm_rev_info); -@@ -1064,37 +1058,44 @@ static struct phylink_pcs *memac_pcs_cre - return pcs; - } - -+static bool memac_supports(struct mac_device *mac_dev, phy_interface_t iface) -+{ -+ /* If there's no serdes device, assume that it's been configured for -+ * whatever the default interface mode is. -+ */ -+ if (!mac_dev->fman_mac->serdes) -+ return mac_dev->phy_if == iface; -+ /* Otherwise, ask the serdes */ -+ return !phy_validate(mac_dev->fman_mac->serdes, PHY_MODE_ETHERNET, -+ iface, NULL); -+} -+ - int memac_initialization(struct mac_device *mac_dev, - struct device_node *mac_node, - struct fman_mac_params *params) - { - int err; -+ struct device_node *fixed; - struct phylink_pcs *pcs; -- struct fixed_phy_status *fixed_link; - struct fman_mac *memac; -+ unsigned long capabilities; -+ unsigned long *supported; - -+ mac_dev->phylink_ops = &memac_mac_ops; - mac_dev->set_promisc = memac_set_promiscuous; - mac_dev->change_addr = memac_modify_mac_address; - mac_dev->add_hash_mac_addr = memac_add_hash_mac_address; - mac_dev->remove_hash_mac_addr = memac_del_hash_mac_address; -- mac_dev->set_tx_pause = memac_set_tx_pause_frames; -- mac_dev->set_rx_pause = memac_accept_rx_pause_frames; - mac_dev->set_exception = memac_set_exception; - mac_dev->set_allmulti = memac_set_allmulti; - mac_dev->set_tstamp = memac_set_tstamp; - mac_dev->set_multi = fman_set_multi; -- mac_dev->adjust_link = adjust_link_memac; - mac_dev->enable = memac_enable; - mac_dev->disable = memac_disable; - -- if (params->max_speed == SPEED_10000) -- mac_dev->phy_if = PHY_INTERFACE_MODE_XGMII; -- - mac_dev->fman_mac = memac_config(mac_dev, params); -- if (!mac_dev->fman_mac) { -- err = -EINVAL; -- goto _return; -- } -+ if (!mac_dev->fman_mac) -+ return -EINVAL; - - memac = mac_dev->fman_mac; - memac->memac_drv_param->max_frame_length = fman_get_max_frm(); -@@ -1136,9 +1137,9 @@ int memac_initialization(struct mac_devi - else - pcs = memac_pcs_create(mac_node, err); - -- if (!pcs) { -- dev_err(mac_dev->dev, "missing pcs\n"); -- err = -ENOENT; -+ if (IS_ERR(pcs)) { -+ err = PTR_ERR(pcs); -+ dev_err_probe(mac_dev->dev, err, "missing pcs\n"); - goto _return_fm_mac_free; - } - -@@ -1159,84 +1160,100 @@ int memac_initialization(struct mac_devi - } else if (IS_ERR(memac->serdes)) { - dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); - goto _return_fm_mac_free; -- } else { -- err = phy_init(memac->serdes); -- if (err) { -- dev_err_probe(mac_dev->dev, err, -- "could not initialize serdes\n"); -- goto _return_fm_mac_free; -- } -- -- err = phy_power_on(memac->serdes); -- if (err) { -- dev_err_probe(mac_dev->dev, err, -- "could not power on serdes\n"); -- goto _return_phy_exit; -- } -- -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || -- memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || -- memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || -- memac->phy_if == PHY_INTERFACE_MODE_QSGMII || -- memac->phy_if == PHY_INTERFACE_MODE_XGMII) { -- err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, -- memac->phy_if); -- if (err) { -- dev_err_probe(mac_dev->dev, err, -- "could not set serdes mode to %s\n", -- phy_modes(memac->phy_if)); -- goto _return_phy_power_off; -- } -- } - } - -- if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { -- struct phy_device *phy; -- -- err = of_phy_register_fixed_link(mac_node); -- if (err) -- goto _return_phy_power_off; -- -- fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); -- if (!fixed_link) { -- err = -ENOMEM; -- goto _return_phy_power_off; -- } -+ /* The internal connection to the serdes is XGMII, but this isn't -+ * really correct for the phy mode (which is the external connection). -+ * However, this is how all older device trees say that they want -+ * 10GBASE-R (aka XFI), so just convert it for them. -+ */ -+ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -+ mac_dev->phy_if = PHY_INTERFACE_MODE_10GBASER; - -- mac_dev->phy_node = of_node_get(mac_node); -- phy = of_phy_find_device(mac_dev->phy_node); -- if (!phy) { -- err = -EINVAL; -- of_node_put(mac_dev->phy_node); -- goto _return_fixed_link_free; -- } -+ /* TODO: The following interface modes are supported by (some) hardware -+ * but not by this driver: -+ * - 1000BASE-KX -+ * - 10GBASE-KR -+ * - XAUI/HiGig -+ */ -+ supported = mac_dev->phylink_config.supported_interfaces; - -- fixed_link->link = phy->link; -- fixed_link->speed = phy->speed; -- fixed_link->duplex = phy->duplex; -- fixed_link->pause = phy->pause; -- fixed_link->asym_pause = phy->asym_pause; -+ /* Note that half duplex is only supported on 10/100M interfaces. */ - -- put_device(&phy->mdio.dev); -- memac->memac_drv_param->fixed_link = fixed_link; -+ if (memac->sgmii_pcs && -+ (memac_supports(mac_dev, PHY_INTERFACE_MODE_SGMII) || -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_1000BASEX))) { -+ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); -+ } -+ -+ if (memac->sgmii_pcs && -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_2500BASEX)) -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); -+ -+ if (memac->qsgmii_pcs && -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_QSGMII)) -+ __set_bit(PHY_INTERFACE_MODE_QSGMII, supported); -+ else if (mac_dev->phy_if == PHY_INTERFACE_MODE_QSGMII) -+ dev_warn(mac_dev->dev, "no QSGMII pcs specified\n"); -+ -+ if (memac->xfi_pcs && -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_10GBASER)) { -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); -+ } else { -+ /* From what I can tell, no 10g macs support RGMII. */ -+ phy_interface_set_rgmii(supported); -+ __set_bit(PHY_INTERFACE_MODE_MII, supported); - } - -+ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 | MAC_100; -+ capabilities |= MAC_1000FD | MAC_2500FD | MAC_10000FD; -+ -+ /* These SoCs don't support half duplex at all; there's no different -+ * FMan version or compatible, so we just have to check the machine -+ * compatible instead -+ */ -+ if (of_machine_is_compatible("fsl,ls1043a") || -+ of_machine_is_compatible("fsl,ls1046a") || -+ of_machine_is_compatible("fsl,B4QDS")) -+ capabilities &= ~(MAC_10HD | MAC_100HD); -+ -+ mac_dev->phylink_config.mac_capabilities = capabilities; -+ -+ /* The T2080 and T4240 don't support half duplex RGMII. There is no -+ * other way to identify these SoCs, so just use the machine -+ * compatible. -+ */ -+ if (of_machine_is_compatible("fsl,T2080QDS") || -+ of_machine_is_compatible("fsl,T2080RDB") || -+ of_machine_is_compatible("fsl,T2081QDS") || -+ of_machine_is_compatible("fsl,T4240QDS") || -+ of_machine_is_compatible("fsl,T4240RDB")) -+ memac->rgmii_no_half_duplex = true; -+ -+ /* Most boards should use MLO_AN_INBAND, but existing boards don't have -+ * a managed property. Default to MLO_AN_INBAND if nothing else is -+ * specified. We need to be careful and not enable this if we have a -+ * fixed link or if we are using MII or RGMII, since those -+ * configurations modes don't use in-band autonegotiation. -+ */ -+ fixed = of_get_child_by_name(mac_node, "fixed-link"); -+ if (!fixed && !of_property_read_bool(mac_node, "fixed-link") && -+ !of_property_read_bool(mac_node, "managed") && -+ mac_dev->phy_if != PHY_INTERFACE_MODE_MII && -+ !phy_interface_mode_is_rgmii(mac_dev->phy_if)) -+ mac_dev->phylink_config.ovr_an_inband = true; -+ of_node_put(fixed); -+ - err = memac_init(mac_dev->fman_mac); - if (err < 0) -- goto _return_fixed_link_free; -+ goto _return_fm_mac_free; - - dev_info(mac_dev->dev, "FMan MEMAC\n"); - -- goto _return; -+ return 0; - --_return_phy_power_off: -- phy_power_off(memac->serdes); --_return_phy_exit: -- phy_exit(memac->serdes); --_return_fixed_link_free: -- kfree(fixed_link); - _return_fm_mac_free: - memac_free(mac_dev->fman_mac); --_return: - return err; - } ---- a/drivers/net/ethernet/freescale/fman/fman_tgec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - /* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ - #define TGEC_TX_IPG_LENGTH_MASK 0x000003ff -@@ -243,10 +244,6 @@ static int init(struct tgec_regs __iomem - - static int check_init_parameters(struct fman_mac *tgec) - { -- if (tgec->max_speed < SPEED_10000) { -- pr_err("10G MAC driver only support 10G speed\n"); -- return -EINVAL; -- } - if (!tgec->exception_cb) { - pr_err("uninitialized exception_cb\n"); - return -EINVAL; -@@ -384,40 +381,13 @@ static void free_init_resources(struct f - tgec->unicast_addr_hash = NULL; - } - --static bool is_init_done(struct tgec_cfg *cfg) --{ -- /* Checks if tGEC driver parameters were initialized */ -- if (!cfg) -- return true; -- -- return false; --} -- - static int tgec_enable(struct fman_mac *tgec) - { -- struct tgec_regs __iomem *regs = tgec->regs; -- u32 tmp; -- -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- -- tmp = ioread32be(®s->command_config); -- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -- iowrite32be(tmp, ®s->command_config); -- - return 0; - } - - static void tgec_disable(struct fman_mac *tgec) - { -- struct tgec_regs __iomem *regs = tgec->regs; -- u32 tmp; -- -- WARN_ON_ONCE(!is_init_done(tgec->cfg)); -- -- tmp = ioread32be(®s->command_config); -- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -- iowrite32be(tmp, ®s->command_config); - } - - static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val) -@@ -425,9 +395,6 @@ static int tgec_set_promiscuous(struct f - struct tgec_regs __iomem *regs = tgec->regs; - u32 tmp; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (new_val) - tmp |= CMD_CFG_PROMIS_EN; -@@ -444,9 +411,6 @@ static int tgec_set_tx_pause_frames(stru - { - struct tgec_regs __iomem *regs = tgec->regs; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - iowrite32be((u32)pause_time, ®s->pause_quant); - - return 0; -@@ -457,9 +421,6 @@ static int tgec_accept_rx_pause_frames(s - struct tgec_regs __iomem *regs = tgec->regs; - u32 tmp; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (!en) - tmp |= CMD_CFG_PAUSE_IGNORE; -@@ -470,12 +431,53 @@ static int tgec_accept_rx_pause_frames(s - return 0; - } - -+static void tgec_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+} -+ -+static void tgec_link_up(struct phylink_config *config, struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct mac_device *mac_dev = fman_config_to_mac(config); -+ struct fman_mac *tgec = mac_dev->fman_mac; -+ struct tgec_regs __iomem *regs = tgec->regs; -+ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : -+ FSL_FM_PAUSE_TIME_DISABLE; -+ u32 tmp; -+ -+ tgec_set_tx_pause_frames(tgec, 0, pause_time, 0); -+ tgec_accept_rx_pause_frames(tgec, rx_pause); -+ mac_dev->update_speed(mac_dev, speed); -+ -+ tmp = ioread32be(®s->command_config); -+ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static void tgec_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct fman_mac *tgec = fman_config_to_mac(config)->fman_mac; -+ struct tgec_regs __iomem *regs = tgec->regs; -+ u32 tmp; -+ -+ tmp = ioread32be(®s->command_config); -+ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static const struct phylink_mac_ops tgec_mac_ops = { -+ .validate = phylink_generic_validate, -+ .mac_config = tgec_mac_config, -+ .mac_link_up = tgec_link_up, -+ .mac_link_down = tgec_link_down, -+}; -+ - static int tgec_modify_mac_address(struct fman_mac *tgec, - const enet_addr_t *p_enet_addr) - { -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr); - set_mac_address(tgec->regs, (const u8 *)(*p_enet_addr)); - -@@ -490,9 +492,6 @@ static int tgec_add_hash_mac_address(str - u32 crc = 0xFFFFFFFF, hash; - u64 addr; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - if (!(addr & GROUP_ADDRESS)) { -@@ -525,9 +524,6 @@ static int tgec_set_allmulti(struct fman - u32 entry; - struct tgec_regs __iomem *regs = tgec->regs; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - if (enable) { - for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++) - iowrite32be(entry | TGEC_HASH_MCAST_EN, -@@ -548,9 +544,6 @@ static int tgec_set_tstamp(struct fman_m - struct tgec_regs __iomem *regs = tgec->regs; - u32 tmp; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - - if (enable) -@@ -572,9 +565,6 @@ static int tgec_del_hash_mac_address(str - u32 crc = 0xFFFFFFFF, hash; - u64 addr; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - addr = ((*(u64 *)eth_addr) >> 16); - - /* CRC calculation */ -@@ -601,22 +591,12 @@ static int tgec_del_hash_mac_address(str - return 0; - } - --static void tgec_adjust_link(struct mac_device *mac_dev) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- -- mac_dev->update_speed(mac_dev, phy_dev->speed); --} -- - static int tgec_set_exception(struct fman_mac *tgec, - enum fman_mac_exceptions exception, bool enable) - { - struct tgec_regs __iomem *regs = tgec->regs; - u32 bit_mask = 0; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - bit_mask = get_exception_flag(exception); - if (bit_mask) { - if (enable) -@@ -641,9 +621,6 @@ static int tgec_init(struct fman_mac *tg - enet_addr_t eth_addr; - int err; - -- if (is_init_done(tgec->cfg)) -- return -EINVAL; -- - if (DEFAULT_RESET_ON_INIT && - (fman_reset_mac(tgec->fm, tgec->mac_id) != 0)) { - pr_err("Can't reset MAC!\n"); -@@ -753,7 +730,6 @@ static struct fman_mac *tgec_config(stru - - tgec->regs = mac_dev->vaddr; - tgec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); -- tgec->max_speed = params->max_speed; - tgec->mac_id = params->mac_id; - tgec->exceptions = (TGEC_IMASK_MDIO_SCAN_EVENT | - TGEC_IMASK_REM_FAULT | -@@ -788,17 +764,15 @@ int tgec_initialization(struct mac_devic - int err; - struct fman_mac *tgec; - -+ mac_dev->phylink_ops = &tgec_mac_ops; - mac_dev->set_promisc = tgec_set_promiscuous; - mac_dev->change_addr = tgec_modify_mac_address; - mac_dev->add_hash_mac_addr = tgec_add_hash_mac_address; - mac_dev->remove_hash_mac_addr = tgec_del_hash_mac_address; -- mac_dev->set_tx_pause = tgec_set_tx_pause_frames; -- mac_dev->set_rx_pause = tgec_accept_rx_pause_frames; - mac_dev->set_exception = tgec_set_exception; - mac_dev->set_allmulti = tgec_set_allmulti; - mac_dev->set_tstamp = tgec_set_tstamp; - mac_dev->set_multi = fman_set_multi; -- mac_dev->adjust_link = tgec_adjust_link; - mac_dev->enable = tgec_enable; - mac_dev->disable = tgec_disable; - -@@ -808,6 +782,19 @@ int tgec_initialization(struct mac_devic - goto _return; - } - -+ /* The internal connection to the serdes is XGMII, but this isn't -+ * really correct for the phy mode (which is the external connection). -+ * However, this is how all older device trees say that they want -+ * XAUI, so just convert it for them. -+ */ -+ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -+ mac_dev->phy_if = PHY_INTERFACE_MODE_XAUI; -+ -+ __set_bit(PHY_INTERFACE_MODE_XAUI, -+ mac_dev->phylink_config.supported_interfaces); -+ mac_dev->phylink_config.mac_capabilities = -+ MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10000FD; -+ - tgec = mac_dev->fman_mac; - tgec->cfg->max_frame_length = fman_get_max_frm(); - err = tgec_init(tgec); ---- a/drivers/net/ethernet/freescale/fman/mac.c -+++ b/drivers/net/ethernet/freescale/fman/mac.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -93,130 +94,8 @@ int fman_set_multi(struct net_device *ne - return 0; - } - --/** -- * fman_set_mac_active_pause -- * @mac_dev: A pointer to the MAC device -- * @rx: Pause frame setting for RX -- * @tx: Pause frame setting for TX -- * -- * Set the MAC RX/TX PAUSE frames settings -- * -- * Avoid redundant calls to FMD, if the MAC driver already contains the desired -- * active PAUSE settings. Otherwise, the new active settings should be reflected -- * in FMan. -- * -- * Return: 0 on success; Error code otherwise. -- */ --int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx) --{ -- struct fman_mac *fman_mac = mac_dev->fman_mac; -- int err = 0; -- -- if (rx != mac_dev->rx_pause_active) { -- err = mac_dev->set_rx_pause(fman_mac, rx); -- if (likely(err == 0)) -- mac_dev->rx_pause_active = rx; -- } -- -- if (tx != mac_dev->tx_pause_active) { -- u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE : -- FSL_FM_PAUSE_TIME_DISABLE); -- -- err = mac_dev->set_tx_pause(fman_mac, 0, pause_time, 0); -- -- if (likely(err == 0)) -- mac_dev->tx_pause_active = tx; -- } -- -- return err; --} --EXPORT_SYMBOL(fman_set_mac_active_pause); -- --/** -- * fman_get_pause_cfg -- * @mac_dev: A pointer to the MAC device -- * @rx_pause: Return value for RX setting -- * @tx_pause: Return value for TX setting -- * -- * Determine the MAC RX/TX PAUSE frames settings based on PHY -- * autonegotiation or values set by eththool. -- * -- * Return: Pointer to FMan device. -- */ --void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, -- bool *tx_pause) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- u16 lcl_adv, rmt_adv; -- u8 flowctrl; -- -- *rx_pause = *tx_pause = false; -- -- if (!phy_dev->duplex) -- return; -- -- /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings -- * are those set by ethtool. -- */ -- if (!mac_dev->autoneg_pause) { -- *rx_pause = mac_dev->rx_pause_req; -- *tx_pause = mac_dev->tx_pause_req; -- return; -- } -- -- /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE -- * settings depend on the result of the link negotiation. -- */ -- -- /* get local capabilities */ -- lcl_adv = linkmode_adv_to_lcl_adv_t(phy_dev->advertising); -- -- /* get link partner capabilities */ -- rmt_adv = 0; -- if (phy_dev->pause) -- rmt_adv |= LPA_PAUSE_CAP; -- if (phy_dev->asym_pause) -- rmt_adv |= LPA_PAUSE_ASYM; -- -- /* Calculate TX/RX settings based on local and peer advertised -- * symmetric/asymmetric PAUSE capabilities. -- */ -- flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); -- if (flowctrl & FLOW_CTRL_RX) -- *rx_pause = true; -- if (flowctrl & FLOW_CTRL_TX) -- *tx_pause = true; --} --EXPORT_SYMBOL(fman_get_pause_cfg); -- --#define DTSEC_SUPPORTED \ -- (SUPPORTED_10baseT_Half \ -- | SUPPORTED_10baseT_Full \ -- | SUPPORTED_100baseT_Half \ -- | SUPPORTED_100baseT_Full \ -- | SUPPORTED_Autoneg \ -- | SUPPORTED_Pause \ -- | SUPPORTED_Asym_Pause \ -- | SUPPORTED_FIBRE \ -- | SUPPORTED_MII) -- - static DEFINE_MUTEX(eth_lock); - --static const u16 phy2speed[] = { -- [PHY_INTERFACE_MODE_MII] = SPEED_100, -- [PHY_INTERFACE_MODE_GMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_TBI] = SPEED_1000, -- [PHY_INTERFACE_MODE_RMII] = SPEED_100, -- [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000, -- [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000, -- [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, -- [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, -- [PHY_INTERFACE_MODE_QSGMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_XGMII] = SPEED_10000 --}; -- - static struct platform_device *dpaa_eth_add_device(int fman_id, - struct mac_device *mac_dev) - { -@@ -263,8 +142,8 @@ no_mem: - } - - static const struct of_device_id mac_match[] = { -- { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, -- { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, -+ { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, -+ { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, - { .compatible = "fsl,fman-memac", .data = memac_initialization }, - {} - }; -@@ -295,6 +174,7 @@ static int mac_probe(struct platform_dev - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; -+ platform_set_drvdata(_of_dev, mac_dev); - - /* Save private information */ - mac_dev->priv = priv; -@@ -424,57 +304,21 @@ static int mac_probe(struct platform_dev - } - mac_dev->phy_if = phy_if; - -- priv->speed = phy2speed[mac_dev->phy_if]; -- params.max_speed = priv->speed; -- mac_dev->if_support = DTSEC_SUPPORTED; -- /* We don't support half-duplex in SGMII mode */ -- if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) -- mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | -- SUPPORTED_100baseT_Half); -- -- /* Gigabit support (no half-duplex) */ -- if (params.max_speed == 1000) -- mac_dev->if_support |= SUPPORTED_1000baseT_Full; -- -- /* The 10G interface only supports one mode */ -- if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -- mac_dev->if_support = SUPPORTED_10000baseT_Full; -- -- /* Get the rest of the PHY information */ -- mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0); -- -- params.basex_if = false; - params.mac_id = priv->cell_index; - params.fm = (void *)priv->fman; - params.exception_cb = mac_exception; - params.event_cb = mac_exception; - - err = init(mac_dev, mac_node, ¶ms); -- if (err < 0) { -- dev_err(dev, "mac_dev->init() = %d\n", err); -- of_node_put(mac_dev->phy_node); -- return err; -- } -- -- /* pause frame autonegotiation enabled */ -- mac_dev->autoneg_pause = true; -- -- /* By intializing the values to false, force FMD to enable PAUSE frames -- * on RX and TX -- */ -- mac_dev->rx_pause_req = true; -- mac_dev->tx_pause_req = true; -- mac_dev->rx_pause_active = false; -- mac_dev->tx_pause_active = false; -- err = fman_set_mac_active_pause(mac_dev, true, true); - if (err < 0) -- dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); -+ return err; - - if (!is_zero_ether_addr(mac_dev->addr)) - dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); - - priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); - if (IS_ERR(priv->eth_dev)) { -+ err = PTR_ERR(priv->eth_dev); - dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", - priv->cell_index); - priv->eth_dev = NULL; ---- a/drivers/net/ethernet/freescale/fman/mac.h -+++ b/drivers/net/ethernet/freescale/fman/mac.h -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - - #include "fman_port.h" -@@ -24,32 +25,22 @@ struct mac_device { - struct resource *res; - u8 addr[ETH_ALEN]; - struct fman_port *port[2]; -- u32 if_support; -- struct phy_device *phy_dev; -+ struct phylink *phylink; -+ struct phylink_config phylink_config; - phy_interface_t phy_if; -- struct device_node *phy_node; -- struct net_device *net_dev; - -- bool autoneg_pause; -- bool rx_pause_req; -- bool tx_pause_req; -- bool rx_pause_active; -- bool tx_pause_active; - bool promisc; - bool allmulti; - -+ const struct phylink_mac_ops *phylink_ops; - int (*enable)(struct fman_mac *mac_dev); - void (*disable)(struct fman_mac *mac_dev); -- void (*adjust_link)(struct mac_device *mac_dev); - int (*set_promisc)(struct fman_mac *mac_dev, bool enable); - int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr); - int (*set_allmulti)(struct fman_mac *mac_dev, bool enable); - int (*set_tstamp)(struct fman_mac *mac_dev, bool enable); - int (*set_multi)(struct net_device *net_dev, - struct mac_device *mac_dev); -- int (*set_rx_pause)(struct fman_mac *mac_dev, bool en); -- int (*set_tx_pause)(struct fman_mac *mac_dev, u8 priority, -- u16 pause_time, u16 thresh_time); - int (*set_exception)(struct fman_mac *mac_dev, - enum fman_mac_exceptions exception, bool enable); - int (*add_hash_mac_addr)(struct fman_mac *mac_dev, -@@ -63,6 +54,12 @@ struct mac_device { - struct mac_priv_s *priv; - }; - -+static inline struct mac_device -+*fman_config_to_mac(struct phylink_config *config) -+{ -+ return container_of(config, struct mac_device, phylink_config); -+} -+ - struct dpaa_eth_data { - struct mac_device *mac_dev; - int mac_hw_id; diff --git a/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch b/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch deleted file mode 100644 index 06c348b1cd..0000000000 --- a/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch +++ /dev/null @@ -1,93 +0,0 @@ -From bf4de031052fe7c5309e8956c342d4e5ce79038e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Mon, 17 Oct 2022 16:22:35 -0400 -Subject: [PATCH 04/21] net: phylink: provide phylink_validate_mask_caps() - helper - -Provide a helper that restricts the link modes according to the -phylink capabilities. - -Signed-off-by: Russell King (Oracle) -[rebased on net-next/master and added documentation] -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 41 +++++++++++++++++++++++++++------------ - include/linux/phylink.h | 3 +++ - 2 files changed, 32 insertions(+), 12 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -564,31 +564,48 @@ unsigned long phylink_get_capabilities(p - EXPORT_SYMBOL_GPL(phylink_get_capabilities); - - /** -- * phylink_generic_validate() - generic validate() callback implementation -- * @config: a pointer to a &struct phylink_config. -+ * phylink_validate_mask_caps() - Restrict link modes based on caps - * @supported: ethtool bitmask for supported link modes. -- * @state: a pointer to a &struct phylink_link_state. -+ * @state: an (optional) pointer to a &struct phylink_link_state. -+ * @mac_capabilities: bitmask of MAC capabilities - * -- * Generic implementation of the validate() callback that MAC drivers can -- * use when they pass the range of supported interfaces and MAC capabilities. -- * This makes use of phylink_get_linkmodes(). -+ * Calculate the supported link modes based on @mac_capabilities, and restrict -+ * @supported and @state based on that. Use this function if your capabiliies -+ * aren't constant, such as if they vary depending on the interface. - */ --void phylink_generic_validate(struct phylink_config *config, -- unsigned long *supported, -- struct phylink_link_state *state) -+void phylink_validate_mask_caps(unsigned long *supported, -+ struct phylink_link_state *state, -+ unsigned long mac_capabilities) - { - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - unsigned long caps; - - phylink_set_port_modes(mask); - phylink_set(mask, Autoneg); -- caps = phylink_get_capabilities(state->interface, -- config->mac_capabilities, -+ caps = phylink_get_capabilities(state->interface, mac_capabilities, - state->rate_matching); - phylink_caps_to_linkmodes(mask, caps); - - linkmode_and(supported, supported, mask); -- linkmode_and(state->advertising, state->advertising, mask); -+ if (state) -+ linkmode_and(state->advertising, state->advertising, mask); -+} -+EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); -+ -+/** -+ * phylink_generic_validate() - generic validate() callback implementation -+ * @config: a pointer to a &struct phylink_config. -+ * @supported: ethtool bitmask for supported link modes. -+ * @state: a pointer to a &struct phylink_link_state. -+ * -+ * Generic implementation of the validate() callback that MAC drivers can -+ * use when they pass the range of supported interfaces and MAC capabilities. -+ */ -+void phylink_generic_validate(struct phylink_config *config, -+ unsigned long *supported, -+ struct phylink_link_state *state) -+{ -+ phylink_validate_mask_caps(supported, state, config->mac_capabilities); - } - EXPORT_SYMBOL_GPL(phylink_generic_validate); - ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -558,6 +558,9 @@ void phylink_caps_to_linkmodes(unsigned - unsigned long phylink_get_capabilities(phy_interface_t interface, - unsigned long mac_capabilities, - int rate_matching); -+void phylink_validate_mask_caps(unsigned long *supported, -+ struct phylink_link_state *state, -+ unsigned long caps); - void phylink_generic_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch b/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch deleted file mode 100644 index e3a1dda688..0000000000 --- a/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 2bf7e4a68c42eed909f3c29582e1fb85cb157e35 Mon Sep 17 00:00:00 2001 -From: Jakub Kicinski -Date: Tue, 25 Oct 2022 11:51:26 -0700 -Subject: [PATCH 05/21] phylink: require valid state argument to - phylink_validate_mask_caps() - -state is deferenced earlier in the function, the NULL check -is pointless. Since we don't have any crash reports presumably -it's safe to assume state is not NULL. - -Fixes: f392a1846489 ("net: phylink: provide phylink_validate_mask_caps() helper") -Reviewed-by: Sean Anderson -Link: https://lore.kernel.org/r/20221025185126.1720553-1-kuba@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -566,7 +566,7 @@ EXPORT_SYMBOL_GPL(phylink_get_capabiliti - /** - * phylink_validate_mask_caps() - Restrict link modes based on caps - * @supported: ethtool bitmask for supported link modes. -- * @state: an (optional) pointer to a &struct phylink_link_state. -+ * @state: pointer to a &struct phylink_link_state. - * @mac_capabilities: bitmask of MAC capabilities - * - * Calculate the supported link modes based on @mac_capabilities, and restrict -@@ -587,8 +587,7 @@ void phylink_validate_mask_caps(unsigned - phylink_caps_to_linkmodes(mask, caps); - - linkmode_and(supported, supported, mask); -- if (state) -- linkmode_and(state->advertising, state->advertising, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); - diff --git a/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch b/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch deleted file mode 100644 index c217ed87b5..0000000000 --- a/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch +++ /dev/null @@ -1,48 +0,0 @@ -From f8fc363bf0c023e4736a0328174b4a24b44ab23a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:37 +0100 -Subject: [PATCH 06/21] net: phylink: add phylink_get_link_timer_ns() helper - -Add a helper to convert the PHY interface mode to the required link -timer setting as stated by the appropriate standard. Inappropriate -interface modes return an error. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - include/linux/phylink.h | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -617,6 +617,30 @@ int phylink_speed_up(struct phylink *pl) - - void phylink_set_port_modes(unsigned long *bits); - -+/** -+ * phylink_get_link_timer_ns - return the PCS link timer value -+ * @interface: link &typedef phy_interface_t mode -+ * -+ * Return the PCS link timer setting in nanoseconds for the PHY @interface -+ * mode, or -EINVAL if not appropriate. -+ */ -+static inline int phylink_get_link_timer_ns(phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_USXGMII: -+ return 1600000; -+ -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return 10000000; -+ -+ default: -+ return -EINVAL; -+ } -+} -+ - void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state, - u16 bmsr, u16 lpa); - void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, diff --git a/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch b/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch deleted file mode 100644 index 28154af920..0000000000 --- a/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch +++ /dev/null @@ -1,250 +0,0 @@ -From b45b773a96b0e9e8d51e5d005485f4e376d6ce9a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 4 Nov 2022 17:13:01 +0000 -Subject: [PATCH 07/21] net: remove explicit phylink_generic_validate() - references - -Virtually all conventional network drivers are now converted to use -phylink_generic_validate() - only DSA drivers and fman_memac remain, -so lets remove the necessity for network drivers to explicitly set -this member, and default to phylink_generic_validate() when unset. -This is possible as .validate must currently be set. - -Any remaining instances that have not been addressed by this patch can -be fixed up later. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Vladimir Oltean -Link: https://lore.kernel.org/r/E1or0FZ-001tRa-DI@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/altera/altera_tse_main.c | 1 - - drivers/net/ethernet/atheros/ag71xx.c | 1 - - drivers/net/ethernet/cadence/macb_main.c | 1 - - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 1 - - drivers/net/ethernet/freescale/enetc/enetc_pf.c | 1 - - drivers/net/ethernet/freescale/fman/fman_dtsec.c | 1 - - drivers/net/ethernet/freescale/fman/fman_tgec.c | 1 - - drivers/net/ethernet/marvell/mvneta.c | 1 - - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 - - drivers/net/ethernet/marvell/prestera/prestera_main.c | 1 - - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 - - drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c | 1 - - drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c | 1 - - drivers/net/ethernet/mscc/ocelot_net.c | 1 - - drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 - - drivers/net/ethernet/ti/am65-cpsw-nuss.c | 1 - - drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 - - drivers/net/phy/phylink.c | 5 ++++- - drivers/net/usb/asix_devices.c | 1 - - include/linux/phylink.h | 5 +++++ - 20 files changed, 9 insertions(+), 19 deletions(-) - ---- a/drivers/net/ethernet/altera/altera_tse_main.c -+++ b/drivers/net/ethernet/altera/altera_tse_main.c -@@ -1096,7 +1096,6 @@ static struct phylink_pcs *alt_tse_selec - } - - static const struct phylink_mac_ops alt_tse_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_an_restart = alt_tse_mac_an_restart, - .mac_config = alt_tse_mac_config, - .mac_link_down = alt_tse_mac_link_down, ---- a/drivers/net/ethernet/atheros/ag71xx.c -+++ b/drivers/net/ethernet/atheros/ag71xx.c -@@ -1086,7 +1086,6 @@ static void ag71xx_mac_link_up(struct ph - } - - static const struct phylink_mac_ops ag71xx_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = ag71xx_mac_config, - .mac_link_down = ag71xx_mac_link_down, - .mac_link_up = ag71xx_mac_link_up, ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -752,7 +752,6 @@ static struct phylink_pcs *macb_mac_sele - } - - static const struct phylink_mac_ops macb_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = macb_mac_select_pcs, - .mac_config = macb_mac_config, - .mac_link_down = macb_mac_link_down, ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -235,7 +235,6 @@ static void dpaa2_mac_link_down(struct p - } - - static const struct phylink_mac_ops dpaa2_mac_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = dpaa2_mac_select_pcs, - .mac_config = dpaa2_mac_config, - .mac_link_up = dpaa2_mac_link_up, ---- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -@@ -1111,7 +1111,6 @@ static void enetc_pl_mac_link_down(struc - } - - static const struct phylink_mac_ops enetc_mac_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = enetc_pl_mac_select_pcs, - .mac_config = enetc_pl_mac_config, - .mac_link_up = enetc_pl_mac_link_up, ---- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c -@@ -986,7 +986,6 @@ static void dtsec_link_down(struct phyli - } - - static const struct phylink_mac_ops dtsec_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = dtsec_select_pcs, - .mac_config = dtsec_mac_config, - .mac_link_up = dtsec_link_up, ---- a/drivers/net/ethernet/freescale/fman/fman_tgec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c -@@ -469,7 +469,6 @@ static void tgec_link_down(struct phylin - } - - static const struct phylink_mac_ops tgec_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = tgec_mac_config, - .mac_link_up = tgec_link_up, - .mac_link_down = tgec_link_down, ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -4228,7 +4228,6 @@ static void mvneta_mac_link_up(struct ph - } - - static const struct phylink_mac_ops mvneta_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = mvneta_mac_select_pcs, - .mac_prepare = mvneta_mac_prepare, - .mac_config = mvneta_mac_config, ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6633,7 +6633,6 @@ static void mvpp2_mac_link_down(struct p - } - - static const struct phylink_mac_ops mvpp2_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = mvpp2_select_pcs, - .mac_prepare = mvpp2_mac_prepare, - .mac_config = mvpp2_mac_config, ---- a/drivers/net/ethernet/marvell/prestera/prestera_main.c -+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c -@@ -360,7 +360,6 @@ static void prestera_pcs_an_restart(stru - } - - static const struct phylink_mac_ops prestera_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = prestera_mac_select_pcs, - .mac_config = prestera_mac_config, - .mac_link_down = prestera_mac_link_down, ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -654,7 +654,6 @@ static void mtk_mac_link_up(struct phyli - } - - static const struct phylink_mac_ops mtk_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = mtk_mac_select_pcs, - .mac_pcs_get_state = mtk_mac_pcs_get_state, - .mac_config = mtk_mac_config, ---- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c -+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c -@@ -125,7 +125,6 @@ static void lan966x_pcs_aneg_restart(str - } - - const struct phylink_mac_ops lan966x_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = lan966x_phylink_mac_select, - .mac_config = lan966x_phylink_mac_config, - .mac_prepare = lan966x_phylink_mac_prepare, ---- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -@@ -138,7 +138,6 @@ const struct phylink_pcs_ops sparx5_phyl - }; - - const struct phylink_mac_ops sparx5_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = sparx5_phylink_mac_select_pcs, - .mac_config = sparx5_phylink_mac_config, - .mac_link_down = sparx5_phylink_mac_link_down, ---- a/drivers/net/ethernet/mscc/ocelot_net.c -+++ b/drivers/net/ethernet/mscc/ocelot_net.c -@@ -1737,7 +1737,6 @@ static void vsc7514_phylink_mac_link_up( - } - - static const struct phylink_mac_ops ocelot_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_config = vsc7514_phylink_mac_config, - .mac_link_down = vsc7514_phylink_mac_link_down, - .mac_link_up = vsc7514_phylink_mac_link_up, ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -1090,7 +1090,6 @@ static void stmmac_mac_link_up(struct ph - } - - static const struct phylink_mac_ops stmmac_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = stmmac_mac_select_pcs, - .mac_config = stmmac_mac_config, - .mac_link_down = stmmac_mac_link_down, ---- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c -+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c -@@ -1493,7 +1493,6 @@ static void am65_cpsw_nuss_mac_link_up(s - } - - static const struct phylink_mac_ops am65_cpsw_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = am65_cpsw_nuss_mac_config, - .mac_link_down = am65_cpsw_nuss_mac_link_down, - .mac_link_up = am65_cpsw_nuss_mac_link_up, ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1736,7 +1736,6 @@ static void axienet_mac_link_up(struct p - } - - static const struct phylink_mac_ops axienet_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = axienet_mac_select_pcs, - .mac_config = axienet_mac_config, - .mac_link_down = axienet_mac_link_down, ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -651,7 +651,10 @@ static int phylink_validate_mac_and_pcs( - } - - /* Then validate the link parameters with the MAC */ -- pl->mac_ops->validate(pl->config, supported, state); -+ if (pl->mac_ops->validate) -+ pl->mac_ops->validate(pl->config, supported, state); -+ else -+ phylink_generic_validate(pl->config, supported, state); - - return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; - } ---- a/drivers/net/usb/asix_devices.c -+++ b/drivers/net/usb/asix_devices.c -@@ -787,7 +787,6 @@ static void ax88772_mac_link_up(struct p - } - - static const struct phylink_mac_ops ax88772_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = ax88772_mac_config, - .mac_link_down = ax88772_mac_link_down, - .mac_link_up = ax88772_mac_link_up, ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -207,6 +207,11 @@ struct phylink_mac_ops { - * - * If the @state->interface mode is not supported, then the @supported - * mask must be cleared. -+ * -+ * This member is optional; if not set, the generic validator will be -+ * used making use of @config->mac_capabilities and -+ * @config->supported_interfaces to determine which link modes are -+ * supported. - */ - void validate(struct phylink_config *config, unsigned long *supported, - struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch b/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch deleted file mode 100644 index 37d82b2cd7..0000000000 --- a/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch +++ /dev/null @@ -1,48 +0,0 @@ -From a90ac762d345890b40d88a1385a34a2449c2d75e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 24 Mar 2023 09:23:42 +0000 -Subject: [PATCH] net: sfp: make sfp_bus_find_fwnode() take a const fwnode - -sfp_bus_find_fwnode() does not write to the fwnode, so let's make it -const. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/phy/sfp-bus.c | 2 +- - include/linux/sfp.h | 5 +++-- - 2 files changed, 4 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/sfp-bus.c -+++ b/drivers/net/phy/sfp-bus.c -@@ -603,7 +603,7 @@ static void sfp_upstream_clear(struct sf - * - %-ENOMEM if we failed to allocate the bus. - * - an error from the upstream's connect_phy() method. - */ --struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) -+struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) - { - struct fwnode_reference_args ref; - struct sfp_bus *bus; ---- a/include/linux/sfp.h -+++ b/include/linux/sfp.h -@@ -548,7 +548,7 @@ int sfp_get_module_eeprom_by_page(struct - void sfp_upstream_start(struct sfp_bus *bus); - void sfp_upstream_stop(struct sfp_bus *bus); - void sfp_bus_put(struct sfp_bus *bus); --struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode); -+struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); - int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, - const struct sfp_upstream_ops *ops); - void sfp_bus_del_upstream(struct sfp_bus *bus); -@@ -610,7 +610,8 @@ static inline void sfp_bus_put(struct sf - { - } - --static inline struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) -+static inline struct sfp_bus * -+sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) - { - return NULL; - } diff --git a/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch b/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch deleted file mode 100644 index 290cb8d161..0000000000 --- a/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ecec0ebbc6381a5a375f1cf10c4858f24e91e2ef Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Wed, 15 Mar 2023 14:46:49 +0000 -Subject: [PATCH] net: pcs: lynx: don't print an_enabled in pcs_get_state() - -an_enabled will be going away, and in any case, pcs_get_state() should -not be updating this member. Remove the print. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Steen Hegelund -Signed-off-by: David S. Miller ---- - drivers/net/pcs/pcs-lynx.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/pcs/pcs-lynx.c -+++ b/drivers/net/pcs/pcs-lynx.c -@@ -115,11 +115,11 @@ static void lynx_pcs_get_state(struct ph - } - - dev_dbg(&lynx->mdio->dev, -- "mode=%s/%s/%s link=%u an_enabled=%u an_complete=%u\n", -+ "mode=%s/%s/%s link=%u an_complete=%u\n", - phy_modes(state->interface), - phy_speed_to_str(state->speed), - phy_duplex_to_str(state->duplex), -- state->link, state->an_enabled, state->an_complete); -+ state->link, state->an_complete); - } - - static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, diff --git a/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch b/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch deleted file mode 100644 index 38ea265476..0000000000 --- a/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 99d0f3a1095f4c938b1665025c29411edafe8a01 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 21 Mar 2023 15:58:44 +0000 -Subject: [PATCH] net: dpaa2-mac: use Autoneg bit rather than an_enabled - -The Autoneg bit in the advertising bitmap and state->an_enabled are -always identical. Thus, we will be removing state->an_enabled. - -Use the Autoneg bit in the advertising bitmap to indicate whether -autonegotiation should be used, rather than using the an_enabled -member which will be going away. This means we use the same condition -as phylink_mii_c22_pcs_config(). - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -158,7 +158,8 @@ static void dpaa2_mac_config(struct phyl - struct dpmac_link_state *dpmac_state = &mac->state; - int err; - -- if (state->an_enabled) -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) - dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG; - else - dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG; diff --git a/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch b/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch deleted file mode 100644 index cb9c411cfb..0000000000 --- a/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 471c40bde606ec0b1ce8c616f7998739c7a783a6 Mon Sep 17 00:00:00 2001 -From: Ivan Bornyakov -Date: Fri, 10 Feb 2023 18:46:27 +0300 -Subject: [PATCH 10/21] net: phylink: support validated pause and autoneg in - fixed-link - -In fixed-link setup phylink_parse_fixedlink() unconditionally sets -Pause, Asym_Pause and Autoneg bits to "supported" bitmap, while MAC may -not support these. - -This leads to ethtool reporting: - - > Supported pause frame use: Symmetric Receive-only - > Supports auto-negotiation: Yes - -regardless of what is actually supported. - -Instead of unconditionally set Pause, Asym_Pause and Autoneg it is -sensible to set them according to validated "supported" bitmap, i.e. the -result of phylink_validate(). - -Signed-off-by: Ivan Bornyakov -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -709,6 +709,7 @@ static int phylink_parse_fixedlink(struc - struct fwnode_handle *fwnode) - { - struct fwnode_handle *fixed_node; -+ bool pause, asym_pause, autoneg; - const struct phy_setting *s; - struct gpio_desc *desc; - u32 speed; -@@ -781,13 +782,23 @@ static int phylink_parse_fixedlink(struc - linkmode_copy(pl->link_config.advertising, pl->supported); - phylink_validate(pl, pl->supported, &pl->link_config); - -+ pause = phylink_test(pl->supported, Pause); -+ asym_pause = phylink_test(pl->supported, Asym_Pause); -+ autoneg = phylink_test(pl->supported, Autoneg); - s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex, - pl->supported, true); - linkmode_zero(pl->supported); - phylink_set(pl->supported, MII); -- phylink_set(pl->supported, Pause); -- phylink_set(pl->supported, Asym_Pause); -- phylink_set(pl->supported, Autoneg); -+ -+ if (pause) -+ phylink_set(pl->supported, Pause); -+ -+ if (asym_pause) -+ phylink_set(pl->supported, Asym_Pause); -+ -+ if (autoneg) -+ phylink_set(pl->supported, Autoneg); -+ - if (s) { - __set_bit(s->bit, pl->supported); - __set_bit(s->bit, pl->link_config.lp_advertising); diff --git a/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch b/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch deleted file mode 100644 index 03b4f9d0c4..0000000000 --- a/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 7211ffd70941933a7825a56cf480f07ee81c321c Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 21 Mar 2023 15:58:54 +0000 -Subject: [PATCH 11/21] net: phylink: remove an_enabled - -The Autoneg bit in the advertising bitmap and state->an_enabled are -always identical. state->an_enabled is now no longer used by any -drivers, so lets kill this duplication. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 37 +++++++++++++++++-------------------- - include/linux/phylink.h | 2 -- - 2 files changed, 17 insertions(+), 22 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -841,7 +841,6 @@ static int phylink_parse_mode(struct phy - phylink_set(pl->supported, Autoneg); - phylink_set(pl->supported, Asym_Pause); - phylink_set(pl->supported, Pause); -- pl->link_config.an_enabled = true; - pl->cfg_link_an_mode = MLO_AN_INBAND; - - switch (pl->link_config.interface) { -@@ -944,9 +943,6 @@ static int phylink_parse_mode(struct phy - "failed to validate link configuration for in-band status\n"); - return -EINVAL; - } -- -- /* Check if MAC/PCS also supports Autoneg. */ -- pl->link_config.an_enabled = phylink_test(pl->supported, Autoneg); - } - - return 0; -@@ -956,7 +952,8 @@ static void phylink_apply_manual_flow(st - struct phylink_link_state *state) - { - /* If autoneg is disabled, pause AN is also disabled */ -- if (!state->an_enabled) -+ if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) - state->pause &= ~MLO_PAUSE_AN; - - /* Manual configuration of pause modes */ -@@ -996,21 +993,22 @@ static void phylink_mac_config(struct ph - const struct phylink_link_state *state) - { - phylink_dbg(pl, -- "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", -+ "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u\n", - __func__, phylink_an_mode_str(pl->cur_link_an_mode), - phy_modes(state->interface), - phy_speed_to_str(state->speed), - phy_duplex_to_str(state->duplex), - phy_rate_matching_to_str(state->rate_matching), - __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising, -- state->pause, state->link, state->an_enabled); -+ state->pause, state->link); - - pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, state); - } - - static void phylink_mac_pcs_an_restart(struct phylink *pl) - { -- if (pl->link_config.an_enabled && -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ pl->link_config.advertising) && - phy_interface_mode_is_8023z(pl->link_config.interface) && - phylink_autoneg_inband(pl->cur_link_an_mode)) { - if (pl->pcs) -@@ -1137,9 +1135,9 @@ static void phylink_mac_pcs_get_state(st - linkmode_copy(state->advertising, pl->link_config.advertising); - linkmode_zero(state->lp_advertising); - state->interface = pl->link_config.interface; -- state->an_enabled = pl->link_config.an_enabled; - state->rate_matching = pl->link_config.rate_matching; -- if (state->an_enabled) { -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) { - state->speed = SPEED_UNKNOWN; - state->duplex = DUPLEX_UNKNOWN; - state->pause = MLO_PAUSE_NONE; -@@ -1531,7 +1529,6 @@ struct phylink *phylink_create(struct ph - pl->link_config.pause = MLO_PAUSE_AN; - pl->link_config.speed = SPEED_UNKNOWN; - pl->link_config.duplex = DUPLEX_UNKNOWN; -- pl->link_config.an_enabled = true; - pl->mac_ops = mac_ops; - __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); - timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -2155,8 +2152,9 @@ static void phylink_get_ksettings(const - kset->base.speed = state->speed; - kset->base.duplex = state->duplex; - } -- kset->base.autoneg = state->an_enabled ? AUTONEG_ENABLE : -- AUTONEG_DISABLE; -+ kset->base.autoneg = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising) ? -+ AUTONEG_ENABLE : AUTONEG_DISABLE; - } - - /** -@@ -2303,9 +2301,8 @@ int phylink_ethtool_ksettings_set(struct - /* We have ruled out the case with a PHY attached, and the - * fixed-link cases. All that is left are in-band links. - */ -- config.an_enabled = kset->base.autoneg == AUTONEG_ENABLE; - linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising, -- config.an_enabled); -+ kset->base.autoneg == AUTONEG_ENABLE); - - /* If this link is with an SFP, ensure that changes to advertised modes - * also cause the associated interface to be selected such that the -@@ -2339,13 +2336,14 @@ int phylink_ethtool_ksettings_set(struct - } - - /* If autonegotiation is enabled, we must have an advertisement */ -- if (config.an_enabled && phylink_is_empty_linkmode(config.advertising)) -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ config.advertising) && -+ phylink_is_empty_linkmode(config.advertising)) - return -EINVAL; - - mutex_lock(&pl->state_mutex); - pl->link_config.speed = config.speed; - pl->link_config.duplex = config.duplex; -- pl->link_config.an_enabled = config.an_enabled; - - if (pl->link_config.interface != config.interface) { - /* The interface changed, e.g. 1000base-X <-> 2500base-X */ -@@ -2951,7 +2949,6 @@ static int phylink_sfp_config_phy(struct - config.speed = SPEED_UNKNOWN; - config.duplex = DUPLEX_UNKNOWN; - config.pause = MLO_PAUSE_AN; -- config.an_enabled = pl->link_config.an_enabled; - - /* Ignore errors if we're expecting a PHY to attach later */ - ret = phylink_validate(pl, support, &config); -@@ -3020,7 +3017,6 @@ static int phylink_sfp_config_optical(st - config.speed = SPEED_UNKNOWN; - config.duplex = DUPLEX_UNKNOWN; - config.pause = MLO_PAUSE_AN; -- config.an_enabled = true; - - /* For all the interfaces that are supported, reduce the sfp_support - * mask to only those link modes that can be supported. -@@ -3354,7 +3350,8 @@ void phylink_mii_c22_pcs_decode_state(st - /* If there is no link or autonegotiation is disabled, the LP advertisement - * data is not meaningful, so don't go any further. - */ -- if (!state->link || !state->an_enabled) -+ if (!state->link || !linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) - return; - - switch (state->interface) { ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -93,7 +93,6 @@ static inline bool phylink_autoneg_inban - * the medium link mode (@speed and @duplex) and the speed/duplex of the phy - * interface mode (@interface) are different. - * @link: true if the link is up. -- * @an_enabled: true if autonegotiation is enabled/desired. - * @an_complete: true if autonegotiation has completed. - */ - struct phylink_link_state { -@@ -105,7 +104,6 @@ struct phylink_link_state { - int pause; - int rate_matching; - unsigned int link:1; -- unsigned int an_enabled:1; - unsigned int an_complete:1; - }; - diff --git a/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch b/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch deleted file mode 100644 index c06a367b8b..0000000000 --- a/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch +++ /dev/null @@ -1,88 +0,0 @@ -From a3555d1f5c208f0a63eafee77381f68d304a0512 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 12 May 2023 17:58:37 +0100 -Subject: [PATCH 12/21] net: phylink: constify fwnode arguments - -Both phylink_create() and phylink_fwnode_phy_connect() do not modify -the fwnode argument that they are passed, so lets constify these. - -Reviewed-by: Simon Horman -Signed-off-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 11 ++++++----- - include/linux/phylink.h | 9 +++++---- - 2 files changed, 11 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -706,7 +706,7 @@ static int phylink_validate(struct phyli - } - - static int phylink_parse_fixedlink(struct phylink *pl, -- struct fwnode_handle *fwnode) -+ const struct fwnode_handle *fwnode) - { - struct fwnode_handle *fixed_node; - bool pause, asym_pause, autoneg; -@@ -817,7 +817,8 @@ static int phylink_parse_fixedlink(struc - return 0; - } - --static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) -+static int phylink_parse_mode(struct phylink *pl, -+ const struct fwnode_handle *fwnode) - { - struct fwnode_handle *dn; - const char *managed; -@@ -1440,7 +1441,7 @@ static void phylink_fixed_poll(struct ti - static const struct sfp_upstream_ops sfp_phylink_ops; - - static int phylink_register_sfp(struct phylink *pl, -- struct fwnode_handle *fwnode) -+ const struct fwnode_handle *fwnode) - { - struct sfp_bus *bus; - int ret; -@@ -1479,7 +1480,7 @@ static int phylink_register_sfp(struct p - * must use IS_ERR() to check for errors from this function. - */ - struct phylink *phylink_create(struct phylink_config *config, -- struct fwnode_handle *fwnode, -+ const struct fwnode_handle *fwnode, - phy_interface_t iface, - const struct phylink_mac_ops *mac_ops) - { -@@ -1809,7 +1810,7 @@ EXPORT_SYMBOL_GPL(phylink_of_phy_connect - * Returns 0 on success or a negative errno. - */ - int phylink_fwnode_phy_connect(struct phylink *pl, -- struct fwnode_handle *fwnode, -+ const struct fwnode_handle *fwnode, - u32 flags) - { - struct fwnode_handle *phy_fwnode; ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -568,16 +568,17 @@ void phylink_generic_validate(struct phy - unsigned long *supported, - struct phylink_link_state *state); - --struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, -- phy_interface_t iface, -- const struct phylink_mac_ops *mac_ops); -+struct phylink *phylink_create(struct phylink_config *, -+ const struct fwnode_handle *, -+ phy_interface_t, -+ const struct phylink_mac_ops *); - void phylink_destroy(struct phylink *); - bool phylink_expects_phy(struct phylink *pl); - - int phylink_connect_phy(struct phylink *, struct phy_device *); - int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags); - int phylink_fwnode_phy_connect(struct phylink *pl, -- struct fwnode_handle *fwnode, -+ const struct fwnode_handle *fwnode, - u32 flags); - void phylink_disconnect_phy(struct phylink *); - diff --git a/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch b/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch deleted file mode 100644 index 2649634dc7..0000000000 --- a/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 4a0faa02d419a6728abef0f1d8a32d8c35ef95e6 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 24 Mar 2023 09:23:53 +0000 -Subject: [PATCH] net: phy: constify fwnode_get_phy_node() fwnode argument - -fwnode_get_phy_node() does not motify the fwnode structure, so make -the argument const, - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 2 +- - include/linux/phy.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3003,7 +3003,7 @@ EXPORT_SYMBOL_GPL(device_phy_find_device - * and "phy-device" are not supported in ACPI. DT supports all the three - * named references to the phy node. - */ --struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode) -+struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode) - { - struct fwnode_handle *phy_node; - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1473,7 +1473,7 @@ int fwnode_get_phy_id(struct fwnode_hand - struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode); - struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode); - struct phy_device *device_phy_find_device(struct device *dev); --struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode); -+struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode); - struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45); - int phy_device_register(struct phy_device *phy); - void phy_device_free(struct phy_device *phydev); diff --git a/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch b/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch deleted file mode 100644 index 5eba18b026..0000000000 --- a/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch +++ /dev/null @@ -1,44 +0,0 @@ -From cc73de0411f7d3cdd157564a78f7a39058420ff8 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 13 May 2023 22:03:45 +0100 -Subject: [PATCH 13/21] net: phylink: fix ksettings_set() ethtool call - -While testing a Fiberstore SFP-10G-T module (which uses 10GBASE-R with -rate adaption) in a Clearfog platform (which can't do that) it was -found that the PHYs advertisement was not limited according to the -hosts capabilities when using ethtool to change it. - -Fix this by ensuring that we mask the advertisement with the computed -support mask as the very first thing we do. - -Fixes: cbc1bb1e4689 ("net: phylink: simplify phy case for ksettings_set method") -Signed-off-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2226,6 +2226,10 @@ int phylink_ethtool_ksettings_set(struct - - ASSERT_RTNL(); - -+ /* Mask out unsupported advertisements */ -+ linkmode_and(config.advertising, kset->link_modes.advertising, -+ pl->supported); -+ - if (pl->phydev) { - /* We can rely on phylib for this update; we also do not need - * to update the pl->link_config settings: -@@ -2250,10 +2254,6 @@ int phylink_ethtool_ksettings_set(struct - - config = pl->link_config; - -- /* Mask out unsupported advertisements */ -- linkmode_and(config.advertising, kset->link_modes.advertising, -- pl->supported); -- - /* FIXME: should we reject autoneg if phy/mac does not support it? */ - switch (kset->base.autoneg) { - case AUTONEG_DISABLE: diff --git a/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch b/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch deleted file mode 100644 index 79de6122b7..0000000000 --- a/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0100d1c5789018ba77bf2f4fab3bd91ecece7b3b Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Wed, 17 May 2023 11:38:12 +0100 -Subject: [PATCH 14/21] net: sfp: add support for setting signalling rate - -Add support to the SFP layer to allow phylink to set the signalling -rate for a SFP module. The rate given will be in units of kilo-baud -(1000 baud). - -Reviewed-by: Simon Horman -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 24 ++++++++++++++++++++++++ - drivers/net/phy/sfp-bus.c | 20 ++++++++++++++++++++ - drivers/net/phy/sfp.c | 5 +++++ - drivers/net/phy/sfp.h | 1 + - include/linux/sfp.h | 6 ++++++ - 5 files changed, 56 insertions(+) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -156,6 +156,23 @@ static const char *phylink_an_mode_str(u - return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; - } - -+static unsigned int phylink_interface_signal_rate(phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */ -+ return 1250; -+ case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */ -+ return 3125; -+ case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */ -+ return 5156; -+ case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */ -+ return 10313; -+ default: -+ return 0; -+ } -+} -+ - /** - * phylink_interface_max_speed() - get the maximum speed of a phy interface - * @interface: phy interface mode defined by &typedef phy_interface_t -@@ -1024,6 +1041,7 @@ static void phylink_major_config(struct - { - struct phylink_pcs *pcs = NULL; - bool pcs_changed = false; -+ unsigned int rate_kbd; - int err; - - phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); -@@ -1083,6 +1101,12 @@ static void phylink_major_config(struct - ERR_PTR(err)); - } - -+ if (pl->sfp_bus) { -+ rate_kbd = phylink_interface_signal_rate(state->interface); -+ if (rate_kbd) -+ sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd); -+ } -+ - phylink_pcs_poll_start(pl); - } - ---- a/drivers/net/phy/sfp-bus.c -+++ b/drivers/net/phy/sfp-bus.c -@@ -586,6 +586,26 @@ static void sfp_upstream_clear(struct sf - } - - /** -+ * sfp_upstream_set_signal_rate() - set data signalling rate -+ * @bus: a pointer to the &struct sfp_bus structure for the sfp module -+ * @rate_kbd: signalling rate in units of 1000 baud -+ * -+ * Configure the rate select settings on the SFP module for the signalling -+ * rate (not the same as the data rate). -+ * -+ * Locks that may be held: -+ * Phylink's state_mutex -+ * rtnl lock -+ * SFP's sm_mutex -+ */ -+void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd) -+{ -+ if (bus->registered) -+ bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd); -+} -+EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate); -+ -+/** - * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode - * @fwnode: firmware node for the parent device (MAC or PHY) - * ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -2474,6 +2474,10 @@ static void sfp_stop(struct sfp *sfp) - sfp_sm_event(sfp, SFP_E_DEV_DOWN); - } - -+static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd) -+{ -+} -+ - static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo) - { - /* locking... and check module is present */ -@@ -2552,6 +2556,7 @@ static const struct sfp_socket_ops sfp_m - .detach = sfp_detach, - .start = sfp_start, - .stop = sfp_stop, -+ .set_signal_rate = sfp_set_signal_rate, - .module_info = sfp_module_info, - .module_eeprom = sfp_module_eeprom, - .module_eeprom_by_page = sfp_module_eeprom_by_page, ---- a/drivers/net/phy/sfp.h -+++ b/drivers/net/phy/sfp.h -@@ -19,6 +19,7 @@ struct sfp_socket_ops { - void (*detach)(struct sfp *sfp); - void (*start)(struct sfp *sfp); - void (*stop)(struct sfp *sfp); -+ void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd); - int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo); - int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee, - u8 *data); ---- a/include/linux/sfp.h -+++ b/include/linux/sfp.h -@@ -547,6 +547,7 @@ int sfp_get_module_eeprom_by_page(struct - struct netlink_ext_ack *extack); - void sfp_upstream_start(struct sfp_bus *bus); - void sfp_upstream_stop(struct sfp_bus *bus); -+void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd); - void sfp_bus_put(struct sfp_bus *bus); - struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); - int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, -@@ -606,6 +607,11 @@ static inline void sfp_upstream_stop(str - { - } - -+static inline void sfp_upstream_set_signal_rate(struct sfp_bus *bus, -+ unsigned int rate_kbd) -+{ -+} -+ - static inline void sfp_bus_put(struct sfp_bus *bus) - { - } diff --git a/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch b/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch deleted file mode 100644 index 8a694c86da..0000000000 --- a/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch +++ /dev/null @@ -1,147 +0,0 @@ -From b84acdb07222a701bfc6403b374249c86f97d18d Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 19 May 2023 14:03:59 +0100 -Subject: [PATCH 15/21] net: phy: add helpers for comparing phy IDs - -There are several places which open code comparing PHY IDs. Provide a -couple of helpers to assist with this, using a slightly simpler test -than the original: - -- phy_id_compare() compares two arbitary PHY IDs and a mask of the - significant bits in the ID. -- phydev_id_compare() compares the bound phydev with the specified - PHY ID, using the bound driver's mask. - -Signed-off-by: Russell King -Reviewed-by: Simon Horman -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/micrel.c | 6 +++--- - drivers/net/phy/phy_device.c | 16 +++++++--------- - drivers/net/phy/phylink.c | 4 ++-- - include/linux/phy.h | 28 ++++++++++++++++++++++++++++ - 4 files changed, 40 insertions(+), 14 deletions(-) - ---- a/drivers/net/phy/micrel.c -+++ b/drivers/net/phy/micrel.c -@@ -620,7 +620,7 @@ static int ksz8051_ksz8795_match_phy_dev - { - int ret; - -- if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051) -+ if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK)) - return 0; - - ret = phy_read(phydev, MII_BMSR); -@@ -1455,7 +1455,7 @@ static int ksz9x31_cable_test_fault_leng - * - * distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity - */ -- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131) -+ if (phydev_id_compare(phydev, PHY_ID_KSZ9131)) - dt = clamp(dt - 22, 0, 255); - - return (dt * 400) / 10; -@@ -1887,7 +1887,7 @@ static __always_inline int ksz886x_cable - */ - dt = FIELD_GET(data_mask, status); - -- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814) -+ if (phydev_id_compare(phydev, PHY_ID_LAN8814)) - return ((dt - 22) * 800) / 10; - else - return (dt * 400) / 10; ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -422,8 +422,7 @@ int phy_unregister_fixup(const char *bus - fixup = list_entry(pos, struct phy_fixup, list); - - if ((!strcmp(fixup->bus_id, bus_id)) && -- ((fixup->phy_uid & phy_uid_mask) == -- (phy_uid & phy_uid_mask))) { -+ phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) { - list_del(&fixup->list); - kfree(fixup); - ret = 0; -@@ -459,8 +458,8 @@ static int phy_needs_fixup(struct phy_de - if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) - return 0; - -- if ((fixup->phy_uid & fixup->phy_uid_mask) != -- (phydev->phy_id & fixup->phy_uid_mask)) -+ if (!phy_id_compare(phydev->phy_id, fixup->phy_uid, -+ fixup->phy_uid_mask)) - if (fixup->phy_uid != PHY_ANY_UID) - return 0; - -@@ -507,15 +506,14 @@ static int phy_bus_match(struct device * - if (phydev->c45_ids.device_ids[i] == 0xffffffff) - continue; - -- if ((phydrv->phy_id & phydrv->phy_id_mask) == -- (phydev->c45_ids.device_ids[i] & -- phydrv->phy_id_mask)) -+ if (phy_id_compare(phydev->c45_ids.device_ids[i], -+ phydrv->phy_id, phydrv->phy_id_mask)) - return 1; - } - return 0; - } else { -- return (phydrv->phy_id & phydrv->phy_id_mask) == -- (phydev->phy_id & phydrv->phy_id_mask); -+ return phy_id_compare(phydev->phy_id, phydrv->phy_id, -+ phydrv->phy_id_mask); - } - } - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3151,8 +3151,8 @@ static void phylink_sfp_link_up(void *up - */ - static bool phylink_phy_no_inband(struct phy_device *phy) - { -- return phy->is_c45 && -- (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150; -+ return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], -+ 0xae025150, 0xfffffff0); - } - - static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -993,6 +993,34 @@ struct phy_driver { - #define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 4) - #define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 10) - -+/** -+ * phy_id_compare - compare @id1 with @id2 taking account of @mask -+ * @id1: first PHY ID -+ * @id2: second PHY ID -+ * @mask: the PHY ID mask, set bits are significant in matching -+ * -+ * Return true if the bits from @id1 and @id2 specified by @mask match. -+ * This uses an equivalent test to (@id & @mask) == (@phy_id & @mask). -+ */ -+static inline bool phy_id_compare(u32 id1, u32 id2, u32 mask) -+{ -+ return !((id1 ^ id2) & mask); -+} -+ -+/** -+ * phydev_id_compare - compare @id with the PHY's Clause 22 ID -+ * @phydev: the PHY device -+ * @id: the PHY ID to be matched -+ * -+ * Compare the @phydev clause 22 ID with the provided @id and return true or -+ * false depending whether it matches, using the bound driver mask. The -+ * @phydev must be bound to a driver. -+ */ -+static inline bool phydev_id_compare(struct phy_device *phydev, u32 id) -+{ -+ return phy_id_compare(id, phydev->phy_id, phydev->drv->phy_id_mask); -+} -+ - /* A Structure for boards to register fixups with the PHY Lib */ - struct phy_fixup { - struct list_head list; diff --git a/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch b/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch deleted file mode 100644 index 5970355a6c..0000000000 --- a/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 441e1e44301fc5762a06737f8ec04bf1ce3fb039 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 20 May 2023 11:41:42 +0100 -Subject: [PATCH 16/21] net: phylink: require supported_interfaces to be filled - -We have been requiring the supported_interfaces bitmap to be filled in -by MAC drivers that have a mac_select_pcs() method. Now that all MAC -drivers fill in the supported_interfaces bitmap, it is time to enforce -this. We have already required supported_interfaces to be set in order -for optical SFPs to be configured in commit f81fa96d8a6c ("net: phylink: -use phy_interface_t bitmaps for optical modules"). - -Refuse phylink creation if supported_interfaces is empty, and remove -code to deal with cases where this mask is empty. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/E1q0K1u-006EIP-ET@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 26 +++++++++++--------------- - 1 file changed, 11 insertions(+), 15 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -710,14 +710,11 @@ static int phylink_validate(struct phyli - { - const unsigned long *interfaces = pl->config->supported_interfaces; - -- if (!phy_interface_empty(interfaces)) { -- if (state->interface == PHY_INTERFACE_MODE_NA) -- return phylink_validate_mask(pl, supported, state, -- interfaces); -+ if (state->interface == PHY_INTERFACE_MODE_NA) -+ return phylink_validate_mask(pl, supported, state, interfaces); - -- if (!test_bit(state->interface, interfaces)) -- return -EINVAL; -- } -+ if (!test_bit(state->interface, interfaces)) -+ return -EINVAL; - - return phylink_validate_mac_and_pcs(pl, supported, state); - } -@@ -1512,19 +1509,18 @@ struct phylink *phylink_create(struct ph - struct phylink *pl; - int ret; - -- if (mac_ops->mac_select_pcs && -- mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != -- ERR_PTR(-EOPNOTSUPP)) -- using_mac_select_pcs = true; -- - /* Validate the supplied configuration */ -- if (using_mac_select_pcs && -- phy_interface_empty(config->supported_interfaces)) { -+ if (phy_interface_empty(config->supported_interfaces)) { - dev_err(config->dev, -- "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n"); -+ "phylink: error: empty supported_interfaces\n"); - return ERR_PTR(-EINVAL); - } - -+ if (mac_ops->mac_select_pcs && -+ mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != -+ ERR_PTR(-EOPNOTSUPP)) -+ using_mac_select_pcs = true; -+ - pl = kzalloc(sizeof(*pl), GFP_KERNEL); - if (!pl) - return ERR_PTR(-ENOMEM); diff --git a/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch b/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch deleted file mode 100644 index 3a26b4b600..0000000000 --- a/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 4b624a39f2ab523ca6a6ad9448fab1deb7b101e2 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 23 May 2023 11:15:53 +0100 -Subject: [PATCH 17/21] net: phylink: remove duplicated linkmode pause - resolution - -Phylink had two chunks of code virtually the same for resolving the -negotiated pause modes. Factor this down to one function. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 15 ++++----------- - 1 file changed, 4 insertions(+), 11 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -976,11 +976,10 @@ static void phylink_apply_manual_flow(st - state->pause = pl->link_config.pause; - } - --static void phylink_resolve_flow(struct phylink_link_state *state) -+static void phylink_resolve_an_pause(struct phylink_link_state *state) - { - bool tx_pause, rx_pause; - -- state->pause = MLO_PAUSE_NONE; - if (state->duplex == DUPLEX_FULL) { - linkmode_resolve_pause(state->advertising, - state->lp_advertising, -@@ -1192,7 +1191,8 @@ static void phylink_get_fixed_state(stru - else if (pl->link_gpio) - state->link = !!gpiod_get_value_cansleep(pl->link_gpio); - -- phylink_resolve_flow(state); -+ state->pause = MLO_PAUSE_NONE; -+ phylink_resolve_an_pause(state); - } - - static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) -@@ -3215,7 +3215,6 @@ static const struct sfp_upstream_ops sfp - static void phylink_decode_c37_word(struct phylink_link_state *state, - uint16_t config_reg, int speed) - { -- bool tx_pause, rx_pause; - int fd_bit; - - if (speed == SPEED_2500) -@@ -3234,13 +3233,7 @@ static void phylink_decode_c37_word(stru - state->link = false; - } - -- linkmode_resolve_pause(state->advertising, state->lp_advertising, -- &tx_pause, &rx_pause); -- -- if (tx_pause) -- state->pause |= MLO_PAUSE_TX; -- if (rx_pause) -- state->pause |= MLO_PAUSE_RX; -+ phylink_resolve_an_pause(state); - } - - static void phylink_decode_sgmii_word(struct phylink_link_state *state, diff --git a/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch b/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch deleted file mode 100644 index 2b2634f80c..0000000000 --- a/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch +++ /dev/null @@ -1,76 +0,0 @@ -From aa8b6bd2b1f235b262bd27f317a0516f196c2c6a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 23 May 2023 11:15:58 +0100 -Subject: [PATCH 18/21] net: phylink: add function to resolve clause 73 - negotiation - -Add a function to resolve clause 73 negotiation according to the -priority resolution function described in clause 73.3.6. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 39 +++++++++++++++++++++++++++++++++++++++ - include/linux/phylink.h | 2 ++ - 2 files changed, 41 insertions(+) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3212,6 +3212,45 @@ static const struct sfp_upstream_ops sfp - - /* Helpers for MAC drivers */ - -+static struct { -+ int bit; -+ int speed; -+} phylink_c73_priority_resolution[] = { -+ { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 }, -+ { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 }, -+ /* 100GBASE-KP4 and 100GBASE-CR10 not supported */ -+ { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 }, -+ { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 }, -+ { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 }, -+ { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 }, -+ /* 5GBASE-KR not supported */ -+ { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 }, -+ { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 }, -+}; -+ -+void phylink_resolve_c73(struct phylink_link_state *state) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) { -+ int bit = phylink_c73_priority_resolution[i].bit; -+ if (linkmode_test_bit(bit, state->advertising) && -+ linkmode_test_bit(bit, state->lp_advertising)) -+ break; -+ } -+ -+ if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) { -+ state->speed = phylink_c73_priority_resolution[i].speed; -+ state->duplex = DUPLEX_FULL; -+ } else { -+ /* negotiation failure */ -+ state->link = false; -+ } -+ -+ phylink_resolve_an_pause(state); -+} -+EXPORT_SYMBOL_GPL(phylink_resolve_c73); -+ - static void phylink_decode_c37_word(struct phylink_link_state *state, - uint16_t config_reg, int speed) - { ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -656,6 +656,8 @@ int phylink_mii_c22_pcs_config(struct md - const unsigned long *advertising); - void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); - -+void phylink_resolve_c73(struct phylink_link_state *state); -+ - void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs, - struct phylink_link_state *state); - diff --git a/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch b/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch deleted file mode 100644 index eea99a5d78..0000000000 --- a/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 796d709363135a6bd6a8ccc07b509c939e5b855f Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 23 May 2023 16:31:50 +0100 -Subject: [PATCH 19/21] net: phylink: provide phylink_pcs_config() and - phylink_pcs_link_up() - -Add two helper functions for calling PCS methods. phylink_pcs_config() -allows us to handle PCS configuration specifics in one location, rather -than the two call sites. phylink_pcs_link_up() gives us consistency. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1q1TzK-007Exd-Rs@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 53 ++++++++++++++++++++++++--------------- - 1 file changed, 33 insertions(+), 20 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -991,6 +991,25 @@ static void phylink_resolve_an_pause(str - } - } - -+static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+ const struct phylink_link_state *state, -+ bool permit_pause_to_mac) -+{ -+ if (!pcs) -+ return 0; -+ -+ return pcs->ops->pcs_config(pcs, mode, state->interface, -+ state->advertising, permit_pause_to_mac); -+} -+ -+static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, int speed, -+ int duplex) -+{ -+ if (pcs && pcs->ops->pcs_link_up) -+ pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); -+} -+ - static void phylink_pcs_poll_stop(struct phylink *pl) - { - if (pl->cfg_link_an_mode == MLO_AN_INBAND) -@@ -1074,18 +1093,15 @@ static void phylink_major_config(struct - - phylink_mac_config(pl, state); - -- if (pl->pcs) { -- err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, -- state->interface, -- state->advertising, -- !!(pl->link_config.pause & -- MLO_PAUSE_AN)); -- if (err < 0) -- phylink_err(pl, "pcs_config failed: %pe\n", -- ERR_PTR(err)); -- if (err > 0) -- restart = true; -- } -+ err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, -+ !!(pl->link_config.pause & -+ MLO_PAUSE_AN)); -+ if (err < 0) -+ phylink_err(pl, "pcs_config failed: %pe\n", -+ ERR_PTR(err)); -+ else if (err > 0) -+ restart = true; -+ - if (restart) - phylink_mac_pcs_an_restart(pl); - -@@ -1136,11 +1152,9 @@ static int phylink_change_inband_advert( - * restart negotiation if the pcs_config() helper indicates that - * the programmed advertisement has changed. - */ -- ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, -- pl->link_config.interface, -- pl->link_config.advertising, -- !!(pl->link_config.pause & -- MLO_PAUSE_AN)); -+ ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, -+ &pl->link_config, -+ !!(pl->link_config.pause & MLO_PAUSE_AN)); - if (ret < 0) - return ret; - -@@ -1272,9 +1286,8 @@ static void phylink_link_up(struct phyli - - pl->cur_interface = link_state.interface; - -- if (pl->pcs && pl->pcs->ops->pcs_link_up) -- pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode, -- pl->cur_interface, speed, duplex); -+ phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, -+ speed, duplex); - - pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, - pl->cur_interface, speed, duplex, diff --git a/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch b/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch deleted file mode 100644 index 2f7f7a5737..0000000000 --- a/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 11933aa76865621d8e82553c8f3bc07796a5aaa2 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 1 Jun 2023 10:12:06 +0100 -Subject: [PATCH 20/21] net: phylink: actually fix ksettings_set() ethtool call - -Raju Lakkaraju reported that the below commit caused a regression -with Lan743x drivers and a 2.5G SFP. Sadly, this is because the commit -was utterly wrong. Let's fix this properly by not moving the -linkmode_and(), but instead copying the link ksettings and then -modifying the advertising mask before passing the modified link -ksettings to phylib. - -Fixes: df0acdc59b09 ("net: phylink: fix ksettings_set() ethtool call") -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1q4eLm-00Ayxk-GZ@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 15 ++++++++++----- - 1 file changed, 10 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2259,11 +2259,13 @@ int phylink_ethtool_ksettings_set(struct - - ASSERT_RTNL(); - -- /* Mask out unsupported advertisements */ -- linkmode_and(config.advertising, kset->link_modes.advertising, -- pl->supported); -- - if (pl->phydev) { -+ struct ethtool_link_ksettings phy_kset = *kset; -+ -+ linkmode_and(phy_kset.link_modes.advertising, -+ phy_kset.link_modes.advertising, -+ pl->supported); -+ - /* We can rely on phylib for this update; we also do not need - * to update the pl->link_config settings: - * - the configuration returned via ksettings_get() will come -@@ -2282,10 +2284,13 @@ int phylink_ethtool_ksettings_set(struct - * the presence of a PHY, this should not be changed as that - * should be determined from the media side advertisement. - */ -- return phy_ethtool_ksettings_set(pl->phydev, kset); -+ return phy_ethtool_ksettings_set(pl->phydev, &phy_kset); - } - - config = pl->link_config; -+ /* Mask out unsupported advertisements */ -+ linkmode_and(config.advertising, kset->link_modes.advertising, -+ pl->supported); - - /* FIXME: should we reject autoneg if phy/mac does not support it? */ - switch (kset->base.autoneg) { diff --git a/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch b/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch deleted file mode 100644 index e1a8539aae..0000000000 --- a/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch +++ /dev/null @@ -1,324 +0,0 @@ -From 79b07c3e9c4a2272927be8848c26b372516e1958 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:22 +0100 -Subject: [PATCH 21/21] net: phylink: add PCS negotiation mode - -PCS have to work out whether they should enable PCS negotiation by -looking at the "mode" and "interface" arguments, and the Autoneg bit -in the advertising mask. - -This leads to some complex logic, so lets pull that out into phylink -and instead pass a "neg_mode" argument to the PCS configuration and -link up methods, instead of the "mode" argument. - -In order to transition drivers, add a "neg_mode" flag to the phylink -PCS structure to PCS can indicate whether they want to be passed the -neg_mode or the old mode argument. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8De-00EaFA-Ht@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 45 +++++++++++++---- - include/linux/phylink.h | 104 +++++++++++++++++++++++++++++++++++--- - 2 files changed, 132 insertions(+), 17 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -71,6 +71,7 @@ struct phylink { - struct mutex state_mutex; - struct phylink_link_state phy_state; - struct work_struct resolve; -+ unsigned int pcs_neg_mode; - - bool mac_link_dropped; - bool using_mac_select_pcs; -@@ -991,23 +992,23 @@ static void phylink_resolve_an_pause(str - } - } - --static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - const struct phylink_link_state *state, - bool permit_pause_to_mac) - { - if (!pcs) - return 0; - -- return pcs->ops->pcs_config(pcs, mode, state->interface, -+ return pcs->ops->pcs_config(pcs, neg_mode, state->interface, - state->advertising, permit_pause_to_mac); - } - --static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -+static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, int speed, - int duplex) - { - if (pcs && pcs->ops->pcs_link_up) -- pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); -+ pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); - } - - static void phylink_pcs_poll_stop(struct phylink *pl) -@@ -1057,10 +1058,15 @@ static void phylink_major_config(struct - struct phylink_pcs *pcs = NULL; - bool pcs_changed = false; - unsigned int rate_kbd; -+ unsigned int neg_mode; - int err; - - phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); - -+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, -+ state->interface, -+ state->advertising); -+ - if (pl->using_mac_select_pcs) { - pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); - if (IS_ERR(pcs)) { -@@ -1093,9 +1099,12 @@ static void phylink_major_config(struct - - phylink_mac_config(pl, state); - -- err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, -- !!(pl->link_config.pause & -- MLO_PAUSE_AN)); -+ neg_mode = pl->cur_link_an_mode; -+ if (pl->pcs && pl->pcs->neg_mode) -+ neg_mode = pl->pcs_neg_mode; -+ -+ err = phylink_pcs_config(pl->pcs, neg_mode, state, -+ !!(pl->link_config.pause & MLO_PAUSE_AN)); - if (err < 0) - phylink_err(pl, "pcs_config failed: %pe\n", - ERR_PTR(err)); -@@ -1130,6 +1139,7 @@ static void phylink_major_config(struct - */ - static int phylink_change_inband_advert(struct phylink *pl) - { -+ unsigned int neg_mode; - int ret; - - if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) -@@ -1148,12 +1158,20 @@ static int phylink_change_inband_advert( - __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, - pl->link_config.pause); - -+ /* Recompute the PCS neg mode */ -+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, -+ pl->link_config.interface, -+ pl->link_config.advertising); -+ -+ neg_mode = pl->cur_link_an_mode; -+ if (pl->pcs->neg_mode) -+ neg_mode = pl->pcs_neg_mode; -+ - /* Modern PCS-based method; update the advert at the PCS, and - * restart negotiation if the pcs_config() helper indicates that - * the programmed advertisement has changed. - */ -- ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, -- &pl->link_config, -+ ret = phylink_pcs_config(pl->pcs, neg_mode, &pl->link_config, - !!(pl->link_config.pause & MLO_PAUSE_AN)); - if (ret < 0) - return ret; -@@ -1256,6 +1274,7 @@ static void phylink_link_up(struct phyli - struct phylink_link_state link_state) - { - struct net_device *ndev = pl->netdev; -+ unsigned int neg_mode; - int speed, duplex; - bool rx_pause; - -@@ -1286,8 +1305,12 @@ static void phylink_link_up(struct phyli - - pl->cur_interface = link_state.interface; - -- phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, -- speed, duplex); -+ neg_mode = pl->cur_link_an_mode; -+ if (pl->pcs && pl->pcs->neg_mode) -+ neg_mode = pl->pcs_neg_mode; -+ -+ phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed, -+ duplex); - - pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, - pl->cur_interface, speed, duplex, ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -21,6 +21,24 @@ enum { - MLO_AN_FIXED, /* Fixed-link mode */ - MLO_AN_INBAND, /* In-band protocol */ - -+ /* PCS "negotiation" mode. -+ * PHYLINK_PCS_NEG_NONE - protocol has no inband capability -+ * PHYLINK_PCS_NEG_OUTBAND - some out of band or fixed link setting -+ * PHYLINK_PCS_NEG_INBAND_DISABLED - inband mode disabled, e.g. -+ * 1000base-X with autoneg off -+ * PHYLINK_PCS_NEG_INBAND_ENABLED - inband mode enabled -+ * Additionally, this can be tested using bitmasks: -+ * PHYLINK_PCS_NEG_INBAND - inband mode selected -+ * PHYLINK_PCS_NEG_ENABLED - negotiation mode enabled -+ */ -+ PHYLINK_PCS_NEG_NONE = 0, -+ PHYLINK_PCS_NEG_ENABLED = BIT(4), -+ PHYLINK_PCS_NEG_OUTBAND = BIT(5), -+ PHYLINK_PCS_NEG_INBAND = BIT(6), -+ PHYLINK_PCS_NEG_INBAND_DISABLED = PHYLINK_PCS_NEG_INBAND, -+ PHYLINK_PCS_NEG_INBAND_ENABLED = PHYLINK_PCS_NEG_INBAND | -+ PHYLINK_PCS_NEG_ENABLED, -+ - /* MAC_SYM_PAUSE and MAC_ASYM_PAUSE are used when configuring our - * autonegotiation advertisement. They correspond to the PAUSE and - * ASM_DIR bits defined by 802.3, respectively. -@@ -80,6 +98,70 @@ static inline bool phylink_autoneg_inban - } - - /** -+ * phylink_pcs_neg_mode() - helper to determine PCS inband mode -+ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. -+ * @interface: interface mode to be used -+ * @advertising: adertisement ethtool link mode mask -+ * -+ * Determines the negotiation mode to be used by the PCS, and returns -+ * one of: -+ * %PHYLINK_PCS_NEG_NONE: interface mode does not support inband -+ * %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY) -+ * will be used. -+ * %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg disabled -+ * %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled -+ * -+ * Note: this is for cases where the PCS itself is involved in negotiation -+ * (e.g. Clause 37, SGMII and similar) not Clause 73. -+ */ -+static inline unsigned int phylink_pcs_neg_mode(unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising) -+{ -+ unsigned int neg_mode; -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_QUSGMII: -+ case PHY_INTERFACE_MODE_USXGMII: -+ /* These protocols are designed for use with a PHY which -+ * communicates its negotiation result back to the MAC via -+ * inband communication. Note: there exist PHYs that run -+ * with SGMII but do not send the inband data. -+ */ -+ if (!phylink_autoneg_inband(mode)) -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ else -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ break; -+ -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ /* 1000base-X is designed for use media-side for Fibre -+ * connections, and thus the Autoneg bit needs to be -+ * taken into account. We also do this for 2500base-X -+ * as well, but drivers may not support this, so may -+ * need to override this. -+ */ -+ if (!phylink_autoneg_inband(mode)) -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ advertising)) -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ else -+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; -+ break; -+ -+ default: -+ neg_mode = PHYLINK_PCS_NEG_NONE; -+ break; -+ } -+ -+ return neg_mode; -+} -+ -+/** - * struct phylink_link_state - link state structure - * @advertising: ethtool bitmask containing advertised link modes - * @lp_advertising: ethtool bitmask containing link partner advertised link -@@ -436,6 +518,7 @@ struct phylink_pcs_ops; - /** - * struct phylink_pcs - PHYLINK PCS instance - * @ops: a pointer to the &struct phylink_pcs_ops structure -+ * @neg_mode: provide PCS neg mode via "mode" argument - * @poll: poll the PCS for link changes - * - * This structure is designed to be embedded within the PCS private data, -@@ -443,6 +526,7 @@ struct phylink_pcs_ops; - */ - struct phylink_pcs { - const struct phylink_pcs_ops *ops; -+ bool neg_mode; - bool poll; - }; - -@@ -460,12 +544,12 @@ struct phylink_pcs_ops { - const struct phylink_link_state *state); - void (*pcs_get_state)(struct phylink_pcs *pcs, - struct phylink_link_state *state); -- int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode, -+ int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac); - void (*pcs_an_restart)(struct phylink_pcs *pcs); -- void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int mode, -+ void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, int speed, int duplex); - }; - -@@ -508,7 +592,7 @@ void pcs_get_state(struct phylink_pcs *p - /** - * pcs_config() - Configure the PCS mode and advertisement - * @pcs: a pointer to a &struct phylink_pcs. -- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. -+ * @neg_mode: link negotiation mode (see below) - * @interface: interface mode to be used - * @advertising: adertisement ethtool link mode mask - * @permit_pause_to_mac: permit forwarding pause resolution to MAC -@@ -526,8 +610,12 @@ void pcs_get_state(struct phylink_pcs *p - * For 1000BASE-X, the advertisement should be programmed into the PCS. - * - * For most 10GBASE-R, there is no advertisement. -+ * -+ * The %neg_mode argument should be tested via the phylink_mode_*() family of -+ * functions, or for PCS that set pcs->neg_mode true, should be tested -+ * against the %PHYLINK_PCS_NEG_* definitions. - */ --int pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+int pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, const unsigned long *advertising, - bool permit_pause_to_mac); - -@@ -543,7 +631,7 @@ void pcs_an_restart(struct phylink_pcs * - /** - * pcs_link_up() - program the PCS for the resolved link configuration - * @pcs: a pointer to a &struct phylink_pcs. -- * @mode: link autonegotiation mode -+ * @neg_mode: link negotiation mode (see below) - * @interface: link &typedef phy_interface_t mode - * @speed: link speed - * @duplex: link duplex -@@ -552,8 +640,12 @@ void pcs_an_restart(struct phylink_pcs * - * the resolved link parameters. For example, a PCS operating in SGMII - * mode without in-band AN needs to be manually configured for the link - * and duplex setting. Otherwise, this should be a no-op. -+ * -+ * The %mode argument should be tested via the phylink_mode_*() family of -+ * functions, or for PCS that set pcs->neg_mode true, should be tested -+ * against the %PHYLINK_PCS_NEG_* definitions. - */ --void pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -+void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, int speed, int duplex); - #endif - diff --git a/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch b/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch deleted file mode 100644 index 473e9d5836..0000000000 --- a/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch +++ /dev/null @@ -1,45 +0,0 @@ -From cdb08aa0473730315dbc088d5394e59622314034 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:27 +0100 -Subject: [PATCH 1/2] net: phylink: convert phylink_mii_c22_pcs_config() to - neg_mode - -Use phylink_pcs_neg_mode() for phylink_mii_c22_pcs_config(). This -results in no functional change. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8Dj-00EaFG-Mt@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3558,6 +3558,7 @@ int phylink_mii_c22_pcs_config(struct md - phy_interface_t interface, - const unsigned long *advertising) - { -+ unsigned int neg_mode; - bool changed = 0; - u16 bmcr; - int ret, adv; -@@ -3571,15 +3572,13 @@ int phylink_mii_c22_pcs_config(struct md - changed = ret; - } - -- /* Ensure ISOLATE bit is disabled */ -- if (mode == MLO_AN_INBAND && -- (interface == PHY_INTERFACE_MODE_SGMII || -- interface == PHY_INTERFACE_MODE_QSGMII || -- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising))) -+ neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) - bmcr = BMCR_ANENABLE; - else - bmcr = 0; - -+ /* Configure the inband state. Ensure ISOLATE bit is disabled */ - ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr); - if (ret < 0) - return ret; diff --git a/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch b/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch deleted file mode 100644 index 5572850e95..0000000000 --- a/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch +++ /dev/null @@ -1,187 +0,0 @@ -From febf2aaf05641f3258cc30e072aff65cffc7c82c Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:32 +0100 -Subject: [PATCH 2/2] net: phylink: pass neg_mode into - phylink_mii_c22_pcs_config() - -Convert fman_dtsec, xilinx_axienet and pcs-lynx to pass the neg_mode -into phylink_mii_c22_pcs_config(). Where appropriate, drivers are -updated to have neg_mode passed into their pcs_config() and -pcs_link_up() functions. For other drivers, we just hoist the call -to phylink_pcs_neg_mode() to their pcs_config() method out of -phylink_mii_c22_pcs_config(). - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8Do-00EaFM-Ra@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - .../net/ethernet/freescale/fman/fman_dtsec.c | 7 ++++--- - .../net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++-- - drivers/net/pcs/pcs-lynx.c | 18 ++++++++++++------ - drivers/net/phy/phylink.c | 9 ++++----- - include/linux/phylink.h | 5 +++-- - 5 files changed, 27 insertions(+), 18 deletions(-) - ---- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c -@@ -763,15 +763,15 @@ static void dtsec_pcs_get_state(struct p - phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); - } - --static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) - { - struct fman_mac *dtsec = pcs_to_dtsec(pcs); - -- return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, -- advertising); -+ return phylink_mii_c22_pcs_config(dtsec->tbidev, interface, -+ advertising, neg_mode); - } - - static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) -@@ -1447,6 +1447,7 @@ int dtsec_initialization(struct mac_devi - goto _return_fm_mac_free; - } - dtsec->pcs.ops = &dtsec_pcs_ops; -+ dtsec->pcs.neg_mode = true; - dtsec->pcs.poll = true; - - supported = mac_dev->phylink_config.supported_interfaces; ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1631,7 +1631,7 @@ static void axienet_pcs_an_restart(struc - phylink_mii_c22_pcs_an_restart(pcs_phy); - } - --static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) -@@ -1653,7 +1653,8 @@ static int axienet_pcs_config(struct phy - } - } - -- ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising); -+ ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising, -+ neg_mode); - if (ret < 0) - netdev_warn(ndev, "Failed to configure PCS: %d\n", ret); - -@@ -2129,6 +2130,7 @@ static int axienet_probe(struct platform - } - of_node_put(np); - lp->pcs.ops = &axienet_pcs_ops; -+ lp->pcs.neg_mode = true; - lp->pcs.poll = true; - } - ---- a/drivers/net/pcs/pcs-lynx.c -+++ b/drivers/net/pcs/pcs-lynx.c -@@ -122,9 +122,10 @@ static void lynx_pcs_get_state(struct ph - state->link, state->an_complete); - } - --static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, -+static int lynx_pcs_config_giga(struct mdio_device *pcs, - phy_interface_t interface, -- const unsigned long *advertising) -+ const unsigned long *advertising, -+ unsigned int neg_mode) - { - u32 link_timer; - u16 if_mode; -@@ -137,8 +138,9 @@ static int lynx_pcs_config_giga(struct m - - if_mode = 0; - } else { -+ /* SGMII and QSGMII */ - if_mode = IF_MODE_SGMII_EN; -- if (mode == MLO_AN_INBAND) { -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { - if_mode |= IF_MODE_USE_SGMII_AN; - - /* Adjust link timer for SGMII */ -@@ -154,7 +156,8 @@ static int lynx_pcs_config_giga(struct m - if (err) - return err; - -- return phylink_mii_c22_pcs_config(pcs, mode, interface, advertising); -+ return phylink_mii_c22_pcs_config(pcs, interface, advertising, -+ neg_mode); - } - - static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode, -@@ -181,13 +184,16 @@ static int lynx_pcs_config(struct phylin - bool permit) - { - struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); -+ unsigned int neg_mode; -+ -+ neg_mode = phylink_pcs_neg_mode(mode, ifmode, advertising); - - switch (ifmode) { - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -- return lynx_pcs_config_giga(lynx->mdio, mode, ifmode, -- advertising); -+ return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising, -+ neg_mode); - case PHY_INTERFACE_MODE_2500BASEX: - if (phylink_autoneg_inband(mode)) { - dev_err(&lynx->mdio->dev, ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3545,20 +3545,20 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_en - /** - * phylink_mii_c22_pcs_config() - configure clause 22 PCS - * @pcs: a pointer to a &struct mdio_device. -- * @mode: link autonegotiation mode - * @interface: the PHY interface mode being configured - * @advertising: the ethtool advertisement mask -+ * @neg_mode: PCS negotiation mode - * - * Configure a Clause 22 PCS PHY with the appropriate negotiation - * parameters for the @mode, @interface and @advertising parameters. - * Returns negative error number on failure, zero if the advertisement - * has not changed, or positive if there is a change. - */ --int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, -+int phylink_mii_c22_pcs_config(struct mdio_device *pcs, - phy_interface_t interface, -- const unsigned long *advertising) -+ const unsigned long *advertising, -+ unsigned int neg_mode) - { -- unsigned int neg_mode; - bool changed = 0; - u16 bmcr; - int ret, adv; -@@ -3572,7 +3572,6 @@ int phylink_mii_c22_pcs_config(struct md - changed = ret; - } - -- neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); - if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) - bmcr = BMCR_ANENABLE; - else ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -743,9 +743,10 @@ void phylink_mii_c22_pcs_get_state(struc - struct phylink_link_state *state); - int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface, - const unsigned long *advertising); --int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, -+int phylink_mii_c22_pcs_config(struct mdio_device *pcs, - phy_interface_t interface, -- const unsigned long *advertising); -+ const unsigned long *advertising, -+ unsigned int neg_mode); - void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); - - void phylink_resolve_c73(struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch b/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch deleted file mode 100644 index 5e0128766c..0000000000 --- a/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 3b2de56a146f34e3f70a84cc3a1897064e445d16 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:43 +0100 -Subject: [PATCH] net: pcs: lynxi: update PCS driver to use neg_mode - -Update the Lynxi PCS driver to use neg_mode rather than the mode -argument. This ensures that the link_up() method will always program -the speed and duplex when negotiation is disabled. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8Dz-00EaFY-5A@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-mtk-lynxi.c | 39 ++++++++++++++------------------- - 1 file changed, 16 insertions(+), 23 deletions(-) - ---- a/drivers/net/pcs/pcs-mtk-lynxi.c -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -102,13 +102,13 @@ static void mtk_pcs_lynxi_get_state(stru - FIELD_GET(SGMII_LPA, adv)); - } - --static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, -+static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) - { - struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -- bool mode_changed = false, changed, use_an; -+ bool mode_changed = false, changed; - unsigned int rgc3, sgm_mode, bmcr; - int advertise, link_timer; - -@@ -121,30 +121,22 @@ static int mtk_pcs_lynxi_config(struct p - * we assume that fixes it's speed at bitrate = line rate (in - * other words, 1000Mbps or 2500Mbps). - */ -- if (interface == PHY_INTERFACE_MODE_SGMII) { -+ if (interface == PHY_INTERFACE_MODE_SGMII) - sgm_mode = SGMII_IF_MODE_SGMII; -- if (phylink_autoneg_inband(mode)) { -- sgm_mode |= SGMII_REMOTE_FAULT_DIS | -- SGMII_SPEED_DUPLEX_AN; -- use_an = true; -- } else { -- use_an = false; -- } -- } else if (phylink_autoneg_inband(mode)) { -- /* 1000base-X or 2500base-X autoneg */ -- sgm_mode = SGMII_REMOTE_FAULT_DIS; -- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -- advertising); -- } else { -+ else - /* 1000base-X or 2500base-X without autoneg */ - sgm_mode = 0; -- use_an = false; -- } - -- if (use_an) -+ if (neg_mode & PHYLINK_PCS_NEG_INBAND) -+ sgm_mode |= SGMII_REMOTE_FAULT_DIS; -+ -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { -+ if (interface == PHY_INTERFACE_MODE_SGMII) -+ sgm_mode |= SGMII_SPEED_DUPLEX_AN; - bmcr = BMCR_ANENABLE; -- else -+ } else { - bmcr = 0; -+ } - - if (mpcs->interface != interface) { - link_timer = phylink_get_link_timer_ns(interface); -@@ -216,14 +208,15 @@ static void mtk_pcs_lynxi_restart_an(str - regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); - } - --static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, -+static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, -+ unsigned int neg_mode, - phy_interface_t interface, int speed, - int duplex) - { - struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); - unsigned int sgm_mode; - -- if (!phylink_autoneg_inband(mode)) { -+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { - /* Force the speed and duplex setting */ - if (speed == SPEED_10) - sgm_mode = SGMII_SPEED_10; -@@ -286,6 +279,7 @@ struct phylink_pcs *mtk_pcs_lynxi_create - mpcs->regmap = regmap; - mpcs->flags = flags; - mpcs->pcs.ops = &mtk_pcs_lynxi_ops; -+ mpcs->pcs.neg_mode = true; - mpcs->pcs.poll = true; - mpcs->interface = PHY_INTERFACE_MODE_NA; - diff --git a/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch b/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch deleted file mode 100644 index 3dd22d2916..0000000000 --- a/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 459fd2f11204c962e3153020f4f56748e0e10afb Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 21 Mar 2023 15:58:49 +0000 -Subject: [PATCH] net: pcs: xpcs: use Autoneg bit rather than an_enabled - -The Autoneg bit in the advertising bitmap and state->an_enabled are -always identical. Thus, we will be removing state->an_enabled. - -Use the Autoneg bit in the advertising bitmap to indicate whether -autonegotiation should be used, rather than using the an_enabled -member which will be going away. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-xpcs.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - ---- a/drivers/net/pcs/pcs-xpcs.c -+++ b/drivers/net/pcs/pcs-xpcs.c -@@ -931,6 +931,7 @@ static int xpcs_get_state_c73(struct dw_ - struct phylink_link_state *state, - const struct xpcs_compat *compat) - { -+ bool an_enabled; - int ret; - - /* Link needs to be read first ... */ -@@ -948,11 +949,13 @@ static int xpcs_get_state_c73(struct dw_ - return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL); - } - -- if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { -+ an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising); -+ if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { - state->an_complete = true; - xpcs_read_lpa_c73(xpcs, state); - xpcs_resolve_lpa_c73(xpcs, state); -- } else if (state->an_enabled) { -+ } else if (an_enabled) { - state->link = 0; - } else if (state->link) { - xpcs_resolve_pma(xpcs, state); -@@ -1007,7 +1010,8 @@ static int xpcs_get_state_c37_1000basex( - { - int lpa, bmsr; - -- if (state->an_enabled) { -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) { - /* Reset link state */ - state->link = false; - diff --git a/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch b/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch deleted file mode 100644 index 7cae8515fa..0000000000 --- a/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 43fb622d91a9f408322735d2f736495c1009f575 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 9 May 2023 12:50:04 +0100 -Subject: [PATCH] net: pcs: xpcs: fix incorrect number of interfaces - -In synopsys_xpcs_compat[], the DW_XPCS_2500BASEX entry was setting -the number of interfaces using the xpcs_2500basex_features array -rather than xpcs_2500basex_interfaces. This causes us to overflow -the array of interfaces. Fix this. - -Fixes: f27abde3042a ("net: pcs: add 2500BASEX support for Intel mGbE controller") -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Reviewed-by: Leon Romanovsky -Signed-off-by: David S. Miller ---- - drivers/net/pcs/pcs-xpcs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-xpcs.c -+++ b/drivers/net/pcs/pcs-xpcs.c -@@ -1211,7 +1211,7 @@ static const struct xpcs_compat synopsys - [DW_XPCS_2500BASEX] = { - .supported = xpcs_2500basex_features, - .interface = xpcs_2500basex_interfaces, -- .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features), -+ .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces), - .an_mode = DW_2500BASEX, - }, - }; diff --git a/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch b/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch deleted file mode 100644 index 816aa67787..0000000000 --- a/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 1b9827ceab08450308f7971d6fd700ec88b6ce67 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Sat, 3 Dec 2022 14:20:37 +0100 -Subject: [PATCH 098/250] net: mtk_eth_soc: enable flow offload support for - MT7986 SoC - -Since Wireless Ethernet Dispatcher is now available for mt7986 in mt76, -enable hw flow support for MT7986 SoC. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/fdcaacd827938e6a8c4aa1ac2c13e46d2c08c821.1670072898.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4333,6 +4333,7 @@ static const struct mtk_soc_data mt7986_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7986_CLKS_BITMAP, - .required_pctl = false, -+ .offload_version = 2, - .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), - .txrx = { diff --git a/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch b/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch deleted file mode 100644 index c48613929d..0000000000 --- a/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch +++ /dev/null @@ -1,591 +0,0 @@ -From: Sujuan Chen -Date: Sat, 5 Nov 2022 23:36:18 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: introduce wed mcu support - -Introduce WED mcu support used to configure WED WO chip. -This is a preliminary patch in order to add RX Wireless -Ethernet Dispatch available on MT7986 SoC. - -Tested-by: Daniel Golle -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Sujuan Chen -Signed-off-by: David S. Miller ---- - create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.c - create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.h - ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -5,7 +5,7 @@ - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o - mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o --mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o -+mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o - ifdef CONFIG_DEBUG_FS - mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o - endif ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -0,0 +1,359 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2022 MediaTek Inc. -+ * -+ * Author: Lorenzo Bianconi -+ * Sujuan Chen -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "mtk_wed_regs.h" -+#include "mtk_wed_wo.h" -+#include "mtk_wed.h" -+ -+static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) -+{ -+ return readl(wo->boot.addr + reg); -+} -+ -+static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) -+{ -+ writel(val, wo->boot.addr + reg); -+} -+ -+static struct sk_buff * -+mtk_wed_mcu_msg_alloc(const void *data, int data_len) -+{ -+ int length = sizeof(struct mtk_wed_mcu_hdr) + data_len; -+ struct sk_buff *skb; -+ -+ skb = alloc_skb(length, GFP_KERNEL); -+ if (!skb) -+ return NULL; -+ -+ memset(skb->head, 0, length); -+ skb_reserve(skb, sizeof(struct mtk_wed_mcu_hdr)); -+ if (data && data_len) -+ skb_put_data(skb, data, data_len); -+ -+ return skb; -+} -+ -+static struct sk_buff * -+mtk_wed_mcu_get_response(struct mtk_wed_wo *wo, unsigned long expires) -+{ -+ if (!time_is_after_jiffies(expires)) -+ return NULL; -+ -+ wait_event_timeout(wo->mcu.wait, !skb_queue_empty(&wo->mcu.res_q), -+ expires - jiffies); -+ return skb_dequeue(&wo->mcu.res_q); -+} -+ -+void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb) -+{ -+ skb_queue_tail(&wo->mcu.res_q, skb); -+ wake_up(&wo->mcu.wait); -+} -+ -+void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, -+ struct sk_buff *skb) -+{ -+ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ -+ switch (hdr->cmd) { -+ case MTK_WED_WO_EVT_LOG_DUMP: { -+ const char *msg = (const char *)(skb->data + sizeof(*hdr)); -+ -+ dev_notice(wo->hw->dev, "%s\n", msg); -+ break; -+ } -+ case MTK_WED_WO_EVT_PROFILING: { -+ struct mtk_wed_wo_log_info *info; -+ u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); -+ int i; -+ -+ info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); -+ for (i = 0 ; i < count ; i++) -+ dev_notice(wo->hw->dev, -+ "SN:%u latency: total=%u, rro:%u, mod:%u\n", -+ le32_to_cpu(info[i].sn), -+ le32_to_cpu(info[i].total), -+ le32_to_cpu(info[i].rro), -+ le32_to_cpu(info[i].mod)); -+ break; -+ } -+ case MTK_WED_WO_EVT_RXCNT_INFO: -+ break; -+ default: -+ break; -+ } -+ -+ dev_kfree_skb(skb); -+} -+ -+static int -+mtk_wed_mcu_skb_send_msg(struct mtk_wed_wo *wo, struct sk_buff *skb, -+ int id, int cmd, u16 *wait_seq, bool wait_resp) -+{ -+ struct mtk_wed_mcu_hdr *hdr; -+ -+ /* TODO: make it dynamic based on cmd */ -+ wo->mcu.timeout = 20 * HZ; -+ -+ hdr = (struct mtk_wed_mcu_hdr *)skb_push(skb, sizeof(*hdr)); -+ hdr->cmd = cmd; -+ hdr->length = cpu_to_le16(skb->len); -+ -+ if (wait_resp && wait_seq) { -+ u16 seq = ++wo->mcu.seq; -+ -+ if (!seq) -+ seq = ++wo->mcu.seq; -+ *wait_seq = seq; -+ -+ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_NEED_RSP); -+ hdr->seq = cpu_to_le16(seq); -+ } -+ if (id == MTK_WED_MODULE_ID_WO) -+ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); -+ -+ dev_kfree_skb(skb); -+ return 0; -+} -+ -+static int -+mtk_wed_mcu_parse_response(struct mtk_wed_wo *wo, struct sk_buff *skb, -+ int cmd, int seq) -+{ -+ struct mtk_wed_mcu_hdr *hdr; -+ -+ if (!skb) { -+ dev_err(wo->hw->dev, "Message %08x (seq %d) timeout\n", -+ cmd, seq); -+ return -ETIMEDOUT; -+ } -+ -+ hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ if (le16_to_cpu(hdr->seq) != seq) -+ return -EAGAIN; -+ -+ skb_pull(skb, sizeof(*hdr)); -+ switch (cmd) { -+ case MTK_WED_WO_CMD_RXCNT_INFO: -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, -+ const void *data, int len, bool wait_resp) -+{ -+ unsigned long expires; -+ struct sk_buff *skb; -+ u16 seq; -+ int ret; -+ -+ skb = mtk_wed_mcu_msg_alloc(data, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ mutex_lock(&wo->mcu.mutex); -+ -+ ret = mtk_wed_mcu_skb_send_msg(wo, skb, id, cmd, &seq, wait_resp); -+ if (ret || !wait_resp) -+ goto unlock; -+ -+ expires = jiffies + wo->mcu.timeout; -+ do { -+ skb = mtk_wed_mcu_get_response(wo, expires); -+ ret = mtk_wed_mcu_parse_response(wo, skb, cmd, seq); -+ dev_kfree_skb(skb); -+ } while (ret == -EAGAIN); -+ -+unlock: -+ mutex_unlock(&wo->mcu.mutex); -+ -+ return ret; -+} -+ -+static int -+mtk_wed_get_memory_region(struct mtk_wed_wo *wo, -+ struct mtk_wed_wo_memory_region *region) -+{ -+ struct reserved_mem *rmem; -+ struct device_node *np; -+ int index; -+ -+ index = of_property_match_string(wo->hw->node, "memory-region-names", -+ region->name); -+ if (index < 0) -+ return index; -+ -+ np = of_parse_phandle(wo->hw->node, "memory-region", index); -+ if (!np) -+ return -ENODEV; -+ -+ rmem = of_reserved_mem_lookup(np); -+ of_node_put(np); -+ -+ if (!rmem) -+ return -ENODEV; -+ -+ region->phy_addr = rmem->base; -+ region->size = rmem->size; -+ region->addr = devm_ioremap(wo->hw->dev, region->phy_addr, region->size); -+ -+ return !region->addr ? -EINVAL : 0; -+} -+ -+static int -+mtk_wed_mcu_run_firmware(struct mtk_wed_wo *wo, const struct firmware *fw, -+ struct mtk_wed_wo_memory_region *region) -+{ -+ const u8 *first_region_ptr, *region_ptr, *trailer_ptr, *ptr = fw->data; -+ const struct mtk_wed_fw_trailer *trailer; -+ const struct mtk_wed_fw_region *fw_region; -+ -+ trailer_ptr = fw->data + fw->size - sizeof(*trailer); -+ trailer = (const struct mtk_wed_fw_trailer *)trailer_ptr; -+ region_ptr = trailer_ptr - trailer->num_region * sizeof(*fw_region); -+ first_region_ptr = region_ptr; -+ -+ while (region_ptr < trailer_ptr) { -+ u32 length; -+ -+ fw_region = (const struct mtk_wed_fw_region *)region_ptr; -+ length = le32_to_cpu(fw_region->len); -+ -+ if (region->phy_addr != le32_to_cpu(fw_region->addr)) -+ goto next; -+ -+ if (region->size < length) -+ goto next; -+ -+ if (first_region_ptr < ptr + length) -+ goto next; -+ -+ if (region->shared && region->consumed) -+ return 0; -+ -+ if (!region->shared || !region->consumed) { -+ memcpy_toio(region->addr, ptr, length); -+ region->consumed = true; -+ return 0; -+ } -+next: -+ region_ptr += sizeof(*fw_region); -+ ptr += length; -+ } -+ -+ return -EINVAL; -+} -+ -+static int -+mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) -+{ -+ static struct mtk_wed_wo_memory_region mem_region[] = { -+ [MTK_WED_WO_REGION_EMI] = { -+ .name = "wo-emi", -+ }, -+ [MTK_WED_WO_REGION_ILM] = { -+ .name = "wo-ilm", -+ }, -+ [MTK_WED_WO_REGION_DATA] = { -+ .name = "wo-data", -+ .shared = true, -+ }, -+ }; -+ const struct mtk_wed_fw_trailer *trailer; -+ const struct firmware *fw; -+ const char *fw_name; -+ u32 val, boot_cr; -+ int ret, i; -+ -+ /* load firmware region metadata */ -+ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -+ ret = mtk_wed_get_memory_region(wo, &mem_region[i]); -+ if (ret) -+ return ret; -+ } -+ -+ wo->boot.name = "wo-boot"; -+ ret = mtk_wed_get_memory_region(wo, &wo->boot); -+ if (ret) -+ return ret; -+ -+ /* set dummy cr */ -+ wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, -+ wo->hw->index + 1); -+ -+ /* load firmware */ -+ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; -+ ret = request_firmware(&fw, fw_name, wo->hw->dev); -+ if (ret) -+ return ret; -+ -+ trailer = (void *)(fw->data + fw->size - -+ sizeof(struct mtk_wed_fw_trailer)); -+ dev_info(wo->hw->dev, -+ "MTK WED WO Firmware Version: %.10s, Build Time: %.15s\n", -+ trailer->fw_ver, trailer->build_date); -+ dev_info(wo->hw->dev, "MTK WED WO Chip ID %02x Region %d\n", -+ trailer->chip_id, trailer->num_region); -+ -+ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -+ ret = mtk_wed_mcu_run_firmware(wo, fw, &mem_region[i]); -+ if (ret) -+ goto out; -+ } -+ -+ /* set the start address */ -+ boot_cr = wo->hw->index ? MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR -+ : MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; -+ wo_w32(wo, boot_cr, mem_region[MTK_WED_WO_REGION_EMI].phy_addr >> 16); -+ /* wo firmware reset */ -+ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00); -+ -+ val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR); -+ val |= wo->hw->index ? MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK -+ : MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; -+ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val); -+out: -+ release_firmware(fw); -+ -+ return ret; -+} -+ -+static u32 -+mtk_wed_mcu_read_fw_dl(struct mtk_wed_wo *wo) -+{ -+ return wed_r32(wo->hw->wed_dev, -+ MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL); -+} -+ -+int mtk_wed_mcu_init(struct mtk_wed_wo *wo) -+{ -+ u32 val; -+ int ret; -+ -+ skb_queue_head_init(&wo->mcu.res_q); -+ init_waitqueue_head(&wo->mcu.wait); -+ mutex_init(&wo->mcu.mutex); -+ -+ ret = mtk_wed_mcu_load_firmware(wo); -+ if (ret) -+ return ret; -+ -+ return readx_poll_timeout(mtk_wed_mcu_read_fw_dl, wo, val, !val, -+ 100, MTK_FW_DL_TIMEOUT); -+} -+ -+MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); -+MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -152,6 +152,7 @@ struct mtk_wdma_desc { - - #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) - -+#define MTK_WED_SCR0 0x3c0 - #define MTK_WED_WPDMA_INT_TRIGGER 0x504 - #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) - #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -0,0 +1,150 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2022 Lorenzo Bianconi */ -+ -+#ifndef __MTK_WED_WO_H -+#define __MTK_WED_WO_H -+ -+#include -+#include -+ -+struct mtk_wed_hw; -+ -+struct mtk_wed_mcu_hdr { -+ /* DW0 */ -+ u8 version; -+ u8 cmd; -+ __le16 length; -+ -+ /* DW1 */ -+ __le16 seq; -+ __le16 flag; -+ -+ /* DW2 */ -+ __le32 status; -+ -+ /* DW3 */ -+ u8 rsv[20]; -+}; -+ -+struct mtk_wed_wo_log_info { -+ __le32 sn; -+ __le32 total; -+ __le32 rro; -+ __le32 mod; -+}; -+ -+enum mtk_wed_wo_event { -+ MTK_WED_WO_EVT_LOG_DUMP = 0x1, -+ MTK_WED_WO_EVT_PROFILING = 0x2, -+ MTK_WED_WO_EVT_RXCNT_INFO = 0x3, -+}; -+ -+#define MTK_WED_MODULE_ID_WO 1 -+#define MTK_FW_DL_TIMEOUT 4000000 /* us */ -+#define MTK_WOCPU_TIMEOUT 2000000 /* us */ -+ -+enum { -+ MTK_WED_WARP_CMD_FLAG_RSP = BIT(0), -+ MTK_WED_WARP_CMD_FLAG_NEED_RSP = BIT(1), -+ MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), -+}; -+ -+enum { -+ MTK_WED_WO_REGION_EMI, -+ MTK_WED_WO_REGION_ILM, -+ MTK_WED_WO_REGION_DATA, -+ MTK_WED_WO_REGION_BOOT, -+ __MTK_WED_WO_REGION_MAX, -+}; -+ -+enum mtk_wed_dummy_cr_idx { -+ MTK_WED_DUMMY_CR_FWDL, -+ MTK_WED_DUMMY_CR_WO_STATUS, -+}; -+ -+#define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" -+#define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" -+ -+#define MTK_WO_MCU_CFG_LS_BASE 0 -+#define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) -+#define MTK_WO_MCU_CFG_LS_FW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x004) -+#define MTK_WO_MCU_CFG_LS_CFG_DBG1_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x00c) -+#define MTK_WO_MCU_CFG_LS_CFG_DBG2_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x010) -+#define MTK_WO_MCU_CFG_LS_WF_MCCR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x014) -+#define MTK_WO_MCU_CFG_LS_WF_MCCR_SET_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x018) -+#define MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x01c) -+#define MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x050) -+#define MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x060) -+#define MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x064) -+ -+#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) -+#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) -+ -+struct mtk_wed_wo_memory_region { -+ const char *name; -+ void __iomem *addr; -+ phys_addr_t phy_addr; -+ u32 size; -+ bool shared:1; -+ bool consumed:1; -+}; -+ -+struct mtk_wed_fw_region { -+ __le32 decomp_crc; -+ __le32 decomp_len; -+ __le32 decomp_blk_sz; -+ u8 rsv0[4]; -+ __le32 addr; -+ __le32 len; -+ u8 feature_set; -+ u8 rsv1[15]; -+} __packed; -+ -+struct mtk_wed_fw_trailer { -+ u8 chip_id; -+ u8 eco_code; -+ u8 num_region; -+ u8 format_ver; -+ u8 format_flag; -+ u8 rsv[2]; -+ char fw_ver[10]; -+ char build_date[15]; -+ u32 crc; -+}; -+ -+struct mtk_wed_wo { -+ struct mtk_wed_hw *hw; -+ struct mtk_wed_wo_memory_region boot; -+ -+ struct { -+ struct mutex mutex; -+ int timeout; -+ u16 seq; -+ -+ struct sk_buff_head res_q; -+ wait_queue_head_t wait; -+ } mcu; -+}; -+ -+static inline int -+mtk_wed_mcu_check_msg(struct mtk_wed_wo *wo, struct sk_buff *skb) -+{ -+ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ -+ if (hdr->version) -+ return -EINVAL; -+ -+ if (skb->len < sizeof(*hdr) || skb->len != le16_to_cpu(hdr->length)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb); -+void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, -+ struct sk_buff *skb); -+int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, -+ const void *data, int len, bool wait_resp); -+int mtk_wed_mcu_init(struct mtk_wed_wo *wo); -+ -+#endif /* __MTK_WED_WO_H */ ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -11,6 +11,35 @@ - struct mtk_wed_hw; - struct mtk_wdma_desc; - -+enum mtk_wed_wo_cmd { -+ MTK_WED_WO_CMD_WED_CFG, -+ MTK_WED_WO_CMD_WED_RX_STAT, -+ MTK_WED_WO_CMD_RRO_SER, -+ MTK_WED_WO_CMD_DBG_INFO, -+ MTK_WED_WO_CMD_DEV_INFO, -+ MTK_WED_WO_CMD_BSS_INFO, -+ MTK_WED_WO_CMD_STA_REC, -+ MTK_WED_WO_CMD_DEV_INFO_DUMP, -+ MTK_WED_WO_CMD_BSS_INFO_DUMP, -+ MTK_WED_WO_CMD_STA_REC_DUMP, -+ MTK_WED_WO_CMD_BA_INFO_DUMP, -+ MTK_WED_WO_CMD_FBCMD_Q_DUMP, -+ MTK_WED_WO_CMD_FW_LOG_CTRL, -+ MTK_WED_WO_CMD_LOG_FLUSH, -+ MTK_WED_WO_CMD_CHANGE_STATE, -+ MTK_WED_WO_CMD_CPU_STATS_ENABLE, -+ MTK_WED_WO_CMD_CPU_STATS_DUMP, -+ MTK_WED_WO_CMD_EXCEPTION_INIT, -+ MTK_WED_WO_CMD_PROF_CTRL, -+ MTK_WED_WO_CMD_STA_BA_DUMP, -+ MTK_WED_WO_CMD_BA_CTRL_DUMP, -+ MTK_WED_WO_CMD_RXCNT_CTRL, -+ MTK_WED_WO_CMD_RXCNT_INFO, -+ MTK_WED_WO_CMD_SET_CAP, -+ MTK_WED_WO_CMD_CCIF_RING_DUMP, -+ MTK_WED_WO_CMD_WED_END -+}; -+ - enum mtk_wed_bus_tye { - MTK_WED_BUS_PCIE, - MTK_WED_BUS_AXI, diff --git a/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch b/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch deleted file mode 100644 index fd5f45df2a..0000000000 --- a/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch +++ /dev/null @@ -1,737 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:19 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: introduce wed wo support - -Introduce WO chip support to mtk wed driver. MTK WED WO is used to -implement RX Wireless Ethernet Dispatch and offload traffic received by -wlan nic to the wired interface. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.c - ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -5,7 +5,7 @@ - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o - mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o --mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o -+mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o - ifdef CONFIG_DEBUG_FS - mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o - endif ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -16,6 +16,7 @@ - #include "mtk_wed_regs.h" - #include "mtk_wed.h" - #include "mtk_ppe.h" -+#include "mtk_wed_wo.h" - - #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) - -@@ -355,6 +356,8 @@ mtk_wed_detach(struct mtk_wed_device *de - - mtk_wed_free_buffer(dev); - mtk_wed_free_tx_rings(dev); -+ if (hw->version != 1) -+ mtk_wed_wo_deinit(hw); - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { - struct device_node *wlan_node; -@@ -878,9 +881,11 @@ mtk_wed_attach(struct mtk_wed_device *de - } - - mtk_wed_hw_init_early(dev); -- if (hw->hifsys) -+ if (hw->version == 1) - regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, - BIT(hw->index), 0); -+ else -+ ret = mtk_wed_wo_init(hw); - - out: - mutex_unlock(&hw_lock); ---- a/drivers/net/ethernet/mediatek/mtk_wed.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed.h -@@ -10,6 +10,7 @@ - #include - - struct mtk_eth; -+struct mtk_wed_wo; - - struct mtk_wed_hw { - struct device_node *node; -@@ -22,6 +23,7 @@ struct mtk_wed_hw { - struct regmap *mirror; - struct dentry *debugfs_dir; - struct mtk_wed_device *wed_dev; -+ struct mtk_wed_wo *wed_wo; - u32 debugfs_reg; - u32 num_flows; - u8 version; ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -122,8 +122,7 @@ mtk_wed_mcu_skb_send_msg(struct mtk_wed_ - if (id == MTK_WED_MODULE_ID_WO) - hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); - -- dev_kfree_skb(skb); -- return 0; -+ return mtk_wed_wo_queue_tx_skb(wo, &wo->q_tx, skb); - } - - static int ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -0,0 +1,508 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2022 MediaTek Inc. -+ * -+ * Author: Lorenzo Bianconi -+ * Sujuan Chen -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mtk_wed.h" -+#include "mtk_wed_regs.h" -+#include "mtk_wed_wo.h" -+ -+static u32 -+mtk_wed_mmio_r32(struct mtk_wed_wo *wo, u32 reg) -+{ -+ u32 val; -+ -+ if (regmap_read(wo->mmio.regs, reg, &val)) -+ val = ~0; -+ -+ return val; -+} -+ -+static void -+mtk_wed_mmio_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) -+{ -+ regmap_write(wo->mmio.regs, reg, val); -+} -+ -+static u32 -+mtk_wed_wo_get_isr(struct mtk_wed_wo *wo) -+{ -+ u32 val = mtk_wed_mmio_r32(wo, MTK_WED_WO_CCIF_RCHNUM); -+ -+ return val & MTK_WED_WO_CCIF_RCHNUM_MASK; -+} -+ -+static void -+mtk_wed_wo_set_isr(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_IRQ0_MASK, mask); -+} -+ -+static void -+mtk_wed_wo_set_ack(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_ACK, mask); -+} -+ -+static void -+mtk_wed_wo_set_isr_mask(struct mtk_wed_wo *wo, u32 mask, u32 val, bool set) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&wo->mmio.lock, flags); -+ wo->mmio.irq_mask &= ~mask; -+ wo->mmio.irq_mask |= val; -+ if (set) -+ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); -+ spin_unlock_irqrestore(&wo->mmio.lock, flags); -+} -+ -+static void -+mtk_wed_wo_irq_enable(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_wo_set_isr_mask(wo, 0, mask, false); -+ tasklet_schedule(&wo->mmio.irq_tasklet); -+} -+ -+static void -+mtk_wed_wo_irq_disable(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_wo_set_isr_mask(wo, mask, 0, true); -+} -+ -+static void -+mtk_wed_wo_kickout(struct mtk_wed_wo *wo) -+{ -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_BUSY, 1 << MTK_WED_WO_TXCH_NUM); -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_TCHNUM, MTK_WED_WO_TXCH_NUM); -+} -+ -+static void -+mtk_wed_wo_queue_kick(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ u32 val) -+{ -+ wmb(); -+ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, val); -+} -+ -+static void * -+mtk_wed_wo_dequeue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, u32 *len, -+ bool flush) -+{ -+ int buf_len = SKB_WITH_OVERHEAD(q->buf_size); -+ int index = (q->tail + 1) % q->n_desc; -+ struct mtk_wed_wo_queue_entry *entry; -+ struct mtk_wed_wo_queue_desc *desc; -+ void *buf; -+ -+ if (!q->queued) -+ return NULL; -+ -+ if (flush) -+ q->desc[index].ctrl |= cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE); -+ else if (!(q->desc[index].ctrl & cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE))) -+ return NULL; -+ -+ q->tail = index; -+ q->queued--; -+ -+ desc = &q->desc[index]; -+ entry = &q->entry[index]; -+ buf = entry->buf; -+ if (len) -+ *len = FIELD_GET(MTK_WED_WO_CTL_SD_LEN0, -+ le32_to_cpu(READ_ONCE(desc->ctrl))); -+ if (buf) -+ dma_unmap_single(wo->hw->dev, entry->addr, buf_len, -+ DMA_FROM_DEVICE); -+ entry->buf = NULL; -+ -+ return buf; -+} -+ -+static int -+mtk_wed_wo_queue_refill(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ gfp_t gfp, bool rx) -+{ -+ enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; -+ int n_buf = 0; -+ -+ spin_lock_bh(&q->lock); -+ while (q->queued < q->n_desc) { -+ void *buf = page_frag_alloc(&q->cache, q->buf_size, gfp); -+ struct mtk_wed_wo_queue_entry *entry; -+ dma_addr_t addr; -+ -+ if (!buf) -+ break; -+ -+ addr = dma_map_single(wo->hw->dev, buf, q->buf_size, dir); -+ if (unlikely(dma_mapping_error(wo->hw->dev, addr))) { -+ skb_free_frag(buf); -+ break; -+ } -+ -+ q->head = (q->head + 1) % q->n_desc; -+ entry = &q->entry[q->head]; -+ entry->addr = addr; -+ entry->len = q->buf_size; -+ q->entry[q->head].buf = buf; -+ -+ if (rx) { -+ struct mtk_wed_wo_queue_desc *desc = &q->desc[q->head]; -+ u32 ctrl = MTK_WED_WO_CTL_LAST_SEC0 | -+ FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, -+ entry->len); -+ -+ WRITE_ONCE(desc->buf0, cpu_to_le32(addr)); -+ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); -+ } -+ q->queued++; -+ n_buf++; -+ } -+ spin_unlock_bh(&q->lock); -+ -+ return n_buf; -+} -+ -+static void -+mtk_wed_wo_rx_complete(struct mtk_wed_wo *wo) -+{ -+ mtk_wed_wo_set_ack(wo, MTK_WED_WO_RXCH_INT_MASK); -+ mtk_wed_wo_irq_enable(wo, MTK_WED_WO_RXCH_INT_MASK); -+} -+ -+static void -+mtk_wed_wo_rx_run_queue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ for (;;) { -+ struct mtk_wed_mcu_hdr *hdr; -+ struct sk_buff *skb; -+ void *data; -+ u32 len; -+ -+ data = mtk_wed_wo_dequeue(wo, q, &len, false); -+ if (!data) -+ break; -+ -+ skb = build_skb(data, q->buf_size); -+ if (!skb) { -+ skb_free_frag(data); -+ continue; -+ } -+ -+ __skb_put(skb, len); -+ if (mtk_wed_mcu_check_msg(wo, skb)) { -+ dev_kfree_skb(skb); -+ continue; -+ } -+ -+ hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ if (hdr->flag & cpu_to_le16(MTK_WED_WARP_CMD_FLAG_RSP)) -+ mtk_wed_mcu_rx_event(wo, skb); -+ else -+ mtk_wed_mcu_rx_unsolicited_event(wo, skb); -+ } -+ -+ if (mtk_wed_wo_queue_refill(wo, q, GFP_ATOMIC, true)) { -+ u32 index = (q->head - 1) % q->n_desc; -+ -+ mtk_wed_wo_queue_kick(wo, q, index); -+ } -+} -+ -+static irqreturn_t -+mtk_wed_wo_irq_handler(int irq, void *data) -+{ -+ struct mtk_wed_wo *wo = data; -+ -+ mtk_wed_wo_set_isr(wo, 0); -+ tasklet_schedule(&wo->mmio.irq_tasklet); -+ -+ return IRQ_HANDLED; -+} -+ -+static void mtk_wed_wo_irq_tasklet(struct tasklet_struct *t) -+{ -+ struct mtk_wed_wo *wo = from_tasklet(wo, t, mmio.irq_tasklet); -+ u32 intr, mask; -+ -+ /* disable interrupts */ -+ mtk_wed_wo_set_isr(wo, 0); -+ -+ intr = mtk_wed_wo_get_isr(wo); -+ intr &= wo->mmio.irq_mask; -+ mask = intr & (MTK_WED_WO_RXCH_INT_MASK | MTK_WED_WO_EXCEPTION_INT_MASK); -+ mtk_wed_wo_irq_disable(wo, mask); -+ -+ if (intr & MTK_WED_WO_RXCH_INT_MASK) { -+ mtk_wed_wo_rx_run_queue(wo, &wo->q_rx); -+ mtk_wed_wo_rx_complete(wo); -+ } -+} -+ -+/* mtk wed wo hw queues */ -+ -+static int -+mtk_wed_wo_queue_alloc(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ int n_desc, int buf_size, int index, -+ struct mtk_wed_wo_queue_regs *regs) -+{ -+ spin_lock_init(&q->lock); -+ q->regs = *regs; -+ q->n_desc = n_desc; -+ q->buf_size = buf_size; -+ -+ q->desc = dmam_alloc_coherent(wo->hw->dev, n_desc * sizeof(*q->desc), -+ &q->desc_dma, GFP_KERNEL); -+ if (!q->desc) -+ return -ENOMEM; -+ -+ q->entry = devm_kzalloc(wo->hw->dev, n_desc * sizeof(*q->entry), -+ GFP_KERNEL); -+ if (!q->entry) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static void -+mtk_wed_wo_queue_free(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); -+ dma_free_coherent(wo->hw->dev, q->n_desc * sizeof(*q->desc), q->desc, -+ q->desc_dma); -+} -+ -+static void -+mtk_wed_wo_queue_tx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ struct page *page; -+ int i; -+ -+ spin_lock_bh(&q->lock); -+ for (i = 0; i < q->n_desc; i++) { -+ struct mtk_wed_wo_queue_entry *entry = &q->entry[i]; -+ -+ dma_unmap_single(wo->hw->dev, entry->addr, entry->len, -+ DMA_TO_DEVICE); -+ skb_free_frag(entry->buf); -+ entry->buf = NULL; -+ } -+ spin_unlock_bh(&q->lock); -+ -+ if (!q->cache.va) -+ return; -+ -+ page = virt_to_page(q->cache.va); -+ __page_frag_cache_drain(page, q->cache.pagecnt_bias); -+ memset(&q->cache, 0, sizeof(q->cache)); -+} -+ -+static void -+mtk_wed_wo_queue_rx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ struct page *page; -+ -+ spin_lock_bh(&q->lock); -+ for (;;) { -+ void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); -+ -+ if (!buf) -+ break; -+ -+ skb_free_frag(buf); -+ } -+ spin_unlock_bh(&q->lock); -+ -+ if (!q->cache.va) -+ return; -+ -+ page = virt_to_page(q->cache.va); -+ __page_frag_cache_drain(page, q->cache.pagecnt_bias); -+ memset(&q->cache, 0, sizeof(q->cache)); -+} -+ -+static void -+mtk_wed_wo_queue_reset(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); -+ mtk_wed_mmio_w32(wo, q->regs.desc_base, q->desc_dma); -+ mtk_wed_mmio_w32(wo, q->regs.ring_size, q->n_desc); -+} -+ -+int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ struct sk_buff *skb) -+{ -+ struct mtk_wed_wo_queue_entry *entry; -+ struct mtk_wed_wo_queue_desc *desc; -+ int ret = 0, index; -+ u32 ctrl; -+ -+ spin_lock_bh(&q->lock); -+ -+ q->tail = mtk_wed_mmio_r32(wo, q->regs.dma_idx); -+ index = (q->head + 1) % q->n_desc; -+ if (q->tail == index) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ entry = &q->entry[index]; -+ if (skb->len > entry->len) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ desc = &q->desc[index]; -+ q->head = index; -+ -+ dma_sync_single_for_cpu(wo->hw->dev, entry->addr, skb->len, -+ DMA_TO_DEVICE); -+ memcpy(entry->buf, skb->data, skb->len); -+ dma_sync_single_for_device(wo->hw->dev, entry->addr, skb->len, -+ DMA_TO_DEVICE); -+ -+ ctrl = FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, skb->len) | -+ MTK_WED_WO_CTL_LAST_SEC0 | MTK_WED_WO_CTL_DMA_DONE; -+ WRITE_ONCE(desc->buf0, cpu_to_le32(entry->addr)); -+ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); -+ -+ mtk_wed_wo_queue_kick(wo, q, q->head); -+ mtk_wed_wo_kickout(wo); -+out: -+ spin_unlock_bh(&q->lock); -+ -+ dev_kfree_skb(skb); -+ -+ return ret; -+} -+ -+static int -+mtk_wed_wo_exception_init(struct mtk_wed_wo *wo) -+{ -+ return 0; -+} -+ -+static int -+mtk_wed_wo_hardware_init(struct mtk_wed_wo *wo) -+{ -+ struct mtk_wed_wo_queue_regs regs; -+ struct device_node *np; -+ int ret; -+ -+ np = of_parse_phandle(wo->hw->node, "mediatek,wo-ccif", 0); -+ if (!np) -+ return -ENODEV; -+ -+ wo->mmio.regs = syscon_regmap_lookup_by_phandle(np, NULL); -+ if (IS_ERR_OR_NULL(wo->mmio.regs)) -+ return PTR_ERR(wo->mmio.regs); -+ -+ wo->mmio.irq = irq_of_parse_and_map(np, 0); -+ wo->mmio.irq_mask = MTK_WED_WO_ALL_INT_MASK; -+ spin_lock_init(&wo->mmio.lock); -+ tasklet_setup(&wo->mmio.irq_tasklet, mtk_wed_wo_irq_tasklet); -+ -+ ret = devm_request_irq(wo->hw->dev, wo->mmio.irq, -+ mtk_wed_wo_irq_handler, IRQF_TRIGGER_HIGH, -+ KBUILD_MODNAME, wo); -+ if (ret) -+ goto error; -+ -+ regs.desc_base = MTK_WED_WO_CCIF_DUMMY1; -+ regs.ring_size = MTK_WED_WO_CCIF_DUMMY2; -+ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW4; -+ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY3; -+ -+ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_tx, MTK_WED_WO_RING_SIZE, -+ MTK_WED_WO_CMD_LEN, MTK_WED_WO_TXCH_NUM, -+ ®s); -+ if (ret) -+ goto error; -+ -+ mtk_wed_wo_queue_refill(wo, &wo->q_tx, GFP_KERNEL, false); -+ mtk_wed_wo_queue_reset(wo, &wo->q_tx); -+ -+ regs.desc_base = MTK_WED_WO_CCIF_DUMMY5; -+ regs.ring_size = MTK_WED_WO_CCIF_DUMMY6; -+ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW8; -+ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY7; -+ -+ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_rx, MTK_WED_WO_RING_SIZE, -+ MTK_WED_WO_CMD_LEN, MTK_WED_WO_RXCH_NUM, -+ ®s); -+ if (ret) -+ goto error; -+ -+ mtk_wed_wo_queue_refill(wo, &wo->q_rx, GFP_KERNEL, true); -+ mtk_wed_wo_queue_reset(wo, &wo->q_rx); -+ -+ /* rx queue irqmask */ -+ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); -+ -+ return 0; -+ -+error: -+ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); -+ -+ return ret; -+} -+ -+static void -+mtk_wed_wo_hw_deinit(struct mtk_wed_wo *wo) -+{ -+ /* disable interrupts */ -+ mtk_wed_wo_set_isr(wo, 0); -+ -+ tasklet_disable(&wo->mmio.irq_tasklet); -+ -+ disable_irq(wo->mmio.irq); -+ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); -+ -+ mtk_wed_wo_queue_tx_clean(wo, &wo->q_tx); -+ mtk_wed_wo_queue_rx_clean(wo, &wo->q_rx); -+ mtk_wed_wo_queue_free(wo, &wo->q_tx); -+ mtk_wed_wo_queue_free(wo, &wo->q_rx); -+} -+ -+int mtk_wed_wo_init(struct mtk_wed_hw *hw) -+{ -+ struct mtk_wed_wo *wo; -+ int ret; -+ -+ wo = devm_kzalloc(hw->dev, sizeof(*wo), GFP_KERNEL); -+ if (!wo) -+ return -ENOMEM; -+ -+ hw->wed_wo = wo; -+ wo->hw = hw; -+ -+ ret = mtk_wed_wo_hardware_init(wo); -+ if (ret) -+ return ret; -+ -+ ret = mtk_wed_mcu_init(wo); -+ if (ret) -+ return ret; -+ -+ return mtk_wed_wo_exception_init(wo); -+} -+ -+void mtk_wed_wo_deinit(struct mtk_wed_hw *hw) -+{ -+ struct mtk_wed_wo *wo = hw->wed_wo; -+ -+ mtk_wed_wo_hw_deinit(wo); -+} ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -80,6 +80,54 @@ enum mtk_wed_dummy_cr_idx { - #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) - #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) - -+#define MTK_WED_WO_RING_SIZE 256 -+#define MTK_WED_WO_CMD_LEN 1504 -+ -+#define MTK_WED_WO_TXCH_NUM 0 -+#define MTK_WED_WO_RXCH_NUM 1 -+#define MTK_WED_WO_RXCH_WO_EXCEPTION 7 -+ -+#define MTK_WED_WO_TXCH_INT_MASK BIT(0) -+#define MTK_WED_WO_RXCH_INT_MASK BIT(1) -+#define MTK_WED_WO_EXCEPTION_INT_MASK BIT(7) -+#define MTK_WED_WO_ALL_INT_MASK (MTK_WED_WO_RXCH_INT_MASK | \ -+ MTK_WED_WO_EXCEPTION_INT_MASK) -+ -+#define MTK_WED_WO_CCIF_BUSY 0x004 -+#define MTK_WED_WO_CCIF_START 0x008 -+#define MTK_WED_WO_CCIF_TCHNUM 0x00c -+#define MTK_WED_WO_CCIF_RCHNUM 0x010 -+#define MTK_WED_WO_CCIF_RCHNUM_MASK GENMASK(7, 0) -+ -+#define MTK_WED_WO_CCIF_ACK 0x014 -+#define MTK_WED_WO_CCIF_IRQ0_MASK 0x018 -+#define MTK_WED_WO_CCIF_IRQ1_MASK 0x01c -+#define MTK_WED_WO_CCIF_DUMMY1 0x020 -+#define MTK_WED_WO_CCIF_DUMMY2 0x024 -+#define MTK_WED_WO_CCIF_DUMMY3 0x028 -+#define MTK_WED_WO_CCIF_DUMMY4 0x02c -+#define MTK_WED_WO_CCIF_SHADOW1 0x030 -+#define MTK_WED_WO_CCIF_SHADOW2 0x034 -+#define MTK_WED_WO_CCIF_SHADOW3 0x038 -+#define MTK_WED_WO_CCIF_SHADOW4 0x03c -+#define MTK_WED_WO_CCIF_DUMMY5 0x050 -+#define MTK_WED_WO_CCIF_DUMMY6 0x054 -+#define MTK_WED_WO_CCIF_DUMMY7 0x058 -+#define MTK_WED_WO_CCIF_DUMMY8 0x05c -+#define MTK_WED_WO_CCIF_SHADOW5 0x060 -+#define MTK_WED_WO_CCIF_SHADOW6 0x064 -+#define MTK_WED_WO_CCIF_SHADOW7 0x068 -+#define MTK_WED_WO_CCIF_SHADOW8 0x06c -+ -+#define MTK_WED_WO_CTL_SD_LEN1 GENMASK(13, 0) -+#define MTK_WED_WO_CTL_LAST_SEC1 BIT(14) -+#define MTK_WED_WO_CTL_BURST BIT(15) -+#define MTK_WED_WO_CTL_SD_LEN0_SHIFT 16 -+#define MTK_WED_WO_CTL_SD_LEN0 GENMASK(29, 16) -+#define MTK_WED_WO_CTL_LAST_SEC0 BIT(30) -+#define MTK_WED_WO_CTL_DMA_DONE BIT(31) -+#define MTK_WED_WO_INFO_WINFO GENMASK(15, 0) -+ - struct mtk_wed_wo_memory_region { - const char *name; - void __iomem *addr; -@@ -112,10 +160,53 @@ struct mtk_wed_fw_trailer { - u32 crc; - }; - -+struct mtk_wed_wo_queue_regs { -+ u32 desc_base; -+ u32 ring_size; -+ u32 cpu_idx; -+ u32 dma_idx; -+}; -+ -+struct mtk_wed_wo_queue_desc { -+ __le32 buf0; -+ __le32 ctrl; -+ __le32 buf1; -+ __le32 info; -+ __le32 reserved[4]; -+} __packed __aligned(32); -+ -+struct mtk_wed_wo_queue_entry { -+ dma_addr_t addr; -+ void *buf; -+ u32 len; -+}; -+ -+struct mtk_wed_wo_queue { -+ struct mtk_wed_wo_queue_regs regs; -+ -+ struct page_frag_cache cache; -+ spinlock_t lock; -+ -+ struct mtk_wed_wo_queue_desc *desc; -+ dma_addr_t desc_dma; -+ -+ struct mtk_wed_wo_queue_entry *entry; -+ -+ u16 head; -+ u16 tail; -+ int n_desc; -+ int queued; -+ int buf_size; -+ -+}; -+ - struct mtk_wed_wo { - struct mtk_wed_hw *hw; - struct mtk_wed_wo_memory_region boot; - -+ struct mtk_wed_wo_queue q_tx; -+ struct mtk_wed_wo_queue q_rx; -+ - struct { - struct mutex mutex; - int timeout; -@@ -124,6 +215,15 @@ struct mtk_wed_wo { - struct sk_buff_head res_q; - wait_queue_head_t wait; - } mcu; -+ -+ struct { -+ struct regmap *regs; -+ -+ spinlock_t lock; -+ struct tasklet_struct irq_tasklet; -+ int irq; -+ u32 irq_mask; -+ } mmio; - }; - - static inline int -@@ -146,5 +246,9 @@ void mtk_wed_mcu_rx_unsolicited_event(st - int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, - const void *data, int len, bool wait_resp); - int mtk_wed_mcu_init(struct mtk_wed_wo *wo); -+int mtk_wed_wo_init(struct mtk_wed_hw *hw); -+void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); -+int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *dev, struct mtk_wed_wo_queue *q, -+ struct sk_buff *skb); - - #endif /* __MTK_WED_WO_H */ diff --git a/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch b/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch deleted file mode 100644 index a002a5f851..0000000000 --- a/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch +++ /dev/null @@ -1,79 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:20 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: rename tx_wdma array in rx_wdma - -Rename tx_wdma queue array in rx_wdma since this is rx side of wdma soc. -Moreover rename mtk_wed_wdma_ring_setup routine in -mtk_wed_wdma_rx_ring_setup() - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -253,8 +253,8 @@ mtk_wed_free_tx_rings(struct mtk_wed_dev - - for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) - mtk_wed_free_ring(dev, &dev->tx_ring[i]); -- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) -- mtk_wed_free_ring(dev, &dev->tx_wdma[i]); -+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) -+ mtk_wed_free_ring(dev, &dev->rx_wdma[i]); - } - - static void -@@ -688,10 +688,10 @@ mtk_wed_ring_alloc(struct mtk_wed_device - } - - static int --mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; -- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx]; -+ struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; - - if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) - return -ENOMEM; -@@ -805,9 +805,9 @@ mtk_wed_start(struct mtk_wed_device *dev - { - int i; - -- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) -- if (!dev->tx_wdma[i].desc) -- mtk_wed_wdma_ring_setup(dev, i, 16); -+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) -+ if (!dev->rx_wdma[i].desc) -+ mtk_wed_wdma_rx_ring_setup(dev, i, 16); - - mtk_wed_hw_init(dev); - mtk_wed_configure_irq(dev, irq_mask); -@@ -916,7 +916,7 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev - sizeof(*ring->desc))) - return -ENOMEM; - -- if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) - return -ENOMEM; - - ring->reg_base = MTK_WED_RING_TX(idx); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -7,6 +7,7 @@ - #include - - #define MTK_WED_TX_QUEUES 2 -+#define MTK_WED_RX_QUEUES 2 - - struct mtk_wed_hw; - struct mtk_wdma_desc; -@@ -66,7 +67,7 @@ struct mtk_wed_device { - - struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; - struct mtk_wed_ring txfree_ring; -- struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; -+ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; - - struct { - int size; diff --git a/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch b/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch deleted file mode 100644 index eca29739b4..0000000000 --- a/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch +++ /dev/null @@ -1,1521 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:21 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add configure wed wo support - -Enable RX Wireless Ethernet Dispatch available on MT7986 Soc. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -23,6 +24,7 @@ - #define MTK_WED_PKT_SIZE 1900 - #define MTK_WED_BUF_SIZE 2048 - #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) -+#define MTK_WED_RX_RING_SIZE 1536 - - #define MTK_WED_TX_RING_SIZE 2048 - #define MTK_WED_WDMA_RING_SIZE 1024 -@@ -31,6 +33,10 @@ - #define MTK_WED_PER_GROUP_PKT 128 - - #define MTK_WED_FBUF_SIZE 128 -+#define MTK_WED_MIOD_CNT 16 -+#define MTK_WED_FB_CMD_CNT 1024 -+#define MTK_WED_RRO_QUE_CNT 8192 -+#define MTK_WED_MIOD_ENTRY_CNT 128 - - static struct mtk_wed_hw *hw_list[2]; - static DEFINE_MUTEX(hw_lock); -@@ -65,12 +71,76 @@ wdma_set(struct mtk_wed_device *dev, u32 - wdma_m32(dev, reg, 0, mask); - } - -+static void -+wdma_clr(struct mtk_wed_device *dev, u32 reg, u32 mask) -+{ -+ wdma_m32(dev, reg, mask, 0); -+} -+ -+static u32 -+wifi_r32(struct mtk_wed_device *dev, u32 reg) -+{ -+ return readl(dev->wlan.base + reg); -+} -+ -+static void -+wifi_w32(struct mtk_wed_device *dev, u32 reg, u32 val) -+{ -+ writel(val, dev->wlan.base + reg); -+} -+ - static u32 - mtk_wed_read_reset(struct mtk_wed_device *dev) - { - return wed_r32(dev, MTK_WED_RESET); - } - -+static u32 -+mtk_wdma_read_reset(struct mtk_wed_device *dev) -+{ -+ return wdma_r32(dev, MTK_WDMA_GLO_CFG); -+} -+ -+static void -+mtk_wdma_rx_reset(struct mtk_wed_device *dev) -+{ -+ u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY; -+ int i; -+ -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN); -+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -+ !(status & mask), 0, 1000)) -+ dev_err(dev->hw->dev, "rx reset failed\n"); -+ -+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) { -+ if (dev->rx_wdma[i].desc) -+ continue; -+ -+ wdma_w32(dev, -+ MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); -+ } -+} -+ -+static void -+mtk_wdma_tx_reset(struct mtk_wed_device *dev) -+{ -+ u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY; -+ int i; -+ -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -+ !(status & mask), 0, 1000)) -+ dev_err(dev->hw->dev, "tx reset failed\n"); -+ -+ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) { -+ if (dev->tx_wdma[i].desc) -+ continue; -+ -+ wdma_w32(dev, -+ MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); -+ } -+} -+ - static void - mtk_wed_reset(struct mtk_wed_device *dev, u32 mask) - { -@@ -82,6 +152,54 @@ mtk_wed_reset(struct mtk_wed_device *dev - WARN_ON_ONCE(1); - } - -+static u32 -+mtk_wed_wo_read_status(struct mtk_wed_device *dev) -+{ -+ return wed_r32(dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_WO_STATUS); -+} -+ -+static void -+mtk_wed_wo_reset(struct mtk_wed_device *dev) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ u8 state = MTK_WED_WO_STATE_DISABLE; -+ void __iomem *reg; -+ u32 val; -+ -+ mtk_wdma_tx_reset(dev); -+ mtk_wed_reset(dev, MTK_WED_RESET_WED); -+ -+ mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &state, -+ sizeof(state), false); -+ -+ if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val, -+ val == MTK_WED_WOIF_DISABLE_DONE, -+ 100, MTK_WOCPU_TIMEOUT)) -+ dev_err(dev->hw->dev, "failed to disable wed-wo\n"); -+ -+ reg = ioremap(MTK_WED_WO_CPU_MCUSYS_RESET_ADDR, 4); -+ -+ val = readl(reg); -+ switch (dev->hw->index) { -+ case 0: -+ val |= MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ val &= ~MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ break; -+ case 1: -+ val |= MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ val &= ~MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ break; -+ default: -+ break; -+ } -+ iounmap(reg); -+} -+ - static struct mtk_wed_hw * - mtk_wed_assign(struct mtk_wed_device *dev) - { -@@ -116,7 +234,7 @@ out: - } - - static int --mtk_wed_buffer_alloc(struct mtk_wed_device *dev) -+mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) - { - struct mtk_wdma_desc *desc; - dma_addr_t desc_phys; -@@ -133,16 +251,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi - if (!page_list) - return -ENOMEM; - -- dev->buf_ring.size = ring_size; -- dev->buf_ring.pages = page_list; -+ dev->tx_buf_ring.size = ring_size; -+ dev->tx_buf_ring.pages = page_list; - - desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), - &desc_phys, GFP_KERNEL); - if (!desc) - return -ENOMEM; - -- dev->buf_ring.desc = desc; -- dev->buf_ring.desc_phys = desc_phys; -+ dev->tx_buf_ring.desc = desc; -+ dev->tx_buf_ring.desc_phys = desc_phys; - - for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { - dma_addr_t page_phys, buf_phys; -@@ -203,10 +321,10 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi - } - - static void --mtk_wed_free_buffer(struct mtk_wed_device *dev) -+mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) - { -- struct mtk_wdma_desc *desc = dev->buf_ring.desc; -- void **page_list = dev->buf_ring.pages; -+ struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; -+ void **page_list = dev->tx_buf_ring.pages; - int page_idx; - int i; - -@@ -216,7 +334,8 @@ mtk_wed_free_buffer(struct mtk_wed_devic - if (!desc) - goto free_pagelist; - -- for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { -+ for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; -+ i += MTK_WED_BUF_PER_PAGE) { - void *page = page_list[page_idx++]; - dma_addr_t buf_addr; - -@@ -229,13 +348,59 @@ mtk_wed_free_buffer(struct mtk_wed_devic - __free_page(page); - } - -- dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc), -- desc, dev->buf_ring.desc_phys); -+ dma_free_coherent(dev->hw->dev, dev->tx_buf_ring.size * sizeof(*desc), -+ desc, dev->tx_buf_ring.desc_phys); - - free_pagelist: - kfree(page_list); - } - -+static int -+mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) -+{ -+ struct mtk_rxbm_desc *desc; -+ dma_addr_t desc_phys; -+ -+ dev->rx_buf_ring.size = dev->wlan.rx_nbuf; -+ desc = dma_alloc_coherent(dev->hw->dev, -+ dev->wlan.rx_nbuf * sizeof(*desc), -+ &desc_phys, GFP_KERNEL); -+ if (!desc) -+ return -ENOMEM; -+ -+ dev->rx_buf_ring.desc = desc; -+ dev->rx_buf_ring.desc_phys = desc_phys; -+ dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt); -+ -+ return 0; -+} -+ -+static void -+mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) -+{ -+ struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc; -+ -+ if (!desc) -+ return; -+ -+ dev->wlan.release_rx_buf(dev); -+ dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc), -+ desc, dev->rx_buf_ring.desc_phys); -+} -+ -+static void -+mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev) -+{ -+ wed_w32(dev, MTK_WED_RX_BM_RX_DMAD, -+ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_size)); -+ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys); -+ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL | -+ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt)); -+ wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH, -+ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff)); -+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); -+} -+ - static void - mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring) - { -@@ -247,6 +412,13 @@ mtk_wed_free_ring(struct mtk_wed_device - } - - static void -+mtk_wed_free_rx_rings(struct mtk_wed_device *dev) -+{ -+ mtk_wed_free_rx_buffer(dev); -+ mtk_wed_free_ring(dev, &dev->rro.ring); -+} -+ -+static void - mtk_wed_free_tx_rings(struct mtk_wed_device *dev) - { - int i; -@@ -291,6 +463,38 @@ mtk_wed_set_512_support(struct mtk_wed_d - } - } - -+#define MTK_WFMDA_RX_DMA_EN BIT(2) -+static void -+mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx) -+{ -+ u32 val; -+ int i; -+ -+ if (!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED)) -+ return; /* queue is not configured by mt76 */ -+ -+ for (i = 0; i < 3; i++) { -+ u32 cur_idx; -+ -+ cur_idx = wed_r32(dev, -+ MTK_WED_WPDMA_RING_RX_DATA(idx) + -+ MTK_WED_RING_OFS_CPU_IDX); -+ if (cur_idx == MTK_WED_RX_RING_SIZE - 1) -+ break; -+ -+ usleep_range(100000, 200000); -+ } -+ -+ if (i == 3) { -+ dev_err(dev->hw->dev, "rx dma enable failed\n"); -+ return; -+ } -+ -+ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) | -+ MTK_WFMDA_RX_DMA_EN; -+ wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val); -+} -+ - static void - mtk_wed_dma_disable(struct mtk_wed_device *dev) - { -@@ -304,20 +508,25 @@ mtk_wed_dma_disable(struct mtk_wed_devic - MTK_WED_GLO_CFG_TX_DMA_EN | - MTK_WED_GLO_CFG_RX_DMA_EN); - -- wdma_m32(dev, MTK_WDMA_GLO_CFG, -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, - MTK_WDMA_GLO_CFG_TX_DMA_EN | - MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | -- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0); -+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); - - if (dev->hw->version == 1) { - regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); -- wdma_m32(dev, MTK_WDMA_GLO_CFG, -- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0); -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, -+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); - } else { - wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); - -+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RX_DRV_EN); -+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, -+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); -+ - mtk_wed_set_512_support(dev, false); - } - } -@@ -338,6 +547,13 @@ mtk_wed_stop(struct mtk_wed_device *dev) - wdma_w32(dev, MTK_WDMA_INT_MASK, 0); - wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); - wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); -+ -+ if (dev->hw->version == 1) -+ return; -+ -+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); -+ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0); -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); - } - - static void -@@ -353,11 +569,21 @@ mtk_wed_detach(struct mtk_wed_device *de - wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); - - mtk_wed_reset(dev, MTK_WED_RESET_WED); -+ if (mtk_wed_get_rx_capa(dev)) { -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -+ } - -- mtk_wed_free_buffer(dev); -+ mtk_wed_free_tx_buffer(dev); - mtk_wed_free_tx_rings(dev); -- if (hw->version != 1) -+ -+ if (mtk_wed_get_rx_capa(dev)) { -+ mtk_wed_wo_reset(dev); -+ mtk_wed_free_rx_rings(dev); - mtk_wed_wo_deinit(hw); -+ mtk_wdma_rx_reset(dev); -+ } - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { - struct device_node *wlan_node; -@@ -434,10 +660,12 @@ mtk_wed_set_wpdma(struct mtk_wed_device - } else { - mtk_wed_bus_init(dev); - -- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); -- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); -- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); -- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); -+ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); -+ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); - } - } - -@@ -487,6 +715,132 @@ mtk_wed_hw_init_early(struct mtk_wed_dev - } - } - -+static int -+mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, -+ int size) -+{ -+ ring->desc = dma_alloc_coherent(dev->hw->dev, -+ size * sizeof(*ring->desc), -+ &ring->desc_phys, GFP_KERNEL); -+ if (!ring->desc) -+ return -ENOMEM; -+ -+ ring->desc_size = sizeof(*ring->desc); -+ ring->size = size; -+ memset(ring->desc, 0, size); -+ -+ return 0; -+} -+ -+#define MTK_WED_MIOD_COUNT (MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT) -+static int -+mtk_wed_rro_alloc(struct mtk_wed_device *dev) -+{ -+ struct reserved_mem *rmem; -+ struct device_node *np; -+ int index; -+ -+ index = of_property_match_string(dev->hw->node, "memory-region-names", -+ "wo-dlm"); -+ if (index < 0) -+ return index; -+ -+ np = of_parse_phandle(dev->hw->node, "memory-region", index); -+ if (!np) -+ return -ENODEV; -+ -+ rmem = of_reserved_mem_lookup(np); -+ of_node_put(np); -+ -+ if (!rmem) -+ return -ENODEV; -+ -+ dev->rro.miod_phys = rmem->base; -+ dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys; -+ -+ return mtk_wed_rro_ring_alloc(dev, &dev->rro.ring, -+ MTK_WED_RRO_QUE_CNT); -+} -+ -+static int -+mtk_wed_rro_cfg(struct mtk_wed_device *dev) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ struct { -+ struct { -+ __le32 base; -+ __le32 cnt; -+ __le32 unit; -+ } ring[2]; -+ __le32 wed; -+ u8 version; -+ } req = { -+ .ring[0] = { -+ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE), -+ .cnt = cpu_to_le32(MTK_WED_MIOD_CNT), -+ .unit = cpu_to_le32(MTK_WED_MIOD_ENTRY_CNT), -+ }, -+ .ring[1] = { -+ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE + -+ MTK_WED_MIOD_COUNT), -+ .cnt = cpu_to_le32(MTK_WED_FB_CMD_CNT), -+ .unit = cpu_to_le32(4), -+ }, -+ }; -+ -+ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_WED_CFG, -+ &req, sizeof(req), true); -+} -+ -+static void -+mtk_wed_rro_hw_init(struct mtk_wed_device *dev) -+{ -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CFG, -+ FIELD_PREP(MTK_WED_RROQM_MIOD_MID_DW, 0x70 >> 2) | -+ FIELD_PREP(MTK_WED_RROQM_MIOD_MOD_DW, 0x10 >> 2) | -+ FIELD_PREP(MTK_WED_RROQM_MIOD_ENTRY_DW, -+ MTK_WED_MIOD_ENTRY_CNT >> 2)); -+ -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_phys); -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL1, -+ FIELD_PREP(MTK_WED_RROQM_MIOD_CNT, MTK_WED_MIOD_CNT)); -+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_phys); -+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL1, -+ FIELD_PREP(MTK_WED_RROQM_FDBK_CNT, MTK_WED_FB_CMD_CNT)); -+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL2, 0); -+ wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.ring.desc_phys); -+ -+ wed_set(dev, MTK_WED_RROQM_RST_IDX, -+ MTK_WED_RROQM_RST_IDX_MIOD | -+ MTK_WED_RROQM_RST_IDX_FDBK); -+ -+ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL2, MTK_WED_MIOD_CNT - 1); -+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN); -+} -+ -+static void -+mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev) -+{ -+ wed_w32(dev, MTK_WED_RESET, MTK_WED_RESET_RX_ROUTE_QM); -+ -+ for (;;) { -+ usleep_range(100, 200); -+ if (!(wed_r32(dev, MTK_WED_RESET) & MTK_WED_RESET_RX_ROUTE_QM)) -+ break; -+ } -+ -+ /* configure RX_ROUTE_QM */ -+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); -+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); -+ wed_set(dev, MTK_WED_RTQM_GLO_CFG, -+ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index)); -+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); -+ /* enable RX_ROUTE_QM */ -+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); -+} -+ - static void - mtk_wed_hw_init(struct mtk_wed_device *dev) - { -@@ -498,11 +852,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d - wed_w32(dev, MTK_WED_TX_BM_CTRL, - MTK_WED_TX_BM_CTRL_PAUSE | - FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, -- dev->buf_ring.size / 128) | -+ dev->tx_buf_ring.size / 128) | - FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, - MTK_WED_TX_RING_SIZE / 256)); - -- wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys); -+ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys); - - wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); - -@@ -529,9 +883,9 @@ mtk_wed_hw_init(struct mtk_wed_device *d - wed_w32(dev, MTK_WED_TX_TKID_CTRL, - MTK_WED_TX_TKID_CTRL_PAUSE | - FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM, -- dev->buf_ring.size / 128) | -+ dev->tx_buf_ring.size / 128) | - FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM, -- dev->buf_ring.size / 128)); -+ dev->tx_buf_ring.size / 128)); - wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, - FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | - MTK_WED_TX_TKID_DYN_THR_HI); -@@ -539,18 +893,28 @@ mtk_wed_hw_init(struct mtk_wed_device *d - - mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); - -- if (dev->hw->version == 1) -+ if (dev->hw->version == 1) { - wed_set(dev, MTK_WED_CTRL, - MTK_WED_CTRL_WED_TX_BM_EN | - MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); -- else -+ } else { - wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); -+ /* rx hw init */ -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, -+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | -+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); -+ -+ mtk_wed_rx_buffer_hw_init(dev); -+ mtk_wed_rro_hw_init(dev); -+ mtk_wed_route_qm_hw_init(dev); -+ } - - wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); - } - - static void --mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size) -+mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx) - { - void *head = (void *)ring->desc; - int i; -@@ -560,7 +924,10 @@ mtk_wed_ring_reset(struct mtk_wed_ring * - - desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size); - desc->buf0 = 0; -- desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); -+ if (tx) -+ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); -+ else -+ desc->ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST); - desc->buf1 = 0; - desc->info = 0; - } -@@ -616,7 +983,8 @@ mtk_wed_reset_dma(struct mtk_wed_device - if (!dev->tx_ring[i].desc) - continue; - -- mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE); -+ mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE, -+ true); - } - - if (mtk_wed_poll_busy(dev)) -@@ -634,6 +1002,9 @@ mtk_wed_reset_dma(struct mtk_wed_device - wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); - wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); - -+ if (mtk_wed_get_rx_capa(dev)) -+ mtk_wdma_rx_reset(dev); -+ - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); -@@ -668,12 +1039,11 @@ mtk_wed_reset_dma(struct mtk_wed_device - MTK_WED_WPDMA_RESET_IDX_RX); - wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); - } -- - } - - static int - mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, -- int size, u32 desc_size) -+ int size, u32 desc_size, bool tx) - { - ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size, - &ring->desc_phys, GFP_KERNEL); -@@ -682,7 +1052,7 @@ mtk_wed_ring_alloc(struct mtk_wed_device - - ring->desc_size = desc_size; - ring->size = size; -- mtk_wed_ring_reset(ring, size); -+ mtk_wed_ring_reset(ring, size, tx); - - return 0; - } -@@ -691,9 +1061,14 @@ static int - mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; -- struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; -+ struct mtk_wed_ring *wdma; - -- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) -+ if (idx >= ARRAY_SIZE(dev->rx_wdma)) -+ return -EINVAL; -+ -+ wdma = &dev->rx_wdma[idx]; -+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -+ true)) - return -ENOMEM; - - wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, -@@ -710,6 +1085,60 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we - return 0; - } - -+static int -+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+{ -+ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; -+ struct mtk_wed_ring *wdma; -+ -+ if (idx >= ARRAY_SIZE(dev->tx_wdma)) -+ return -EINVAL; -+ -+ wdma = &dev->tx_wdma[idx]; -+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -+ true)) -+ return -ENOMEM; -+ -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, -+ wdma->desc_phys); -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, -+ size); -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0); -+ -+ if (!idx) { -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE, -+ wdma->desc_phys); -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_COUNT, -+ size); -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_CPU_IDX, -+ 0); -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_DMA_IDX, -+ 0); -+ } -+ -+ return 0; -+} -+ -+static void -+mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb, -+ u32 reason, u32 hash) -+{ -+ struct mtk_eth *eth = dev->hw->eth; -+ struct ethhdr *eh; -+ -+ if (!skb) -+ return; -+ -+ if (reason != MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -+ return; -+ -+ skb_set_mac_header(skb, 0); -+ eh = eth_hdr(skb); -+ skb->protocol = eh->h_proto; -+ mtk_ppe_check_skb(eth->ppe[dev->hw->index], skb, hash); -+} -+ - static void - mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask) - { -@@ -732,6 +1161,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev - - wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); - } else { -+ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, -+ GENMASK(1, 0)); - /* initail tx interrupt trigger */ - wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, - MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | -@@ -750,6 +1181,16 @@ mtk_wed_configure_irq(struct mtk_wed_dev - FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG, - dev->wlan.txfree_tbit)); - -+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, -+ MTK_WED_WPDMA_INT_CTRL_RX0_EN | -+ MTK_WED_WPDMA_INT_CTRL_RX0_CLR | -+ MTK_WED_WPDMA_INT_CTRL_RX1_EN | -+ MTK_WED_WPDMA_INT_CTRL_RX1_CLR | -+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, -+ dev->wlan.rx_tbit[0]) | -+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, -+ dev->wlan.rx_tbit[1])); -+ - wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask); - wed_set(dev, MTK_WED_WDMA_INT_CTRL, - FIELD_PREP(MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL, -@@ -787,9 +1228,15 @@ mtk_wed_dma_enable(struct mtk_wed_device - wdma_set(dev, MTK_WDMA_GLO_CFG, - MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); - } else { -+ int i; -+ - wed_set(dev, MTK_WED_WPDMA_CTRL, - MTK_WED_WPDMA_CTRL_SDL1_FIXED); - -+ wed_set(dev, MTK_WED_WDMA_GLO_CFG, -+ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | -+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); -+ - wed_set(dev, MTK_WED_WPDMA_GLO_CFG, - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); -@@ -797,6 +1244,15 @@ mtk_wed_dma_enable(struct mtk_wed_device - wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, - MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | - MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); -+ -+ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RX_DRV_EN | -+ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | -+ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, -+ 0x2)); -+ -+ for (i = 0; i < MTK_WED_RX_QUEUES; i++) -+ mtk_wed_check_wfdma_rx_fill(dev, i); - } - } - -@@ -822,7 +1278,19 @@ mtk_wed_start(struct mtk_wed_device *dev - val |= BIT(0) | (BIT(1) * !!dev->hw->index); - regmap_write(dev->hw->mirror, dev->hw->index * 4, val); - } else { -- mtk_wed_set_512_support(dev, true); -+ /* driver set mid ready and only once */ -+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, -+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); -+ wed_w32(dev, MTK_WED_EXT_INT_MASK2, -+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); -+ -+ wed_r32(dev, MTK_WED_EXT_INT_MASK1); -+ wed_r32(dev, MTK_WED_EXT_INT_MASK2); -+ -+ if (mtk_wed_rro_cfg(dev)) -+ return; -+ -+ mtk_wed_set_512_support(dev, dev->wlan.wcid_512); - } - - mtk_wed_dma_enable(dev); -@@ -856,7 +1324,7 @@ mtk_wed_attach(struct mtk_wed_device *de - if (!hw) { - module_put(THIS_MODULE); - ret = -ENODEV; -- goto out; -+ goto unlock; - } - - device = dev->wlan.bus_type == MTK_WED_BUS_PCIE -@@ -869,15 +1337,24 @@ mtk_wed_attach(struct mtk_wed_device *de - dev->dev = hw->dev; - dev->irq = hw->irq; - dev->wdma_idx = hw->index; -+ dev->version = hw->version; - - if (hw->eth->dma_dev == hw->eth->dev && - of_dma_is_coherent(hw->eth->dev->of_node)) - mtk_eth_set_dma_device(hw->eth, hw->dev); - -- ret = mtk_wed_buffer_alloc(dev); -- if (ret) { -- mtk_wed_detach(dev); -+ ret = mtk_wed_tx_buffer_alloc(dev); -+ if (ret) - goto out; -+ -+ if (mtk_wed_get_rx_capa(dev)) { -+ ret = mtk_wed_rx_buffer_alloc(dev); -+ if (ret) -+ goto out; -+ -+ ret = mtk_wed_rro_alloc(dev); -+ if (ret) -+ goto out; - } - - mtk_wed_hw_init_early(dev); -@@ -886,8 +1363,10 @@ mtk_wed_attach(struct mtk_wed_device *de - BIT(hw->index), 0); - else - ret = mtk_wed_wo_init(hw); -- - out: -+ if (ret) -+ mtk_wed_detach(dev); -+unlock: - mutex_unlock(&hw_lock); - - return ret; -@@ -910,10 +1389,11 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev - * WDMA RX. - */ - -- BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring)); -+ if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring))) -+ return -EINVAL; - - if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, -- sizeof(*ring->desc))) -+ sizeof(*ring->desc), true)) - return -ENOMEM; - - if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -@@ -960,6 +1440,37 @@ mtk_wed_txfree_ring_setup(struct mtk_wed - return 0; - } - -+static int -+mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) -+{ -+ struct mtk_wed_ring *ring = &dev->rx_ring[idx]; -+ -+ if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring))) -+ return -EINVAL; -+ -+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, -+ sizeof(*ring->desc), false)) -+ return -ENOMEM; -+ -+ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ return -ENOMEM; -+ -+ ring->reg_base = MTK_WED_RING_RX_DATA(idx); -+ ring->wpdma = regs; -+ ring->flags |= MTK_WED_RING_CONFIGURED; -+ -+ /* WPDMA -> WED */ -+ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); -+ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_RX_RING_SIZE); -+ -+ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_BASE, -+ ring->desc_phys); -+ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_COUNT, -+ MTK_WED_RX_RING_SIZE); -+ -+ return 0; -+} -+ - static u32 - mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) - { -@@ -1056,7 +1567,9 @@ void mtk_wed_add_hw(struct device_node * - static const struct mtk_wed_ops wed_ops = { - .attach = mtk_wed_attach, - .tx_ring_setup = mtk_wed_tx_ring_setup, -+ .rx_ring_setup = mtk_wed_rx_ring_setup, - .txfree_ring_setup = mtk_wed_txfree_ring_setup, -+ .msg_update = mtk_wed_mcu_msg_update, - .start = mtk_wed_start, - .stop = mtk_wed_stop, - .reset_dma = mtk_wed_reset_dma, -@@ -1065,6 +1578,7 @@ void mtk_wed_add_hw(struct device_node * - .irq_get = mtk_wed_irq_get, - .irq_set_mask = mtk_wed_irq_set_mask, - .detach = mtk_wed_detach, -+ .ppe_check = mtk_wed_ppe_check, - }; - struct device_node *eth_np = eth->dev->of_node; - struct platform_device *pdev; ---- a/drivers/net/ethernet/mediatek/mtk_wed.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed.h -@@ -87,6 +87,24 @@ wpdma_tx_w32(struct mtk_wed_device *dev, - } - - static inline u32 -+wpdma_rx_r32(struct mtk_wed_device *dev, int ring, u32 reg) -+{ -+ if (!dev->rx_ring[ring].wpdma) -+ return 0; -+ -+ return readl(dev->rx_ring[ring].wpdma + reg); -+} -+ -+static inline void -+wpdma_rx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val) -+{ -+ if (!dev->rx_ring[ring].wpdma) -+ return; -+ -+ writel(val, dev->rx_ring[ring].wpdma + reg); -+} -+ -+static inline u32 - wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg) - { - if (!dev->txfree_ring.wpdma) -@@ -128,6 +146,7 @@ static inline int mtk_wed_flow_add(int i - static inline void mtk_wed_flow_remove(int index) - { - } -+ - #endif - - #ifdef CONFIG_DEBUG_FS ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include "mtk_wed_regs.h" - #include "mtk_wed_wo.h" -@@ -60,24 +61,37 @@ void mtk_wed_mcu_rx_event(struct mtk_wed - wake_up(&wo->mcu.wait); - } - -+static void -+mtk_wed_update_rx_stats(struct mtk_wed_device *wed, struct sk_buff *skb) -+{ -+ u32 count = get_unaligned_le32(skb->data); -+ struct mtk_wed_wo_rx_stats *stats; -+ int i; -+ -+ if (count * sizeof(*stats) > skb->len - sizeof(u32)) -+ return; -+ -+ stats = (struct mtk_wed_wo_rx_stats *)(skb->data + sizeof(u32)); -+ for (i = 0 ; i < count ; i++) -+ wed->wlan.update_wo_rx_stats(wed, &stats[i]); -+} -+ - void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, - struct sk_buff *skb) - { - struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; - -- switch (hdr->cmd) { -- case MTK_WED_WO_EVT_LOG_DUMP: { -- const char *msg = (const char *)(skb->data + sizeof(*hdr)); -+ skb_pull(skb, sizeof(*hdr)); - -- dev_notice(wo->hw->dev, "%s\n", msg); -+ switch (hdr->cmd) { -+ case MTK_WED_WO_EVT_LOG_DUMP: -+ dev_notice(wo->hw->dev, "%s\n", skb->data); - break; -- } - case MTK_WED_WO_EVT_PROFILING: { -- struct mtk_wed_wo_log_info *info; -- u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); -+ struct mtk_wed_wo_log_info *info = (void *)skb->data; -+ u32 count = skb->len / sizeof(*info); - int i; - -- info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); - for (i = 0 ; i < count ; i++) - dev_notice(wo->hw->dev, - "SN:%u latency: total=%u, rro:%u, mod:%u\n", -@@ -88,6 +102,7 @@ void mtk_wed_mcu_rx_unsolicited_event(st - break; - } - case MTK_WED_WO_EVT_RXCNT_INFO: -+ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); - break; - default: - break; -@@ -144,6 +159,8 @@ mtk_wed_mcu_parse_response(struct mtk_we - skb_pull(skb, sizeof(*hdr)); - switch (cmd) { - case MTK_WED_WO_CMD_RXCNT_INFO: -+ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); -+ break; - default: - break; - } -@@ -182,6 +199,18 @@ unlock: - return ret; - } - -+int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, -+ int len) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ -+ if (dev->hw->version == 1) -+ return 0; -+ -+ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, -+ true); -+} -+ - static int - mtk_wed_get_memory_region(struct mtk_wed_wo *wo, - struct mtk_wed_wo_memory_region *region) ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -4,6 +4,7 @@ - #ifndef __MTK_WED_REGS_H - #define __MTK_WED_REGS_H - -+#define MTK_WFDMA_DESC_CTRL_TO_HOST BIT(8) - #define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0) - #define MTK_WDMA_DESC_CTRL_LEN1_V2 GENMASK(13, 0) - #define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15) -@@ -28,6 +29,8 @@ struct mtk_wdma_desc { - #define MTK_WED_RESET_WED_TX_DMA BIT(12) - #define MTK_WED_RESET_WDMA_RX_DRV BIT(17) - #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) -+#define MTK_WED_RESET_RX_RRO_QM BIT(20) -+#define MTK_WED_RESET_RX_ROUTE_QM BIT(21) - #define MTK_WED_RESET_WED BIT(31) - - #define MTK_WED_CTRL 0x00c -@@ -39,8 +42,12 @@ struct mtk_wdma_desc { - #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) - #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) - #define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11) --#define MTK_WED_CTRL_RESERVE_EN BIT(12) --#define MTK_WED_CTRL_RESERVE_BUSY BIT(13) -+#define MTK_WED_CTRL_WED_RX_BM_EN BIT(12) -+#define MTK_WED_CTRL_WED_RX_BM_BUSY BIT(13) -+#define MTK_WED_CTRL_RX_RRO_QM_EN BIT(14) -+#define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15) -+#define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16) -+#define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17) - #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) - #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25) - #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) -@@ -62,6 +69,9 @@ struct mtk_wdma_desc { - #define MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR BIT(22) - #define MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR BIT(23) - #define MTK_WED_EXT_INT_STATUS_RX_DRV_DMA_RECYCLE BIT(24) -+#define MTK_WED_EXT_INT_STATUS_RX_DRV_GET_BM_DMAD_SKIP BIT(25) -+#define MTK_WED_EXT_INT_STATUS_WPDMA_RX_D_DRV_ERR BIT(26) -+#define MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY BIT(27) - #define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \ - MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \ - MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \ -@@ -71,6 +81,8 @@ struct mtk_wdma_desc { - MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR) - - #define MTK_WED_EXT_INT_MASK 0x028 -+#define MTK_WED_EXT_INT_MASK1 0x02c -+#define MTK_WED_EXT_INT_MASK2 0x030 - - #define MTK_WED_STATUS 0x060 - #define MTK_WED_STATUS_TX GENMASK(15, 8) -@@ -151,6 +163,7 @@ struct mtk_wdma_desc { - #define MTK_WED_RING_TX(_n) (0x300 + (_n) * 0x10) - - #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) -+#define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10) - - #define MTK_WED_SCR0 0x3c0 - #define MTK_WED_WPDMA_INT_TRIGGER 0x504 -@@ -213,6 +226,12 @@ struct mtk_wdma_desc { - #define MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG GENMASK(14, 10) - - #define MTK_WED_WPDMA_INT_CTRL_RX 0x534 -+#define MTK_WED_WPDMA_INT_CTRL_RX0_EN BIT(0) -+#define MTK_WED_WPDMA_INT_CTRL_RX0_CLR BIT(1) -+#define MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG GENMASK(6, 2) -+#define MTK_WED_WPDMA_INT_CTRL_RX1_EN BIT(8) -+#define MTK_WED_WPDMA_INT_CTRL_RX1_CLR BIT(9) -+#define MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG GENMASK(14, 10) - - #define MTK_WED_WPDMA_INT_CTRL_TX_FREE 0x538 - #define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN BIT(0) -@@ -242,11 +261,34 @@ struct mtk_wdma_desc { - - #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) - #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) -+#define MTK_WED_WPDMA_RING_RX_DATA(_n) (0x730 + (_n) * 0x10) -+ -+#define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c -+#define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0) -+#define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7) -+#define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24) -+ -+#define MTK_WED_WPDMA_RX_D_RST_IDX 0x760 -+#define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16) -+#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) -+ -+#define MTK_WED_WPDMA_RX_GLO_CFG 0x76c -+#define MTK_WED_WPDMA_RX_RING 0x770 -+ -+#define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c -+ -+#define MTK_WED_WDMA_RING_TX 0x800 -+ -+#define MTK_WED_WDMA_TX_MIB 0x810 -+ - #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) - #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) - - #define MTK_WED_WDMA_GLO_CFG 0xa04 - #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) -+#define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1) - #define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2) - #define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3) - #define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4) -@@ -291,6 +333,20 @@ struct mtk_wdma_desc { - #define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4) - #define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4) - -+#define MTK_WED_RX_BM_RX_DMAD 0xd80 -+#define MTK_WED_RX_BM_RX_DMAD_SDL0 GENMASK(13, 0) -+ -+#define MTK_WED_RX_BM_BASE 0xd84 -+#define MTK_WED_RX_BM_INIT_PTR 0xd88 -+#define MTK_WED_RX_BM_SW_TAIL GENMASK(15, 0) -+#define MTK_WED_RX_BM_INIT_SW_TAIL BIT(16) -+ -+#define MTK_WED_RX_PTR 0xd8c -+ -+#define MTK_WED_RX_BM_DYN_ALLOC_TH 0xdb4 -+#define MTK_WED_RX_BM_DYN_ALLOC_TH_H GENMASK(31, 16) -+#define MTK_WED_RX_BM_DYN_ALLOC_TH_L GENMASK(15, 0) -+ - #define MTK_WED_RING_OFS_BASE 0x00 - #define MTK_WED_RING_OFS_COUNT 0x04 - #define MTK_WED_RING_OFS_CPU_IDX 0x08 -@@ -301,7 +357,9 @@ struct mtk_wdma_desc { - - #define MTK_WDMA_GLO_CFG 0x204 - #define MTK_WDMA_GLO_CFG_TX_DMA_EN BIT(0) -+#define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1) - #define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2) -+#define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3) - #define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26) - #define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27) - #define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28) -@@ -330,4 +388,70 @@ struct mtk_wdma_desc { - /* DMA channel mapping */ - #define HIFSYS_DMA_AG_MAP 0x008 - -+#define MTK_WED_RTQM_GLO_CFG 0xb00 -+#define MTK_WED_RTQM_BUSY BIT(1) -+#define MTK_WED_RTQM_Q_RST BIT(2) -+#define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) -+#define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) -+ -+#define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4) -+#define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4) -+#define MTK_WED_RTQM_Q2N_MIB 0xb80 -+#define MTK_WED_RTQM_Q2H_MIB(_n) (0xb84 + (_n) * 0x4) -+ -+#define MTK_WED_RTQM_Q2B_MIB 0xb8c -+#define MTK_WED_RTQM_PFDBK_MIB 0xb90 -+ -+#define MTK_WED_RROQM_GLO_CFG 0xc04 -+#define MTK_WED_RROQM_RST_IDX 0xc08 -+#define MTK_WED_RROQM_RST_IDX_MIOD BIT(0) -+#define MTK_WED_RROQM_RST_IDX_FDBK BIT(4) -+ -+#define MTK_WED_RROQM_MIOD_CTRL0 0xc40 -+#define MTK_WED_RROQM_MIOD_CTRL1 0xc44 -+#define MTK_WED_RROQM_MIOD_CNT GENMASK(11, 0) -+ -+#define MTK_WED_RROQM_MIOD_CTRL2 0xc48 -+#define MTK_WED_RROQM_MIOD_CTRL3 0xc4c -+ -+#define MTK_WED_RROQM_FDBK_CTRL0 0xc50 -+#define MTK_WED_RROQM_FDBK_CTRL1 0xc54 -+#define MTK_WED_RROQM_FDBK_CNT GENMASK(11, 0) -+ -+#define MTK_WED_RROQM_FDBK_CTRL2 0xc58 -+ -+#define MTK_WED_RROQ_BASE_L 0xc80 -+#define MTK_WED_RROQ_BASE_H 0xc84 -+ -+#define MTK_WED_RROQM_MIOD_CFG 0xc8c -+#define MTK_WED_RROQM_MIOD_MID_DW GENMASK(5, 0) -+#define MTK_WED_RROQM_MIOD_MOD_DW GENMASK(13, 8) -+#define MTK_WED_RROQM_MIOD_ENTRY_DW GENMASK(22, 16) -+ -+#define MTK_WED_RROQM_MID_MIB 0xcc0 -+#define MTK_WED_RROQM_MOD_MIB 0xcc4 -+#define MTK_WED_RROQM_MOD_COHERENT_MIB 0xcc8 -+#define MTK_WED_RROQM_FDBK_MIB 0xcd0 -+#define MTK_WED_RROQM_FDBK_COHERENT_MIB 0xcd4 -+#define MTK_WED_RROQM_FDBK_IND_MIB 0xce0 -+#define MTK_WED_RROQM_FDBK_ENQ_MIB 0xce4 -+#define MTK_WED_RROQM_FDBK_ANC_MIB 0xce8 -+#define MTK_WED_RROQM_FDBK_ANC2H_MIB 0xcec -+ -+#define MTK_WED_RX_BM_RX_DMAD 0xd80 -+#define MTK_WED_RX_BM_BASE 0xd84 -+#define MTK_WED_RX_BM_INIT_PTR 0xd88 -+#define MTK_WED_RX_BM_PTR 0xd8c -+#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16) -+#define MTK_WED_RX_BM_PTR_TAIL GENMASK(15, 0) -+ -+#define MTK_WED_RX_BM_BLEN 0xd90 -+#define MTK_WED_RX_BM_STS 0xd94 -+#define MTK_WED_RX_BM_INTF2 0xd98 -+#define MTK_WED_RX_BM_INTF 0xd9c -+#define MTK_WED_RX_BM_ERR_STS 0xda8 -+ -+#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 -+#define MTK_WED_PCIE_INT_MASK 0x0 -+ - #endif ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -49,6 +49,10 @@ enum { - MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), - }; - -+#define MTK_WED_WO_CPU_MCUSYS_RESET_ADDR 0x15194050 -+#define MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK 0x20 -+#define MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK 0x1 -+ - enum { - MTK_WED_WO_REGION_EMI, - MTK_WED_WO_REGION_ILM, -@@ -57,6 +61,28 @@ enum { - __MTK_WED_WO_REGION_MAX, - }; - -+enum mtk_wed_wo_state { -+ MTK_WED_WO_STATE_UNDEFINED, -+ MTK_WED_WO_STATE_INIT, -+ MTK_WED_WO_STATE_ENABLE, -+ MTK_WED_WO_STATE_DISABLE, -+ MTK_WED_WO_STATE_HALT, -+ MTK_WED_WO_STATE_GATING, -+ MTK_WED_WO_STATE_SER_RESET, -+ MTK_WED_WO_STATE_WF_RESET, -+}; -+ -+enum mtk_wed_wo_done_state { -+ MTK_WED_WOIF_UNDEFINED, -+ MTK_WED_WOIF_DISABLE_DONE, -+ MTK_WED_WOIF_TRIGGER_ENABLE, -+ MTK_WED_WOIF_ENABLE_DONE, -+ MTK_WED_WOIF_TRIGGER_GATING, -+ MTK_WED_WOIF_GATING_DONE, -+ MTK_WED_WOIF_TRIGGER_HALT, -+ MTK_WED_WOIF_HALT_DONE, -+}; -+ - enum mtk_wed_dummy_cr_idx { - MTK_WED_DUMMY_CR_FWDL, - MTK_WED_DUMMY_CR_WO_STATUS, -@@ -245,6 +271,8 @@ void mtk_wed_mcu_rx_unsolicited_event(st - struct sk_buff *skb); - int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, - const void *data, int len, bool wait_resp); -+int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, -+ int len); - int mtk_wed_mcu_init(struct mtk_wed_wo *wo); - int mtk_wed_wo_init(struct mtk_wed_hw *hw); - void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -5,10 +5,13 @@ - #include - #include - #include -+#include - - #define MTK_WED_TX_QUEUES 2 - #define MTK_WED_RX_QUEUES 2 - -+#define WED_WO_STA_REC 0x6 -+ - struct mtk_wed_hw; - struct mtk_wdma_desc; - -@@ -41,21 +44,37 @@ enum mtk_wed_wo_cmd { - MTK_WED_WO_CMD_WED_END - }; - -+struct mtk_rxbm_desc { -+ __le32 buf0; -+ __le32 token; -+} __packed __aligned(4); -+ - enum mtk_wed_bus_tye { - MTK_WED_BUS_PCIE, - MTK_WED_BUS_AXI, - }; - -+#define MTK_WED_RING_CONFIGURED BIT(0) - struct mtk_wed_ring { - struct mtk_wdma_desc *desc; - dma_addr_t desc_phys; - u32 desc_size; - int size; -+ u32 flags; - - u32 reg_base; - void __iomem *wpdma; - }; - -+struct mtk_wed_wo_rx_stats { -+ __le16 wlan_idx; -+ __le16 tid; -+ __le32 rx_pkt_cnt; -+ __le32 rx_byte_cnt; -+ __le32 rx_err_cnt; -+ __le32 rx_drop_cnt; -+}; -+ - struct mtk_wed_device { - #ifdef CONFIG_NET_MEDIATEK_SOC_WED - const struct mtk_wed_ops *ops; -@@ -64,9 +83,12 @@ struct mtk_wed_device { - bool init_done, running; - int wdma_idx; - int irq; -+ u8 version; - - struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; -+ struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES]; - struct mtk_wed_ring txfree_ring; -+ struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; - struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; - - struct { -@@ -74,7 +96,20 @@ struct mtk_wed_device { - void **pages; - struct mtk_wdma_desc *desc; - dma_addr_t desc_phys; -- } buf_ring; -+ } tx_buf_ring; -+ -+ struct { -+ int size; -+ struct page_frag_cache rx_page; -+ struct mtk_rxbm_desc *desc; -+ dma_addr_t desc_phys; -+ } rx_buf_ring; -+ -+ struct { -+ struct mtk_wed_ring ring; -+ dma_addr_t miod_phys; -+ dma_addr_t fdbk_phys; -+ } rro; - - /* filled by driver: */ - struct { -@@ -83,22 +118,36 @@ struct mtk_wed_device { - struct pci_dev *pci_dev; - }; - enum mtk_wed_bus_tye bus_type; -+ void __iomem *base; -+ u32 phy_base; - - u32 wpdma_phys; - u32 wpdma_int; - u32 wpdma_mask; - u32 wpdma_tx; - u32 wpdma_txfree; -+ u32 wpdma_rx_glo; -+ u32 wpdma_rx; -+ -+ bool wcid_512; - - u16 token_start; - unsigned int nbuf; -+ unsigned int rx_nbuf; -+ unsigned int rx_npkt; -+ unsigned int rx_size; - - u8 tx_tbit[MTK_WED_TX_QUEUES]; -+ u8 rx_tbit[MTK_WED_RX_QUEUES]; - u8 txfree_tbit; - - u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); - int (*offload_enable)(struct mtk_wed_device *wed); - void (*offload_disable)(struct mtk_wed_device *wed); -+ u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size); -+ void (*release_rx_buf)(struct mtk_wed_device *wed); -+ void (*update_wo_rx_stats)(struct mtk_wed_device *wed, -+ struct mtk_wed_wo_rx_stats *stats); - } wlan; - #endif - }; -@@ -107,9 +156,15 @@ struct mtk_wed_ops { - int (*attach)(struct mtk_wed_device *dev); - int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, - void __iomem *regs); -+ int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, -+ void __iomem *regs); - int (*txfree_ring_setup)(struct mtk_wed_device *dev, - void __iomem *regs); -+ int (*msg_update)(struct mtk_wed_device *dev, int cmd_id, -+ void *data, int len); - void (*detach)(struct mtk_wed_device *dev); -+ void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb, -+ u32 reason, u32 hash); - - void (*stop)(struct mtk_wed_device *dev); - void (*start)(struct mtk_wed_device *dev, u32 irq_mask); -@@ -144,6 +199,16 @@ mtk_wed_device_attach(struct mtk_wed_dev - return ret; - } - -+static inline bool -+mtk_wed_get_rx_capa(struct mtk_wed_device *dev) -+{ -+#ifdef CONFIG_NET_MEDIATEK_SOC_WED -+ return dev->version != 1; -+#else -+ return false; -+#endif -+} -+ - #ifdef CONFIG_NET_MEDIATEK_SOC_WED - #define mtk_wed_device_active(_dev) !!(_dev)->ops - #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) -@@ -160,6 +225,12 @@ mtk_wed_device_attach(struct mtk_wed_dev - (_dev)->ops->irq_get(_dev, _mask) - #define mtk_wed_device_irq_set_mask(_dev, _mask) \ - (_dev)->ops->irq_set_mask(_dev, _mask) -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \ -+ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs) -+#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \ -+ (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) -+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ -+ (_dev)->ops->msg_update(_dev, _id, _msg, _len) - #else - static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) - { -@@ -173,6 +244,9 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) - #define mtk_wed_device_irq_get(_dev, _mask) 0 - #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV -+#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) -+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV - #endif - - #endif diff --git a/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch b/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch deleted file mode 100644 index bb1066dece..0000000000 --- a/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch +++ /dev/null @@ -1,149 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:22 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add rx mib counters - -Introduce WED RX MIB counters support available on MT7986a SoC. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -@@ -2,6 +2,7 @@ - /* Copyright (C) 2021 Felix Fietkau */ - - #include -+#include - #include "mtk_wed.h" - #include "mtk_wed_regs.h" - -@@ -18,6 +19,8 @@ enum { - DUMP_TYPE_WDMA, - DUMP_TYPE_WPDMA_TX, - DUMP_TYPE_WPDMA_TXFREE, -+ DUMP_TYPE_WPDMA_RX, -+ DUMP_TYPE_WED_RRO, - }; - - #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } -@@ -36,6 +39,9 @@ enum { - - #define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n) - #define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE) -+#define DUMP_WPDMA_RX_RING(_n) DUMP_RING("WPDMA_RX" #_n, 0, DUMP_TYPE_WPDMA_RX, _n) -+#define DUMP_WED_RRO_RING(_base)DUMP_RING("WED_RRO_MIOD", MTK_##_base, DUMP_TYPE_WED_RRO) -+#define DUMP_WED_RRO_FDBK(_base)DUMP_RING("WED_RRO_FDBK", MTK_##_base, DUMP_TYPE_WED_RRO) - - static void - print_reg_val(struct seq_file *s, const char *name, u32 val) -@@ -57,6 +63,7 @@ dump_wed_regs(struct seq_file *s, struct - cur > regs ? "\n" : "", - cur->name); - continue; -+ case DUMP_TYPE_WED_RRO: - case DUMP_TYPE_WED: - val = wed_r32(dev, cur->offset); - break; -@@ -69,6 +76,9 @@ dump_wed_regs(struct seq_file *s, struct - case DUMP_TYPE_WPDMA_TXFREE: - val = wpdma_txfree_r32(dev, cur->offset); - break; -+ case DUMP_TYPE_WPDMA_RX: -+ val = wpdma_rx_r32(dev, cur->base, cur->offset); -+ break; - } - print_reg_val(s, cur->name, val); - } -@@ -132,6 +142,80 @@ wed_txinfo_show(struct seq_file *s, void - } - DEFINE_SHOW_ATTRIBUTE(wed_txinfo); - -+static int -+wed_rxinfo_show(struct seq_file *s, void *data) -+{ -+ static const struct reg_dump regs[] = { -+ DUMP_STR("WPDMA RX"), -+ DUMP_WPDMA_RX_RING(0), -+ DUMP_WPDMA_RX_RING(1), -+ -+ DUMP_STR("WPDMA RX"), -+ DUMP_WED(WED_WPDMA_RX_D_MIB(0)), -+ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(0)), -+ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(0)), -+ DUMP_WED(WED_WPDMA_RX_D_MIB(1)), -+ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(1)), -+ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(1)), -+ DUMP_WED(WED_WPDMA_RX_D_COHERENT_MIB), -+ -+ DUMP_STR("WED RX"), -+ DUMP_WED_RING(WED_RING_RX_DATA(0)), -+ DUMP_WED_RING(WED_RING_RX_DATA(1)), -+ -+ DUMP_STR("WED RRO"), -+ DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0), -+ DUMP_WED(WED_RROQM_MID_MIB), -+ DUMP_WED(WED_RROQM_MOD_MIB), -+ DUMP_WED(WED_RROQM_MOD_COHERENT_MIB), -+ DUMP_WED_RRO_FDBK(WED_RROQM_FDBK_CTRL0), -+ DUMP_WED(WED_RROQM_FDBK_IND_MIB), -+ DUMP_WED(WED_RROQM_FDBK_ENQ_MIB), -+ DUMP_WED(WED_RROQM_FDBK_ANC_MIB), -+ DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB), -+ -+ DUMP_STR("WED Route QM"), -+ DUMP_WED(WED_RTQM_R2H_MIB(0)), -+ DUMP_WED(WED_RTQM_R2Q_MIB(0)), -+ DUMP_WED(WED_RTQM_Q2H_MIB(0)), -+ DUMP_WED(WED_RTQM_R2H_MIB(1)), -+ DUMP_WED(WED_RTQM_R2Q_MIB(1)), -+ DUMP_WED(WED_RTQM_Q2H_MIB(1)), -+ DUMP_WED(WED_RTQM_Q2N_MIB), -+ DUMP_WED(WED_RTQM_Q2B_MIB), -+ DUMP_WED(WED_RTQM_PFDBK_MIB), -+ -+ DUMP_STR("WED WDMA TX"), -+ DUMP_WED(WED_WDMA_TX_MIB), -+ DUMP_WED_RING(WED_WDMA_RING_TX), -+ -+ DUMP_STR("WDMA TX"), -+ DUMP_WDMA(WDMA_GLO_CFG), -+ DUMP_WDMA_RING(WDMA_RING_TX(0)), -+ DUMP_WDMA_RING(WDMA_RING_TX(1)), -+ -+ DUMP_STR("WED RX BM"), -+ DUMP_WED(WED_RX_BM_BASE), -+ DUMP_WED(WED_RX_BM_RX_DMAD), -+ DUMP_WED(WED_RX_BM_PTR), -+ DUMP_WED(WED_RX_BM_TKID_MIB), -+ DUMP_WED(WED_RX_BM_BLEN), -+ DUMP_WED(WED_RX_BM_STS), -+ DUMP_WED(WED_RX_BM_INTF2), -+ DUMP_WED(WED_RX_BM_INTF), -+ DUMP_WED(WED_RX_BM_ERR_STS), -+ }; -+ struct mtk_wed_hw *hw = s->private; -+ struct mtk_wed_device *dev = hw->wed_dev; -+ -+ if (!dev) -+ return 0; -+ -+ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); -+ -+ return 0; -+} -+DEFINE_SHOW_ATTRIBUTE(wed_rxinfo); - - static int - mtk_wed_reg_set(void *data, u64 val) -@@ -175,4 +259,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w - debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); - debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); - debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); -+ if (hw->version != 1) -+ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, -+ &wed_rxinfo_fops); - } diff --git a/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch b/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch deleted file mode 100644 index cefe1eefff..0000000000 --- a/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 17 Nov 2022 00:58:46 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: remove cpu_relax in - mtk_pending_work - -Get rid of cpu_relax in mtk_pending_work routine since MTK_RESETTING is -set only in mtk_pending_work() and it runs holding rtnl lock - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3480,11 +3480,8 @@ static void mtk_pending_work(struct work - rtnl_lock(); - - dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__); -+ set_bit(MTK_RESETTING, ð->state); - -- while (test_and_set_bit_lock(MTK_RESETTING, ð->state)) -- cpu_relax(); -- -- dev_dbg(eth->dev, "[%s][%d] mtk_stop starts\n", __func__, __LINE__); - /* stop all devices to make sure that dma is properly shut down */ - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!eth->netdev[i]) -@@ -3518,7 +3515,7 @@ static void mtk_pending_work(struct work - - dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__); - -- clear_bit_unlock(MTK_RESETTING, ð->state); -+ clear_bit(MTK_RESETTING, ð->state); - - rtnl_unlock(); - } diff --git a/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch b/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch deleted file mode 100644 index 117ccc0902..0000000000 --- a/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch +++ /dev/null @@ -1,80 +0,0 @@ -From: Sujuan Chen -Date: Thu, 24 Nov 2022 11:18:14 +0800 -Subject: [PATCH] net: ethernet: mtk_wed: add wcid overwritten support for wed - v1 - -All wed versions should enable the wcid overwritten feature, -since the wcid size is controlled by the wlan driver. - -Tested-by: Sujuan Chen -Co-developed-by: Bo Jiao -Signed-off-by: Bo Jiao -Signed-off-by: Sujuan Chen -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -526,9 +526,9 @@ mtk_wed_dma_disable(struct mtk_wed_devic - MTK_WED_WPDMA_RX_D_RX_DRV_EN); - wed_clr(dev, MTK_WED_WDMA_GLO_CFG, - MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); -- -- mtk_wed_set_512_support(dev, false); - } -+ -+ mtk_wed_set_512_support(dev, false); - } - - static void -@@ -1290,9 +1290,10 @@ mtk_wed_start(struct mtk_wed_device *dev - if (mtk_wed_rro_cfg(dev)) - return; - -- mtk_wed_set_512_support(dev, dev->wlan.wcid_512); - } - -+ mtk_wed_set_512_support(dev, dev->wlan.wcid_512); -+ - mtk_wed_dma_enable(dev); - dev->running = true; - } -@@ -1358,11 +1359,13 @@ mtk_wed_attach(struct mtk_wed_device *de - } - - mtk_wed_hw_init_early(dev); -- if (hw->version == 1) -+ if (hw->version == 1) { - regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, - BIT(hw->index), 0); -- else -+ } else { -+ dev->rev_id = wed_r32(dev, MTK_WED_REV_ID); - ret = mtk_wed_wo_init(hw); -+ } - out: - if (ret) - mtk_wed_detach(dev); ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -20,6 +20,8 @@ struct mtk_wdma_desc { - __le32 info; - } __packed __aligned(4); - -+#define MTK_WED_REV_ID 0x004 -+ - #define MTK_WED_RESET 0x008 - #define MTK_WED_RESET_TX_BM BIT(0) - #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -85,6 +85,9 @@ struct mtk_wed_device { - int irq; - u8 version; - -+ /* used by wlan driver */ -+ u32 rev_id; -+ - struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; - struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES]; - struct mtk_wed_ring txfree_ring; diff --git a/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch b/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch deleted file mode 100644 index ec58c3fc57..0000000000 --- a/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch +++ /dev/null @@ -1,85 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:51 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: return status value in - mtk_wdma_rx_reset - -Move MTK_WDMA_RESET_IDX configuration in mtk_wdma_rx_reset routine. -Increase poll timeout to 10ms in order to be aligned with vendor sdk. -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -101,17 +101,21 @@ mtk_wdma_read_reset(struct mtk_wed_devic - return wdma_r32(dev, MTK_WDMA_GLO_CFG); - } - --static void -+static int - mtk_wdma_rx_reset(struct mtk_wed_device *dev) - { - u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY; -- int i; -+ int i, ret; - - wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN); -- if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -- !(status & mask), 0, 1000)) -+ ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status, -+ !(status & mask), 0, 10000); -+ if (ret) - dev_err(dev->hw->dev, "rx reset failed\n"); - -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -+ - for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) { - if (dev->rx_wdma[i].desc) - continue; -@@ -119,6 +123,8 @@ mtk_wdma_rx_reset(struct mtk_wed_device - wdma_w32(dev, - MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); - } -+ -+ return ret; - } - - static void -@@ -565,9 +571,7 @@ mtk_wed_detach(struct mtk_wed_device *de - - mtk_wed_stop(dev); - -- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -- -+ mtk_wdma_rx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); - if (mtk_wed_get_rx_capa(dev)) { - wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -@@ -582,7 +586,6 @@ mtk_wed_detach(struct mtk_wed_device *de - mtk_wed_wo_reset(dev); - mtk_wed_free_rx_rings(dev); - mtk_wed_wo_deinit(hw); -- mtk_wdma_rx_reset(dev); - } - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { -@@ -999,11 +1002,7 @@ mtk_wed_reset_dma(struct mtk_wed_device - wed_w32(dev, MTK_WED_RESET_IDX, 0); - } - -- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -- -- if (mtk_wed_get_rx_capa(dev)) -- mtk_wdma_rx_reset(dev); -+ mtk_wdma_rx_reset(dev); - - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); diff --git a/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch b/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch deleted file mode 100644 index 10c1732c96..0000000000 --- a/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:52 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: move MTK_WDMA_RESET_IDX_TX - configuration in mtk_wdma_tx_reset - -Remove duplicated code. Increase poll timeout to 10ms in order to be -aligned with vendor sdk. -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -135,16 +135,15 @@ mtk_wdma_tx_reset(struct mtk_wed_device - - wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); - if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -- !(status & mask), 0, 1000)) -+ !(status & mask), 0, 10000)) - dev_err(dev->hw->dev, "tx reset failed\n"); - -- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) { -- if (dev->tx_wdma[i].desc) -- continue; -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); - -+ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) - wdma_w32(dev, - MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); -- } - } - - static void -@@ -573,12 +572,6 @@ mtk_wed_detach(struct mtk_wed_device *de - - mtk_wdma_rx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); -- if (mtk_wed_get_rx_capa(dev)) { -- wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -- } -- - mtk_wed_free_tx_buffer(dev); - mtk_wed_free_tx_rings(dev); - diff --git a/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch b/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch deleted file mode 100644 index f4e842d515..0000000000 --- a/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch +++ /dev/null @@ -1,98 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:53 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: update mtk_wed_stop - -Update mtk_wed_stop routine and rename old mtk_wed_stop() to -mtk_wed_deinit(). This is a preliminary patch to add Wireless Ethernet -Dispatcher reset support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -539,14 +539,8 @@ mtk_wed_dma_disable(struct mtk_wed_devic - static void - mtk_wed_stop(struct mtk_wed_device *dev) - { -- mtk_wed_dma_disable(dev); - mtk_wed_set_ext_int(dev, false); - -- wed_clr(dev, MTK_WED_CTRL, -- MTK_WED_CTRL_WDMA_INT_AGENT_EN | -- MTK_WED_CTRL_WPDMA_INT_AGENT_EN | -- MTK_WED_CTRL_WED_TX_BM_EN | -- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); - wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); - wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); - wdma_w32(dev, MTK_WDMA_INT_MASK, 0); -@@ -558,7 +552,27 @@ mtk_wed_stop(struct mtk_wed_device *dev) - - wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); - wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0); -- wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); -+} -+ -+static void -+mtk_wed_deinit(struct mtk_wed_device *dev) -+{ -+ mtk_wed_stop(dev); -+ mtk_wed_dma_disable(dev); -+ -+ wed_clr(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_WDMA_INT_AGENT_EN | -+ MTK_WED_CTRL_WPDMA_INT_AGENT_EN | -+ MTK_WED_CTRL_WED_TX_BM_EN | -+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); -+ -+ if (dev->hw->version == 1) -+ return; -+ -+ wed_clr(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_RX_ROUTE_QM_EN | -+ MTK_WED_CTRL_WED_RX_BM_EN | -+ MTK_WED_CTRL_RX_RRO_QM_EN); - } - - static void -@@ -568,7 +582,7 @@ mtk_wed_detach(struct mtk_wed_device *de - - mutex_lock(&hw_lock); - -- mtk_wed_stop(dev); -+ mtk_wed_deinit(dev); - - mtk_wdma_rx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); -@@ -670,7 +684,7 @@ mtk_wed_hw_init_early(struct mtk_wed_dev - { - u32 mask, set; - -- mtk_wed_stop(dev); -+ mtk_wed_deinit(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); - mtk_wed_set_wpdma(dev); - ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -234,6 +234,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ - (_dev)->ops->msg_update(_dev, _id, _msg, _len) -+#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev) -+#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) - #else - static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) - { -@@ -250,6 +252,8 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV - #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV -+#define mtk_wed_device_stop(_dev) do {} while (0) -+#define mtk_wed_device_dma_reset(_dev) do {} while (0) - #endif - - #endif diff --git a/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch b/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch deleted file mode 100644 index a0fc9da99e..0000000000 --- a/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch +++ /dev/null @@ -1,309 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:54 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add mtk_wed_rx_reset routine - -Introduce mtk_wed_rx_reset routine in order to reset rx DMA for Wireless -Ethernet Dispatcher available on MT7986 SoC. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -944,42 +944,130 @@ mtk_wed_ring_reset(struct mtk_wed_ring * - } - - static u32 --mtk_wed_check_busy(struct mtk_wed_device *dev) -+mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) - { -- if (wed_r32(dev, MTK_WED_GLO_CFG) & MTK_WED_GLO_CFG_TX_DMA_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_WPDMA_GLO_CFG) & -- MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_CTRL) & MTK_WED_CTRL_WDMA_INT_AGENT_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_WDMA_GLO_CFG) & -- MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) -- return true; -- -- if (wdma_r32(dev, MTK_WDMA_GLO_CFG) & -- MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_CTRL) & -- (MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY)) -- return true; -- -- return false; -+ return !!(wed_r32(dev, reg) & mask); - } - - static int --mtk_wed_poll_busy(struct mtk_wed_device *dev) -+mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) - { - int sleep = 15000; - int timeout = 100 * sleep; - u32 val; - - return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, -- timeout, false, dev); -+ timeout, false, dev, reg, mask); -+} -+ -+static int -+mtk_wed_rx_reset(struct mtk_wed_device *dev) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ u8 val = MTK_WED_WO_STATE_SER_RESET; -+ int i, ret; -+ -+ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &val, -+ sizeof(val), true); -+ if (ret) -+ return ret; -+ -+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN); -+ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RX_DRV_BUSY); -+ if (ret) { -+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); -+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV); -+ } else { -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, -+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | -+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); -+ -+ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE | -+ MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE); -+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE | -+ MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE); -+ -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); -+ } -+ -+ /* reset rro qm */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN); -+ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_RX_RRO_QM_BUSY); -+ if (ret) { -+ mtk_wed_reset(dev, MTK_WED_RESET_RX_RRO_QM); -+ } else { -+ wed_set(dev, MTK_WED_RROQM_RST_IDX, -+ MTK_WED_RROQM_RST_IDX_MIOD | -+ MTK_WED_RROQM_RST_IDX_FDBK); -+ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); -+ } -+ -+ /* reset route qm */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); -+ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_RX_ROUTE_QM_BUSY); -+ if (ret) -+ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM); -+ else -+ wed_set(dev, MTK_WED_RTQM_GLO_CFG, -+ MTK_WED_RTQM_Q_RST); -+ -+ /* reset tx wdma */ -+ mtk_wdma_tx_reset(dev); -+ -+ /* reset tx wdma drv */ -+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN); -+ mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_WDMA_INT_AGENT_BUSY); -+ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV); -+ -+ /* reset wed rx dma */ -+ ret = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, -+ MTK_WED_GLO_CFG_RX_DMA_BUSY); -+ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_RX_DMA_EN); -+ if (ret) { -+ mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA); -+ } else { -+ struct mtk_eth *eth = dev->hw->eth; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ wed_set(dev, MTK_WED_RESET_IDX, -+ MTK_WED_RESET_IDX_RX_V2); -+ else -+ wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX); -+ wed_w32(dev, MTK_WED_RESET_IDX, 0); -+ } -+ -+ /* reset rx bm */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); -+ mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_WED_RX_BM_BUSY); -+ mtk_wed_reset(dev, MTK_WED_RESET_RX_BM); -+ -+ /* wo change to enable state */ -+ val = MTK_WED_WO_STATE_ENABLE; -+ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &val, -+ sizeof(val), true); -+ if (ret) -+ return ret; -+ -+ /* wed_rx_ring_reset */ -+ for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++) { -+ if (!dev->rx_ring[i].desc) -+ continue; -+ -+ mtk_wed_ring_reset(&dev->rx_ring[i], MTK_WED_RX_RING_SIZE, -+ false); -+ } -+ mtk_wed_free_rx_buffer(dev); -+ -+ return 0; - } - - static void -@@ -997,19 +1085,23 @@ mtk_wed_reset_dma(struct mtk_wed_device - true); - } - -- if (mtk_wed_poll_busy(dev)) -- busy = mtk_wed_check_busy(dev); -- -+ /* 1. reset WED tx DMA */ -+ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_EN); -+ busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, -+ MTK_WED_GLO_CFG_TX_DMA_BUSY); - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); - } else { -- wed_w32(dev, MTK_WED_RESET_IDX, -- MTK_WED_RESET_IDX_TX | -- MTK_WED_RESET_IDX_RX); -+ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX); - wed_w32(dev, MTK_WED_RESET_IDX, 0); - } - -- mtk_wdma_rx_reset(dev); -+ /* 2. reset WDMA rx DMA */ -+ busy = !!mtk_wdma_rx_reset(dev); -+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); -+ if (!busy) -+ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG, -+ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY); - - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); -@@ -1026,6 +1118,9 @@ mtk_wed_reset_dma(struct mtk_wed_device - MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE); - } - -+ /* 3. reset WED WPDMA tx */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); -+ - for (i = 0; i < 100; i++) { - val = wed_r32(dev, MTK_WED_TX_BM_INTF); - if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40) -@@ -1033,8 +1128,19 @@ mtk_wed_reset_dma(struct mtk_wed_device - } - - mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT); -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_BM_EN); - mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); - -+ /* 4. reset WED WPDMA tx */ -+ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG, -+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY); -+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, -+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | -+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); -+ if (!busy) -+ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG, -+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY); -+ - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); - mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); -@@ -1045,6 +1151,17 @@ mtk_wed_reset_dma(struct mtk_wed_device - MTK_WED_WPDMA_RESET_IDX_RX); - wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); - } -+ -+ dev->init_done = false; -+ if (dev->hw->version == 1) -+ return; -+ -+ if (!busy) { -+ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_WPDMA_IDX_RX); -+ wed_w32(dev, MTK_WED_RESET_IDX, 0); -+ } -+ -+ mtk_wed_rx_reset(dev); - } - - static int -@@ -1267,6 +1384,9 @@ mtk_wed_start(struct mtk_wed_device *dev - { - int i; - -+ if (mtk_wed_get_rx_capa(dev) && mtk_wed_rx_buffer_alloc(dev)) -+ return; -+ - for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) - if (!dev->rx_wdma[i].desc) - mtk_wed_wdma_rx_ring_setup(dev, i, 16); -@@ -1355,10 +1475,6 @@ mtk_wed_attach(struct mtk_wed_device *de - goto out; - - if (mtk_wed_get_rx_capa(dev)) { -- ret = mtk_wed_rx_buffer_alloc(dev); -- if (ret) -- goto out; -- - ret = mtk_wed_rro_alloc(dev); - if (ret) - goto out; ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -24,11 +24,15 @@ struct mtk_wdma_desc { - - #define MTK_WED_RESET 0x008 - #define MTK_WED_RESET_TX_BM BIT(0) -+#define MTK_WED_RESET_RX_BM BIT(1) - #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) - #define MTK_WED_RESET_WPDMA_TX_DRV BIT(8) - #define MTK_WED_RESET_WPDMA_RX_DRV BIT(9) -+#define MTK_WED_RESET_WPDMA_RX_D_DRV BIT(10) - #define MTK_WED_RESET_WPDMA_INT_AGENT BIT(11) - #define MTK_WED_RESET_WED_TX_DMA BIT(12) -+#define MTK_WED_RESET_WED_RX_DMA BIT(13) -+#define MTK_WED_RESET_WDMA_TX_DRV BIT(16) - #define MTK_WED_RESET_WDMA_RX_DRV BIT(17) - #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) - #define MTK_WED_RESET_RX_RRO_QM BIT(20) -@@ -158,6 +162,8 @@ struct mtk_wdma_desc { - #define MTK_WED_RESET_IDX 0x20c - #define MTK_WED_RESET_IDX_TX GENMASK(3, 0) - #define MTK_WED_RESET_IDX_RX GENMASK(17, 16) -+#define MTK_WED_RESET_IDX_RX_V2 GENMASK(7, 6) -+#define MTK_WED_RESET_WPDMA_IDX_RX GENMASK(31, 30) - - #define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4) - #define MTK_WED_RX_MIB(_n) (0x2e0 + (_n) * 4) -@@ -267,6 +273,9 @@ struct mtk_wdma_desc { - - #define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c - #define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0) -+#define MTK_WED_WPDMA_RX_D_RX_DRV_BUSY BIT(1) -+#define MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE BIT(3) -+#define MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE BIT(4) - #define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7) - #define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24) - diff --git a/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch b/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch deleted file mode 100644 index 4404971cc7..0000000000 --- a/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:55 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add reset to tx_ring_setup callback - -Introduce reset parameter to mtk_wed_tx_ring_setup signature. -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1181,7 +1181,8 @@ mtk_wed_ring_alloc(struct mtk_wed_device - } - - static int --mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size, -+ bool reset) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; - struct mtk_wed_ring *wdma; -@@ -1190,8 +1191,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we - return -EINVAL; - - wdma = &dev->rx_wdma[idx]; -- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -- true)) -+ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, -+ desc_size, true)) - return -ENOMEM; - - wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, -@@ -1389,7 +1390,7 @@ mtk_wed_start(struct mtk_wed_device *dev - - for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) - if (!dev->rx_wdma[i].desc) -- mtk_wed_wdma_rx_ring_setup(dev, i, 16); -+ mtk_wed_wdma_rx_ring_setup(dev, i, 16, false); - - mtk_wed_hw_init(dev); - mtk_wed_configure_irq(dev, irq_mask); -@@ -1498,7 +1499,8 @@ unlock: - } - - static int --mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) -+mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs, -+ bool reset) - { - struct mtk_wed_ring *ring = &dev->tx_ring[idx]; - -@@ -1517,11 +1519,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev - if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring))) - return -EINVAL; - -- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, -- sizeof(*ring->desc), true)) -+ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, -+ sizeof(*ring->desc), true)) - return -ENOMEM; - -- if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, -+ reset)) - return -ENOMEM; - - ring->reg_base = MTK_WED_RING_TX(idx); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -158,7 +158,7 @@ struct mtk_wed_device { - struct mtk_wed_ops { - int (*attach)(struct mtk_wed_device *dev); - int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, -- void __iomem *regs); -+ void __iomem *regs, bool reset); - int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, - void __iomem *regs); - int (*txfree_ring_setup)(struct mtk_wed_device *dev, -@@ -216,8 +216,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - #define mtk_wed_device_active(_dev) !!(_dev)->ops - #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) - #define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask) --#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) \ -- (_dev)->ops->tx_ring_setup(_dev, _ring, _regs) -+#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) \ -+ (_dev)->ops->tx_ring_setup(_dev, _ring, _regs, _reset) - #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \ - (_dev)->ops->txfree_ring_setup(_dev, _regs) - #define mtk_wed_device_reg_read(_dev, _reg) \ -@@ -243,7 +243,7 @@ static inline bool mtk_wed_device_active - } - #define mtk_wed_device_detach(_dev) do {} while (0) - #define mtk_wed_device_start(_dev, _mask) do {} while (0) --#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV -+#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV - #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV - #define mtk_wed_device_reg_read(_dev, _reg) 0 - #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) diff --git a/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch b/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch deleted file mode 100644 index f9b11326b1..0000000000 --- a/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 1 Dec 2022 16:26:53 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: fix sleep while atomic in - mtk_wed_wo_queue_refill - -In order to fix the following sleep while atomic bug always alloc pages -with GFP_ATOMIC in mtk_wed_wo_queue_refill since page_frag_alloc runs in -spin_lock critical section. - -[ 9.049719] Hardware name: MediaTek MT7986a RFB (DT) -[ 9.054665] Call trace: -[ 9.057096] dump_backtrace+0x0/0x154 -[ 9.060751] show_stack+0x14/0x1c -[ 9.064052] dump_stack_lvl+0x64/0x7c -[ 9.067702] dump_stack+0x14/0x2c -[ 9.071001] ___might_sleep+0xec/0x120 -[ 9.074736] __might_sleep+0x4c/0x9c -[ 9.078296] __alloc_pages+0x184/0x2e4 -[ 9.082030] page_frag_alloc_align+0x98/0x1ac -[ 9.086369] mtk_wed_wo_queue_refill+0x134/0x234 -[ 9.090974] mtk_wed_wo_init+0x174/0x2c0 -[ 9.094881] mtk_wed_attach+0x7c8/0x7e0 -[ 9.098701] mt7915_mmio_wed_init+0x1f0/0x3a0 [mt7915e] -[ 9.103940] mt7915_pci_probe+0xec/0x3bc [mt7915e] -[ 9.108727] pci_device_probe+0xac/0x13c -[ 9.112638] really_probe.part.0+0x98/0x2f4 -[ 9.116807] __driver_probe_device+0x94/0x13c -[ 9.121147] driver_probe_device+0x40/0x114 -[ 9.125314] __driver_attach+0x7c/0x180 -[ 9.129133] bus_for_each_dev+0x5c/0x90 -[ 9.132953] driver_attach+0x20/0x2c -[ 9.136513] bus_add_driver+0x104/0x1fc -[ 9.140333] driver_register+0x74/0x120 -[ 9.144153] __pci_register_driver+0x40/0x50 -[ 9.148407] mt7915_init+0x5c/0x1000 [mt7915e] -[ 9.152848] do_one_initcall+0x40/0x25c -[ 9.156669] do_init_module+0x44/0x230 -[ 9.160403] load_module+0x1f30/0x2750 -[ 9.164135] __do_sys_init_module+0x150/0x200 -[ 9.168475] __arm64_sys_init_module+0x18/0x20 -[ 9.172901] invoke_syscall.constprop.0+0x4c/0xe0 -[ 9.177589] do_el0_svc+0x48/0xe0 -[ 9.180889] el0_svc+0x14/0x50 -[ 9.183929] el0t_64_sync_handler+0x9c/0x120 -[ 9.188183] el0t_64_sync+0x158/0x15c - -Fixes: 799684448e3e ("net: ethernet: mtk_wed: introduce wed wo support") -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Pavan Chebbi -Link: https://lore.kernel.org/r/67ca94bdd3d9eaeb86e52b3050fbca0bcf7bb02f.1669908312.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -133,17 +133,18 @@ mtk_wed_wo_dequeue(struct mtk_wed_wo *wo - - static int - mtk_wed_wo_queue_refill(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -- gfp_t gfp, bool rx) -+ bool rx) - { - enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - int n_buf = 0; - - spin_lock_bh(&q->lock); - while (q->queued < q->n_desc) { -- void *buf = page_frag_alloc(&q->cache, q->buf_size, gfp); - struct mtk_wed_wo_queue_entry *entry; - dma_addr_t addr; -+ void *buf; - -+ buf = page_frag_alloc(&q->cache, q->buf_size, GFP_ATOMIC); - if (!buf) - break; - -@@ -215,7 +216,7 @@ mtk_wed_wo_rx_run_queue(struct mtk_wed_w - mtk_wed_mcu_rx_unsolicited_event(wo, skb); - } - -- if (mtk_wed_wo_queue_refill(wo, q, GFP_ATOMIC, true)) { -+ if (mtk_wed_wo_queue_refill(wo, q, true)) { - u32 index = (q->head - 1) % q->n_desc; - - mtk_wed_wo_queue_kick(wo, q, index); -@@ -432,7 +433,7 @@ mtk_wed_wo_hardware_init(struct mtk_wed_ - if (ret) - goto error; - -- mtk_wed_wo_queue_refill(wo, &wo->q_tx, GFP_KERNEL, false); -+ mtk_wed_wo_queue_refill(wo, &wo->q_tx, false); - mtk_wed_wo_queue_reset(wo, &wo->q_tx); - - regs.desc_base = MTK_WED_WO_CCIF_DUMMY5; -@@ -446,7 +447,7 @@ mtk_wed_wo_hardware_init(struct mtk_wed_ - if (ret) - goto error; - -- mtk_wed_wo_queue_refill(wo, &wo->q_rx, GFP_KERNEL, true); -+ mtk_wed_wo_queue_refill(wo, &wo->q_rx, true); - mtk_wed_wo_queue_reset(wo, &wo->q_rx); - - /* rx queue irqmask */ diff --git a/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch b/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch deleted file mode 100644 index fa6f56dbe7..0000000000 --- a/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Lorenzo Bianconi -Date: Tue, 10 Jan 2023 10:31:26 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: get rid of queue lock for rx queue - -Queue spinlock is currently held in mtk_wed_wo_queue_rx_clean and -mtk_wed_wo_queue_refill routines for MTK Wireless Ethernet Dispatcher -MCU rx queue. mtk_wed_wo_queue_refill() is running during initialization -and in rx tasklet while mtk_wed_wo_queue_rx_clean() is running in -mtk_wed_wo_hw_deinit() during hw de-init phase after rx tasklet has been -disabled. Since mtk_wed_wo_queue_rx_clean and mtk_wed_wo_queue_refill -routines can't run concurrently get rid of spinlock for mcu rx queue. - -Reviewed-by: Alexander Duyck -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/36ec3b729542ea60898471d890796f745479ba32.1673342990.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -138,7 +138,6 @@ mtk_wed_wo_queue_refill(struct mtk_wed_w - enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - int n_buf = 0; - -- spin_lock_bh(&q->lock); - while (q->queued < q->n_desc) { - struct mtk_wed_wo_queue_entry *entry; - dma_addr_t addr; -@@ -172,7 +171,6 @@ mtk_wed_wo_queue_refill(struct mtk_wed_w - q->queued++; - n_buf++; - } -- spin_unlock_bh(&q->lock); - - return n_buf; - } -@@ -316,7 +314,6 @@ mtk_wed_wo_queue_rx_clean(struct mtk_wed - { - struct page *page; - -- spin_lock_bh(&q->lock); - for (;;) { - void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); - -@@ -325,7 +322,6 @@ mtk_wed_wo_queue_rx_clean(struct mtk_wed - - skb_free_frag(buf); - } -- spin_unlock_bh(&q->lock); - - if (!q->cache.va) - return; diff --git a/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch b/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch deleted file mode 100644 index 9b1e4c3250..0000000000 --- a/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 12 Jan 2023 10:21:29 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: get rid of queue lock for tx queue - -Similar to MTK Wireless Ethernet Dispatcher (WED) MCU rx queue, -we do not need to protect WED MCU tx queue with a spin lock since -the tx queue is accessed in the two following routines: -- mtk_wed_wo_queue_tx_skb(): - it is run at initialization and during mt7915 normal operation. - Moreover MCU messages are serialized through MCU mutex. -- mtk_wed_wo_queue_tx_clean(): - it runs just at mt7915 driver module unload when no more messages - are sent to the MCU. - -Remove tx queue spinlock. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/7bd0337b2a13ab1a63673b7c03fd35206b3b284e.1673515140.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -258,7 +258,6 @@ mtk_wed_wo_queue_alloc(struct mtk_wed_wo - int n_desc, int buf_size, int index, - struct mtk_wed_wo_queue_regs *regs) - { -- spin_lock_init(&q->lock); - q->regs = *regs; - q->n_desc = n_desc; - q->buf_size = buf_size; -@@ -290,7 +289,6 @@ mtk_wed_wo_queue_tx_clean(struct mtk_wed - struct page *page; - int i; - -- spin_lock_bh(&q->lock); - for (i = 0; i < q->n_desc; i++) { - struct mtk_wed_wo_queue_entry *entry = &q->entry[i]; - -@@ -299,7 +297,6 @@ mtk_wed_wo_queue_tx_clean(struct mtk_wed - skb_free_frag(entry->buf); - entry->buf = NULL; - } -- spin_unlock_bh(&q->lock); - - if (!q->cache.va) - return; -@@ -347,8 +344,6 @@ int mtk_wed_wo_queue_tx_skb(struct mtk_w - int ret = 0, index; - u32 ctrl; - -- spin_lock_bh(&q->lock); -- - q->tail = mtk_wed_mmio_r32(wo, q->regs.dma_idx); - index = (q->head + 1) % q->n_desc; - if (q->tail == index) { -@@ -379,8 +374,6 @@ int mtk_wed_wo_queue_tx_skb(struct mtk_w - mtk_wed_wo_queue_kick(wo, q, q->head); - mtk_wed_wo_kickout(wo); - out: -- spin_unlock_bh(&q->lock); -- - dev_kfree_skb(skb); - - return ret; ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -211,7 +211,6 @@ struct mtk_wed_wo_queue { - struct mtk_wed_wo_queue_regs regs; - - struct page_frag_cache cache; -- spinlock_t lock; - - struct mtk_wed_wo_queue_desc *desc; - dma_addr_t desc_dma; diff --git a/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch b/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch deleted file mode 100644 index c91861a8f1..0000000000 --- a/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch +++ /dev/null @@ -1,70 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:28 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: introduce mtk_hw_reset utility - routine - -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3256,6 +3256,27 @@ static void mtk_set_mcr_max_rx(struct mt - mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); - } - -+static void mtk_hw_reset(struct mtk_eth *eth) -+{ -+ u32 val; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); -+ val = RSTCTRL_PPE0_V2; -+ } else { -+ val = RSTCTRL_PPE0; -+ } -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= RSTCTRL_PPE1; -+ -+ ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, -+ 0x3ffffff); -+} -+ - static int mtk_hw_init(struct mtk_eth *eth) - { - u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -@@ -3295,22 +3316,9 @@ static int mtk_hw_init(struct mtk_eth *e - return 0; - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); -- val = RSTCTRL_PPE0_V2; -- } else { -- val = RSTCTRL_PPE0; -- } -- -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val |= RSTCTRL_PPE1; -- -- ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); -+ mtk_hw_reset(eth); - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, -- 0x3ffffff); -- - /* Set FE to PDMAv2 if necessary */ - val = mtk_r32(eth, MTK_FE_GLO_MISC); - mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); diff --git a/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch b/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch deleted file mode 100644 index 6597eb5b74..0000000000 --- a/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch +++ /dev/null @@ -1,107 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:29 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: introduce mtk_hw_warm_reset - support - -Introduce mtk_hw_warm_reset utility routine. This is a preliminary patch -to align reset procedure to vendor sdk and avoid to power down the chip -during hw reset. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3277,7 +3277,54 @@ static void mtk_hw_reset(struct mtk_eth - 0x3ffffff); - } - --static int mtk_hw_init(struct mtk_eth *eth) -+static u32 mtk_hw_reset_read(struct mtk_eth *eth) -+{ -+ u32 val; -+ -+ regmap_read(eth->ethsys, ETHSYS_RSTCTRL, &val); -+ return val; -+} -+ -+static void mtk_hw_warm_reset(struct mtk_eth *eth) -+{ -+ u32 rst_mask, val; -+ -+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, RSTCTRL_FE, -+ RSTCTRL_FE); -+ if (readx_poll_timeout_atomic(mtk_hw_reset_read, eth, val, -+ val & RSTCTRL_FE, 1, 1000)) { -+ dev_err(eth->dev, "warm reset failed\n"); -+ mtk_hw_reset(eth); -+ return; -+ } -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; -+ else -+ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ rst_mask |= RSTCTRL_PPE1; -+ -+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); -+ -+ udelay(1); -+ val = mtk_hw_reset_read(eth); -+ if (!(val & rst_mask)) -+ dev_err(eth->dev, "warm reset stage0 failed %08x (%08x)\n", -+ val, rst_mask); -+ -+ rst_mask |= RSTCTRL_FE; -+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, ~rst_mask); -+ -+ udelay(1); -+ val = mtk_hw_reset_read(eth); -+ if (val & rst_mask) -+ dev_err(eth->dev, "warm reset stage1 failed %08x (%08x)\n", -+ val, rst_mask); -+} -+ -+static int mtk_hw_init(struct mtk_eth *eth, bool reset) - { - u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | - ETHSYS_DMA_AG_MAP_PPE; -@@ -3316,7 +3363,12 @@ static int mtk_hw_init(struct mtk_eth *e - return 0; - } - -- mtk_hw_reset(eth); -+ msleep(100); -+ -+ if (reset) -+ mtk_hw_warm_reset(eth); -+ else -+ mtk_hw_reset(eth); - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - /* Set FE to PDMAv2 if necessary */ -@@ -3507,7 +3559,7 @@ static void mtk_pending_work(struct work - if (eth->dev->pins) - pinctrl_select_state(eth->dev->pins->p, - eth->dev->pins->default_state); -- mtk_hw_init(eth); -+ mtk_hw_init(eth, true); - - /* restart DMA and enable IRQs */ - for (i = 0; i < MTK_MAC_COUNT; i++) { -@@ -4109,7 +4161,7 @@ static int mtk_probe(struct platform_dev - eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); - INIT_WORK(ð->pending_work, mtk_pending_work); - -- err = mtk_hw_init(eth); -+ err = mtk_hw_init(eth, false); - if (err) - goto err_wed_exit; - diff --git a/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch b/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch deleted file mode 100644 index 55ab19f4c8..0000000000 --- a/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch +++ /dev/null @@ -1,262 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:30 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: align reset procedure to vendor - sdk - -Avoid to power-down the ethernet chip during hw reset and align reset -procedure to vendor sdk. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2844,14 +2844,29 @@ static void mtk_dma_free(struct mtk_eth - kfree(eth->scratch_head); - } - -+static bool mtk_hw_reset_check(struct mtk_eth *eth) -+{ -+ u32 val = mtk_r32(eth, MTK_INT_STATUS2); -+ -+ return (val & MTK_FE_INT_FQ_EMPTY) || (val & MTK_FE_INT_RFIFO_UF) || -+ (val & MTK_FE_INT_RFIFO_OV) || (val & MTK_FE_INT_TSO_FAIL) || -+ (val & MTK_FE_INT_TSO_ALIGN) || (val & MTK_FE_INT_TSO_ILLEGAL); -+} -+ - static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue) - { - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - -+ if (test_bit(MTK_RESETTING, ð->state)) -+ return; -+ -+ if (!mtk_hw_reset_check(eth)) -+ return; -+ - eth->netdev[mac->id]->stats.tx_errors++; -- netif_err(eth, tx_err, dev, -- "transmit timed out\n"); -+ netif_err(eth, tx_err, dev, "transmit timed out\n"); -+ - schedule_work(ð->pending_work); - } - -@@ -3331,15 +3346,17 @@ static int mtk_hw_init(struct mtk_eth *e - const struct mtk_reg_map *reg_map = eth->soc->reg_map; - int i, val, ret; - -- if (test_and_set_bit(MTK_HW_INIT, ð->state)) -+ if (!reset && test_and_set_bit(MTK_HW_INIT, ð->state)) - return 0; - -- pm_runtime_enable(eth->dev); -- pm_runtime_get_sync(eth->dev); -+ if (!reset) { -+ pm_runtime_enable(eth->dev); -+ pm_runtime_get_sync(eth->dev); - -- ret = mtk_clk_enable(eth); -- if (ret) -- goto err_disable_pm; -+ ret = mtk_clk_enable(eth); -+ if (ret) -+ goto err_disable_pm; -+ } - - if (eth->ethsys) - regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, dma_mask, -@@ -3468,8 +3485,10 @@ static int mtk_hw_init(struct mtk_eth *e - return 0; - - err_disable_pm: -- pm_runtime_put_sync(eth->dev); -- pm_runtime_disable(eth->dev); -+ if (!reset) { -+ pm_runtime_put_sync(eth->dev); -+ pm_runtime_disable(eth->dev); -+ } - - return ret; - } -@@ -3531,30 +3550,53 @@ static int mtk_do_ioctl(struct net_devic - return -EOPNOTSUPP; - } - -+static void mtk_prepare_for_reset(struct mtk_eth *eth) -+{ -+ u32 val; -+ int i; -+ -+ /* disabe FE P3 and P4 */ -+ val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= MTK_FE_LINK_DOWN_P4; -+ mtk_w32(eth, val, MTK_FE_GLO_CFG); -+ -+ /* adjust PPE configurations to prepare for reset */ -+ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) -+ mtk_ppe_prepare_reset(eth->ppe[i]); -+ -+ /* disable NETSYS interrupts */ -+ mtk_w32(eth, 0, MTK_FE_INT_ENABLE); -+ -+ /* force link down GMAC */ -+ for (i = 0; i < 2; i++) { -+ val = mtk_r32(eth, MTK_MAC_MCR(i)) & ~MAC_MCR_FORCE_LINK; -+ mtk_w32(eth, val, MTK_MAC_MCR(i)); -+ } -+} -+ - static void mtk_pending_work(struct work_struct *work) - { - struct mtk_eth *eth = container_of(work, struct mtk_eth, pending_work); -- int err, i; - unsigned long restart = 0; -+ u32 val; -+ int i; - - rtnl_lock(); -- -- dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__); - set_bit(MTK_RESETTING, ð->state); - -+ mtk_prepare_for_reset(eth); -+ - /* stop all devices to make sure that dma is properly shut down */ - for (i = 0; i < MTK_MAC_COUNT; i++) { -- if (!eth->netdev[i]) -+ if (!eth->netdev[i] || !netif_running(eth->netdev[i])) - continue; -+ - mtk_stop(eth->netdev[i]); - __set_bit(i, &restart); - } -- dev_dbg(eth->dev, "[%s][%d] mtk_stop ends\n", __func__, __LINE__); - -- /* restart underlying hardware such as power, clock, pin mux -- * and the connected phy -- */ -- mtk_hw_deinit(eth); -+ usleep_range(15000, 16000); - - if (eth->dev->pins) - pinctrl_select_state(eth->dev->pins->p, -@@ -3565,15 +3607,19 @@ static void mtk_pending_work(struct work - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!test_bit(i, &restart)) - continue; -- err = mtk_open(eth->netdev[i]); -- if (err) { -+ -+ if (mtk_open(eth->netdev[i])) { - netif_alert(eth, ifup, eth->netdev[i], -- "Driver up/down cycle failed, closing device.\n"); -+ "Driver up/down cycle failed\n"); - dev_close(eth->netdev[i]); - } - } - -- dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__); -+ /* enabe FE P3 and P4 */ -+ val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val &= ~MTK_FE_LINK_DOWN_P4; -+ mtk_w32(eth, val, MTK_FE_GLO_CFG); - - clear_bit(MTK_RESETTING, ð->state); - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -72,12 +72,24 @@ - #define MTK_HW_LRO_REPLACE_DELTA 1000 - #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 - -+/* Frame Engine Global Configuration */ -+#define MTK_FE_GLO_CFG 0x00 -+#define MTK_FE_LINK_DOWN_P3 BIT(11) -+#define MTK_FE_LINK_DOWN_P4 BIT(12) -+ - /* Frame Engine Global Reset Register */ - #define MTK_RST_GL 0x04 - #define RST_GL_PSE BIT(0) - - /* Frame Engine Interrupt Status Register */ - #define MTK_INT_STATUS2 0x08 -+#define MTK_FE_INT_ENABLE 0x0c -+#define MTK_FE_INT_FQ_EMPTY BIT(8) -+#define MTK_FE_INT_TSO_FAIL BIT(12) -+#define MTK_FE_INT_TSO_ILLEGAL BIT(13) -+#define MTK_FE_INT_TSO_ALIGN BIT(14) -+#define MTK_FE_INT_RFIFO_OV BIT(18) -+#define MTK_FE_INT_RFIFO_UF BIT(19) - #define MTK_GDM1_AF BIT(28) - #define MTK_GDM2_AF BIT(29) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -710,6 +710,33 @@ int mtk_foe_entry_idle_time(struct mtk_p - return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); - } - -+int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) -+{ -+ if (!ppe) -+ return -EINVAL; -+ -+ /* disable KA */ -+ ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE); -+ ppe_clear(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE); -+ ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0); -+ usleep_range(10000, 11000); -+ -+ /* set KA timer to maximum */ -+ ppe_set(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE); -+ ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0xffffffff); -+ -+ /* set KA tick select */ -+ ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_TICK_SEL); -+ ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE); -+ usleep_range(10000, 11000); -+ -+ /* disable scan mode */ -+ ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_SCAN_MODE); -+ usleep_range(10000, 11000); -+ -+ return mtk_ppe_wait_busy(ppe); -+} -+ - struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, - int version, int index) - { ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -306,6 +306,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ - void mtk_ppe_deinit(struct mtk_eth *eth); - void mtk_ppe_start(struct mtk_ppe *ppe); - int mtk_ppe_stop(struct mtk_ppe *ppe); -+int mtk_ppe_prepare_reset(struct mtk_ppe *ppe); - - void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -@@ -58,6 +58,12 @@ - #define MTK_PPE_TB_CFG_SCAN_MODE GENMASK(17, 16) - #define MTK_PPE_TB_CFG_HASH_DEBUG GENMASK(19, 18) - #define MTK_PPE_TB_CFG_INFO_SEL BIT(20) -+#define MTK_PPE_TB_TICK_SEL BIT(24) -+ -+#define MTK_PPE_BIND_LMT1 0x230 -+#define MTK_PPE_NTU_KEEPALIVE GENMASK(23, 16) -+ -+#define MTK_PPE_KEEPALIVE 0x234 - - enum { - MTK_PPE_SCAN_MODE_DISABLED, diff --git a/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch b/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch deleted file mode 100644 index d5a7c0eba2..0000000000 --- a/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch +++ /dev/null @@ -1,249 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:31 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add dma checks to - mtk_hw_reset_check - -Introduce mtk_hw_check_dma_hang routine to monitor possible dma hangs. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -50,6 +50,7 @@ static const struct mtk_reg_map mtk_reg_ - .delay_irq = 0x0a0c, - .irq_status = 0x0a20, - .irq_mask = 0x0a28, -+ .adma_rx_dbg0 = 0x0a38, - .int_grp = 0x0a50, - }, - .qdma = { -@@ -79,6 +80,8 @@ static const struct mtk_reg_map mtk_reg_ - [0] = 0x2800, - [1] = 0x2c00, - }, -+ .pse_iq_sta = 0x0110, -+ .pse_oq_sta = 0x0118, - }; - - static const struct mtk_reg_map mt7628_reg_map = { -@@ -109,6 +112,7 @@ static const struct mtk_reg_map mt7986_r - .delay_irq = 0x620c, - .irq_status = 0x6220, - .irq_mask = 0x6228, -+ .adma_rx_dbg0 = 0x6238, - .int_grp = 0x6250, - }, - .qdma = { -@@ -138,6 +142,8 @@ static const struct mtk_reg_map mt7986_r - [0] = 0x4800, - [1] = 0x4c00, - }, -+ .pse_iq_sta = 0x0180, -+ .pse_oq_sta = 0x01a0, - }; - - /* strings used by ethtool */ -@@ -3339,6 +3345,102 @@ static void mtk_hw_warm_reset(struct mtk - val, rst_mask); - } - -+static bool mtk_hw_check_dma_hang(struct mtk_eth *eth) -+{ -+ const struct mtk_reg_map *reg_map = eth->soc->reg_map; -+ bool gmac1_tx, gmac2_tx, gdm1_tx, gdm2_tx; -+ bool oq_hang, cdm1_busy, adma_busy; -+ bool wtx_busy, cdm_full, oq_free; -+ u32 wdidx, val, gdm1_fc, gdm2_fc; -+ bool qfsm_hang, qfwd_hang; -+ bool ret = false; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) -+ return false; -+ -+ /* WDMA sanity checks */ -+ wdidx = mtk_r32(eth, reg_map->wdma_base[0] + 0xc); -+ -+ val = mtk_r32(eth, reg_map->wdma_base[0] + 0x204); -+ wtx_busy = FIELD_GET(MTK_TX_DMA_BUSY, val); -+ -+ val = mtk_r32(eth, reg_map->wdma_base[0] + 0x230); -+ cdm_full = !FIELD_GET(MTK_CDM_TXFIFO_RDY, val); -+ -+ oq_free = (!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(24, 16)) && -+ !(mtk_r32(eth, reg_map->pse_oq_sta + 0x4) & GENMASK(8, 0)) && -+ !(mtk_r32(eth, reg_map->pse_oq_sta + 0x10) & GENMASK(24, 16))); -+ -+ if (wdidx == eth->reset.wdidx && wtx_busy && cdm_full && oq_free) { -+ if (++eth->reset.wdma_hang_count > 2) { -+ eth->reset.wdma_hang_count = 0; -+ ret = true; -+ } -+ goto out; -+ } -+ -+ /* QDMA sanity checks */ -+ qfsm_hang = !!mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x234); -+ qfwd_hang = !mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x308); -+ -+ gdm1_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM1_FSM)) > 0; -+ gdm2_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM2_FSM)) > 0; -+ gmac1_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(0))) != 1; -+ gmac2_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(1))) != 1; -+ gdm1_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x24); -+ gdm2_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x64); -+ -+ if (qfsm_hang && qfwd_hang && -+ ((gdm1_tx && gmac1_tx && gdm1_fc < 1) || -+ (gdm2_tx && gmac2_tx && gdm2_fc < 1))) { -+ if (++eth->reset.qdma_hang_count > 2) { -+ eth->reset.qdma_hang_count = 0; -+ ret = true; -+ } -+ goto out; -+ } -+ -+ /* ADMA sanity checks */ -+ oq_hang = !!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(8, 0)); -+ cdm1_busy = !!(mtk_r32(eth, MTK_FE_CDM1_FSM) & GENMASK(31, 16)); -+ adma_busy = !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & GENMASK(4, 0)) && -+ !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & BIT(6)); -+ -+ if (oq_hang && cdm1_busy && adma_busy) { -+ if (++eth->reset.adma_hang_count > 2) { -+ eth->reset.adma_hang_count = 0; -+ ret = true; -+ } -+ goto out; -+ } -+ -+ eth->reset.wdma_hang_count = 0; -+ eth->reset.qdma_hang_count = 0; -+ eth->reset.adma_hang_count = 0; -+out: -+ eth->reset.wdidx = wdidx; -+ -+ return ret; -+} -+ -+static void mtk_hw_reset_monitor_work(struct work_struct *work) -+{ -+ struct delayed_work *del_work = to_delayed_work(work); -+ struct mtk_eth *eth = container_of(del_work, struct mtk_eth, -+ reset.monitor_work); -+ -+ if (test_bit(MTK_RESETTING, ð->state)) -+ goto out; -+ -+ /* DMA stuck checks */ -+ if (mtk_hw_check_dma_hang(eth)) -+ schedule_work(ð->pending_work); -+ -+out: -+ schedule_delayed_work(ð->reset.monitor_work, -+ MTK_DMA_MONITOR_TIMEOUT); -+} -+ - static int mtk_hw_init(struct mtk_eth *eth, bool reset) - { - u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -@@ -3657,6 +3759,7 @@ static int mtk_cleanup(struct mtk_eth *e - mtk_unreg_dev(eth); - mtk_free_dev(eth); - cancel_work_sync(ð->pending_work); -+ cancel_delayed_work_sync(ð->reset.monitor_work); - - return 0; - } -@@ -4094,6 +4197,7 @@ static int mtk_probe(struct platform_dev - - eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; - INIT_WORK(ð->rx_dim.work, mtk_dim_rx); -+ INIT_DELAYED_WORK(ð->reset.monitor_work, mtk_hw_reset_monitor_work); - - eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; - INIT_WORK(ð->tx_dim.work, mtk_dim_tx); -@@ -4296,6 +4400,8 @@ static int mtk_probe(struct platform_dev - netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx); - - platform_set_drvdata(pdev, eth); -+ schedule_delayed_work(ð->reset.monitor_work, -+ MTK_DMA_MONITOR_TIMEOUT); - - return 0; - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -257,6 +257,8 @@ - - #define MTK_RX_DONE_INT_V2 BIT(14) - -+#define MTK_CDM_TXFIFO_RDY BIT(7) -+ - /* QDMA Interrupt grouping registers */ - #define MTK_RLS_DONE_INT BIT(0) - -@@ -542,6 +544,17 @@ - #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) - #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) - -+#define MTK_FE_CDM1_FSM 0x220 -+#define MTK_FE_CDM2_FSM 0x224 -+#define MTK_FE_CDM3_FSM 0x238 -+#define MTK_FE_CDM4_FSM 0x298 -+#define MTK_FE_CDM5_FSM 0x318 -+#define MTK_FE_CDM6_FSM 0x328 -+#define MTK_FE_GDM1_FSM 0x228 -+#define MTK_FE_GDM2_FSM 0x22C -+ -+#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) -+ - struct mtk_rx_dma { - unsigned int rxd1; - unsigned int rxd2; -@@ -938,6 +951,7 @@ struct mtk_reg_map { - u32 delay_irq; /* delay interrupt */ - u32 irq_status; /* interrupt status */ - u32 irq_mask; /* interrupt mask */ -+ u32 adma_rx_dbg0; - u32 int_grp; - } pdma; - struct { -@@ -964,6 +978,8 @@ struct mtk_reg_map { - u32 gdma_to_ppe; - u32 ppe_base; - u32 wdma_base[2]; -+ u32 pse_iq_sta; -+ u32 pse_oq_sta; - }; - - /* struct mtk_eth_data - This is the structure holding all differences -@@ -1006,6 +1022,8 @@ struct mtk_soc_data { - } txrx; - }; - -+#define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) -+ - /* currently no SoC has more than 2 macs */ - #define MTK_MAX_DEVS 2 - -@@ -1128,6 +1146,14 @@ struct mtk_eth { - struct rhashtable flow_table; - - struct bpf_prog __rcu *prog; -+ -+ struct { -+ struct delayed_work monitor_work; -+ u32 wdidx; -+ u8 wdma_hang_count; -+ u8 qdma_hang_count; -+ u8 adma_hang_count; -+ } reset; - }; - - /* struct mtk_mac - the structure that holds the info about the MACs of the diff --git a/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch b/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch deleted file mode 100644 index c21d094ae8..0000000000 --- a/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch +++ /dev/null @@ -1,124 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:32 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add reset/reset_complete callbacks - -Introduce reset and reset_complete wlan callback to schedule WLAN driver -reset when ethernet/wed driver is resetting. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3688,6 +3688,11 @@ static void mtk_pending_work(struct work - set_bit(MTK_RESETTING, ð->state); - - mtk_prepare_for_reset(eth); -+ mtk_wed_fe_reset(); -+ /* Run again reset preliminary configuration in order to avoid any -+ * possible race during FE reset since it can run releasing RTNL lock. -+ */ -+ mtk_prepare_for_reset(eth); - - /* stop all devices to make sure that dma is properly shut down */ - for (i = 0; i < MTK_MAC_COUNT; i++) { -@@ -3725,6 +3730,8 @@ static void mtk_pending_work(struct work - - clear_bit(MTK_RESETTING, ð->state); - -+ mtk_wed_fe_reset_complete(); -+ - rtnl_unlock(); - } - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -205,6 +205,48 @@ mtk_wed_wo_reset(struct mtk_wed_device * - iounmap(reg); - } - -+void mtk_wed_fe_reset(void) -+{ -+ int i; -+ -+ mutex_lock(&hw_lock); -+ -+ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { -+ struct mtk_wed_hw *hw = hw_list[i]; -+ struct mtk_wed_device *dev = hw->wed_dev; -+ int err; -+ -+ if (!dev || !dev->wlan.reset) -+ continue; -+ -+ /* reset callback blocks until WLAN reset is completed */ -+ err = dev->wlan.reset(dev); -+ if (err) -+ dev_err(dev->dev, "wlan reset failed: %d\n", err); -+ } -+ -+ mutex_unlock(&hw_lock); -+} -+ -+void mtk_wed_fe_reset_complete(void) -+{ -+ int i; -+ -+ mutex_lock(&hw_lock); -+ -+ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { -+ struct mtk_wed_hw *hw = hw_list[i]; -+ struct mtk_wed_device *dev = hw->wed_dev; -+ -+ if (!dev || !dev->wlan.reset_complete) -+ continue; -+ -+ dev->wlan.reset_complete(dev); -+ } -+ -+ mutex_unlock(&hw_lock); -+} -+ - static struct mtk_wed_hw * - mtk_wed_assign(struct mtk_wed_device *dev) - { ---- a/drivers/net/ethernet/mediatek/mtk_wed.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed.h -@@ -128,6 +128,8 @@ void mtk_wed_add_hw(struct device_node * - void mtk_wed_exit(void); - int mtk_wed_flow_add(int index); - void mtk_wed_flow_remove(int index); -+void mtk_wed_fe_reset(void); -+void mtk_wed_fe_reset_complete(void); - #else - static inline void - mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, -@@ -147,6 +149,13 @@ static inline void mtk_wed_flow_remove(i - { - } - -+static inline void mtk_wed_fe_reset(void) -+{ -+} -+ -+static inline void mtk_wed_fe_reset_complete(void) -+{ -+} - #endif - - #ifdef CONFIG_DEBUG_FS ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -151,6 +151,8 @@ struct mtk_wed_device { - void (*release_rx_buf)(struct mtk_wed_device *wed); - void (*update_wo_rx_stats)(struct mtk_wed_device *wed, - struct mtk_wed_wo_rx_stats *stats); -+ int (*reset)(struct mtk_wed_device *wed); -+ void (*reset_complete)(struct mtk_wed_device *wed); - } wlan; - #endif - }; diff --git a/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch b/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch deleted file mode 100644 index c63628da99..0000000000 --- a/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Lorenzo Bianconi -Date: Mon, 5 Dec 2022 12:34:42 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add reset to rx_ring_setup callback - -This patch adds reset parameter to mtk_wed_rx_ring_setup signature -in order to align rx_ring_setup callback to tx_ring_setup one introduced -in 'commit 23dca7a90017 ("net: ethernet: mtk_wed: add reset to -tx_ring_setup callback")' - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Leon Romanovsky -Link: https://lore.kernel.org/r/29c6e7a5469e784406cf3e2920351d1207713d05.1670239984.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1252,7 +1252,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we - } - - static int --mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size, -+ bool reset) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; - struct mtk_wed_ring *wdma; -@@ -1261,8 +1262,8 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we - return -EINVAL; - - wdma = &dev->tx_wdma[idx]; -- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -- true)) -+ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, -+ desc_size, true)) - return -ENOMEM; - - wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, -@@ -1272,6 +1273,9 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we - wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); - wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0); - -+ if (reset) -+ mtk_wed_ring_reset(wdma, MTK_WED_WDMA_RING_SIZE, true); -+ - if (!idx) { - wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE, - wdma->desc_phys); -@@ -1611,18 +1615,20 @@ mtk_wed_txfree_ring_setup(struct mtk_wed - } - - static int --mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) -+mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs, -+ bool reset) - { - struct mtk_wed_ring *ring = &dev->rx_ring[idx]; - - if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring))) - return -EINVAL; - -- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, -- sizeof(*ring->desc), false)) -+ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, -+ sizeof(*ring->desc), false)) - return -ENOMEM; - -- if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, -+ reset)) - return -ENOMEM; - - ring->reg_base = MTK_WED_RING_RX_DATA(idx); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -162,7 +162,7 @@ struct mtk_wed_ops { - int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, - void __iomem *regs, bool reset); - int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, -- void __iomem *regs); -+ void __iomem *regs, bool reset); - int (*txfree_ring_setup)(struct mtk_wed_device *dev, - void __iomem *regs); - int (*msg_update)(struct mtk_wed_device *dev, int cmd_id, -@@ -230,8 +230,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - (_dev)->ops->irq_get(_dev, _mask) - #define mtk_wed_device_irq_set_mask(_dev, _mask) \ - (_dev)->ops->irq_set_mask(_dev, _mask) --#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \ -- (_dev)->ops->rx_ring_setup(_dev, _ring, _regs) -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \ -+ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs, _reset) - #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \ - (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ -@@ -251,7 +251,7 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) - #define mtk_wed_device_irq_get(_dev, _mask) 0 - #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) --#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV - #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV - #define mtk_wed_device_stop(_dev) do {} while (0) diff --git a/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch b/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch deleted file mode 100644 index 45af898cf0..0000000000 --- a/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felix Fietkau -Date: Thu, 27 Oct 2022 19:50:31 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: account for vlan in rx - header length - -The network stack assumes that devices can handle an extra VLAN tag without -increasing the MTU - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -29,7 +29,7 @@ - #define MTK_TX_DMA_BUF_LEN_V2 0xffff - #define MTK_DMA_SIZE 512 - #define MTK_MAC_COUNT 2 --#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) -+#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + ETH_FCS_LEN) - #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) - #define MTK_DMA_DUMMY_DESC 0xffffffff - #define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \ diff --git a/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch b/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch deleted file mode 100644 index 046a581224..0000000000 --- a/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch +++ /dev/null @@ -1,143 +0,0 @@ -From: Felix Fietkau -Date: Thu, 27 Oct 2022 19:53:57 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: increase tx ring side for - QDMA devices - -In order to use the hardware traffic shaper feature, a larger tx ring is -needed, especially for the scratch ring, which the hardware shaper uses to -reorder packets. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -944,7 +944,7 @@ static int mtk_init_fq_dma(struct mtk_et - { - const struct mtk_soc_data *soc = eth->soc; - dma_addr_t phy_ring_tail; -- int cnt = MTK_DMA_SIZE; -+ int cnt = MTK_QDMA_RING_SIZE; - dma_addr_t dma_addr; - int i; - -@@ -2208,19 +2208,25 @@ static int mtk_tx_alloc(struct mtk_eth * - struct mtk_tx_ring *ring = ð->tx_ring; - int i, sz = soc->txrx.txd_size; - struct mtk_tx_dma_v2 *txd; -+ int ring_size; - -- ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf), -+ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) -+ ring_size = MTK_QDMA_RING_SIZE; -+ else -+ ring_size = MTK_DMA_SIZE; -+ -+ ring->buf = kcalloc(ring_size, sizeof(*ring->buf), - GFP_KERNEL); - if (!ring->buf) - goto no_tx_mem; - -- ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, -+ ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, - &ring->phys, GFP_KERNEL); - if (!ring->dma) - goto no_tx_mem; - -- for (i = 0; i < MTK_DMA_SIZE; i++) { -- int next = (i + 1) % MTK_DMA_SIZE; -+ for (i = 0; i < ring_size; i++) { -+ int next = (i + 1) % ring_size; - u32 next_ptr = ring->phys + next * sz; - - txd = ring->dma + i * sz; -@@ -2240,22 +2246,22 @@ static int mtk_tx_alloc(struct mtk_eth * - * descriptors in ring->dma_pdma. - */ - if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { -- ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, -+ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, - &ring->phys_pdma, GFP_KERNEL); - if (!ring->dma_pdma) - goto no_tx_mem; - -- for (i = 0; i < MTK_DMA_SIZE; i++) { -+ for (i = 0; i < ring_size; i++) { - ring->dma_pdma[i].txd2 = TX_DMA_DESP2_DEF; - ring->dma_pdma[i].txd4 = 0; - } - } - -- ring->dma_size = MTK_DMA_SIZE; -- atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); -+ ring->dma_size = ring_size; -+ atomic_set(&ring->free_count, ring_size - 2); - ring->next_free = ring->dma; - ring->last_free = (void *)txd; -- ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz)); -+ ring->last_free_ptr = (u32)(ring->phys + ((ring_size - 1) * sz)); - ring->thresh = MAX_SKB_FRAGS; - - /* make sure that all changes to the dma ring are flushed before we -@@ -2267,14 +2273,14 @@ static int mtk_tx_alloc(struct mtk_eth * - mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr); - mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr); - mtk_w32(eth, -- ring->phys + ((MTK_DMA_SIZE - 1) * sz), -+ ring->phys + ((ring_size - 1) * sz), - soc->reg_map->qdma.crx_ptr); - mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); - mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, - soc->reg_map->qdma.qtx_cfg); - } else { - mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); -- mtk_w32(eth, MTK_DMA_SIZE, MT7628_TX_MAX_CNT0); -+ mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); - mtk_w32(eth, 0, MT7628_TX_CTX_IDX0); - mtk_w32(eth, MT7628_PST_DTX_IDX0, soc->reg_map->pdma.rst_idx); - } -@@ -2292,7 +2298,7 @@ static void mtk_tx_clean(struct mtk_eth - int i; - - if (ring->buf) { -- for (i = 0; i < MTK_DMA_SIZE; i++) -+ for (i = 0; i < ring->dma_size; i++) - mtk_tx_unmap(eth, &ring->buf[i], NULL, false); - kfree(ring->buf); - ring->buf = NULL; -@@ -2300,14 +2306,14 @@ static void mtk_tx_clean(struct mtk_eth - - if (ring->dma) { - dma_free_coherent(eth->dma_dev, -- MTK_DMA_SIZE * soc->txrx.txd_size, -+ ring->dma_size * soc->txrx.txd_size, - ring->dma, ring->phys); - ring->dma = NULL; - } - - if (ring->dma_pdma) { - dma_free_coherent(eth->dma_dev, -- MTK_DMA_SIZE * soc->txrx.txd_size, -+ ring->dma_size * soc->txrx.txd_size, - ring->dma_pdma, ring->phys_pdma); - ring->dma_pdma = NULL; - } -@@ -2832,7 +2838,7 @@ static void mtk_dma_free(struct mtk_eth - netdev_reset_queue(eth->netdev[i]); - if (eth->scratch_ring) { - dma_free_coherent(eth->dma_dev, -- MTK_DMA_SIZE * soc->txrx.txd_size, -+ MTK_QDMA_RING_SIZE * soc->txrx.txd_size, - eth->scratch_ring, eth->phy_scratch_ring); - eth->scratch_ring = NULL; - eth->phy_scratch_ring = 0; ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -27,6 +27,7 @@ - #define MTK_MAX_RX_LENGTH_2K 2048 - #define MTK_TX_DMA_BUF_LEN 0x3fff - #define MTK_TX_DMA_BUF_LEN_V2 0xffff -+#define MTK_QDMA_RING_SIZE 2048 - #define MTK_DMA_SIZE 512 - #define MTK_MAC_COUNT 2 - #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + ETH_FCS_LEN) diff --git a/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch b/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch deleted file mode 100644 index 7e879ca1d5..0000000000 --- a/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Felix Fietkau -Date: Fri, 4 Nov 2022 19:49:08 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: avoid port_mg assignment on - MT7622 and newer - -On newer chips, this field is unused and contains some bits related to queue -assignment. Initialize it to 0 in those cases. -Fix offload_version on MT7621 and MT7623, which still need the previous value. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4479,7 +4479,7 @@ static const struct mtk_soc_data mt7621_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7621_CLKS_BITMAP, - .required_pctl = false, -- .offload_version = 2, -+ .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, - .txrx = { -@@ -4518,7 +4518,7 @@ static const struct mtk_soc_data mt7623_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7623_CLKS_BITMAP, - .required_pctl = true, -- .offload_version = 2, -+ .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, - .txrx = { ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -175,6 +175,8 @@ int mtk_foe_entry_prepare(struct mtk_eth - val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, pse_port) | - FIELD_PREP(MTK_FOE_IB2_PORT_AG_V2, 0xf); - } else { -+ int port_mg = eth->soc->offload_version > 1 ? 0 : 0x3f; -+ - val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | - FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE, type) | - FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | -@@ -182,7 +184,7 @@ int mtk_foe_entry_prepare(struct mtk_eth - entry->ib1 = val; - - val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT, pse_port) | -- FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) | -+ FIELD_PREP(MTK_FOE_IB2_PORT_MG, port_mg) | - FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0x1f); - } - diff --git a/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch b/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch deleted file mode 100644 index 8ceba7831e..0000000000 --- a/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch +++ /dev/null @@ -1,654 +0,0 @@ -From: Felix Fietkau -Date: Thu, 27 Oct 2022 20:17:27 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: implement multi-queue - support for per-port queues - -When sending traffic to multiple ports with different link speeds, queued -packets to one port can drown out tx to other ports. -In order to better handle transmission to multiple ports, use the hardware -shaper feature to implement weighted fair queueing between ports. -Weight and maximum rate are automatically adjusted based on the link speed -of the port. -The first 3 queues are unrestricted and reserved for non-DSA direct tx on -GMAC ports. The following queues are automatically assigned by the MTK DSA -tag driver based on the target port number. -The PPE offload code configures the queues for offloaded traffic in the same -way. -This feature is only supported on devices supporting QDMA. All queues still -share the same DMA ring and descriptor pool. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -55,6 +55,7 @@ static const struct mtk_reg_map mtk_reg_ - }, - .qdma = { - .qtx_cfg = 0x1800, -+ .qtx_sch = 0x1804, - .rx_ptr = 0x1900, - .rx_cnt_cfg = 0x1904, - .qcrx_ptr = 0x1908, -@@ -62,6 +63,7 @@ static const struct mtk_reg_map mtk_reg_ - .rst_idx = 0x1a08, - .delay_irq = 0x1a0c, - .fc_th = 0x1a10, -+ .tx_sch_rate = 0x1a14, - .int_grp = 0x1a20, - .hred = 0x1a44, - .ctx_ptr = 0x1b00, -@@ -117,6 +119,7 @@ static const struct mtk_reg_map mt7986_r - }, - .qdma = { - .qtx_cfg = 0x4400, -+ .qtx_sch = 0x4404, - .rx_ptr = 0x4500, - .rx_cnt_cfg = 0x4504, - .qcrx_ptr = 0x4508, -@@ -134,6 +137,7 @@ static const struct mtk_reg_map mt7986_r - .fq_tail = 0x4724, - .fq_count = 0x4728, - .fq_blen = 0x472c, -+ .tx_sch_rate = 0x4798, - }, - .gdm1_cnt = 0x1c00, - .gdma_to_ppe = 0x3333, -@@ -620,6 +624,75 @@ static void mtk_mac_link_down(struct phy - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); - } - -+static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -+ int speed) -+{ -+ const struct mtk_soc_data *soc = eth->soc; -+ u32 ofs, val; -+ -+ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) -+ return; -+ -+ val = MTK_QTX_SCH_MIN_RATE_EN | -+ /* minimum: 10 Mbps */ -+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | -+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | -+ MTK_QTX_SCH_LEAKY_BUCKET_SIZE; -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; -+ -+ if (IS_ENABLED(CONFIG_SOC_MT7621)) { -+ switch (speed) { -+ case SPEED_10: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 2) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_100: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3); -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_1000: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 105) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); -+ break; -+ default: -+ break; -+ } -+ } else { -+ switch (speed) { -+ case SPEED_10: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_100: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5); -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_1000: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ ofs = MTK_QTX_OFFSET * idx; -+ mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); -+} -+ - static void mtk_mac_link_up(struct phylink_config *config, - struct phy_device *phy, - unsigned int mode, phy_interface_t interface, -@@ -645,6 +718,8 @@ static void mtk_mac_link_up(struct phyli - break; - } - -+ mtk_set_queue_speed(mac->hw, mac->id, speed); -+ - /* Configure duplex */ - if (duplex == DUPLEX_FULL) - mcr |= MAC_MCR_FORCE_DPX; -@@ -1105,7 +1180,8 @@ static void mtk_tx_set_dma_desc_v1(struc - - WRITE_ONCE(desc->txd1, info->addr); - -- data = TX_DMA_SWC | TX_DMA_PLEN0(info->size); -+ data = TX_DMA_SWC | TX_DMA_PLEN0(info->size) | -+ FIELD_PREP(TX_DMA_PQID, info->qid); - if (info->last) - data |= TX_DMA_LS0; - WRITE_ONCE(desc->txd3, data); -@@ -1139,9 +1215,6 @@ static void mtk_tx_set_dma_desc_v2(struc - data |= TX_DMA_LS0; - WRITE_ONCE(desc->txd3, data); - -- if (!info->qid && mac->id) -- info->qid = MTK_QDMA_GMAC2_QID; -- - data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ - data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); - WRITE_ONCE(desc->txd4, data); -@@ -1185,11 +1258,12 @@ static int mtk_tx_map(struct sk_buff *sk - .gso = gso, - .csum = skb->ip_summed == CHECKSUM_PARTIAL, - .vlan = skb_vlan_tag_present(skb), -- .qid = skb->mark & MTK_QDMA_TX_MASK, -+ .qid = skb_get_queue_mapping(skb), - .vlan_tci = skb_vlan_tag_get(skb), - .first = true, - .last = !skb_is_nonlinear(skb), - }; -+ struct netdev_queue *txq; - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - const struct mtk_soc_data *soc = eth->soc; -@@ -1197,8 +1271,10 @@ static int mtk_tx_map(struct sk_buff *sk - struct mtk_tx_dma *itxd_pdma, *txd_pdma; - struct mtk_tx_buf *itx_buf, *tx_buf; - int i, n_desc = 1; -+ int queue = skb_get_queue_mapping(skb); - int k = 0; - -+ txq = netdev_get_tx_queue(dev, queue); - itxd = ring->next_free; - itxd_pdma = qdma_to_pdma(ring, itxd); - if (itxd == ring->last_free) -@@ -1247,7 +1323,7 @@ static int mtk_tx_map(struct sk_buff *sk - memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); - txd_info.size = min_t(unsigned int, frag_size, - soc->txrx.dma_max_len); -- txd_info.qid = skb->mark & MTK_QDMA_TX_MASK; -+ txd_info.qid = queue; - txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && - !(frag_size - txd_info.size); - txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, -@@ -1286,7 +1362,7 @@ static int mtk_tx_map(struct sk_buff *sk - txd_pdma->txd2 |= TX_DMA_LS1; - } - -- netdev_sent_queue(dev, skb->len); -+ netdev_tx_sent_queue(txq, skb->len); - skb_tx_timestamp(skb); - - ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); -@@ -1298,8 +1374,7 @@ static int mtk_tx_map(struct sk_buff *sk - wmb(); - - if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { -- if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) || -- !netdev_xmit_more()) -+ if (netif_xmit_stopped(txq) || !netdev_xmit_more()) - mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr); - } else { - int next_idx; -@@ -1368,7 +1443,7 @@ static void mtk_wake_queue(struct mtk_et - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!eth->netdev[i]) - continue; -- netif_wake_queue(eth->netdev[i]); -+ netif_tx_wake_all_queues(eth->netdev[i]); - } - } - -@@ -1392,7 +1467,7 @@ static netdev_tx_t mtk_start_xmit(struct - - tx_num = mtk_cal_txd_req(eth, skb); - if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { -- netif_stop_queue(dev); -+ netif_tx_stop_all_queues(dev); - netif_err(eth, tx_queued, dev, - "Tx Ring full when queue awake!\n"); - spin_unlock(ð->page_lock); -@@ -1418,7 +1493,7 @@ static netdev_tx_t mtk_start_xmit(struct - goto drop; - - if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) -- netif_stop_queue(dev); -+ netif_tx_stop_all_queues(dev); - - spin_unlock(ð->page_lock); - -@@ -1585,10 +1660,12 @@ static int mtk_xdp_submit_frame(struct m - struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf); - const struct mtk_soc_data *soc = eth->soc; - struct mtk_tx_ring *ring = ð->tx_ring; -+ struct mtk_mac *mac = netdev_priv(dev); - struct mtk_tx_dma_desc_info txd_info = { - .size = xdpf->len, - .first = true, - .last = !xdp_frame_has_frags(xdpf), -+ .qid = mac->id, - }; - int err, index = 0, n_desc = 1, nr_frags; - struct mtk_tx_buf *htx_buf, *tx_buf; -@@ -1638,6 +1715,7 @@ static int mtk_xdp_submit_frame(struct m - memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); - txd_info.size = skb_frag_size(&sinfo->frags[index]); - txd_info.last = index + 1 == nr_frags; -+ txd_info.qid = mac->id; - data = skb_frag_address(&sinfo->frags[index]); - - index++; -@@ -1992,8 +2070,46 @@ rx_done: - return done; - } - -+struct mtk_poll_state { -+ struct netdev_queue *txq; -+ unsigned int total; -+ unsigned int done; -+ unsigned int bytes; -+}; -+ -+static void -+mtk_poll_tx_done(struct mtk_eth *eth, struct mtk_poll_state *state, u8 mac, -+ struct sk_buff *skb) -+{ -+ struct netdev_queue *txq; -+ struct net_device *dev; -+ unsigned int bytes = skb->len; -+ -+ state->total++; -+ eth->tx_packets++; -+ eth->tx_bytes += bytes; -+ -+ dev = eth->netdev[mac]; -+ if (!dev) -+ return; -+ -+ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); -+ if (state->txq == txq) { -+ state->done++; -+ state->bytes += bytes; -+ return; -+ } -+ -+ if (state->txq) -+ netdev_tx_completed_queue(state->txq, state->done, state->bytes); -+ -+ state->txq = txq; -+ state->done = 1; -+ state->bytes = bytes; -+} -+ - static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, -- unsigned int *done, unsigned int *bytes) -+ struct mtk_poll_state *state) - { - const struct mtk_reg_map *reg_map = eth->soc->reg_map; - struct mtk_tx_ring *ring = ð->tx_ring; -@@ -2025,12 +2141,9 @@ static int mtk_poll_tx_qdma(struct mtk_e - break; - - if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { -- if (tx_buf->type == MTK_TYPE_SKB) { -- struct sk_buff *skb = tx_buf->data; -+ if (tx_buf->type == MTK_TYPE_SKB) -+ mtk_poll_tx_done(eth, state, mac, tx_buf->data); - -- bytes[mac] += skb->len; -- done[mac]++; -- } - budget--; - } - mtk_tx_unmap(eth, tx_buf, &bq, true); -@@ -2049,7 +2162,7 @@ static int mtk_poll_tx_qdma(struct mtk_e - } - - static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget, -- unsigned int *done, unsigned int *bytes) -+ struct mtk_poll_state *state) - { - struct mtk_tx_ring *ring = ð->tx_ring; - struct mtk_tx_buf *tx_buf; -@@ -2067,12 +2180,8 @@ static int mtk_poll_tx_pdma(struct mtk_e - break; - - if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { -- if (tx_buf->type == MTK_TYPE_SKB) { -- struct sk_buff *skb = tx_buf->data; -- -- bytes[0] += skb->len; -- done[0]++; -- } -+ if (tx_buf->type == MTK_TYPE_SKB) -+ mtk_poll_tx_done(eth, state, 0, tx_buf->data); - budget--; - } - mtk_tx_unmap(eth, tx_buf, &bq, true); -@@ -2094,26 +2203,15 @@ static int mtk_poll_tx(struct mtk_eth *e - { - struct mtk_tx_ring *ring = ð->tx_ring; - struct dim_sample dim_sample = {}; -- unsigned int done[MTK_MAX_DEVS]; -- unsigned int bytes[MTK_MAX_DEVS]; -- int total = 0, i; -- -- memset(done, 0, sizeof(done)); -- memset(bytes, 0, sizeof(bytes)); -+ struct mtk_poll_state state = {}; - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -- budget = mtk_poll_tx_qdma(eth, budget, done, bytes); -+ budget = mtk_poll_tx_qdma(eth, budget, &state); - else -- budget = mtk_poll_tx_pdma(eth, budget, done, bytes); -+ budget = mtk_poll_tx_pdma(eth, budget, &state); - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -- if (!eth->netdev[i] || !done[i]) -- continue; -- netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); -- total += done[i]; -- eth->tx_packets += done[i]; -- eth->tx_bytes += bytes[i]; -- } -+ if (state.txq) -+ netdev_tx_completed_queue(state.txq, state.done, state.bytes); - - dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes, - &dim_sample); -@@ -2123,7 +2221,7 @@ static int mtk_poll_tx(struct mtk_eth *e - (atomic_read(&ring->free_count) > ring->thresh)) - mtk_wake_queue(eth); - -- return total; -+ return state.total; - } - - static void mtk_handle_status_irq(struct mtk_eth *eth) -@@ -2209,6 +2307,7 @@ static int mtk_tx_alloc(struct mtk_eth * - int i, sz = soc->txrx.txd_size; - struct mtk_tx_dma_v2 *txd; - int ring_size; -+ u32 ofs, val; - - if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) - ring_size = MTK_QDMA_RING_SIZE; -@@ -2276,8 +2375,25 @@ static int mtk_tx_alloc(struct mtk_eth * - ring->phys + ((ring_size - 1) * sz), - soc->reg_map->qdma.crx_ptr); - mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); -- mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, -- soc->reg_map->qdma.qtx_cfg); -+ -+ for (i = 0, ofs = 0; i < MTK_QDMA_NUM_QUEUES; i++) { -+ val = (QDMA_RES_THRES << 8) | QDMA_RES_THRES; -+ mtk_w32(eth, val, soc->reg_map->qdma.qtx_cfg + ofs); -+ -+ val = MTK_QTX_SCH_MIN_RATE_EN | -+ /* minimum: 10 Mbps */ -+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | -+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | -+ MTK_QTX_SCH_LEAKY_BUCKET_SIZE; -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; -+ mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); -+ ofs += MTK_QTX_OFFSET; -+ } -+ val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); -+ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); - } else { - mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); - mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); -@@ -2962,7 +3078,7 @@ static int mtk_start_dma(struct mtk_eth - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) - val |= MTK_MUTLI_CNT | MTK_RESV_BUF | - MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | -- MTK_CHK_DDONE_EN; -+ MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; - else - val |= MTK_RX_BT_32DWORDS; - mtk_w32(eth, val, reg_map->qdma.glo_cfg); -@@ -3008,6 +3124,45 @@ static void mtk_gdm_config(struct mtk_et - mtk_w32(eth, 0, MTK_RST_GL); - } - -+static int mtk_device_event(struct notifier_block *n, unsigned long event, void *ptr) -+{ -+ struct mtk_mac *mac = container_of(n, struct mtk_mac, device_notifier); -+ struct mtk_eth *eth = mac->hw; -+ struct net_device *dev = netdev_notifier_info_to_dev(ptr); -+ struct ethtool_link_ksettings s; -+ struct net_device *ldev; -+ struct list_head *iter; -+ struct dsa_port *dp; -+ -+ if (event != NETDEV_CHANGE) -+ return NOTIFY_DONE; -+ -+ netdev_for_each_lower_dev(dev, ldev, iter) { -+ if (netdev_priv(ldev) == mac) -+ goto found; -+ } -+ -+ return NOTIFY_DONE; -+ -+found: -+ if (!dsa_slave_dev_check(dev)) -+ return NOTIFY_DONE; -+ -+ if (__ethtool_get_link_ksettings(dev, &s)) -+ return NOTIFY_DONE; -+ -+ if (s.base.speed == 0 || s.base.speed == ((__u32)-1)) -+ return NOTIFY_DONE; -+ -+ dp = dsa_port_from_netdev(dev); -+ if (dp->index >= MTK_QDMA_NUM_QUEUES) -+ return NOTIFY_DONE; -+ -+ mtk_set_queue_speed(eth, dp->index + 3, s.base.speed); -+ -+ return NOTIFY_DONE; -+} -+ - static int mtk_open(struct net_device *dev) - { - struct mtk_mac *mac = netdev_priv(dev); -@@ -3050,7 +3205,8 @@ static int mtk_open(struct net_device *d - refcount_inc(ð->dma_refcnt); - - phylink_start(mac->phylink); -- netif_start_queue(dev); -+ netif_tx_start_all_queues(dev); -+ - return 0; - } - -@@ -3759,8 +3915,12 @@ static int mtk_unreg_dev(struct mtk_eth - int i; - - for (i = 0; i < MTK_MAC_COUNT; i++) { -+ struct mtk_mac *mac; - if (!eth->netdev[i]) - continue; -+ mac = netdev_priv(eth->netdev[i]); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -+ unregister_netdevice_notifier(&mac->device_notifier); - unregister_netdev(eth->netdev[i]); - } - -@@ -3977,6 +4137,23 @@ static int mtk_set_rxnfc(struct net_devi - return ret; - } - -+static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, -+ struct net_device *sb_dev) -+{ -+ struct mtk_mac *mac = netdev_priv(dev); -+ unsigned int queue = 0; -+ -+ if (netdev_uses_dsa(dev)) -+ queue = skb_get_queue_mapping(skb) + 3; -+ else -+ queue = mac->id; -+ -+ if (queue >= dev->num_tx_queues) -+ queue = 0; -+ -+ return queue; -+} -+ - static const struct ethtool_ops mtk_ethtool_ops = { - .get_link_ksettings = mtk_get_link_ksettings, - .set_link_ksettings = mtk_set_link_ksettings, -@@ -4011,6 +4188,7 @@ static const struct net_device_ops mtk_n - .ndo_setup_tc = mtk_eth_setup_tc, - .ndo_bpf = mtk_xdp, - .ndo_xdp_xmit = mtk_xdp_xmit, -+ .ndo_select_queue = mtk_select_queue, - }; - - static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) -@@ -4020,6 +4198,7 @@ static int mtk_add_mac(struct mtk_eth *e - struct phylink *phylink; - struct mtk_mac *mac; - int id, err; -+ int txqs = 1; - - if (!_id) { - dev_err(eth->dev, "missing mac id\n"); -@@ -4037,7 +4216,10 @@ static int mtk_add_mac(struct mtk_eth *e - return -EINVAL; - } - -- eth->netdev[id] = alloc_etherdev(sizeof(*mac)); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -+ txqs = MTK_QDMA_NUM_QUEUES; -+ -+ eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1); - if (!eth->netdev[id]) { - dev_err(eth->dev, "alloc_etherdev failed\n"); - return -ENOMEM; -@@ -4145,6 +4327,11 @@ static int mtk_add_mac(struct mtk_eth *e - else - eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { -+ mac->device_notifier.notifier_call = mtk_device_event; -+ register_netdevice_notifier(&mac->device_notifier); -+ } -+ - return 0; - - free_netdev: ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -22,6 +22,7 @@ - #include - #include "mtk_ppe.h" - -+#define MTK_QDMA_NUM_QUEUES 16 - #define MTK_QDMA_PAGE_SIZE 2048 - #define MTK_MAX_RX_LENGTH 1536 - #define MTK_MAX_RX_LENGTH_2K 2048 -@@ -216,8 +217,26 @@ - #define MTK_RING_MAX_AGG_CNT_H ((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3) - - /* QDMA TX Queue Configuration Registers */ -+#define MTK_QTX_OFFSET 0x10 - #define QDMA_RES_THRES 4 - -+/* QDMA Tx Queue Scheduler Configuration Registers */ -+#define MTK_QTX_SCH_TX_SEL BIT(31) -+#define MTK_QTX_SCH_TX_SEL_V2 GENMASK(31, 30) -+ -+#define MTK_QTX_SCH_LEAKY_BUCKET_EN BIT(30) -+#define MTK_QTX_SCH_LEAKY_BUCKET_SIZE GENMASK(29, 28) -+#define MTK_QTX_SCH_MIN_RATE_EN BIT(27) -+#define MTK_QTX_SCH_MIN_RATE_MAN GENMASK(26, 20) -+#define MTK_QTX_SCH_MIN_RATE_EXP GENMASK(19, 16) -+#define MTK_QTX_SCH_MAX_RATE_WEIGHT GENMASK(15, 12) -+#define MTK_QTX_SCH_MAX_RATE_EN BIT(11) -+#define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4) -+#define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0) -+ -+/* QDMA TX Scheduler Rate Control Register */ -+#define MTK_QDMA_TX_SCH_MAX_WFQ BIT(15) -+ - /* QDMA Global Configuration Register */ - #define MTK_RX_2B_OFFSET BIT(31) - #define MTK_RX_BT_32DWORDS (3 << 11) -@@ -236,6 +255,7 @@ - #define MTK_WCOMP_EN BIT(24) - #define MTK_RESV_BUF (0x40 << 16) - #define MTK_MUTLI_CNT (0x4 << 12) -+#define MTK_LEAKY_BUCKET_EN BIT(11) - - /* QDMA Flow Control Register */ - #define FC_THRES_DROP_MODE BIT(20) -@@ -266,8 +286,6 @@ - #define MTK_STAT_OFFSET 0x40 - - /* QDMA TX NUM */ --#define MTK_QDMA_TX_NUM 16 --#define MTK_QDMA_TX_MASK (MTK_QDMA_TX_NUM - 1) - #define QID_BITS_V2(x) (((x) & 0x3f) << 16) - #define MTK_QDMA_GMAC2_QID 8 - -@@ -297,6 +315,7 @@ - #define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) - #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) - #define TX_DMA_SWC BIT(14) -+#define TX_DMA_PQID GENMASK(3, 0) - - /* PDMA on MT7628 */ - #define TX_DMA_DONE BIT(31) -@@ -957,6 +976,7 @@ struct mtk_reg_map { - } pdma; - struct { - u32 qtx_cfg; /* tx queue configuration */ -+ u32 qtx_sch; /* tx queue scheduler configuration */ - u32 rx_ptr; /* rx base pointer */ - u32 rx_cnt_cfg; /* rx max count configuration */ - u32 qcrx_ptr; /* rx cpu pointer */ -@@ -974,6 +994,7 @@ struct mtk_reg_map { - u32 fq_tail; /* fq tail pointer */ - u32 fq_count; /* fq free page count */ - u32 fq_blen; /* fq free page buffer length */ -+ u32 tx_sch_rate; /* tx scheduler rate control registers */ - } qdma; - u32 gdm1_cnt; - u32 gdma_to_ppe; -@@ -1177,6 +1198,7 @@ struct mtk_mac { - __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; - int hwlro_ip_cnt; - unsigned int syscfg0; -+ struct notifier_block device_notifier; - }; - - /* the struct describing the SoC. these are declared in the soc_xyz.c files */ diff --git a/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch b/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch deleted file mode 100644 index 186df4bdc9..0000000000 --- a/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Felix Fietkau -Date: Fri, 28 Oct 2022 18:16:03 +0200 -Subject: [PATCH] net: dsa: tag_mtk: assign per-port queues - -Keeps traffic sent to the switch within link speed limits - -Signed-off-by: Felix Fietkau ---- - ---- a/net/dsa/tag_mtk.c -+++ b/net/dsa/tag_mtk.c -@@ -25,6 +25,8 @@ static struct sk_buff *mtk_tag_xmit(stru - u8 xmit_tpid; - u8 *mtk_tag; - -+ skb_set_queue_mapping(skb, dp->index); -+ - /* Build the special tag after the MAC Source Address. If VLAN header - * is present, it's required that VLAN header and special tag is - * being combined. Only in this way we can allow the switch can parse diff --git a/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch b/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch deleted file mode 100644 index d29177eee7..0000000000 --- a/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch +++ /dev/null @@ -1,93 +0,0 @@ -From: Felix Fietkau -Date: Thu, 3 Nov 2022 17:49:44 +0100 -Subject: [PATCH] net: ethernet: mediatek: ppe: assign per-port queues - for offloaded traffic - -Keeps traffic sent to the switch within link speed limits - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -399,6 +399,24 @@ int mtk_foe_entry_set_wdma(struct mtk_et - return 0; - } - -+int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, -+ unsigned int queue) -+{ -+ u32 *ib2 = mtk_foe_entry_ib2(eth, entry); -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ *ib2 &= ~MTK_FOE_IB2_QID_V2; -+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); -+ *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; -+ } else { -+ *ib2 &= ~MTK_FOE_IB2_QID; -+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, queue); -+ *ib2 |= MTK_FOE_IB2_PSE_QOS; -+ } -+ -+ return 0; -+} -+ - static bool - mtk_flow_entry_match(struct mtk_eth *eth, struct mtk_flow_entry *entry, - struct mtk_foe_entry *data) ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -68,7 +68,9 @@ enum { - #define MTK_FOE_IB2_DSCP GENMASK(31, 24) - - /* CONFIG_MEDIATEK_NETSYS_V2 */ -+#define MTK_FOE_IB2_QID_V2 GENMASK(6, 0) - #define MTK_FOE_IB2_PORT_MG_V2 BIT(7) -+#define MTK_FOE_IB2_PSE_QOS_V2 BIT(8) - #define MTK_FOE_IB2_DEST_PORT_V2 GENMASK(12, 9) - #define MTK_FOE_IB2_MULTICAST_V2 BIT(13) - #define MTK_FOE_IB2_WDMA_WINFO_V2 BIT(19) -@@ -351,6 +353,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e - int sid); - int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, - int wdma_idx, int txq, int bss, int wcid); -+int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, -+ unsigned int queue); - int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -188,7 +188,7 @@ mtk_flow_set_output_device(struct mtk_et - int *wed_index) - { - struct mtk_wdma_info info = {}; -- int pse_port, dsa_port; -+ int pse_port, dsa_port, queue; - - if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { - mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, -@@ -212,8 +212,6 @@ mtk_flow_set_output_device(struct mtk_et - } - - dsa_port = mtk_flow_get_dsa_port(&dev); -- if (dsa_port >= 0) -- mtk_foe_entry_set_dsa(eth, foe, dsa_port); - - if (dev == eth->netdev[0]) - pse_port = 1; -@@ -222,6 +220,14 @@ mtk_flow_set_output_device(struct mtk_et - else - return -EOPNOTSUPP; - -+ if (dsa_port >= 0) { -+ mtk_foe_entry_set_dsa(eth, foe, dsa_port); -+ queue = 3 + dsa_port; -+ } else { -+ queue = pse_port - 1; -+ } -+ mtk_foe_entry_set_queue(eth, foe, queue); -+ - out: - mtk_foe_entry_set_pse_port(eth, foe, pse_port); - diff --git a/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch b/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch deleted file mode 100644 index 6b7f3d6018..0000000000 --- a/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: Felix Fietkau -Date: Tue, 8 Nov 2022 15:03:15 +0100 -Subject: [PATCH] net: dsa: add support for DSA rx offloading via - metadata dst - -If a metadata dst is present with the type METADATA_HW_PORT_MUX on a dsa cpu -port netdev, assume that it carries the port number and that there is no DSA -tag present in the skb data. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/core/flow_dissector.c -+++ b/net/core/flow_dissector.c -@@ -971,12 +971,14 @@ bool __skb_flow_dissect(const struct net - #if IS_ENABLED(CONFIG_NET_DSA) - if (unlikely(skb->dev && netdev_uses_dsa(skb->dev) && - proto == htons(ETH_P_XDSA))) { -+ struct metadata_dst *md_dst = skb_metadata_dst(skb); - const struct dsa_device_ops *ops; - int offset = 0; - - ops = skb->dev->dsa_ptr->tag_ops; - /* Only DSA header taggers break flow dissection */ -- if (ops->needed_headroom) { -+ if (ops->needed_headroom && -+ (!md_dst || md_dst->type != METADATA_HW_PORT_MUX)) { - if (ops->flow_dissect) - ops->flow_dissect(skb, &proto, &offset); - else ---- a/net/dsa/dsa.c -+++ b/net/dsa/dsa.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include "dsa_priv.h" - -@@ -216,6 +217,7 @@ static bool dsa_skb_defer_rx_timestamp(s - static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, struct net_device *unused) - { -+ struct metadata_dst *md_dst = skb_metadata_dst(skb); - struct dsa_port *cpu_dp = dev->dsa_ptr; - struct sk_buff *nskb = NULL; - struct dsa_slave_priv *p; -@@ -229,7 +231,22 @@ static int dsa_switch_rcv(struct sk_buff - if (!skb) - return 0; - -- nskb = cpu_dp->rcv(skb, dev); -+ if (md_dst && md_dst->type == METADATA_HW_PORT_MUX) { -+ unsigned int port = md_dst->u.port_info.port_id; -+ -+ skb_dst_drop(skb); -+ if (!skb_has_extensions(skb)) -+ skb->slow_gro = 0; -+ -+ skb->dev = dsa_master_find_slave(dev, 0, port); -+ if (likely(skb->dev)) { -+ dsa_default_offload_fwd_mark(skb); -+ nskb = skb; -+ } -+ } else { -+ nskb = cpu_dp->rcv(skb, dev); -+ } -+ - if (!nskb) { - kfree_skb(skb); - return 0; diff --git a/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch b/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch deleted file mode 100644 index b8e3452f30..0000000000 --- a/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch +++ /dev/null @@ -1,192 +0,0 @@ -From: Felix Fietkau -Date: Fri, 28 Oct 2022 11:01:12 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix VLAN rx hardware - acceleration - -- enable VLAN untagging for PDMA rx -- make it possible to disable the feature via ethtool -- pass VLAN tag to the DSA driver -- untag special tag on PDMA only if no non-DSA devices are in use -- disable special tag untagging on 7986 for now, since it's not working yet - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include "mtk_eth_soc.h" - #include "mtk_wed.h" -@@ -2021,16 +2022,22 @@ static int mtk_poll_rx(struct napi_struc - htons(RX_DMA_VPID(trxd.rxd4)), - RX_DMA_VID(trxd.rxd4)); - } else if (trxd.rxd2 & RX_DMA_VTAG) { -- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), -+ __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), - RX_DMA_VID(trxd.rxd3)); - } -+ } -+ -+ /* When using VLAN untagging in combination with DSA, the -+ * hardware treats the MTK special tag as a VLAN and untags it. -+ */ -+ if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { -+ unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); - -- /* If the device is attached to a dsa switch, the special -- * tag inserted in VLAN field by hw switch can * be offloaded -- * by RX HW VLAN offload. Clear vlan info. -- */ -- if (netdev_uses_dsa(netdev)) -- __vlan_hwaccel_clear_tag(skb); -+ if (port < ARRAY_SIZE(eth->dsa_meta) && -+ eth->dsa_meta[port]) -+ skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); -+ -+ __vlan_hwaccel_clear_tag(skb); - } - - skb_record_rx_queue(skb, 0); -@@ -2858,15 +2865,30 @@ static netdev_features_t mtk_fix_feature - - static int mtk_set_features(struct net_device *dev, netdev_features_t features) - { -- int err = 0; -+ struct mtk_mac *mac = netdev_priv(dev); -+ struct mtk_eth *eth = mac->hw; -+ netdev_features_t diff = dev->features ^ features; -+ int i; -+ -+ if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) -+ mtk_hwlro_netdev_disable(dev); - -- if (!((dev->features ^ features) & NETIF_F_LRO)) -+ /* Set RX VLAN offloading */ -+ if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) - return 0; - -- if (!(features & NETIF_F_LRO)) -- mtk_hwlro_netdev_disable(dev); -+ mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), -+ MTK_CDMP_EG_CTRL); - -- return err; -+ /* sync features with other MAC */ -+ for (i = 0; i < MTK_MAC_COUNT; i++) { -+ if (!eth->netdev[i] || eth->netdev[i] == dev) -+ continue; -+ eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; -+ eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; -+ } -+ -+ return 0; - } - - /* wait for DMA to finish whatever it is doing before we start using it again */ -@@ -3163,11 +3185,45 @@ found: - return NOTIFY_DONE; - } - -+static bool mtk_uses_dsa(struct net_device *dev) -+{ -+#if IS_ENABLED(CONFIG_NET_DSA) -+ return netdev_uses_dsa(dev) && -+ dev->dsa_ptr->tag_ops->proto == DSA_TAG_PROTO_MTK; -+#else -+ return false; -+#endif -+} -+ - static int mtk_open(struct net_device *dev) - { - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; -- int err; -+ int i, err; -+ -+ if (mtk_uses_dsa(dev) && !eth->prog) { -+ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -+ struct metadata_dst *md_dst = eth->dsa_meta[i]; -+ -+ if (md_dst) -+ continue; -+ -+ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, -+ GFP_KERNEL); -+ if (!md_dst) -+ return -ENOMEM; -+ -+ md_dst->u.port_info.port_id = i; -+ eth->dsa_meta[i] = md_dst; -+ } -+ } else { -+ /* Hardware special tag parsing needs to be disabled if at least -+ * one MAC does not use DSA. -+ */ -+ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -+ val &= ~MTK_CDMP_STAG_EN; -+ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); -+ } - - err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); - if (err) { -@@ -3688,6 +3744,10 @@ static int mtk_hw_init(struct mtk_eth *e - */ - val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); - mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -+ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); -+ } - - /* Enable RX VLan Offloading */ - mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); -@@ -3907,6 +3967,12 @@ static int mtk_free_dev(struct mtk_eth * - free_netdev(eth->netdev[i]); - } - -+ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -+ if (!eth->dsa_meta[i]) -+ break; -+ metadata_dst_free(eth->dsa_meta[i]); -+ } -+ - return 0; - } - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -22,6 +22,9 @@ - #include - #include "mtk_ppe.h" - -+#define MTK_MAX_DSA_PORTS 7 -+#define MTK_DSA_PORT_MASK GENMASK(2, 0) -+ - #define MTK_QDMA_NUM_QUEUES 16 - #define MTK_QDMA_PAGE_SIZE 2048 - #define MTK_MAX_RX_LENGTH 1536 -@@ -105,6 +108,9 @@ - #define MTK_CDMQ_IG_CTRL 0x1400 - #define MTK_CDMQ_STAG_EN BIT(0) - -+/* CDMQ Exgress Control Register */ -+#define MTK_CDMQ_EG_CTRL 0x1404 -+ - /* CDMP Ingress Control Register */ - #define MTK_CDMP_IG_CTRL 0x400 - #define MTK_CDMP_STAG_EN BIT(0) -@@ -1164,6 +1170,8 @@ struct mtk_eth { - - int ip_align; - -+ struct metadata_dst *dsa_meta[MTK_MAX_DSA_PORTS]; -+ - struct mtk_ppe *ppe[2]; - struct rhashtable flow_table; - diff --git a/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch b/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch deleted file mode 100644 index a88df2b8e3..0000000000 --- a/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= -Date: Sat, 28 Jan 2023 12:42:32 +0300 -Subject: [PATCH] net: ethernet: mtk_eth_soc: disable hardware DSA untagging - for second MAC -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -According to my tests on MT7621AT and MT7623NI SoCs, hardware DSA untagging -won't work on the second MAC. Therefore, disable this feature when the -second MAC of the MT7621 and MT7623 SoCs is being used. - -Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") -Link: https://lore.kernel.org/netdev/6249fc14-b38a-c770-36b4-5af6d41c21d3@arinc9.com/ -Tested-by: Arınç ÜNAL -Signed-off-by: Arınç ÜNAL -Link: https://lore.kernel.org/r/20230128094232.2451947-1-arinc.unal@arinc9.com -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3201,7 +3201,8 @@ static int mtk_open(struct net_device *d - struct mtk_eth *eth = mac->hw; - int i, err; - -- if (mtk_uses_dsa(dev) && !eth->prog) { -+ if ((mtk_uses_dsa(dev) && !eth->prog) && -+ !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { - for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { - struct metadata_dst *md_dst = eth->dsa_meta[i]; - -@@ -3218,7 +3219,8 @@ static int mtk_open(struct net_device *d - } - } else { - /* Hardware special tag parsing needs to be disabled if at least -- * one MAC does not use DSA. -+ * one MAC does not use DSA, or the second MAC of the MT7621 and -+ * MT7623 SoCs is being used. - */ - u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - val &= ~MTK_CDMP_STAG_EN; diff --git a/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch b/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch deleted file mode 100644 index 8da728b9e9..0000000000 --- a/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= -Date: Sun, 5 Feb 2023 20:53:31 +0300 -Subject: [PATCH] net: ethernet: mtk_eth_soc: enable special tag when any MAC - uses DSA -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The special tag is only enabled when the first MAC uses DSA. However, it -must be enabled when any MAC uses DSA. Change the check accordingly. - -This fixes hardware DSA untagging not working on the second MAC of the -MT7621 and MT7623 SoCs, and likely other SoCs too. Therefore, remove the -check that disables hardware DSA untagging for the second MAC of the MT7621 -and MT7623 SoCs. - -Fixes: a1f47752fd62 ("net: ethernet: mtk_eth_soc: disable hardware DSA untagging for second MAC") -Co-developed-by: Richard van Schagen -Signed-off-by: Richard van Schagen -Signed-off-by: Arınç ÜNAL -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3136,7 +3136,7 @@ static void mtk_gdm_config(struct mtk_et - - val |= config; - -- if (!i && eth->netdev[0] && netdev_uses_dsa(eth->netdev[0])) -+ if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) - val |= MTK_GDMA_SPECIAL_TAG; - - mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); -@@ -3201,8 +3201,7 @@ static int mtk_open(struct net_device *d - struct mtk_eth *eth = mac->hw; - int i, err; - -- if ((mtk_uses_dsa(dev) && !eth->prog) && -- !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { -+ if (mtk_uses_dsa(dev) && !eth->prog) { - for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { - struct metadata_dst *md_dst = eth->dsa_meta[i]; - -@@ -3219,8 +3218,7 @@ static int mtk_open(struct net_device *d - } - } else { - /* Hardware special tag parsing needs to be disabled if at least -- * one MAC does not use DSA, or the second MAC of the MT7621 and -- * MT7623 SoCs is being used. -+ * one MAC does not use DSA. - */ - u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - val &= ~MTK_CDMP_STAG_EN; diff --git a/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch b/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch deleted file mode 100644 index 51cd572ab2..0000000000 --- a/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch +++ /dev/null @@ -1,129 +0,0 @@ -From: Vladimir Oltean -Date: Tue, 7 Feb 2023 12:30:27 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix DSA TX tag hwaccel for switch - port 0 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Arınç reports that on his MT7621AT Unielec U7621-06 board and MT7623NI -Bananapi BPI-R2, packets received by the CPU over mt7530 switch port 0 -(of which this driver acts as the DSA master) are not processed -correctly by software. More precisely, they arrive without a DSA tag -(in packet or in the hwaccel area - skb_metadata_dst()), so DSA cannot -demux them towards the switch's interface for port 0. Traffic from other -ports receives a skb_metadata_dst() with the correct port and is demuxed -properly. - -Looking at mtk_poll_rx(), it becomes apparent that this driver uses the -skb vlan hwaccel area: - - union { - u32 vlan_all; - struct { - __be16 vlan_proto; - __u16 vlan_tci; - }; - }; - -as a temporary storage for the VLAN hwaccel tag, or the DSA hwaccel tag. -If this is a DSA master it's a DSA hwaccel tag, and finally clears up -the skb VLAN hwaccel header. - -I'm guessing that the problem is the (mis)use of API. -skb_vlan_tag_present() looks like this: - - #define skb_vlan_tag_present(__skb) (!!(__skb)->vlan_all) - -So if both vlan_proto and vlan_tci are zeroes, skb_vlan_tag_present() -returns precisely false. I don't know for sure what is the format of the -DSA hwaccel tag, but I surely know that lowermost 3 bits of vlan_proto -are 0 when receiving from port 0: - - unsigned int port = vlan_proto & GENMASK(2, 0); - -If the RX descriptor has no other bits set to non-zero values in -RX_DMA_VTAG, then the call to __vlan_hwaccel_put_tag() will not, in -fact, make the subsequent skb_vlan_tag_present() return true, because -it's implemented like this: - -static inline void __vlan_hwaccel_put_tag(struct sk_buff *skb, - __be16 vlan_proto, u16 vlan_tci) -{ - skb->vlan_proto = vlan_proto; - skb->vlan_tci = vlan_tci; -} - -What we need to do to fix this problem (assuming this is the problem) is -to stop using skb->vlan_all as temporary storage for driver affairs, and -just create some local variables that serve the same purpose, but -hopefully better. Instead of calling skb_vlan_tag_present(), let's look -at a boolean has_hwaccel_tag which we set to true when the RX DMA -descriptors have something. Disambiguate based on netdev_uses_dsa() -whether this is a VLAN or DSA hwaccel tag, and only call -__vlan_hwaccel_put_tag() if we're certain it's a VLAN tag. - -Arınç confirms that the treatment works, so this validates the -assumption. - -Link: https://lore.kernel.org/netdev/704f3a72-fc9e-714a-db54-272e17612637@arinc9.com/ -Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") -Reported-by: Arınç ÜNAL -Tested-by: Arınç ÜNAL -Signed-off-by: Vladimir Oltean -Reviewed-by: Felix Fietkau -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1877,7 +1877,9 @@ static int mtk_poll_rx(struct napi_struc - - while (done < budget) { - unsigned int pktlen, *rxdcsum; -+ bool has_hwaccel_tag = false; - struct net_device *netdev; -+ u16 vlan_proto, vlan_tci; - dma_addr_t dma_addr; - u32 hash, reason; - int mac = 0; -@@ -2017,27 +2019,29 @@ static int mtk_poll_rx(struct napi_struc - - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- if (trxd.rxd3 & RX_DMA_VTAG_V2) -- __vlan_hwaccel_put_tag(skb, -- htons(RX_DMA_VPID(trxd.rxd4)), -- RX_DMA_VID(trxd.rxd4)); -+ if (trxd.rxd3 & RX_DMA_VTAG_V2) { -+ vlan_proto = RX_DMA_VPID(trxd.rxd4); -+ vlan_tci = RX_DMA_VID(trxd.rxd4); -+ has_hwaccel_tag = true; -+ } - } else if (trxd.rxd2 & RX_DMA_VTAG) { -- __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), -- RX_DMA_VID(trxd.rxd3)); -+ vlan_proto = RX_DMA_VPID(trxd.rxd3); -+ vlan_tci = RX_DMA_VID(trxd.rxd3); -+ has_hwaccel_tag = true; - } - } - - /* When using VLAN untagging in combination with DSA, the - * hardware treats the MTK special tag as a VLAN and untags it. - */ -- if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { -- unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); -+ if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { -+ unsigned int port = vlan_proto & GENMASK(2, 0); - - if (port < ARRAY_SIZE(eth->dsa_meta) && - eth->dsa_meta[port]) - skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); -- -- __vlan_hwaccel_clear_tag(skb); -+ } else if (has_hwaccel_tag) { -+ __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); - } - - skb_record_rx_queue(skb, 0); diff --git a/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch b/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch deleted file mode 100644 index a3bb1c5db7..0000000000 --- a/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Christophe JAILLET -Date: Sun, 12 Feb 2023 07:51:51 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: No need to clear memory after a - dma_alloc_coherent() call - -dma_alloc_coherent() already clears the allocated memory, there is no need -to explicitly call memset(). - -Moreover, it is likely that the size in the memset() is incorrect and -should be "size * sizeof(*ring->desc)". - -Signed-off-by: Christophe JAILLET -Link: https://lore.kernel.org/r/d5acce7dd108887832c9719f62c7201b4c83b3fb.1676184599.git.christophe.jaillet@wanadoo.fr -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -779,7 +779,6 @@ mtk_wed_rro_ring_alloc(struct mtk_wed_de - - ring->desc_size = sizeof(*ring->desc); - ring->size = size; -- memset(ring->desc, 0, size); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch b/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch deleted file mode 100644 index e043a681da..0000000000 --- a/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From: Lorenzo Bianconi -Date: Wed, 7 Dec 2022 15:04:54 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: fix some possible NULL pointer - dereferences - -Fix possible NULL pointer dereference in mtk_wed_detach routine checking -wo pointer is properly allocated before running mtk_wed_wo_reset() and -mtk_wed_wo_deinit(). -Even if it is just a theoretical issue at the moment check wo pointer is -not NULL in mtk_wed_mcu_msg_update. -Moreover, honor mtk_wed_mcu_send_msg return value in mtk_wed_wo_reset() - -Fixes: 799684448e3e ("net: ethernet: mtk_wed: introduce wed wo support") -Fixes: 4c5de09eb0d0 ("net: ethernet: mtk_wed: add configure wed wo support") -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Leon Romanovsky -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -174,9 +174,10 @@ mtk_wed_wo_reset(struct mtk_wed_device * - mtk_wdma_tx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); - -- mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -- MTK_WED_WO_CMD_CHANGE_STATE, &state, -- sizeof(state), false); -+ if (mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &state, -+ sizeof(state), false)) -+ return; - - if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val, - val == MTK_WED_WOIF_DISABLE_DONE, -@@ -632,9 +633,11 @@ mtk_wed_detach(struct mtk_wed_device *de - mtk_wed_free_tx_rings(dev); - - if (mtk_wed_get_rx_capa(dev)) { -- mtk_wed_wo_reset(dev); -+ if (hw->wed_wo) -+ mtk_wed_wo_reset(dev); - mtk_wed_free_rx_rings(dev); -- mtk_wed_wo_deinit(hw); -+ if (hw->wed_wo) -+ mtk_wed_wo_deinit(hw); - } - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -207,6 +207,9 @@ int mtk_wed_mcu_msg_update(struct mtk_we - if (dev->hw->version == 1) - return 0; - -+ if (WARN_ON(!wo)) -+ return -ENODEV; -+ - return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, - true); - } diff --git a/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch b/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch deleted file mode 100644 index 0afe7106e5..0000000000 --- a/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Lorenzo Bianconi -Date: Wed, 7 Dec 2022 15:04:55 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: fix possible deadlock if - mtk_wed_wo_init fails - -Introduce __mtk_wed_detach() in order to avoid a deadlock in -mtk_wed_attach routine if mtk_wed_wo_init fails since both -mtk_wed_attach and mtk_wed_detach run holding hw_lock mutex. - -Fixes: 4c5de09eb0d0 ("net: ethernet: mtk_wed: add configure wed wo support") -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Leon Romanovsky -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -619,12 +619,10 @@ mtk_wed_deinit(struct mtk_wed_device *de - } - - static void --mtk_wed_detach(struct mtk_wed_device *dev) -+__mtk_wed_detach(struct mtk_wed_device *dev) - { - struct mtk_wed_hw *hw = dev->hw; - -- mutex_lock(&hw_lock); -- - mtk_wed_deinit(dev); - - mtk_wdma_rx_reset(dev); -@@ -657,6 +655,13 @@ mtk_wed_detach(struct mtk_wed_device *de - module_put(THIS_MODULE); - - hw->wed_dev = NULL; -+} -+ -+static void -+mtk_wed_detach(struct mtk_wed_device *dev) -+{ -+ mutex_lock(&hw_lock); -+ __mtk_wed_detach(dev); - mutex_unlock(&hw_lock); - } - -@@ -1538,8 +1543,10 @@ mtk_wed_attach(struct mtk_wed_device *de - ret = mtk_wed_wo_init(hw); - } - out: -- if (ret) -- mtk_wed_detach(dev); -+ if (ret) { -+ dev_err(dev->hw->dev, "failed to attach wed device\n"); -+ __mtk_wed_detach(dev); -+ } - unlock: - mutex_unlock(&hw_lock); - diff --git a/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch b/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch deleted file mode 100644 index ca5b6b3a3e..0000000000 --- a/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Felix Fietkau -Date: Fri, 24 Mar 2023 14:56:58 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix tx throughput regression with - direct 1G links - -Using the QDMA tx scheduler to throttle tx to line speed works fine for -switch ports, but apparently caused a regression on non-switch ports. - -Based on a number of tests, it seems that this throttling can be safely -dropped without re-introducing the issues on switch ports that the -tx scheduling changes resolved. - -Link: https://lore.kernel.org/netdev/trinity-92c3826f-c2c8-40af-8339-bc6d0d3ffea4-1678213958520@3c-app-gmx-bs16/ -Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues") -Reported-by: Frank Wunderlich -Reported-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -719,8 +719,6 @@ static void mtk_mac_link_up(struct phyli - break; - } - -- mtk_set_queue_speed(mac->hw, mac->id, speed); -- - /* Configure duplex */ - if (duplex == DUPLEX_FULL) - mcr |= MAC_MCR_FORCE_DPX; diff --git a/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch b/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch deleted file mode 100644 index 850b806410..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch +++ /dev/null @@ -1,55 +0,0 @@ -From b6a709cb51f7bdc55c01cec886098a9753ce8c28 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:42 +0100 -Subject: [PATCH 01/10] net: mtk_eth_soc: add definitions for PCS - -As a result of help from Frank Wunderlich to investigate and test, we -know a bit more about the PCS on the Mediatek platforms. Update the -definitions from this investigation. - -This PCS appears similar, but not identical to the Lynx PCS. - -Although not included in this patch, but for future reference, the PHY -ID registers at offset 4 read as 0x4d544950 'MTIP'. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -504,8 +504,10 @@ - #define ETHSYS_DMA_AG_MAP_PPE BIT(2) - - /* SGMII subsystem config registers */ --/* Register to auto-negotiation restart */ -+/* BMCR (low 16) BMSR (high 16) */ - #define SGMSYS_PCS_CONTROL_1 0x0 -+#define SGMII_BMCR GENMASK(15, 0) -+#define SGMII_BMSR GENMASK(31, 16) - #define SGMII_AN_RESTART BIT(9) - #define SGMII_ISOLATE BIT(10) - #define SGMII_AN_ENABLE BIT(12) -@@ -515,13 +517,18 @@ - #define SGMII_PCS_FAULT BIT(23) - #define SGMII_AN_EXPANSION_CLR BIT(30) - -+#define SGMSYS_PCS_ADVERTISE 0x8 -+#define SGMII_ADVERTISE GENMASK(15, 0) -+#define SGMII_LPA GENMASK(31, 16) -+ - /* Register to programmable link timer, the unit in 2 * 8ns */ - #define SGMSYS_PCS_LINK_TIMER 0x18 --#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0)) -+#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) -+#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK) - - /* Register to control remote fault */ - #define SGMSYS_SGMII_MODE 0x20 --#define SGMII_IF_MODE_BIT0 BIT(0) -+#define SGMII_IF_MODE_SGMII BIT(0) - #define SGMII_SPEED_DUPLEX_AN BIT(1) - #define SGMII_SPEED_MASK GENMASK(3, 2) - #define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) diff --git a/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch b/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch deleted file mode 100644 index 4ea428c9d6..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 5cf7797526ee81bea0f627bccaa3d887f48f53e0 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:47 +0100 -Subject: [PATCH 02/10] net: mtk_eth_soc: eliminate unnecessary error handling - -The functions called by the pcs_config() method always return zero, so -there is no point trying to handle an error from these functions. Make -these functions void, eliminate the "err" variable and simply return -zero from the pcs_config() function itself. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++------------ - 1 file changed, 6 insertions(+), 12 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -20,7 +20,7 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st - } - - /* For SGMII interface mode */ --static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) -+static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { - unsigned int val; - -@@ -39,16 +39,13 @@ static int mtk_pcs_setup_mode_an(struct - regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); - val &= ~SGMII_PHYA_PWD; - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -- -- return 0; -- - } - - /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a - * fixed speed. - */ --static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, -- phy_interface_t interface) -+static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, -+ phy_interface_t interface) - { - unsigned int val; - -@@ -73,8 +70,6 @@ static int mtk_pcs_setup_mode_force(stru - regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); - val &= ~SGMII_PHYA_PWD; - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -- -- return 0; - } - - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -@@ -83,15 +78,14 @@ static int mtk_pcs_config(struct phylink - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- int err = 0; - - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) -- err = mtk_pcs_setup_mode_force(mpcs, interface); -+ mtk_pcs_setup_mode_force(mpcs, interface); - else if (phylink_autoneg_inband(mode)) -- err = mtk_pcs_setup_mode_an(mpcs); -+ mtk_pcs_setup_mode_an(mpcs); - -- return err; -+ return 0; - } - - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch b/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch deleted file mode 100644 index 64a4a72fa6..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch +++ /dev/null @@ -1,46 +0,0 @@ -From c000dca098002da193b98099df051c9ead0cacb4 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:52 +0100 -Subject: [PATCH 03/10] net: mtk_eth_soc: add pcs_get_state() implementation - -Add a pcs_get_state() implementation which uses the advertisements -to compute the resulting link modes, and BMSR contents to determine -negotiation and link status. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -19,6 +19,20 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st - return container_of(pcs, struct mtk_pcs, pcs); - } - -+static void mtk_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ unsigned int bm, adv; -+ -+ /* Read the BMSR and LPA */ -+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); -+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); -+ -+ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), -+ FIELD_GET(SGMII_LPA, adv)); -+} -+ - /* For SGMII interface mode */ - static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { -@@ -117,6 +131,7 @@ static void mtk_pcs_link_up(struct phyli - } - - static const struct phylink_pcs_ops mtk_pcs_ops = { -+ .pcs_get_state = mtk_pcs_get_state, - .pcs_config = mtk_pcs_config, - .pcs_an_restart = mtk_pcs_restart_an, - .pcs_link_up = mtk_pcs_link_up, diff --git a/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch b/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch deleted file mode 100644 index 24610fe11e..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0d2351dc2768061689abd4de1529fa206bbd574e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:58 +0100 -Subject: [PATCH 04/10] net: mtk_eth_soc: convert mtk_sgmii to use - regmap_update_bits() - -mtk_sgmii does a lot of read-modify-write operations, for which there -is a specific regmap function. Use this function instead of open-coding -the operations. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 61 ++++++++++------------- - 1 file changed, 26 insertions(+), 35 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -36,23 +36,18 @@ static void mtk_pcs_get_state(struct phy - /* For SGMII interface mode */ - static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { -- unsigned int val; -- - /* Setup the link timer and QPHY power up inside SGMIISYS */ - regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, - SGMII_LINK_TIMER_DEFAULT); - -- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); -- val |= SGMII_REMOTE_FAULT_DIS; -- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); -- -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); -- val |= SGMII_AN_RESTART; -- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); -- -- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); -- val &= ~SGMII_PHYA_PWD; -- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); -+ -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_RESTART, SGMII_AN_RESTART); -+ -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, 0); - } - - /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a -@@ -61,29 +56,26 @@ static void mtk_pcs_setup_mode_an(struct - static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, - phy_interface_t interface) - { -- unsigned int val; -+ unsigned int rgc3; - -- regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); -- val &= ~RG_PHY_SPEED_MASK; - if (interface == PHY_INTERFACE_MODE_2500BASEX) -- val |= RG_PHY_SPEED_3_125G; -- regmap_write(mpcs->regmap, mpcs->ana_rgc3, val); -+ rgc3 = RG_PHY_SPEED_3_125G; -+ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ RG_PHY_SPEED_3_125G, rgc3); - - /* Disable SGMII AN */ -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); -- val &= ~SGMII_AN_ENABLE; -- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_ENABLE, 0); - - /* Set the speed etc but leave the duplex unchanged */ -- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); -- val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK; -- val |= SGMII_SPEED_1000; -- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, -+ SGMII_SPEED_1000); - - /* Release PHYA power down state */ -- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); -- val &= ~SGMII_PHYA_PWD; -- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, 0); - } - - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -@@ -105,29 +97,28 @@ static int mtk_pcs_config(struct phylink - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int val; - -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); -- val |= SGMII_AN_RESTART; -- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_RESTART, SGMII_AN_RESTART); - } - - static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, int speed, int duplex) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int val; -+ unsigned int sgm_mode; - - if (!phy_interface_mode_is_8023z(interface)) - return; - - /* SGMII force duplex setting */ -- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); -- val &= ~SGMII_DUPLEX_FULL; - if (duplex == DUPLEX_FULL) -- val |= SGMII_DUPLEX_FULL; -+ sgm_mode = SGMII_DUPLEX_FULL; -+ else -+ sgm_mode = 0; - -- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_DUPLEX_FULL, sgm_mode); - } - - static const struct phylink_pcs_ops mtk_pcs_ops = { diff --git a/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch b/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch deleted file mode 100644 index ba76ca40ff..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 12198c3a410fe69843e335c1bbf6d4c2a4d48e4e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:03 +0100 -Subject: [PATCH 05/10] net: mtk_eth_soc: add out of band forcing of speed and - duplex in pcs_link_up - -Add support for forcing the link speed and duplex setting in the -pcs_link_up() method for out of band modes, which will be useful when -we finish converting the pcs_config() method. Until then, we still have -to force duplex for 802.3z modes to work correctly. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 28 ++++++++++++++--------- - 1 file changed, 17 insertions(+), 11 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -108,17 +108,23 @@ static void mtk_pcs_link_up(struct phyli - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int sgm_mode; - -- if (!phy_interface_mode_is_8023z(interface)) -- return; -+ if (!phylink_autoneg_inband(mode) || -+ phy_interface_mode_is_8023z(interface)) { -+ /* Force the speed and duplex setting */ -+ if (speed == SPEED_10) -+ sgm_mode = SGMII_SPEED_10; -+ else if (speed == SPEED_100) -+ sgm_mode = SGMII_SPEED_100; -+ else -+ sgm_mode = SGMII_SPEED_1000; - -- /* SGMII force duplex setting */ -- if (duplex == DUPLEX_FULL) -- sgm_mode = SGMII_DUPLEX_FULL; -- else -- sgm_mode = 0; -+ if (duplex == DUPLEX_FULL) -+ sgm_mode |= SGMII_DUPLEX_FULL; - -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_DUPLEX_FULL, sgm_mode); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_DUPLEX_FULL | SGMII_SPEED_MASK, -+ sgm_mode); -+ } - } - - static const struct phylink_pcs_ops mtk_pcs_ops = { diff --git a/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch b/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch deleted file mode 100644 index b76e159275..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 6f38fffe2179dd29612aea2c67c46ed6682b4e46 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:08 +0100 -Subject: [PATCH 06/10] net: mtk_eth_soc: move PHY power up - -The PHY power up is common to both configuration paths, so move it into -the parent function. We need to do this for all serdes modes. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -45,9 +45,6 @@ static void mtk_pcs_setup_mode_an(struct - - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, - SGMII_AN_RESTART, SGMII_AN_RESTART); -- -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, 0); - } - - /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a -@@ -72,10 +69,6 @@ static void mtk_pcs_setup_mode_force(str - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, - SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, - SGMII_SPEED_1000); -- -- /* Release PHYA power down state */ -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, 0); - } - - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -@@ -91,6 +84,10 @@ static int mtk_pcs_config(struct phylink - else if (phylink_autoneg_inband(mode)) - mtk_pcs_setup_mode_an(mpcs); - -+ /* Release PHYA power down state */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, 0); -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch b/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch deleted file mode 100644 index cd9f0699b3..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch +++ /dev/null @@ -1,48 +0,0 @@ -From f752c0df13dfeb721c11d3debb79f08cf437344f Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:13 +0100 -Subject: [PATCH 07/10] net: mtk_eth_soc: move interface speed selection - -Move the selection of the underlying interface speed to the pcs_config -function, so we always program the interface speed. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++++++-------- - 1 file changed, 10 insertions(+), 8 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -53,14 +53,6 @@ static void mtk_pcs_setup_mode_an(struct - static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, - phy_interface_t interface) - { -- unsigned int rgc3; -- -- if (interface == PHY_INTERFACE_MODE_2500BASEX) -- rgc3 = RG_PHY_SPEED_3_125G; -- -- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -- RG_PHY_SPEED_3_125G, rgc3); -- - /* Disable SGMII AN */ - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, - SGMII_AN_ENABLE, 0); -@@ -77,6 +69,16 @@ static int mtk_pcs_config(struct phylink - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ unsigned int rgc3; -+ -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) -+ rgc3 = RG_PHY_SPEED_3_125G; -+ else -+ rgc3 = 0; -+ -+ /* Configure the underlying interface speed */ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ RG_PHY_SPEED_3_125G, rgc3); - - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) diff --git a/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch b/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch deleted file mode 100644 index f08358e963..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch +++ /dev/null @@ -1,52 +0,0 @@ -From c125c66ea71b9377ae2478c4f1b87b180cc5c6ef Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:18 +0100 -Subject: [PATCH 08/10] net: mtk_eth_soc: add advertisement programming - -Program the advertisement into the mtk PCS block. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -70,16 +70,27 @@ static int mtk_pcs_config(struct phylink - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int rgc3; -+ int advertise; -+ bool changed; - - if (interface == PHY_INTERFACE_MODE_2500BASEX) - rgc3 = RG_PHY_SPEED_3_125G; - else - rgc3 = 0; - -+ advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -+ advertising); -+ if (advertise < 0) -+ return advertise; -+ - /* Configure the underlying interface speed */ - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); - -+ /* Update the advertisement, noting whether it has changed */ -+ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -+ SGMII_ADVERTISE, advertise, &changed); -+ - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) - mtk_pcs_setup_mode_force(mpcs, interface); -@@ -90,7 +101,7 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, 0); - -- return 0; -+ return changed; - } - - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch b/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch deleted file mode 100644 index 602d52c6f4..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 3027d89f87707e7f3e5b683e0d37a32afb5bde96 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:23 +0100 -Subject: [PATCH 09/10] net: mtk_eth_soc: move and correct link timer - programming - -Program the link timer appropriately for the interface mode being -used, using the newly introduced phylink helper that provides the -nanosecond link timer interval. - -The intervals are 1.6ms for SGMII based protocols and 10ms for -802.3z based protocols. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -36,10 +36,6 @@ static void mtk_pcs_get_state(struct phy - /* For SGMII interface mode */ - static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { -- /* Setup the link timer and QPHY power up inside SGMIISYS */ -- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, -- SGMII_LINK_TIMER_DEFAULT); -- - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, - SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); - -@@ -69,8 +65,8 @@ static int mtk_pcs_config(struct phylink - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ int advertise, link_timer; - unsigned int rgc3; -- int advertise; - bool changed; - - if (interface == PHY_INTERFACE_MODE_2500BASEX) -@@ -83,6 +79,10 @@ static int mtk_pcs_config(struct phylink - if (advertise < 0) - return advertise; - -+ link_timer = phylink_get_link_timer_ns(interface); -+ if (link_timer < 0) -+ return link_timer; -+ - /* Configure the underlying interface speed */ - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); -@@ -91,6 +91,9 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, - SGMII_ADVERTISE, advertise, &changed); - -+ /* Setup the link timer and QPHY power up inside SGMIISYS */ -+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -+ - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) - mtk_pcs_setup_mode_force(mpcs, interface); diff --git a/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch b/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch deleted file mode 100644 index 0e9a0535a7..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 81b0f12a2a8a1699a7d49c3995e5f71e4ec018e6 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:28 +0100 -Subject: [PATCH 10/10] net: mtk_eth_soc: add support for in-band 802.3z - negotiation - -As a result of help from Frank Wunderlich to investigate and test, we -now know how to program this PCS for in-band 802.3z negotiation. Add -support for this by moving the contents of the two functions into the -common mtk_pcs_config() function and adding the register settings for -802.3z negotiation. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 77 ++++++++++++----------- - 1 file changed, 42 insertions(+), 35 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -33,41 +33,15 @@ static void mtk_pcs_get_state(struct phy - FIELD_GET(SGMII_LPA, adv)); - } - --/* For SGMII interface mode */ --static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) --{ -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); -- -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_RESTART, SGMII_AN_RESTART); --} -- --/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a -- * fixed speed. -- */ --static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, -- phy_interface_t interface) --{ -- /* Disable SGMII AN */ -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_ENABLE, 0); -- -- /* Set the speed etc but leave the duplex unchanged */ -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, -- SGMII_SPEED_1000); --} -- - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ unsigned int rgc3, sgm_mode, bmcr; - int advertise, link_timer; -- unsigned int rgc3; -- bool changed; -+ bool changed, use_an; - - if (interface == PHY_INTERFACE_MODE_2500BASEX) - rgc3 = RG_PHY_SPEED_3_125G; -@@ -83,6 +57,37 @@ static int mtk_pcs_config(struct phylink - if (link_timer < 0) - return link_timer; - -+ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and -+ * we assume that fixes it's speed at bitrate = line rate (in -+ * other words, 1000Mbps or 2500Mbps). -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII) { -+ sgm_mode = SGMII_IF_MODE_SGMII; -+ if (phylink_autoneg_inband(mode)) { -+ sgm_mode |= SGMII_REMOTE_FAULT_DIS | -+ SGMII_SPEED_DUPLEX_AN; -+ use_an = true; -+ } else { -+ use_an = false; -+ } -+ } else if (phylink_autoneg_inband(mode)) { -+ /* 1000base-X or 2500base-X autoneg */ -+ sgm_mode = SGMII_REMOTE_FAULT_DIS; -+ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ advertising); -+ } else { -+ /* 1000base-X or 2500base-X without autoneg */ -+ sgm_mode = 0; -+ use_an = false; -+ } -+ -+ if (use_an) { -+ /* FIXME: Do we need to set AN_RESTART here? */ -+ bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE; -+ } else { -+ bmcr = 0; -+ } -+ - /* Configure the underlying interface speed */ - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); -@@ -94,11 +99,14 @@ static int mtk_pcs_config(struct phylink - /* Setup the link timer and QPHY power up inside SGMIISYS */ - regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); - -- /* Setup SGMIISYS with the determined property */ -- if (interface != PHY_INTERFACE_MODE_SGMII) -- mtk_pcs_setup_mode_force(mpcs, interface); -- else if (phylink_autoneg_inband(mode)) -- mtk_pcs_setup_mode_an(mpcs); -+ /* Update the sgmsys mode register */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -+ SGMII_IF_MODE_SGMII, sgm_mode); -+ -+ /* Update the BMCR */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); - - /* Release PHYA power down state */ - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -@@ -121,8 +129,7 @@ static void mtk_pcs_link_up(struct phyli - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int sgm_mode; - -- if (!phylink_autoneg_inband(mode) || -- phy_interface_mode_is_8023z(interface)) { -+ if (!phylink_autoneg_inband(mode)) { - /* Force the speed and duplex setting */ - if (speed == SPEED_10) - sgm_mode = SGMII_SPEED_10; diff --git a/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch b/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch deleted file mode 100644 index a02c583deb..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 7ff82416de8295c61423ef6fd75f052d3837d2f7 Mon Sep 17 00:00:00 2001 -From: Alexander Couzens -Date: Wed, 1 Feb 2023 19:23:29 +0100 -Subject: [PATCH 11/13] net: mediatek: sgmii: ensure the SGMII PHY is powered - down on configuration -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The code expect the PHY to be in power down which is only true after reset. -Allow changes of the SGMII parameters more than once. - -Only power down when reconfiguring to avoid bouncing the link when there's -no reason to - based on code from Russell King. - -There are cases when the SGMII_PHYA_PWD register contains 0x9 which -prevents SGMII from working. The SGMII still shows link but no traffic -can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -taken from a good working state of the SGMII interface. - -Fixes: 42c03844e93d ("net-next: mediatek: add support for MediaTek MT7622 SoC") -Suggested-by: Russell King (Oracle) -Signed-off-by: Alexander Couzens -[ bmork: rebased and squashed into one patch ] -Reviewed-by: Russell King (Oracle) -Signed-off-by: Bjørn Mork -Acked-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++ - drivers/net/ethernet/mediatek/mtk_sgmii.c | 39 +++++++++++++++------ - 2 files changed, 30 insertions(+), 11 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1067,11 +1067,13 @@ struct mtk_soc_data { - * @regmap: The register map pointing at the range used to setup - * SGMII modes - * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap -+ * @interface: Currently configured interface mode - * @pcs: Phylink PCS structure - */ - struct mtk_pcs { - struct regmap *regmap; - u32 ana_rgc3; -+ phy_interface_t interface; - struct phylink_pcs pcs; - }; - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink - int advertise, link_timer; - bool changed, use_an; - -- if (interface == PHY_INTERFACE_MODE_2500BASEX) -- rgc3 = RG_PHY_SPEED_3_125G; -- else -- rgc3 = 0; -- - advertise = phylink_mii_c22_pcs_encode_advertisement(interface, - advertising); - if (advertise < 0) -@@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink - bmcr = 0; - } - -- /* Configure the underlying interface speed */ -- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -- RG_PHY_SPEED_3_125G, rgc3); -+ if (mpcs->interface != interface) { -+ /* PHYA power down */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, SGMII_PHYA_PWD); -+ -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) -+ rgc3 = RG_PHY_SPEED_3_125G; -+ else -+ rgc3 = 0; -+ -+ /* Configure the underlying interface speed */ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ RG_PHY_SPEED_3_125G, rgc3); -+ -+ mpcs->interface = interface; -+ } - - /* Update the advertisement, noting whether it has changed */ - regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -@@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, - SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); - -- /* Release PHYA power down state */ -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, 0); -+ /* Release PHYA power down state -+ * Only removing bit SGMII_PHYA_PWD isn't enough. -+ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which -+ * prevents SGMII from working. The SGMII still shows link but no traffic -+ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -+ * taken from a good working state of the SGMII interface. -+ * Unknown how much the QPHY needs but it is racy without a sleep. -+ * Tested on mt7622 & mt7986. -+ */ -+ usleep_range(50, 100); -+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); - - return changed; - } -@@ -171,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, - return PTR_ERR(ss->pcs[i].regmap); - - ss->pcs[i].pcs.ops = &mtk_pcs_ops; -+ ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; - } - - return 0; diff --git a/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch b/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch deleted file mode 100644 index a06298c0a9..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 9d32637122de88f1ef614c29703f0e050cad342e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= -Date: Wed, 1 Feb 2023 19:23:30 +0100 -Subject: [PATCH 12/13] net: mediatek: sgmii: fix duplex configuration -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The logic of the duplex bit is inverted. Setting it means half -duplex, not full duplex. - -Fix and rename macro to avoid confusion. - -Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") -Reviewed-by: Russell King (Oracle) -Signed-off-by: Bjørn Mork -Acked-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 6 +++--- - 2 files changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -534,7 +534,7 @@ - #define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) - #define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) - #define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) --#define SGMII_DUPLEX_FULL BIT(4) -+#define SGMII_DUPLEX_HALF BIT(4) - #define SGMII_IF_MODE_BIT5 BIT(5) - #define SGMII_REMOTE_FAULT_DIS BIT(8) - #define SGMII_CODE_SYNC_SET_VAL BIT(9) ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -154,11 +154,11 @@ static void mtk_pcs_link_up(struct phyli - else - sgm_mode = SGMII_SPEED_1000; - -- if (duplex == DUPLEX_FULL) -- sgm_mode |= SGMII_DUPLEX_FULL; -+ if (duplex != DUPLEX_FULL) -+ sgm_mode |= SGMII_DUPLEX_HALF; - - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_DUPLEX_FULL | SGMII_SPEED_MASK, -+ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, - sgm_mode); - } - } diff --git a/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch b/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch deleted file mode 100644 index 56d7a1348f..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 3337a6e04ddf2923a1bdcf3d31b3b52412bf82dd Mon Sep 17 00:00:00 2001 -From: Alexander Couzens -Date: Wed, 1 Feb 2023 19:23:31 +0100 -Subject: [PATCH 13/13] mtk_sgmii: enable PCS polling to allow SFP work -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Currently there is no IRQ handling (even the SGMII supports it). -Enable polling to support SFP ports. - -Fixes: 14a44ab0330d ("net: mtk_eth_soc: partially convert to phylink_pcs") -Reviewed-by: Russell King (Oracle) -Signed-off-by: Alexander Couzens -[ bmork: changed "1" => "true" ] -Signed-off-by: Bjørn Mork -Acked-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -187,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, - return PTR_ERR(ss->pcs[i].regmap); - - ss->pcs[i].pcs.ops = &mtk_pcs_ops; -+ ss->pcs[i].pcs.poll = true; - ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; - } - diff --git a/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch b/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch deleted file mode 100644 index 6acc62d4ab..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 611e2dabb4b3243d176739fd6a5a34d007fa3f86 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 14 Mar 2023 00:34:26 +0000 -Subject: [PATCH 1/2] net: ethernet: mtk_eth_soc: reset PCS state -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reset the internal PCS state machine when changing interface mode. -This prevents confusing the state machine when changing interface -modes, e.g. from SGMII to 2500Base-X or vice-versa. - -Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") -Reviewed-by: Russell King (Oracle) -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++ - drivers/net/ethernet/mediatek/mtk_sgmii.c | 4 ++++ - 2 files changed, 8 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -542,6 +542,10 @@ - #define SGMII_SEND_AN_ERROR_EN BIT(11) - #define SGMII_IF_MODE_MASK GENMASK(5, 1) - -+/* Register to reset SGMII design */ -+#define SGMII_RESERVED_0 0x34 -+#define SGMII_SW_RESET BIT(0) -+ - /* Register to set SGMII speed, ANA RG_ Control Signals III*/ - #define SGMSYS_ANA_RG_CS3 0x2028 - #define RG_PHY_SPEED_MASK (BIT(2) | BIT(3)) ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -88,6 +88,10 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, SGMII_PHYA_PWD); - -+ /* Reset SGMII PCS state */ -+ regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, -+ SGMII_SW_RESET, SGMII_SW_RESET); -+ - if (interface == PHY_INTERFACE_MODE_2500BASEX) - rgc3 = RG_PHY_SPEED_3_125G; - else diff --git a/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch b/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch deleted file mode 100644 index 0fabeea20c..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 6e933a804c7db8be64f367f33e63cd7dcc302ebb Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 14 Mar 2023 00:34:45 +0000 -Subject: [PATCH 2/2] net: ethernet: mtk_eth_soc: only write values if needed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Only restart auto-negotiation and write link timer if actually -necessary. This prevents losing the link in case of minor -changes. - -Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") -Reviewed-by: Russell King (Oracle) -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 24 +++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -38,20 +38,16 @@ static int mtk_pcs_config(struct phylink - const unsigned long *advertising, - bool permit_pause_to_mac) - { -+ bool mode_changed = false, changed, use_an; - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int rgc3, sgm_mode, bmcr; - int advertise, link_timer; -- bool changed, use_an; - - advertise = phylink_mii_c22_pcs_encode_advertisement(interface, - advertising); - if (advertise < 0) - return advertise; - -- link_timer = phylink_get_link_timer_ns(interface); -- if (link_timer < 0) -- return link_timer; -- - /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and - * we assume that fixes it's speed at bitrate = line rate (in - * other words, 1000Mbps or 2500Mbps). -@@ -77,13 +73,16 @@ static int mtk_pcs_config(struct phylink - } - - if (use_an) { -- /* FIXME: Do we need to set AN_RESTART here? */ -- bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE; -+ bmcr = SGMII_AN_ENABLE; - } else { - bmcr = 0; - } - - if (mpcs->interface != interface) { -+ link_timer = phylink_get_link_timer_ns(interface); -+ if (link_timer < 0) -+ return link_timer; -+ - /* PHYA power down */ - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, SGMII_PHYA_PWD); -@@ -101,16 +100,17 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); - -+ /* Setup the link timer */ -+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -+ - mpcs->interface = interface; -+ mode_changed = true; - } - - /* Update the advertisement, noting whether it has changed */ - regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, - SGMII_ADVERTISE, advertise, &changed); - -- /* Setup the link timer and QPHY power up inside SGMIISYS */ -- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -- - /* Update the sgmsys mode register */ - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, - SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -@@ -118,7 +118,7 @@ static int mtk_pcs_config(struct phylink - - /* Update the BMCR */ - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); -+ SGMII_AN_ENABLE, bmcr); - - /* Release PHYA power down state - * Only removing bit SGMII_PHYA_PWD isn't enough. -@@ -132,7 +132,7 @@ static int mtk_pcs_config(struct phylink - usleep_range(50, 100); - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); - -- return changed; -+ return changed || mode_changed; - } - - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch b/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch deleted file mode 100644 index a1247218b0..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch +++ /dev/null @@ -1,206 +0,0 @@ -From f5d43ddd334b7c32fcaed9ba46afbd85cb467f1f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:56:28 +0000 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for MT7981 SoC - -The MediaTek MT7981 SoC comes with two 1G/2.5G SGMII ports, just like -MT7986. - -In addition MT7981 is equipped with a built-in 1000Base-T PHY which can -be used with GMAC1. - -As many MT7981 boards make use of inverting SGMII signal polarity, add -new device-tree attribute 'mediatek,pn_swap' to support them. - -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_path.c | 14 +++++++-- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 31 ++++++++++++++++++++ - drivers/net/ethernet/mediatek/mtk_sgmii.c | 10 +++++++ - 4 files changed, 73 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_path.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c -@@ -96,12 +96,20 @@ static int set_mux_gmac2_gmac0_to_gephy( - - static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) - { -- unsigned int val = 0; -+ unsigned int val = 0, mask = 0, reg = 0; - bool updated = true; - - switch (path) { - case MTK_ETH_PATH_GMAC2_SGMII: -- val = CO_QPHY_SEL; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) { -+ reg = USB_PHY_SWITCH_REG; -+ val = SGMII_QPHY_SEL; -+ mask = QPHY_SEL_MASK; -+ } else { -+ reg = INFRA_MISC2; -+ val = CO_QPHY_SEL; -+ mask = val; -+ } - break; - default: - updated = false; -@@ -109,7 +117,7 @@ static int set_mux_u3_gmac2_to_qphy(stru - } - - if (updated) -- regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val); -+ regmap_update_bits(eth->infra, reg, mask, val); - - dev_dbg(eth->dev, "path %s in %s updated = %d\n", - mtk_eth_path_name(path), __func__, updated); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4803,6 +4803,26 @@ static const struct mtk_soc_data mt7629_ - }, - }; - -+static const struct mtk_soc_data mt7981_data = { -+ .reg_map = &mt7986_reg_map, -+ .ana_rgc3 = 0x128, -+ .caps = MT7981_CAPS, -+ .hw_features = MTK_HW_FEATURES, -+ .required_clks = MT7981_CLKS_BITMAP, -+ .required_pctl = false, -+ .offload_version = 2, -+ .hash_offset = 4, -+ .foe_entry_size = sizeof(struct mtk_foe_entry), -+ .txrx = { -+ .txd_size = sizeof(struct mtk_tx_dma_v2), -+ .rxd_size = sizeof(struct mtk_rx_dma_v2), -+ .rx_irq_done_mask = MTK_RX_DONE_INT_V2, -+ .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, -+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, -+ .dma_len_offset = 8, -+ }, -+}; -+ - static const struct mtk_soc_data mt7986_data = { - .reg_map = &mt7986_reg_map, - .ana_rgc3 = 0x128, -@@ -4845,6 +4865,7 @@ const struct of_device_id of_mtk_match[] - { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, - { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, - { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data}, -+ { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data}, - { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data}, - { .compatible = "ralink,rt5350-eth", .data = &rt5350_data}, - {}, ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -556,11 +556,22 @@ - #define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 - #define SGMII_PHYA_PWD BIT(4) - -+/* Register to QPHY wrapper control */ -+#define SGMSYS_QPHY_WRAP_CTRL 0xec -+#define SGMII_PN_SWAP_MASK GENMASK(1, 0) -+#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) -+#define MTK_SGMII_FLAG_PN_SWAP BIT(0) -+ - /* Infrasys subsystem config registers */ - #define INFRA_MISC2 0x70c - #define CO_QPHY_SEL BIT(0) - #define GEPHY_MAC_SEL BIT(1) - -+/* Top misc registers */ -+#define USB_PHY_SWITCH_REG 0x218 -+#define QPHY_SEL_MASK GENMASK(1, 0) -+#define SGMII_QPHY_SEL 0x2 -+ - /* MT7628/88 specific stuff */ - #define MT7628_PDMA_OFFSET 0x0800 - #define MT7628_SDM_OFFSET 0x0c00 -@@ -741,6 +752,17 @@ enum mtk_clks_map { - BIT(MTK_CLK_SGMII2_CDR_FB) | \ - BIT(MTK_CLK_SGMII_CK) | \ - BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP)) -+#define MT7981_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ -+ BIT(MTK_CLK_WOCPU0) | \ -+ BIT(MTK_CLK_SGMII_TX_250M) | \ -+ BIT(MTK_CLK_SGMII_RX_250M) | \ -+ BIT(MTK_CLK_SGMII_CDR_REF) | \ -+ BIT(MTK_CLK_SGMII_CDR_FB) | \ -+ BIT(MTK_CLK_SGMII2_TX_250M) | \ -+ BIT(MTK_CLK_SGMII2_RX_250M) | \ -+ BIT(MTK_CLK_SGMII2_CDR_REF) | \ -+ BIT(MTK_CLK_SGMII2_CDR_FB) | \ -+ BIT(MTK_CLK_SGMII_CK)) - #define MT7986_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ - BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \ - BIT(MTK_CLK_SGMII_TX_250M) | \ -@@ -854,6 +876,7 @@ enum mkt_eth_capabilities { - MTK_NETSYS_V2_BIT, - MTK_SOC_MT7628_BIT, - MTK_RSTCTRL_PPE1_BIT, -+ MTK_U3_COPHY_V2_BIT, - - /* MUX BITS*/ - MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, -@@ -888,6 +911,7 @@ enum mkt_eth_capabilities { - #define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT) - #define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) - #define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) -+#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ - BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) -@@ -960,6 +984,11 @@ enum mkt_eth_capabilities { - MTK_MUX_U3_GMAC2_TO_QPHY | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA) - -+#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ -+ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ -+ MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ -+ MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) -+ - #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) -@@ -1073,12 +1102,14 @@ struct mtk_soc_data { - * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap - * @interface: Currently configured interface mode - * @pcs: Phylink PCS structure -+ * @flags: Flags indicating hardware properties - */ - struct mtk_pcs { - struct regmap *regmap; - u32 ana_rgc3; - phy_interface_t interface; - struct phylink_pcs pcs; -+ u32 flags; - }; - - /* struct mtk_sgmii - This is the structure holding sgmii regmap and its ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -87,6 +87,11 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, SGMII_PHYA_PWD); - -+ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, -+ SGMII_PN_SWAP_MASK, -+ SGMII_PN_SWAP_TX_RX); -+ - /* Reset SGMII PCS state */ - regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, - SGMII_SW_RESET, SGMII_SW_RESET); -@@ -186,6 +191,11 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, - - ss->pcs[i].ana_rgc3 = ana_rgc3; - ss->pcs[i].regmap = syscon_node_to_regmap(np); -+ -+ ss->pcs[i].flags = 0; -+ if (of_property_read_bool(np, "mediatek,pnswap")) -+ ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP; -+ - of_node_put(np); - if (IS_ERR(ss->pcs[i].regmap)) - return PTR_ERR(ss->pcs[i].regmap); diff --git a/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch b/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch deleted file mode 100644 index 1cb1f40538..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch +++ /dev/null @@ -1,76 +0,0 @@ -From c0a440031d4314d1023c1b87f43a4233634eebdb Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:57:15 +0000 -Subject: [PATCH] net: ethernet: mtk_eth_soc: set MDIO bus clock frequency -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Set MDIO bus clock frequency and allow setting a custom maximum -frequency from device tree. - -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++++ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 +++++++ - 2 files changed, 28 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -744,8 +744,10 @@ static const struct phylink_mac_ops mtk_ - - static int mtk_mdio_init(struct mtk_eth *eth) - { -+ unsigned int max_clk = 2500000, divider; - struct device_node *mii_np; - int ret; -+ u32 val; - - mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus"); - if (!mii_np) { -@@ -772,6 +774,25 @@ static int mtk_mdio_init(struct mtk_eth - eth->mii_bus->parent = eth->dev; - - snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np); -+ -+ if (!of_property_read_u32(mii_np, "clock-frequency", &val)) { -+ if (val > MDC_MAX_FREQ || val < MDC_MAX_FREQ / MDC_MAX_DIVIDER) { -+ dev_err(eth->dev, "MDIO clock frequency out of range"); -+ ret = -EINVAL; -+ goto err_put_node; -+ } -+ max_clk = val; -+ } -+ divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63); -+ -+ /* Configure MDC Divider */ -+ val = mtk_r32(eth, MTK_PPSC); -+ val &= ~PPSC_MDC_CFG; -+ val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; -+ mtk_w32(eth, val, MTK_PPSC); -+ -+ dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); -+ - ret = of_mdiobus_register(eth->mii_bus, mii_np); - - err_put_node: ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -363,6 +363,13 @@ - #define RX_DMA_VTAG_V2 BIT(0) - #define RX_DMA_L4_VALID_V2 BIT(2) - -+/* PHY Polling and SMI Master Control registers */ -+#define MTK_PPSC 0x10000 -+#define PPSC_MDC_CFG GENMASK(29, 24) -+#define PPSC_MDC_TURBO BIT(20) -+#define MDC_MAX_FREQ 25000000 -+#define MDC_MAX_DIVIDER 63 -+ - /* PHY Indirect Access Control registers */ - #define MTK_PHY_IAC 0x10004 - #define PHY_IAC_ACCESS BIT(31) diff --git a/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch b/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch deleted file mode 100644 index 110944658d..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch +++ /dev/null @@ -1,512 +0,0 @@ -From 2a3ec7ae313310c1092e4256208cc04d1958e469 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:58:02 +0000 -Subject: [PATCH] net: ethernet: mtk_eth_soc: switch to external PCS driver - -Now that we got a PCS driver, use it and remove the now redundant -PCS code and it's header macros from the Ethernet driver. - -Signed-off-by: Daniel Golle -Tested-by: Frank Wunderlich -Reviewed-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/Kconfig | 2 + - drivers/net/ethernet/mediatek/Makefile | 2 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 61 +++++- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 93 +-------- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 217 -------------------- - 5 files changed, 56 insertions(+), 319 deletions(-) - delete mode 100644 drivers/net/ethernet/mediatek/mtk_sgmii.c - ---- a/drivers/net/ethernet/mediatek/Kconfig -+++ b/drivers/net/ethernet/mediatek/Kconfig -@@ -19,6 +19,8 @@ config NET_MEDIATEK_SOC - select DIMLIB - select PAGE_POOL - select PAGE_POOL_STATS -+ select PCS_MTK_LYNXI -+ select REGMAP_MMIO - help - This driver supports the gigabit ethernet MACs in the - MediaTek SoC family. ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -4,7 +4,7 @@ - # - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o --mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o -+mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o - mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o - ifdef CONFIG_DEBUG_FS - mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -400,7 +401,7 @@ static struct phylink_pcs *mtk_mac_selec - sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? - 0 : mac->id; - -- return mtk_sgmii_select_pcs(eth->sgmii, sid); -+ return eth->sgmii_pcs[sid]; - } - - return NULL; -@@ -4016,8 +4017,17 @@ static int mtk_unreg_dev(struct mtk_eth - return 0; - } - -+static void mtk_sgmii_destroy(struct mtk_eth *eth) -+{ -+ int i; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) -+ mtk_pcs_lynxi_destroy(eth->sgmii_pcs[i]); -+} -+ - static int mtk_cleanup(struct mtk_eth *eth) - { -+ mtk_sgmii_destroy(eth); - mtk_unreg_dev(eth); - mtk_free_dev(eth); - cancel_work_sync(ð->pending_work); -@@ -4457,6 +4467,36 @@ void mtk_eth_set_dma_device(struct mtk_e - rtnl_unlock(); - } - -+static int mtk_sgmii_init(struct mtk_eth *eth) -+{ -+ struct device_node *np; -+ struct regmap *regmap; -+ u32 flags; -+ int i; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ np = of_parse_phandle(eth->dev->of_node, "mediatek,sgmiisys", i); -+ if (!np) -+ break; -+ -+ regmap = syscon_node_to_regmap(np); -+ flags = 0; -+ if (of_property_read_bool(np, "mediatek,pnswap")) -+ flags |= MTK_SGMII_FLAG_PN_SWAP; -+ -+ of_node_put(np); -+ -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ eth->sgmii_pcs[i] = mtk_pcs_lynxi_create(eth->dev, regmap, -+ eth->soc->ana_rgc3, -+ flags); -+ } -+ -+ return 0; -+} -+ - static int mtk_probe(struct platform_device *pdev) - { - struct resource *res = NULL; -@@ -4520,13 +4560,7 @@ static int mtk_probe(struct platform_dev - } - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { -- eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii), -- GFP_KERNEL); -- if (!eth->sgmii) -- return -ENOMEM; -- -- err = mtk_sgmii_init(eth->sgmii, pdev->dev.of_node, -- eth->soc->ana_rgc3); -+ err = mtk_sgmii_init(eth); - - if (err) - return err; -@@ -4537,14 +4571,17 @@ static int mtk_probe(struct platform_dev - "mediatek,pctl"); - if (IS_ERR(eth->pctl)) { - dev_err(&pdev->dev, "no pctl regmap found\n"); -- return PTR_ERR(eth->pctl); -+ err = PTR_ERR(eth->pctl); -+ goto err_destroy_sgmii; - } - } - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!res) -- return -EINVAL; -+ if (!res) { -+ err = -EINVAL; -+ goto err_destroy_sgmii; -+ } - } - - if (eth->soc->offload_version) { -@@ -4703,6 +4740,8 @@ err_deinit_hw: - mtk_hw_deinit(eth); - err_wed_exit: - mtk_wed_exit(); -+err_destroy_sgmii: -+ mtk_sgmii_destroy(eth); - - return err; - } ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -510,65 +510,6 @@ - #define ETHSYS_DMA_AG_MAP_QDMA BIT(1) - #define ETHSYS_DMA_AG_MAP_PPE BIT(2) - --/* SGMII subsystem config registers */ --/* BMCR (low 16) BMSR (high 16) */ --#define SGMSYS_PCS_CONTROL_1 0x0 --#define SGMII_BMCR GENMASK(15, 0) --#define SGMII_BMSR GENMASK(31, 16) --#define SGMII_AN_RESTART BIT(9) --#define SGMII_ISOLATE BIT(10) --#define SGMII_AN_ENABLE BIT(12) --#define SGMII_LINK_STATYS BIT(18) --#define SGMII_AN_ABILITY BIT(19) --#define SGMII_AN_COMPLETE BIT(21) --#define SGMII_PCS_FAULT BIT(23) --#define SGMII_AN_EXPANSION_CLR BIT(30) -- --#define SGMSYS_PCS_ADVERTISE 0x8 --#define SGMII_ADVERTISE GENMASK(15, 0) --#define SGMII_LPA GENMASK(31, 16) -- --/* Register to programmable link timer, the unit in 2 * 8ns */ --#define SGMSYS_PCS_LINK_TIMER 0x18 --#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) --#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK) -- --/* Register to control remote fault */ --#define SGMSYS_SGMII_MODE 0x20 --#define SGMII_IF_MODE_SGMII BIT(0) --#define SGMII_SPEED_DUPLEX_AN BIT(1) --#define SGMII_SPEED_MASK GENMASK(3, 2) --#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) --#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) --#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) --#define SGMII_DUPLEX_HALF BIT(4) --#define SGMII_IF_MODE_BIT5 BIT(5) --#define SGMII_REMOTE_FAULT_DIS BIT(8) --#define SGMII_CODE_SYNC_SET_VAL BIT(9) --#define SGMII_CODE_SYNC_SET_EN BIT(10) --#define SGMII_SEND_AN_ERROR_EN BIT(11) --#define SGMII_IF_MODE_MASK GENMASK(5, 1) -- --/* Register to reset SGMII design */ --#define SGMII_RESERVED_0 0x34 --#define SGMII_SW_RESET BIT(0) -- --/* Register to set SGMII speed, ANA RG_ Control Signals III*/ --#define SGMSYS_ANA_RG_CS3 0x2028 --#define RG_PHY_SPEED_MASK (BIT(2) | BIT(3)) --#define RG_PHY_SPEED_1_25G 0x0 --#define RG_PHY_SPEED_3_125G BIT(2) -- --/* Register to power up QPHY */ --#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 --#define SGMII_PHYA_PWD BIT(4) -- --/* Register to QPHY wrapper control */ --#define SGMSYS_QPHY_WRAP_CTRL 0xec --#define SGMII_PN_SWAP_MASK GENMASK(1, 0) --#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) --#define MTK_SGMII_FLAG_PN_SWAP BIT(0) -- - /* Infrasys subsystem config registers */ - #define INFRA_MISC2 0x70c - #define CO_QPHY_SEL BIT(0) -@@ -1102,31 +1043,6 @@ struct mtk_soc_data { - /* currently no SoC has more than 2 macs */ - #define MTK_MAX_DEVS 2 - --/* struct mtk_pcs - This structure holds each sgmii regmap and associated -- * data -- * @regmap: The register map pointing at the range used to setup -- * SGMII modes -- * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap -- * @interface: Currently configured interface mode -- * @pcs: Phylink PCS structure -- * @flags: Flags indicating hardware properties -- */ --struct mtk_pcs { -- struct regmap *regmap; -- u32 ana_rgc3; -- phy_interface_t interface; -- struct phylink_pcs pcs; -- u32 flags; --}; -- --/* struct mtk_sgmii - This is the structure holding sgmii regmap and its -- * characteristics -- * @pcs Array of individual PCS structures -- */ --struct mtk_sgmii { -- struct mtk_pcs pcs[MTK_MAX_DEVS]; --}; -- - /* struct mtk_eth - This is the main datasructure for holding the state - * of the driver - * @dev: The device pointer -@@ -1146,6 +1062,7 @@ struct mtk_sgmii { - * MII modes - * @infra: The register map pointing at the range used to setup - * SGMII and GePHY path -+ * @sgmii_pcs: Pointers to mtk-pcs-lynxi phylink_pcs instances - * @pctl: The register map pointing at the range used to setup - * GMAC port drive/slew values - * @dma_refcnt: track how many netdevs are using the DMA engine -@@ -1186,8 +1103,8 @@ struct mtk_eth { - u32 msg_enable; - unsigned long sysclk; - struct regmap *ethsys; -- struct regmap *infra; -- struct mtk_sgmii *sgmii; -+ struct regmap *infra; -+ struct phylink_pcs *sgmii_pcs[MTK_MAX_DEVS]; - struct regmap *pctl; - bool hwlro; - refcount_t dma_refcnt; -@@ -1349,10 +1266,6 @@ void mtk_stats_update_mac(struct mtk_mac - void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); - u32 mtk_r32(struct mtk_eth *eth, unsigned reg); - --struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id); --int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np, -- u32 ana_rgc3); -- - int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); - int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); - int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id); ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ /dev/null -@@ -1,217 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --// Copyright (c) 2018-2019 MediaTek Inc. -- --/* A library for MediaTek SGMII circuit -- * -- * Author: Sean Wang -- * -- */ -- --#include --#include --#include --#include -- --#include "mtk_eth_soc.h" -- --static struct mtk_pcs *pcs_to_mtk_pcs(struct phylink_pcs *pcs) --{ -- return container_of(pcs, struct mtk_pcs, pcs); --} -- --static void mtk_pcs_get_state(struct phylink_pcs *pcs, -- struct phylink_link_state *state) --{ -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int bm, adv; -- -- /* Read the BMSR and LPA */ -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); -- regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); -- -- phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), -- FIELD_GET(SGMII_LPA, adv)); --} -- --static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -- phy_interface_t interface, -- const unsigned long *advertising, -- bool permit_pause_to_mac) --{ -- bool mode_changed = false, changed, use_an; -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int rgc3, sgm_mode, bmcr; -- int advertise, link_timer; -- -- advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -- advertising); -- if (advertise < 0) -- return advertise; -- -- /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and -- * we assume that fixes it's speed at bitrate = line rate (in -- * other words, 1000Mbps or 2500Mbps). -- */ -- if (interface == PHY_INTERFACE_MODE_SGMII) { -- sgm_mode = SGMII_IF_MODE_SGMII; -- if (phylink_autoneg_inband(mode)) { -- sgm_mode |= SGMII_REMOTE_FAULT_DIS | -- SGMII_SPEED_DUPLEX_AN; -- use_an = true; -- } else { -- use_an = false; -- } -- } else if (phylink_autoneg_inband(mode)) { -- /* 1000base-X or 2500base-X autoneg */ -- sgm_mode = SGMII_REMOTE_FAULT_DIS; -- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -- advertising); -- } else { -- /* 1000base-X or 2500base-X without autoneg */ -- sgm_mode = 0; -- use_an = false; -- } -- -- if (use_an) { -- bmcr = SGMII_AN_ENABLE; -- } else { -- bmcr = 0; -- } -- -- if (mpcs->interface != interface) { -- link_timer = phylink_get_link_timer_ns(interface); -- if (link_timer < 0) -- return link_timer; -- -- /* PHYA power down */ -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, SGMII_PHYA_PWD); -- -- if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, -- SGMII_PN_SWAP_MASK, -- SGMII_PN_SWAP_TX_RX); -- -- /* Reset SGMII PCS state */ -- regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, -- SGMII_SW_RESET, SGMII_SW_RESET); -- -- if (interface == PHY_INTERFACE_MODE_2500BASEX) -- rgc3 = RG_PHY_SPEED_3_125G; -- else -- rgc3 = 0; -- -- /* Configure the underlying interface speed */ -- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -- RG_PHY_SPEED_3_125G, rgc3); -- -- /* Setup the link timer */ -- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -- -- mpcs->interface = interface; -- mode_changed = true; -- } -- -- /* Update the advertisement, noting whether it has changed */ -- regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -- SGMII_ADVERTISE, advertise, &changed); -- -- /* Update the sgmsys mode register */ -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -- SGMII_IF_MODE_SGMII, sgm_mode); -- -- /* Update the BMCR */ -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_ENABLE, bmcr); -- -- /* Release PHYA power down state -- * Only removing bit SGMII_PHYA_PWD isn't enough. -- * There are cases when the SGMII_PHYA_PWD register contains 0x9 which -- * prevents SGMII from working. The SGMII still shows link but no traffic -- * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -- * taken from a good working state of the SGMII interface. -- * Unknown how much the QPHY needs but it is racy without a sleep. -- * Tested on mt7622 & mt7986. -- */ -- usleep_range(50, 100); -- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); -- -- return changed || mode_changed; --} -- --static void mtk_pcs_restart_an(struct phylink_pcs *pcs) --{ -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_RESTART, SGMII_AN_RESTART); --} -- --static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -- phy_interface_t interface, int speed, int duplex) --{ -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int sgm_mode; -- -- if (!phylink_autoneg_inband(mode)) { -- /* Force the speed and duplex setting */ -- if (speed == SPEED_10) -- sgm_mode = SGMII_SPEED_10; -- else if (speed == SPEED_100) -- sgm_mode = SGMII_SPEED_100; -- else -- sgm_mode = SGMII_SPEED_1000; -- -- if (duplex != DUPLEX_FULL) -- sgm_mode |= SGMII_DUPLEX_HALF; -- -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, -- sgm_mode); -- } --} -- --static const struct phylink_pcs_ops mtk_pcs_ops = { -- .pcs_get_state = mtk_pcs_get_state, -- .pcs_config = mtk_pcs_config, -- .pcs_an_restart = mtk_pcs_restart_an, -- .pcs_link_up = mtk_pcs_link_up, --}; -- --int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) --{ -- struct device_node *np; -- int i; -- -- for (i = 0; i < MTK_MAX_DEVS; i++) { -- np = of_parse_phandle(r, "mediatek,sgmiisys", i); -- if (!np) -- break; -- -- ss->pcs[i].ana_rgc3 = ana_rgc3; -- ss->pcs[i].regmap = syscon_node_to_regmap(np); -- -- ss->pcs[i].flags = 0; -- if (of_property_read_bool(np, "mediatek,pnswap")) -- ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP; -- -- of_node_put(np); -- if (IS_ERR(ss->pcs[i].regmap)) -- return PTR_ERR(ss->pcs[i].regmap); -- -- ss->pcs[i].pcs.ops = &mtk_pcs_ops; -- ss->pcs[i].pcs.poll = true; -- ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; -- } -- -- return 0; --} -- --struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id) --{ -- if (!ss->pcs[id].regmap) -- return NULL; -- -- return &ss->pcs[id].pcs; --} diff --git a/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch b/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch deleted file mode 100644 index 9ce2735951..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch +++ /dev/null @@ -1,46 +0,0 @@ -From f5af7931d2a2cae66d0f9dad4ba517b1b00620b3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 19 Apr 2023 19:07:23 +0100 -Subject: [PATCH] net: mtk_eth_soc: use WO firmware for MT7981 - -In order to support wireless offloading on MT7981 we need to load the -appropriate firmware. Recognize MT7981 and load mt7981_wo.bin. - -Signed-off-by: Daniel Golle ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 7 ++++++- - drivers/net/ethernet/mediatek/mtk_wed_wo.h | 1 + - 2 files changed, 7 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -326,7 +326,11 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - wo->hw->index + 1); - - /* load firmware */ -- fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; -+ if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed")) -+ fw_name = MT7981_FIRMWARE_WO; -+ else -+ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; -+ - ret = request_firmware(&fw, fw_name, wo->hw->dev); - if (ret) - return ret; -@@ -386,5 +390,6 @@ int mtk_wed_mcu_init(struct mtk_wed_wo * - 100, MTK_FW_DL_TIMEOUT); - } - -+MODULE_FIRMWARE(MT7981_FIRMWARE_WO); - MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); - MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -88,6 +88,7 @@ enum mtk_wed_dummy_cr_idx { - MTK_WED_DUMMY_CR_WO_STATUS, - }; - -+#define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin" - #define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" - #define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" - diff --git a/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch b/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch deleted file mode 100644 index d715c4aa68..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 7c83e28f10830aa5105c25eaabe890e3adac36aa Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 9 May 2023 03:20:06 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix NULL pointer dereference - -Check for NULL pointer to avoid kernel crashing in case of missing WO -firmware in case only a single WEDv2 device has been initialized, e.g. on -MT7981 which can connect just one wireless frontend. - -Fixes: 86ce0d09e424 ("net: ethernet: mtk_eth_soc: use WO firmware for MT7981") -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_wed.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -647,7 +647,7 @@ __mtk_wed_detach(struct mtk_wed_device * - BIT(hw->index), BIT(hw->index)); - } - -- if (!hw_list[!hw->index]->wed_dev && -+ if ((!hw_list[!hw->index] || !hw_list[!hw->index]->wed_dev) && - hw->eth->dma_dev != hw->eth->dev) - mtk_eth_set_dma_device(hw->eth, hw->eth->dev); - diff --git a/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch b/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch deleted file mode 100644 index 93eaffa19e..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch +++ /dev/null @@ -1,403 +0,0 @@ -From f601293f37c4be618c5efaef85d2ee21f97e82e0 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:57:35 +0000 -Subject: [PATCH 092/250] net: ethernet: mtk_eth_soc: ppe: add support for flow - accounting -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The PPE units found in MT7622 and newer support packet and byte -accounting of hw-offloaded flows. Add support for reading those counters -as found in MediaTek's SDK[1]. - -[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92 -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + - drivers/net/ethernet/mediatek/mtk_ppe.c | 114 +++++++++++++++++- - drivers/net/ethernet/mediatek/mtk_ppe.h | 25 +++- - .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 9 +- - .../net/ethernet/mediatek/mtk_ppe_offload.c | 8 ++ - drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 14 +++ - 7 files changed, 172 insertions(+), 9 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4691,8 +4691,8 @@ static int mtk_probe(struct platform_dev - for (i = 0; i < num_ppe; i++) { - u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; - -- eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, -- eth->soc->offload_version, i); -+ eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, i); -+ - if (!eth->ppe[i]) { - err = -ENOMEM; - goto err_deinit_ppe; -@@ -4816,6 +4816,7 @@ static const struct mtk_soc_data mt7622_ - .required_pctl = false, - .offload_version = 2, - .hash_offset = 2, -+ .has_accounting = true, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), -@@ -4853,6 +4854,7 @@ static const struct mtk_soc_data mt7629_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7629_CLKS_BITMAP, - .required_pctl = false, -+ .has_accounting = true, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4873,6 +4875,7 @@ static const struct mtk_soc_data mt7981_ - .offload_version = 2, - .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), -+ .has_accounting = true, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), -@@ -4893,6 +4896,7 @@ static const struct mtk_soc_data mt7986_ - .offload_version = 2, - .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), -+ .has_accounting = true, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1011,6 +1011,8 @@ struct mtk_reg_map { - * the extra setup for those pins used by GMAC. - * @hash_offset Flow table hash offset. - * @foe_entry_size Foe table entry size. -+ * @has_accounting Bool indicating support for accounting of -+ * offloaded flows. - * @txd_size Tx DMA descriptor size. - * @rxd_size Rx DMA descriptor size. - * @rx_irq_done_mask Rx irq done register mask. -@@ -1028,6 +1030,7 @@ struct mtk_soc_data { - u8 hash_offset; - u16 foe_entry_size; - netdev_features_t hw_features; -+ bool has_accounting; - struct { - u32 txd_size; - u32 rxd_size; ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -74,6 +74,48 @@ static int mtk_ppe_wait_busy(struct mtk_ - return ret; - } - -+static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe) -+{ -+ int ret; -+ u32 val; -+ -+ ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val, -+ !(val & MTK_PPE_MIB_SER_CR_ST), -+ 20, MTK_PPE_WAIT_TIMEOUT_US); -+ -+ if (ret) -+ dev_err(ppe->dev, "MIB table busy"); -+ -+ return ret; -+} -+ -+static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) -+{ -+ u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; -+ u32 val, cnt_r0, cnt_r1, cnt_r2; -+ int ret; -+ -+ val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST; -+ ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val); -+ -+ ret = mtk_ppe_mib_wait_busy(ppe); -+ if (ret) -+ return ret; -+ -+ cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); -+ cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); -+ cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); -+ -+ byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); -+ byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); -+ pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); -+ pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); -+ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; -+ *packets = (pkt_cnt_high << 16) | pkt_cnt_low; -+ -+ return 0; -+} -+ - static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) - { - ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); -@@ -459,6 +501,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp - hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); - dma_wmb(); - mtk_ppe_cache_clear(ppe); -+ if (ppe->accounting) { -+ struct mtk_foe_accounting *acct; -+ -+ acct = ppe->acct_table + entry->hash * sizeof(*acct); -+ acct->packets = 0; -+ acct->bytes = 0; -+ } - } - entry->hash = 0xffff; - -@@ -566,6 +615,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - wmb(); - hwe->ib1 = entry->ib1; - -+ if (ppe->accounting) -+ *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; -+ - dma_wmb(); - - mtk_ppe_cache_clear(ppe); -@@ -757,11 +809,39 @@ int mtk_ppe_prepare_reset(struct mtk_ppe - return mtk_ppe_wait_busy(ppe); - } - --struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, -- int version, int index) -+struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, -+ struct mtk_foe_accounting *diff) -+{ -+ struct mtk_foe_accounting *acct; -+ int size = sizeof(struct mtk_foe_accounting); -+ u64 bytes, packets; -+ -+ if (!ppe->accounting) -+ return NULL; -+ -+ if (mtk_mib_entry_read(ppe, index, &bytes, &packets)) -+ return NULL; -+ -+ acct = ppe->acct_table + index * size; -+ -+ acct->bytes += bytes; -+ acct->packets += packets; -+ -+ if (diff) { -+ diff->bytes = bytes; -+ diff->packets = packets; -+ } -+ -+ return acct; -+} -+ -+struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index) - { -+ bool accounting = eth->soc->has_accounting; - const struct mtk_soc_data *soc = eth->soc; -+ struct mtk_foe_accounting *acct; - struct device *dev = eth->dev; -+ struct mtk_mib_entry *mib; - struct mtk_ppe *ppe; - u32 foe_flow_size; - void *foe; -@@ -778,7 +858,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ - ppe->base = base; - ppe->eth = eth; - ppe->dev = dev; -- ppe->version = version; -+ ppe->version = eth->soc->offload_version; -+ ppe->accounting = accounting; - - foe = dmam_alloc_coherent(ppe->dev, - MTK_PPE_ENTRIES * soc->foe_entry_size, -@@ -794,6 +875,23 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ - if (!ppe->foe_flow) - goto err_free_l2_flows; - -+ if (accounting) { -+ mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib), -+ &ppe->mib_phys, GFP_KERNEL); -+ if (!mib) -+ return NULL; -+ -+ ppe->mib_table = mib; -+ -+ acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct), -+ GFP_KERNEL); -+ -+ if (!acct) -+ return NULL; -+ -+ ppe->acct_table = acct; -+ } -+ - mtk_ppe_debugfs_init(ppe, index); - - return ppe; -@@ -923,6 +1021,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); - ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); - } -+ -+ if (ppe->accounting && ppe->mib_phys) { -+ ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys); -+ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN, -+ MTK_PPE_MIB_CFG_EN); -+ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR, -+ MTK_PPE_MIB_CFG_RD_CLR); -+ ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN, -+ MTK_PPE_MIB_CFG_RD_CLR); -+ } - } - - int mtk_ppe_stop(struct mtk_ppe *ppe) ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -57,6 +57,7 @@ enum { - #define MTK_FOE_IB2_MULTICAST BIT(8) - - #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) -+#define MTK_FOE_IB2_MIB_CNT BIT(15) - #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) - #define MTK_FOE_IB2_WDMA_WINFO BIT(17) - -@@ -285,16 +286,34 @@ struct mtk_flow_entry { - unsigned long cookie; - }; - -+struct mtk_mib_entry { -+ u32 byt_cnt_l; -+ u16 byt_cnt_h; -+ u32 pkt_cnt_l; -+ u8 pkt_cnt_h; -+ u8 _rsv0; -+ u32 _rsv1; -+} __packed; -+ -+struct mtk_foe_accounting { -+ u64 bytes; -+ u64 packets; -+}; -+ - struct mtk_ppe { - struct mtk_eth *eth; - struct device *dev; - void __iomem *base; - int version; - char dirname[5]; -+ bool accounting; - - void *foe_table; - dma_addr_t foe_phys; - -+ struct mtk_mib_entry *mib_table; -+ dma_addr_t mib_phys; -+ - u16 foe_check_time[MTK_PPE_ENTRIES]; - struct hlist_head *foe_flow; - -@@ -303,8 +322,8 @@ struct mtk_ppe { - void *acct_table; - }; - --struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, -- int version, int index); -+struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index); -+ - void mtk_ppe_deinit(struct mtk_eth *eth); - void mtk_ppe_start(struct mtk_ppe *ppe); - int mtk_ppe_stop(struct mtk_ppe *ppe); -@@ -359,5 +378,7 @@ int mtk_foe_entry_commit(struct mtk_ppe - void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index); -+struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, -+ struct mtk_foe_accounting *diff); - - #endif ---- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -@@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file - struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i); - struct mtk_foe_mac_info *l2; - struct mtk_flow_addr_info ai = {}; -+ struct mtk_foe_accounting *acct; - unsigned char h_source[ETH_ALEN]; - unsigned char h_dest[ETH_ALEN]; - int type, state; -@@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file - if (bind && state != MTK_FOE_STATE_BIND) - continue; - -+ acct = mtk_foe_entry_get_mib(ppe, i, NULL); -+ - type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); - seq_printf(m, "%05x %s %7s", i, - mtk_foe_entry_state_str(state), -@@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file - *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo); - - seq_printf(m, " eth=%pM->%pM etype=%04x" -- " vlan=%d,%d ib1=%08x ib2=%08x\n", -+ " vlan=%d,%d ib1=%08x ib2=%08x" -+ " packets=%llu bytes=%llu\n", - h_source, h_dest, ntohs(l2->etype), -- l2->vlan1, l2->vlan2, entry->ib1, ib2); -+ l2->vlan1, l2->vlan2, entry->ib1, ib2, -+ acct ? acct->packets : 0, acct ? acct->bytes : 0); - } - - return 0; ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -497,6 +497,7 @@ static int - mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) - { - struct mtk_flow_entry *entry; -+ struct mtk_foe_accounting diff; - u32 idle; - - entry = rhashtable_lookup(ð->flow_table, &f->cookie, -@@ -507,6 +508,13 @@ mtk_flow_offload_stats(struct mtk_eth *e - idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry); - f->stats.lastused = jiffies - idle * HZ; - -+ if (entry->hash != 0xFFFF && -+ mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, -+ &diff)) { -+ f->stats.pkts += diff.packets; -+ f->stats.bytes += diff.bytes; -+ } -+ - return 0; - } - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -@@ -149,6 +149,20 @@ enum { - - #define MTK_PPE_MIB_TB_BASE 0x338 - -+#define MTK_PPE_MIB_SER_CR 0x33C -+#define MTK_PPE_MIB_SER_CR_ST BIT(16) -+#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0) -+ -+#define MTK_PPE_MIB_SER_R0 0x340 -+#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0) -+ -+#define MTK_PPE_MIB_SER_R1 0x344 -+#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16) -+#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0) -+ -+#define MTK_PPE_MIB_SER_R2 0x348 -+#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) -+ - #define MTK_PPE_MIB_CACHE_CTL 0x350 - #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) - #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) diff --git a/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch b/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch deleted file mode 100644 index 64352426ae..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 88a0fd5927b7c2c7aecd6dc747d898eb38043d2b Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 20 Apr 2023 22:06:42 +0100 -Subject: [PATCH 093/250] net: mtk_eth_soc: mediatek: fix ppe flow accounting - for v1 hardware - -Older chips (like MT7622) use a different bit in ib2 to enable hardware -counter support. Add macros for both and select the appropriate bit. - -Fixes: 3fbe4d8c0e53 ("net: ethernet: mtk_eth_soc: ppe: add support for flow accounting") -Signed-off-by: Felix Fietkau -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_ppe.c | 10 ++++++++-- - drivers/net/ethernet/mediatek/mtk_ppe.h | 3 ++- - 2 files changed, 10 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -599,6 +599,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - struct mtk_eth *eth = ppe->eth; - u16 timestamp = mtk_eth_timestamp(eth); - struct mtk_foe_entry *hwe; -+ u32 val; - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP_V2; -@@ -615,8 +616,13 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - wmb(); - hwe->ib1 = entry->ib1; - -- if (ppe->accounting) -- *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; -+ if (ppe->accounting) { -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ val = MTK_FOE_IB2_MIB_CNT_V2; -+ else -+ val = MTK_FOE_IB2_MIB_CNT; -+ *mtk_foe_entry_ib2(eth, hwe) |= val; -+ } - - dma_wmb(); - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -55,9 +55,10 @@ enum { - #define MTK_FOE_IB2_PSE_QOS BIT(4) - #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) - #define MTK_FOE_IB2_MULTICAST BIT(8) -+#define MTK_FOE_IB2_MIB_CNT BIT(10) - - #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) --#define MTK_FOE_IB2_MIB_CNT BIT(15) -+#define MTK_FOE_IB2_MIB_CNT_V2 BIT(15) - #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) - #define MTK_FOE_IB2_WDMA_WINFO BIT(17) - diff --git a/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch b/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch deleted file mode 100644 index 217e517c3a..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch +++ /dev/null @@ -1,201 +0,0 @@ -From: Felix Fietkau -Date: Sun, 20 Nov 2022 23:01:00 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: drop generic vlan rx offload, - only use DSA untagging - -Through testing I found out that hardware vlan rx offload support seems to -have some hardware issues. At least when using multiple MACs and when receiving -tagged packets on the secondary MAC, the hardware can sometimes start to emit -wrong tags on the first MAC as well. - -In order to avoid such issues, drop the feature configuration and use the -offload feature only for DSA hardware untagging on MT7621/MT7622 devices which -only use one MAC. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1897,9 +1897,7 @@ static int mtk_poll_rx(struct napi_struc - - while (done < budget) { - unsigned int pktlen, *rxdcsum; -- bool has_hwaccel_tag = false; - struct net_device *netdev; -- u16 vlan_proto, vlan_tci; - dma_addr_t dma_addr; - u32 hash, reason; - int mac = 0; -@@ -2034,36 +2032,21 @@ static int mtk_poll_rx(struct napi_struc - skb_checksum_none_assert(skb); - skb->protocol = eth_type_trans(skb, netdev); - -- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -- mtk_ppe_check_skb(eth->ppe[0], skb, hash); -- -- if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- if (trxd.rxd3 & RX_DMA_VTAG_V2) { -- vlan_proto = RX_DMA_VPID(trxd.rxd4); -- vlan_tci = RX_DMA_VID(trxd.rxd4); -- has_hwaccel_tag = true; -- } -- } else if (trxd.rxd2 & RX_DMA_VTAG) { -- vlan_proto = RX_DMA_VPID(trxd.rxd3); -- vlan_tci = RX_DMA_VID(trxd.rxd3); -- has_hwaccel_tag = true; -- } -- } -- - /* When using VLAN untagging in combination with DSA, the - * hardware treats the MTK special tag as a VLAN and untags it. - */ -- if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { -- unsigned int port = vlan_proto & GENMASK(2, 0); -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && -+ (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { -+ unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); - - if (port < ARRAY_SIZE(eth->dsa_meta) && - eth->dsa_meta[port]) - skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); -- } else if (has_hwaccel_tag) { -- __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); - } - -+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -+ mtk_ppe_check_skb(eth->ppe[0], skb, hash); -+ - skb_record_rx_queue(skb, 0); - napi_gro_receive(napi, skb); - -@@ -2889,29 +2872,11 @@ static netdev_features_t mtk_fix_feature - - static int mtk_set_features(struct net_device *dev, netdev_features_t features) - { -- struct mtk_mac *mac = netdev_priv(dev); -- struct mtk_eth *eth = mac->hw; - netdev_features_t diff = dev->features ^ features; -- int i; - - if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) - mtk_hwlro_netdev_disable(dev); - -- /* Set RX VLAN offloading */ -- if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) -- return 0; -- -- mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), -- MTK_CDMP_EG_CTRL); -- -- /* sync features with other MAC */ -- for (i = 0; i < MTK_MAC_COUNT; i++) { -- if (!eth->netdev[i] || eth->netdev[i] == dev) -- continue; -- eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; -- eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; -- } -- - return 0; - } - -@@ -3225,30 +3190,6 @@ static int mtk_open(struct net_device *d - struct mtk_eth *eth = mac->hw; - int i, err; - -- if (mtk_uses_dsa(dev) && !eth->prog) { -- for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -- struct metadata_dst *md_dst = eth->dsa_meta[i]; -- -- if (md_dst) -- continue; -- -- md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, -- GFP_KERNEL); -- if (!md_dst) -- return -ENOMEM; -- -- md_dst->u.port_info.port_id = i; -- eth->dsa_meta[i] = md_dst; -- } -- } else { -- /* Hardware special tag parsing needs to be disabled if at least -- * one MAC does not use DSA. -- */ -- u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -- val &= ~MTK_CDMP_STAG_EN; -- mtk_w32(eth, val, MTK_CDMP_IG_CTRL); -- } -- - err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); - if (err) { - netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -@@ -3287,6 +3228,35 @@ static int mtk_open(struct net_device *d - phylink_start(mac->phylink); - netif_tx_start_all_queues(dev); - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ return 0; -+ -+ if (mtk_uses_dsa(dev) && !eth->prog) { -+ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -+ struct metadata_dst *md_dst = eth->dsa_meta[i]; -+ -+ if (md_dst) -+ continue; -+ -+ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, -+ GFP_KERNEL); -+ if (!md_dst) -+ return -ENOMEM; -+ -+ md_dst->u.port_info.port_id = i; -+ eth->dsa_meta[i] = md_dst; -+ } -+ } else { -+ /* Hardware special tag parsing needs to be disabled if at least -+ * one MAC does not use DSA. -+ */ -+ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -+ val &= ~MTK_CDMP_STAG_EN; -+ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); -+ -+ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); -+ } -+ - return 0; - } - -@@ -3771,10 +3741,9 @@ static int mtk_hw_init(struct mtk_eth *e - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); -- } - -- /* Enable RX VLan Offloading */ -- mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); -+ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); -+ } - - /* set interrupt delays based on current Net DIM sample */ - mtk_dim_rx(ð->rx_dim.work); -@@ -4414,7 +4383,7 @@ static int mtk_add_mac(struct mtk_eth *e - eth->netdev[id]->hw_features |= NETIF_F_LRO; - - eth->netdev[id]->vlan_features = eth->soc->hw_features & -- ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); -+ ~NETIF_F_HW_VLAN_CTAG_TX; - eth->netdev[id]->features |= eth->soc->hw_features; - eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -48,7 +48,6 @@ - #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \ - NETIF_F_RXCSUM | \ - NETIF_F_HW_VLAN_CTAG_TX | \ -- NETIF_F_HW_VLAN_CTAG_RX | \ - NETIF_F_SG | NETIF_F_TSO | \ - NETIF_F_TSO6 | \ - NETIF_F_IPV6_CSUM |\ diff --git a/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch b/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch deleted file mode 100644 index 2704faec12..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b804f765485109f9644cc05d1e8fc79ca6c6e4aa Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 19 Jul 2023 01:39:36 +0100 -Subject: [PATCH 094/250] net: ethernet: mtk_eth_soc: always - mtk_get_ib1_pkt_type - -entries and bind debugfs files would display wrong data on NETSYS_V2 and -later because instead of using mtk_get_ib1_pkt_type the driver would use -MTK_FOE_IB1_PACKET_TYPE which corresponds to NETSYS_V1(.x) SoCs. -Use mtk_get_ib1_pkt_type so entries and bind records display correctly. - -Fixes: 03a3180e5c09e ("net: ethernet: mtk_eth_soc: introduce flow offloading support for mt7986") -Signed-off-by: Daniel Golle -Acked-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/c0ae03d0182f4d27b874cbdf0059bc972c317f3c.1689727134.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -@@ -98,7 +98,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file - - acct = mtk_foe_entry_get_mib(ppe, i, NULL); - -- type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); -+ type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1); - seq_printf(m, "%05x %s %7s", i, - mtk_foe_entry_state_str(state), - mtk_foe_pkt_type_str(type)); diff --git a/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch b/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch deleted file mode 100644 index d7d1c08fce..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 5ea0e1312bcfebc06b5f91d1bb82b823d6395125 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Wed, 19 Jul 2023 12:29:49 +0200 -Subject: [PATCH 095/250] net: ethernet: mtk_ppe: add MTK_FOE_ENTRY_V{1,2}_SIZE - macros - -Introduce MTK_FOE_ENTRY_V{1,2}_SIZE macros in order to make more -explicit foe_entry size for different chipset revisions. - -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +++++----- - drivers/net/ethernet/mediatek/mtk_ppe.h | 3 +++ - 2 files changed, 8 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4765,7 +4765,7 @@ static const struct mtk_soc_data mt7621_ - .required_pctl = false, - .offload_version = 1, - .hash_offset = 2, -- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, -+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4786,7 +4786,7 @@ static const struct mtk_soc_data mt7622_ - .offload_version = 2, - .hash_offset = 2, - .has_accounting = true, -- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, -+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4805,7 +4805,7 @@ static const struct mtk_soc_data mt7623_ - .required_pctl = true, - .offload_version = 1, - .hash_offset = 2, -- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, -+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4843,8 +4843,8 @@ static const struct mtk_soc_data mt7981_ - .required_pctl = false, - .offload_version = 2, - .hash_offset = 4, -- .foe_entry_size = sizeof(struct mtk_foe_entry), - .has_accounting = true, -+ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), -@@ -4864,8 +4864,8 @@ static const struct mtk_soc_data mt7986_ - .required_pctl = false, - .offload_version = 2, - .hash_offset = 4, -- .foe_entry_size = sizeof(struct mtk_foe_entry), - .has_accounting = true, -+ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -216,6 +216,9 @@ struct mtk_foe_ipv6_6rd { - struct mtk_foe_mac_info l2; - }; - -+#define MTK_FOE_ENTRY_V1_SIZE 80 -+#define MTK_FOE_ENTRY_V2_SIZE 96 -+ - struct mtk_foe_entry { - u32 ib1; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch b/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch deleted file mode 100644 index fb54f404b2..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 8cfa2576d79f9379d167a8994f0fca935c07a8bc Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 22 Jul 2023 21:32:49 +0100 -Subject: [PATCH 096/250] net: ethernet: mtk_eth_soc: remove incorrect PLL - configuration - -MT7623 GMAC0 attempts to configure the system clocking according to the -required speed in the .mac_config callback for non-SGMII, non-baseX and -non-TRGMII modes. - -state->speed setting has never been reliable in the .mac_config -callback - there are cases where this is not the link speed, -particularly via ethtool paths, so this has always been unreliable (as -detailed in phylink's documentation.) - -There is the additional issue that mtk_gmac0_rgmii_adjust() will only -be called if state->interface changes, which means it only configures -the system clocking on the very first .mac_config call, which will be -made when the network device is first brought up before any link is -established. - -Essentially, this code is incredibly buggy, and probably never worked. - -Moreover, checking the in-kernel DT files, it seems no platform makes -use of this code path. - -Therefore, let's remove it, and disable interface modes for port 0 that -are not SGMII, 1000base-X, 2500base-X or TRGMII on the MT7623. - -Reviewed-by: Daniel Golle -Tested-by: Daniel Golle -Tested-by: Frank Wunderlich -Signed-off-by: Russell King (Oracle) -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 54 ++++++--------------- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + - 2 files changed, 17 insertions(+), 38 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -352,7 +352,7 @@ static int mt7621_gmac0_rgmii_adjust(str - } - - static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, -- phy_interface_t interface, int speed) -+ phy_interface_t interface) - { - u32 val; - int ret; -@@ -366,26 +366,7 @@ static void mtk_gmac0_rgmii_adjust(struc - return; - } - -- val = (speed == SPEED_1000) ? -- INTF_MODE_RGMII_1000 : INTF_MODE_RGMII_10_100; -- mtk_w32(eth, val, INTF_MODE); -- -- regmap_update_bits(eth->ethsys, ETHSYS_CLKCFG0, -- ETHSYS_TRGMII_CLK_SEL362_5, -- ETHSYS_TRGMII_CLK_SEL362_5); -- -- val = (speed == SPEED_1000) ? 250000000 : 500000000; -- ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], val); -- if (ret) -- dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret); -- -- val = (speed == SPEED_1000) ? -- RCK_CTRL_RGMII_1000 : RCK_CTRL_RGMII_10_100; -- mtk_w32(eth, val, TRGMII_RCK_CTRL); -- -- val = (speed == SPEED_1000) ? -- TCK_CTRL_RGMII_1000 : TCK_CTRL_RGMII_10_100; -- mtk_w32(eth, val, TRGMII_TCK_CTRL); -+ dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); - } - - static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, -@@ -471,17 +452,8 @@ static void mtk_mac_config(struct phylin - state->interface)) - goto err_phy; - } else { -- /* FIXME: this is incorrect. Not only does it -- * use state->speed (which is not guaranteed -- * to be correct) but it also makes use of it -- * in a code path that will only be reachable -- * when the PHY interface mode changes, not -- * when the speed changes. Consequently, RGMII -- * is probably broken. -- */ - mtk_gmac0_rgmii_adjust(mac->hw, -- state->interface, -- state->speed); -+ state->interface); - - /* mt7623_pad_clk_setup */ - for (i = 0 ; i < NUM_TRGMII_CTRL; i++) -@@ -4342,13 +4314,19 @@ static int mtk_add_mac(struct mtk_eth *e - mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; - -- __set_bit(PHY_INTERFACE_MODE_MII, -- mac->phylink_config.supported_interfaces); -- __set_bit(PHY_INTERFACE_MODE_GMII, -- mac->phylink_config.supported_interfaces); -+ /* MT7623 gmac0 is now missing its speed-specific PLL configuration -+ * in its .mac_config method (since state->speed is not valid there. -+ * Disable support for MII, GMII and RGMII. -+ */ -+ if (!mac->hw->soc->disable_pll_modes || mac->id != 0) { -+ __set_bit(PHY_INTERFACE_MODE_MII, -+ mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_GMII, -+ mac->phylink_config.supported_interfaces); - -- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) -- phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); -+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) -+ phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); -+ } - - if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id) - __set_bit(PHY_INTERFACE_MODE_TRGMII, -@@ -4806,6 +4784,7 @@ static const struct mtk_soc_data mt7623_ - .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -+ .disable_pll_modes = true, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1030,6 +1030,7 @@ struct mtk_soc_data { - u16 foe_entry_size; - netdev_features_t hw_features; - bool has_accounting; -+ bool disable_pll_modes; - struct { - u32 txd_size; - u32 rxd_size; diff --git a/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch b/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch deleted file mode 100644 index 293066fa9a..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch +++ /dev/null @@ -1,81 +0,0 @@ -From a4c2233b1e4359b6c64b6f9ba98c8718a11fffee Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 22 Jul 2023 21:32:54 +0100 -Subject: [PATCH 097/250] net: ethernet: mtk_eth_soc: remove mac_pcs_get_state - and modernise - -Remove the .mac_pcs_get_state function, since as far as I can tell is -never called - no DT appears to specify an in-band-status management -nor SFP support for this driver. - -Removal of this, along with the previous patch to remove the incorrect -clocking configuration, means that the driver becomes non-legacy, so -we can remove the "legacy_pre_march2020" status from this driver. - -Reviewed-by: Daniel Golle -Tested-by: Daniel Golle -Tested-by: Frank Wunderlich -Signed-off-by: Russell King (Oracle) -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 --------------------- - 1 file changed, 35 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -555,38 +555,6 @@ static int mtk_mac_finish(struct phylink - return 0; - } - --static void mtk_mac_pcs_get_state(struct phylink_config *config, -- struct phylink_link_state *state) --{ -- struct mtk_mac *mac = container_of(config, struct mtk_mac, -- phylink_config); -- u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id)); -- -- state->link = (pmsr & MAC_MSR_LINK); -- state->duplex = (pmsr & MAC_MSR_DPX) >> 1; -- -- switch (pmsr & (MAC_MSR_SPEED_1000 | MAC_MSR_SPEED_100)) { -- case 0: -- state->speed = SPEED_10; -- break; -- case MAC_MSR_SPEED_100: -- state->speed = SPEED_100; -- break; -- case MAC_MSR_SPEED_1000: -- state->speed = SPEED_1000; -- break; -- default: -- state->speed = SPEED_UNKNOWN; -- break; -- } -- -- state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); -- if (pmsr & MAC_MSR_RX_FC) -- state->pause |= MLO_PAUSE_RX; -- if (pmsr & MAC_MSR_TX_FC) -- state->pause |= MLO_PAUSE_TX; --} -- - static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, - phy_interface_t interface) - { -@@ -708,7 +676,6 @@ static void mtk_mac_link_up(struct phyli - - static const struct phylink_mac_ops mtk_phylink_ops = { - .mac_select_pcs = mtk_mac_select_pcs, -- .mac_pcs_get_state = mtk_mac_pcs_get_state, - .mac_config = mtk_mac_config, - .mac_finish = mtk_mac_finish, - .mac_link_down = mtk_mac_link_down, -@@ -4309,8 +4276,6 @@ static int mtk_add_mac(struct mtk_eth *e - - mac->phylink_config.dev = ð->netdev[id]->dev; - mac->phylink_config.type = PHYLINK_NETDEV; -- /* This driver makes use of state->speed in mac_config */ -- mac->phylink_config.legacy_pre_march2020 = true; - mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch b/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch deleted file mode 100644 index 25c87b0415..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch +++ /dev/null @@ -1,550 +0,0 @@ -From 5d8d05fbf804b4485646d39551ac27452e45afd3 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:02 +0100 -Subject: [PATCH 099/250] net: ethernet: mtk_eth_soc: add version in - mtk_soc_data - -Introduce version field in mtk_soc_data data structure in order to -make mtk_eth driver easier to maintain for chipset configuration -codebase. Get rid of MTK_NETSYS_V2 bit in chip capabilities. -This is a preliminary patch to introduce support for MT7988 SoC. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/e52fae302ca135436e5cdd26d38d87be2da63055.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 55 +++++++++++-------- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 36 +++++++----- - drivers/net/ethernet/mediatek/mtk_ppe.c | 18 +++--- - .../net/ethernet/mediatek/mtk_ppe_offload.c | 2 +- - drivers/net/ethernet/mediatek/mtk_wed.c | 4 +- - 5 files changed, 66 insertions(+), 49 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -580,7 +580,7 @@ static void mtk_set_queue_speed(struct m - FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | - FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | - MTK_QTX_SCH_LEAKY_BUCKET_SIZE; -- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v1(eth)) - val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; - - if (IS_ENABLED(CONFIG_SOC_MT7621)) { -@@ -955,7 +955,7 @@ static bool mtk_rx_get_desc(struct mtk_e - rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); - rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); - rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); - rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); - } -@@ -1013,7 +1013,7 @@ static int mtk_init_fq_dma(struct mtk_et - - txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); - txd->txd4 = 0; -- if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - txd->txd5 = 0; - txd->txd6 = 0; - txd->txd7 = 0; -@@ -1204,7 +1204,7 @@ static void mtk_tx_set_dma_desc(struct n - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - mtk_tx_set_dma_desc_v2(dev, txd, info); - else - mtk_tx_set_dma_desc_v1(dev, txd, info); -@@ -1511,7 +1511,7 @@ static void mtk_update_rx_cpu_idx(struct - - static bool mtk_page_pool_enabled(struct mtk_eth *eth) - { -- return MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2); -+ return eth->soc->version == 2; - } - - static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, -@@ -1853,7 +1853,7 @@ static int mtk_poll_rx(struct napi_struc - break; - - /* find out which mac the packet come from. values start at 1 */ -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1; - else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && - !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) -@@ -1949,7 +1949,7 @@ static int mtk_poll_rx(struct napi_struc - skb->dev = netdev; - bytes += skb->len; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); - hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; - if (hash != MTK_RXD5_FOE_ENTRY) -@@ -1974,8 +1974,8 @@ static int mtk_poll_rx(struct napi_struc - /* When using VLAN untagging in combination with DSA, the - * hardware treats the MTK special tag as a VLAN and untags it. - */ -- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && -- (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { -+ if (mtk_is_netsys_v1(eth) && (trxd.rxd2 & RX_DMA_VTAG) && -+ netdev_uses_dsa(netdev)) { - unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); - - if (port < ARRAY_SIZE(eth->dsa_meta) && -@@ -2285,7 +2285,7 @@ static int mtk_tx_alloc(struct mtk_eth * - txd->txd2 = next_ptr; - txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; - txd->txd4 = 0; -- if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - txd->txd5 = 0; - txd->txd6 = 0; - txd->txd7 = 0; -@@ -2338,14 +2338,14 @@ static int mtk_tx_alloc(struct mtk_eth * - FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | - FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | - MTK_QTX_SCH_LEAKY_BUCKET_SIZE; -- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v1(eth)) - val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; - mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); - ofs += MTK_QTX_OFFSET; - } - val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); - mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); - } else { - mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); -@@ -2474,7 +2474,7 @@ static int mtk_rx_alloc(struct mtk_eth * - - rxd->rxd3 = 0; - rxd->rxd4 = 0; -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - rxd->rxd5 = 0; - rxd->rxd6 = 0; - rxd->rxd7 = 0; -@@ -3025,7 +3025,7 @@ static int mtk_start_dma(struct mtk_eth - MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | - MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - val |= MTK_MUTLI_CNT | MTK_RESV_BUF | - MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | - MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; -@@ -3167,7 +3167,7 @@ static int mtk_open(struct net_device *d - phylink_start(mac->phylink); - netif_tx_start_all_queues(dev); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return 0; - - if (mtk_uses_dsa(dev) && !eth->prog) { -@@ -3432,7 +3432,7 @@ static void mtk_hw_reset(struct mtk_eth - { - u32 val; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); - val = RSTCTRL_PPE0_V2; - } else { -@@ -3444,7 +3444,7 @@ static void mtk_hw_reset(struct mtk_eth - - ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, - 0x3ffffff); - } -@@ -3470,7 +3470,7 @@ static void mtk_hw_warm_reset(struct mtk - return; - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; - else - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; -@@ -3640,7 +3640,7 @@ static int mtk_hw_init(struct mtk_eth *e - else - mtk_hw_reset(eth); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - /* Set FE to PDMAv2 if necessary */ - val = mtk_r32(eth, MTK_FE_GLO_MISC); - mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); -@@ -3677,7 +3677,7 @@ static int mtk_hw_init(struct mtk_eth *e - */ - val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); - mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); -- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v1(eth)) { - val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); - -@@ -3699,7 +3699,7 @@ static int mtk_hw_init(struct mtk_eth *e - mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); - mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - /* PSE should not drop port8 and port9 packets from WDMA Tx */ - mtk_w32(eth, 0x00000300, PSE_DROP_CFG); - -@@ -4488,7 +4488,7 @@ static int mtk_probe(struct platform_dev - } - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - err = -EINVAL; -@@ -4596,9 +4596,8 @@ static int mtk_probe(struct platform_dev - } - - if (eth->soc->offload_version) { -- u32 num_ppe; -+ u32 num_ppe = mtk_is_netsys_v2_or_greater(eth) ? 2 : 1; - -- num_ppe = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; - num_ppe = min_t(u32, ARRAY_SIZE(eth->ppe), num_ppe); - for (i = 0; i < num_ppe; i++) { - u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; -@@ -4690,6 +4689,7 @@ static const struct mtk_soc_data mt2701_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7623_CLKS_BITMAP, - .required_pctl = true, -+ .version = 1, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4706,6 +4706,7 @@ static const struct mtk_soc_data mt7621_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7621_CLKS_BITMAP, - .required_pctl = false, -+ .version = 1, - .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -@@ -4726,6 +4727,7 @@ static const struct mtk_soc_data mt7622_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7622_CLKS_BITMAP, - .required_pctl = false, -+ .version = 1, - .offload_version = 2, - .hash_offset = 2, - .has_accounting = true, -@@ -4746,6 +4748,7 @@ static const struct mtk_soc_data mt7623_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7623_CLKS_BITMAP, - .required_pctl = true, -+ .version = 1, - .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -@@ -4768,6 +4771,7 @@ static const struct mtk_soc_data mt7629_ - .required_clks = MT7629_CLKS_BITMAP, - .required_pctl = false, - .has_accounting = true, -+ .version = 1, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4785,6 +4789,7 @@ static const struct mtk_soc_data mt7981_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7981_CLKS_BITMAP, - .required_pctl = false, -+ .version = 2, - .offload_version = 2, - .hash_offset = 4, - .has_accounting = true, -@@ -4806,6 +4811,7 @@ static const struct mtk_soc_data mt7986_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7986_CLKS_BITMAP, - .required_pctl = false, -+ .version = 2, - .offload_version = 2, - .hash_offset = 4, - .has_accounting = true, -@@ -4826,6 +4832,7 @@ static const struct mtk_soc_data rt5350_ - .hw_features = MTK_HW_FEATURES_MT7628, - .required_clks = MT7628_CLKS_BITMAP, - .required_pctl = false, -+ .version = 1, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -820,7 +820,6 @@ enum mkt_eth_capabilities { - MTK_SHARED_INT_BIT, - MTK_TRGMII_MT7621_CLK_BIT, - MTK_QDMA_BIT, -- MTK_NETSYS_V2_BIT, - MTK_SOC_MT7628_BIT, - MTK_RSTCTRL_PPE1_BIT, - MTK_U3_COPHY_V2_BIT, -@@ -855,7 +854,6 @@ enum mkt_eth_capabilities { - #define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT) - #define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) - #define MTK_QDMA BIT(MTK_QDMA_BIT) --#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT) - #define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) - #define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) - #define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) -@@ -934,11 +932,11 @@ enum mkt_eth_capabilities { - #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ -- MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) -+ MTK_RSTCTRL_PPE1) - - #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ -- MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) -+ MTK_RSTCTRL_PPE1) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; -@@ -1009,6 +1007,7 @@ struct mtk_reg_map { - * @required_pctl A bool value to show whether the SoC requires - * the extra setup for those pins used by GMAC. - * @hash_offset Flow table hash offset. -+ * @version SoC version. - * @foe_entry_size Foe table entry size. - * @has_accounting Bool indicating support for accounting of - * offloaded flows. -@@ -1027,6 +1026,7 @@ struct mtk_soc_data { - bool required_pctl; - u8 offload_version; - u8 hash_offset; -+ u8 version; - u16 foe_entry_size; - netdev_features_t hw_features; - bool has_accounting; -@@ -1183,6 +1183,16 @@ struct mtk_mac { - /* the struct describing the SoC. these are declared in the soc_xyz.c files */ - extern const struct of_device_id of_mtk_match[]; - -+static inline bool mtk_is_netsys_v1(struct mtk_eth *eth) -+{ -+ return eth->soc->version == 1; -+} -+ -+static inline bool mtk_is_netsys_v2_or_greater(struct mtk_eth *eth) -+{ -+ return eth->soc->version > 1; -+} -+ - static inline struct mtk_foe_entry * - mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) - { -@@ -1193,7 +1203,7 @@ mtk_foe_get_entry(struct mtk_ppe *ppe, u - - static inline u32 mtk_get_ib1_ts_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_TIMESTAMP_V2; - - return MTK_FOE_IB1_BIND_TIMESTAMP; -@@ -1201,7 +1211,7 @@ static inline u32 mtk_get_ib1_ts_mask(st - - static inline u32 mtk_get_ib1_ppoe_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_PPPOE_V2; - - return MTK_FOE_IB1_BIND_PPPOE; -@@ -1209,7 +1219,7 @@ static inline u32 mtk_get_ib1_ppoe_mask( - - static inline u32 mtk_get_ib1_vlan_tag_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_VLAN_TAG_V2; - - return MTK_FOE_IB1_BIND_VLAN_TAG; -@@ -1217,7 +1227,7 @@ static inline u32 mtk_get_ib1_vlan_tag_m - - static inline u32 mtk_get_ib1_vlan_layer_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_VLAN_LAYER_V2; - - return MTK_FOE_IB1_BIND_VLAN_LAYER; -@@ -1225,7 +1235,7 @@ static inline u32 mtk_get_ib1_vlan_layer - - static inline u32 mtk_prep_ib1_vlan_layer(struct mtk_eth *eth, u32 val) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); - - return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, val); -@@ -1233,7 +1243,7 @@ static inline u32 mtk_prep_ib1_vlan_laye - - static inline u32 mtk_get_ib1_vlan_layer(struct mtk_eth *eth, u32 val) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); - - return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER, val); -@@ -1241,7 +1251,7 @@ static inline u32 mtk_get_ib1_vlan_layer - - static inline u32 mtk_get_ib1_pkt_type_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_PACKET_TYPE_V2; - - return MTK_FOE_IB1_PACKET_TYPE; -@@ -1249,7 +1259,7 @@ static inline u32 mtk_get_ib1_pkt_type_m - - static inline u32 mtk_get_ib1_pkt_type(struct mtk_eth *eth, u32 val) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE_V2, val); - - return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, val); -@@ -1257,7 +1267,7 @@ static inline u32 mtk_get_ib1_pkt_type(s - - static inline u32 mtk_get_ib2_multicast_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB2_MULTICAST_V2; - - return MTK_FOE_IB2_MULTICAST; ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -207,7 +207,7 @@ int mtk_foe_entry_prepare(struct mtk_eth - - memset(entry, 0, sizeof(*entry)); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | - FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE_V2, type) | - FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | -@@ -271,7 +271,7 @@ int mtk_foe_entry_set_pse_port(struct mt - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - u32 val = *ib2; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - val &= ~MTK_FOE_IB2_DEST_PORT_V2; - val |= FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, port); - } else { -@@ -422,7 +422,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et - struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; - *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | - MTK_FOE_IB2_WDMA_WINFO_V2; -@@ -446,7 +446,7 @@ int mtk_foe_entry_set_queue(struct mtk_e - { - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - *ib2 &= ~MTK_FOE_IB2_QID_V2; - *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); - *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; -@@ -601,7 +601,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - struct mtk_foe_entry *hwe; - u32 val; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP_V2; - entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP_V2, - timestamp); -@@ -617,7 +617,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - hwe->ib1 = entry->ib1; - - if (ppe->accounting) { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - val = MTK_FOE_IB2_MIB_CNT_V2; - else - val = MTK_FOE_IB2_MIB_CNT; -@@ -965,7 +965,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | - FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, - MTK_PPE_ENTRIES_SHIFT); -- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(ppe->eth)) - val |= MTK_PPE_TB_CFG_INFO_SEL; - ppe_w32(ppe, MTK_PPE_TB_CFG, val); - -@@ -981,7 +981,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - MTK_PPE_FLOW_CFG_IP4_NAPT | - MTK_PPE_FLOW_CFG_IP4_DSLITE | - MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; -- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(ppe->eth)) - val |= MTK_PPE_MD_TOAP_BYP_CRSN0 | - MTK_PPE_MD_TOAP_BYP_CRSN1 | - MTK_PPE_MD_TOAP_BYP_CRSN2 | -@@ -1023,7 +1023,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - - ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0); - -- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(ppe->eth)) { - ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); - ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); - } ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -193,7 +193,7 @@ mtk_flow_set_output_device(struct mtk_et - if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { - mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, - info.bss, info.wcid); -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - switch (info.wdma_idx) { - case 0: - pse_port = 8; ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1084,7 +1084,7 @@ mtk_wed_rx_reset(struct mtk_wed_device * - } else { - struct mtk_eth *eth = dev->hw->eth; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - wed_set(dev, MTK_WED_RESET_IDX, - MTK_WED_RESET_IDX_RX_V2); - else -@@ -1806,7 +1806,7 @@ void mtk_wed_add_hw(struct device_node * - hw->wdma = wdma; - hw->index = index; - hw->irq = irq; -- hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; -+ hw->version = mtk_is_netsys_v1(eth) ? 1 : 2; - - if (hw->version == 1) { - hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, diff --git a/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch b/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch deleted file mode 100644 index 7b945bb869..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch +++ /dev/null @@ -1,29 +0,0 @@ -From f8fb8dbd158c585be7574faf92db7d614b6722ff Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:27 +0100 -Subject: [PATCH 100/250] net: ethernet: mtk_eth_soc: increase MAX_DEVS to 3 - -This is a preliminary patch to add MT7988 SoC support since it runs 3 -macs instead of 2. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/3563e5fab367e7d79a7f1296fabaa5c20f202d7a.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1043,8 +1043,8 @@ struct mtk_soc_data { - - #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) - --/* currently no SoC has more than 2 macs */ --#define MTK_MAX_DEVS 2 -+/* currently no SoC has more than 3 macs */ -+#define MTK_MAX_DEVS 3 - - /* struct mtk_eth - This is the main datasructure for holding the state - * of the driver diff --git a/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch b/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch deleted file mode 100644 index 8071658313..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch +++ /dev/null @@ -1,186 +0,0 @@ -From 856be974290f28d7943be2ac5a382c4139486196 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:44 +0100 -Subject: [PATCH 101/250] net: ethernet: mtk_eth_soc: rely on MTK_MAX_DEVS and - remove MTK_MAC_COUNT - -Get rid of MTK_MAC_COUNT since it is a duplicated of MTK_MAX_DEVS. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/1856f4266f2fc80677807b1bad867659e7b00c65.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++++++++++++--------- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 - - 2 files changed, 27 insertions(+), 23 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -881,7 +881,7 @@ static void mtk_stats_update(struct mtk_ - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->mac[i] || !eth->mac[i]->hw_stats) - continue; - if (spin_trylock(ð->mac[i]->hw_stats->stats_lock)) { -@@ -1386,7 +1386,7 @@ static int mtk_queue_stopped(struct mtk_ - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; - if (netif_queue_stopped(eth->netdev[i])) -@@ -1400,7 +1400,7 @@ static void mtk_wake_queue(struct mtk_et - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; - netif_tx_wake_all_queues(eth->netdev[i]); -@@ -1859,7 +1859,7 @@ static int mtk_poll_rx(struct napi_struc - !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) - mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1; - -- if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || -+ if (unlikely(mac < 0 || mac >= MTK_MAX_DEVS || - !eth->netdev[mac])) - goto release_desc; - -@@ -2899,7 +2899,7 @@ static void mtk_dma_free(struct mtk_eth - const struct mtk_soc_data *soc = eth->soc; - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) -+ for (i = 0; i < MTK_MAX_DEVS; i++) - if (eth->netdev[i]) - netdev_reset_queue(eth->netdev[i]); - if (eth->scratch_ring) { -@@ -3053,8 +3053,13 @@ static void mtk_gdm_config(struct mtk_et - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) - return; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -- u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ u32 val; -+ -+ if (!eth->netdev[i]) -+ continue; -+ -+ val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); - - /* default setup the forward port to send frame to PDMA */ - val &= ~0xffff; -@@ -3064,7 +3069,7 @@ static void mtk_gdm_config(struct mtk_et - - val |= config; - -- if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) -+ if (netdev_uses_dsa(eth->netdev[i])) - val |= MTK_GDMA_SPECIAL_TAG; - - mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); -@@ -3661,15 +3666,15 @@ static int mtk_hw_init(struct mtk_eth *e - * up with the more appropriate value when mtk_mac_config call is being - * invoked. - */ -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - struct net_device *dev = eth->netdev[i]; - -- mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); -- if (dev) { -- struct mtk_mac *mac = netdev_priv(dev); -+ if (!dev) -+ continue; - -- mtk_set_mcr_max_rx(mac, dev->mtu + MTK_RX_ETH_HLEN); -- } -+ mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); -+ mtk_set_mcr_max_rx(netdev_priv(dev), -+ dev->mtu + MTK_RX_ETH_HLEN); - } - - /* Indicates CDM to parse the MTK special tag from CPU -@@ -3849,7 +3854,7 @@ static void mtk_pending_work(struct work - mtk_prepare_for_reset(eth); - - /* stop all devices to make sure that dma is properly shut down */ -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i] || !netif_running(eth->netdev[i])) - continue; - -@@ -3865,8 +3870,8 @@ static void mtk_pending_work(struct work - mtk_hw_init(eth, true); - - /* restart DMA and enable IRQs */ -- for (i = 0; i < MTK_MAC_COUNT; i++) { -- if (!test_bit(i, &restart)) -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ if (!eth->netdev[i] || !test_bit(i, &restart)) - continue; - - if (mtk_open(eth->netdev[i])) { -@@ -3893,7 +3898,7 @@ static int mtk_free_dev(struct mtk_eth * - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; - free_netdev(eth->netdev[i]); -@@ -3912,7 +3917,7 @@ static int mtk_unreg_dev(struct mtk_eth - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - struct mtk_mac *mac; - if (!eth->netdev[i]) - continue; -@@ -4213,7 +4218,7 @@ static int mtk_add_mac(struct mtk_eth *e - } - - id = be32_to_cpup(_id); -- if (id >= MTK_MAC_COUNT) { -+ if (id >= MTK_MAX_DEVS) { - dev_err(eth->dev, "%d is not a valid mac id\n", id); - return -EINVAL; - } -@@ -4358,7 +4363,7 @@ void mtk_eth_set_dma_device(struct mtk_e - - rtnl_lock(); - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - dev = eth->netdev[i]; - - if (!dev || !(dev->flags & IFF_UP)) -@@ -4664,7 +4669,7 @@ static int mtk_remove(struct platform_de - int i; - - /* stop all devices to make sure that dma is properly shut down */ -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; - mtk_stop(eth->netdev[i]); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -33,7 +33,6 @@ - #define MTK_TX_DMA_BUF_LEN_V2 0xffff - #define MTK_QDMA_RING_SIZE 2048 - #define MTK_DMA_SIZE 512 --#define MTK_MAC_COUNT 2 - #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + ETH_FCS_LEN) - #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) - #define MTK_DMA_DUMMY_DESC 0xffffffff diff --git a/target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch b/target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch deleted file mode 100644 index 1a9b31f526..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch +++ /dev/null @@ -1,307 +0,0 @@ -From a41d535855976838d246c079143c948dcf0f7931 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:59 +0100 -Subject: [PATCH 102/250] net: ethernet: mtk_eth_soc: add NETSYS_V3 version - support - -Introduce NETSYS_V3 chipset version support. -This is a preliminary patch to introduce support for MT7988 SoC. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/0db2260910755d76fa48e303b9f9bdf4e5a82340.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 105 ++++++++++++++------ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 48 +++++++-- - 2 files changed, 116 insertions(+), 37 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -861,17 +861,32 @@ void mtk_stats_update_mac(struct mtk_mac - mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x20 + offs); - hw_stats->rx_flow_control_packets += - mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x24 + offs); -- hw_stats->tx_skip += -- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs); -- hw_stats->tx_collisions += -- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs); -- hw_stats->tx_bytes += -- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs); -- stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs); -- if (stats) -- hw_stats->tx_bytes += (stats << 32); -- hw_stats->tx_packets += -- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs); -+ -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ hw_stats->tx_skip += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x50 + offs); -+ hw_stats->tx_collisions += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x54 + offs); -+ hw_stats->tx_bytes += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x40 + offs); -+ stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x44 + offs); -+ if (stats) -+ hw_stats->tx_bytes += (stats << 32); -+ hw_stats->tx_packets += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x48 + offs); -+ } else { -+ hw_stats->tx_skip += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs); -+ hw_stats->tx_collisions += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs); -+ hw_stats->tx_bytes += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs); -+ stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs); -+ if (stats) -+ hw_stats->tx_bytes += (stats << 32); -+ hw_stats->tx_packets += -+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs); -+ } - } - - u64_stats_update_end(&hw_stats->syncp); -@@ -1175,7 +1190,10 @@ static void mtk_tx_set_dma_desc_v2(struc - data |= TX_DMA_LS0; - WRITE_ONCE(desc->txd3, data); - -- data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ -+ if (mac->id == MTK_GMAC3_ID) -+ data = PSE_GDM3_PORT; -+ else -+ data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ - data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); - WRITE_ONCE(desc->txd4, data); - -@@ -1186,6 +1204,8 @@ static void mtk_tx_set_dma_desc_v2(struc - /* tx checksum offload */ - if (info->csum) - data |= TX_DMA_CHKSUM_V2; -+ if (mtk_is_netsys_v3_or_greater(eth) && netdev_uses_dsa(dev)) -+ data |= TX_DMA_SPTAG_V3; - } - WRITE_ONCE(desc->txd5, data); - -@@ -1251,8 +1271,7 @@ static int mtk_tx_map(struct sk_buff *sk - mtk_tx_set_dma_desc(dev, itxd, &txd_info); - - itx_buf->flags |= MTK_TX_FLAGS_SINGLE0; -- itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : -- MTK_TX_FLAGS_FPORT1; -+ itx_buf->mac_id = mac->id; - setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, - k++); - -@@ -1300,8 +1319,7 @@ static int mtk_tx_map(struct sk_buff *sk - memset(tx_buf, 0, sizeof(*tx_buf)); - tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; - tx_buf->flags |= MTK_TX_FLAGS_PAGE0; -- tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : -- MTK_TX_FLAGS_FPORT1; -+ tx_buf->mac_id = mac->id; - - setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, - txd_info.size, k++); -@@ -1603,7 +1621,7 @@ static int mtk_xdp_frame_map(struct mtk_ - } - mtk_tx_set_dma_desc(dev, txd, txd_info); - -- tx_buf->flags |= !mac->id ? MTK_TX_FLAGS_FPORT0 : MTK_TX_FLAGS_FPORT1; -+ tx_buf->mac_id = mac->id; - tx_buf->type = dma_map ? MTK_TYPE_XDP_NDO : MTK_TYPE_XDP_TX; - tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; - -@@ -1853,11 +1871,24 @@ static int mtk_poll_rx(struct napi_struc - break; - - /* find out which mac the packet come from. values start at 1 */ -- if (mtk_is_netsys_v2_or_greater(eth)) -- mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1; -- else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && -- !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) -+ if (mtk_is_netsys_v2_or_greater(eth)) { -+ u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); -+ -+ switch (val) { -+ case PSE_GDM1_PORT: -+ case PSE_GDM2_PORT: -+ mac = val - 1; -+ break; -+ case PSE_GDM3_PORT: -+ mac = MTK_GMAC3_ID; -+ break; -+ default: -+ break; -+ } -+ } else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && -+ !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) { - mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1; -+ } - - if (unlikely(mac < 0 || mac >= MTK_MAX_DEVS || - !eth->netdev[mac])) -@@ -2079,7 +2110,6 @@ static int mtk_poll_tx_qdma(struct mtk_e - - while ((cpu != dma) && budget) { - u32 next_cpu = desc->txd2; -- int mac = 0; - - desc = mtk_qdma_phys_to_virt(ring, desc->txd2); - if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) -@@ -2087,15 +2117,13 @@ static int mtk_poll_tx_qdma(struct mtk_e - - tx_buf = mtk_desc_to_tx_buf(ring, desc, - eth->soc->txrx.txd_size); -- if (tx_buf->flags & MTK_TX_FLAGS_FPORT1) -- mac = 1; -- - if (!tx_buf->data) - break; - - if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { - if (tx_buf->type == MTK_TYPE_SKB) -- mtk_poll_tx_done(eth, state, mac, tx_buf->data); -+ mtk_poll_tx_done(eth, state, tx_buf->mac_id, -+ tx_buf->data); - - budget--; - } -@@ -3704,7 +3732,24 @@ static int mtk_hw_init(struct mtk_eth *e - mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); - mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); - -- if (mtk_is_netsys_v2_or_greater(eth)) { -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ /* PSE should not drop port1, port8 and port9 packets */ -+ mtk_w32(eth, 0x00000302, PSE_DROP_CFG); -+ -+ /* GDM and CDM Threshold */ -+ mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES); -+ mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES); -+ -+ /* Disable GDM1 RX CRC stripping */ -+ mtk_m32(eth, MTK_GDMA_STRP_CRC, 0, MTK_GDMA_FWD_CFG(0)); -+ -+ /* PSE GDM3 MIB counter has incorrect hw default values, -+ * so the driver ought to read clear the values beforehand -+ * in case ethtool retrieve wrong mib values. -+ */ -+ for (i = 0; i < 0x80; i += 0x4) -+ mtk_r32(eth, reg_map->gdm1_cnt + 0x100 + i); -+ } else if (!mtk_is_netsys_v1(eth)) { - /* PSE should not drop port8 and port9 packets from WDMA Tx */ - mtk_w32(eth, 0x00000300, PSE_DROP_CFG); - -@@ -4266,7 +4311,11 @@ static int mtk_add_mac(struct mtk_eth *e - } - spin_lock_init(&mac->hw_stats->stats_lock); - u64_stats_init(&mac->hw_stats->syncp); -- mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET; -+ -+ if (mtk_is_netsys_v3_or_greater(eth)) -+ mac->hw_stats->reg_offset = id * 0x80; -+ else -+ mac->hw_stats->reg_offset = id * 0x40; - - /* phylink create */ - err = of_get_phy_mode(np, &phy_mode); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -122,6 +122,7 @@ - #define MTK_GDMA_ICS_EN BIT(22) - #define MTK_GDMA_TCS_EN BIT(21) - #define MTK_GDMA_UCS_EN BIT(20) -+#define MTK_GDMA_STRP_CRC BIT(16) - #define MTK_GDMA_TO_PDMA 0x0 - #define MTK_GDMA_DROP_ALL 0x7777 - -@@ -287,8 +288,6 @@ - /* QDMA Interrupt grouping registers */ - #define MTK_RLS_DONE_INT BIT(0) - --#define MTK_STAT_OFFSET 0x40 -- - /* QDMA TX NUM */ - #define QID_BITS_V2(x) (((x) & 0x3f) << 16) - #define MTK_QDMA_GMAC2_QID 8 -@@ -301,6 +300,8 @@ - #define TX_DMA_CHKSUM_V2 (0x7 << 28) - #define TX_DMA_TSO_V2 BIT(31) - -+#define TX_DMA_SPTAG_V3 BIT(27) -+ - /* QDMA V2 descriptor txd4 */ - #define TX_DMA_FPORT_SHIFT_V2 8 - #define TX_DMA_FPORT_MASK_V2 0xf -@@ -634,12 +635,6 @@ enum mtk_tx_flags { - */ - MTK_TX_FLAGS_SINGLE0 = 0x01, - MTK_TX_FLAGS_PAGE0 = 0x02, -- -- /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted -- * SKB out instead of looking up through hardware TX descriptor. -- */ -- MTK_TX_FLAGS_FPORT0 = 0x04, -- MTK_TX_FLAGS_FPORT1 = 0x08, - }; - - /* This enum allows us to identify how the clock is defined on the array of the -@@ -725,6 +720,35 @@ enum mtk_dev_state { - MTK_RESETTING - }; - -+/* PSE Port Definition */ -+enum mtk_pse_port { -+ PSE_ADMA_PORT = 0, -+ PSE_GDM1_PORT, -+ PSE_GDM2_PORT, -+ PSE_PPE0_PORT, -+ PSE_PPE1_PORT, -+ PSE_QDMA_TX_PORT, -+ PSE_QDMA_RX_PORT, -+ PSE_DROP_PORT, -+ PSE_WDMA0_PORT, -+ PSE_WDMA1_PORT, -+ PSE_TDMA_PORT, -+ PSE_NONE_PORT, -+ PSE_PPE2_PORT, -+ PSE_WDMA2_PORT, -+ PSE_EIP197_PORT, -+ PSE_GDM3_PORT, -+ PSE_PORT_MAX -+}; -+ -+/* GMAC Identifier */ -+enum mtk_gmac_id { -+ MTK_GMAC1_ID = 0, -+ MTK_GMAC2_ID, -+ MTK_GMAC3_ID, -+ MTK_GMAC_ID_MAX -+}; -+ - enum mtk_tx_buf_type { - MTK_TYPE_SKB, - MTK_TYPE_XDP_TX, -@@ -743,7 +767,8 @@ struct mtk_tx_buf { - enum mtk_tx_buf_type type; - void *data; - -- u32 flags; -+ u16 mac_id; -+ u16 flags; - DEFINE_DMA_UNMAP_ADDR(dma_addr0); - DEFINE_DMA_UNMAP_LEN(dma_len0); - DEFINE_DMA_UNMAP_ADDR(dma_addr1); -@@ -1192,6 +1217,11 @@ static inline bool mtk_is_netsys_v2_or_g - return eth->soc->version > 1; - } - -+static inline bool mtk_is_netsys_v3_or_greater(struct mtk_eth *eth) -+{ -+ return eth->soc->version > 2; -+} -+ - static inline struct mtk_foe_entry * - mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) - { diff --git a/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch b/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch deleted file mode 100644 index 7a0b285f2c..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch +++ /dev/null @@ -1,193 +0,0 @@ -From db797ae0542220a98658229397da464c383c991c Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:53:13 +0100 -Subject: [PATCH 103/250] net: ethernet: mtk_eth_soc: convert caps in - mtk_soc_data struct to u64 - -This is a preliminary patch to introduce support for MT7988 SoC. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/9499ac3670b2fc5b444404b84e8a4a169beabbf2.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_path.c | 22 ++++---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 56 ++++++++++---------- - 2 files changed, 39 insertions(+), 39 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_path.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c -@@ -15,10 +15,10 @@ - struct mtk_eth_muxc { - const char *name; - int cap_bit; -- int (*set_path)(struct mtk_eth *eth, int path); -+ int (*set_path)(struct mtk_eth *eth, u64 path); - }; - --static const char *mtk_eth_path_name(int path) -+static const char *mtk_eth_path_name(u64 path) - { - switch (path) { - case MTK_ETH_PATH_GMAC1_RGMII: -@@ -40,7 +40,7 @@ static const char *mtk_eth_path_name(int - } - } - --static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path) -+static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) - { - bool updated = true; - u32 val, mask, set; -@@ -71,7 +71,7 @@ static int set_mux_gdm1_to_gmac1_esw(str - return 0; - } - --static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path) -+static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path) - { - unsigned int val = 0; - bool updated = true; -@@ -94,7 +94,7 @@ static int set_mux_gmac2_gmac0_to_gephy( - return 0; - } - --static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) -+static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path) - { - unsigned int val = 0, mask = 0, reg = 0; - bool updated = true; -@@ -125,7 +125,7 @@ static int set_mux_u3_gmac2_to_qphy(stru - return 0; - } - --static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path) -+static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path) - { - unsigned int val = 0; - bool updated = true; -@@ -163,7 +163,7 @@ static int set_mux_gmac1_gmac2_to_sgmii_ - return 0; - } - --static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path) -+static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path) - { - unsigned int val = 0; - bool updated = true; -@@ -218,7 +218,7 @@ static const struct mtk_eth_muxc mtk_eth - }, - }; - --static int mtk_eth_mux_setup(struct mtk_eth *eth, int path) -+static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path) - { - int i, err = 0; - -@@ -249,7 +249,7 @@ out: - - int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) - { -- int path; -+ u64 path; - - path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : - MTK_ETH_PATH_GMAC2_SGMII; -@@ -260,7 +260,7 @@ int mtk_gmac_sgmii_path_setup(struct mtk - - int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id) - { -- int path = 0; -+ u64 path = 0; - - if (mac_id == 1) - path = MTK_ETH_PATH_GMAC2_GEPHY; -@@ -274,7 +274,7 @@ int mtk_gmac_gephy_path_setup(struct mtk - - int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id) - { -- int path; -+ u64 path; - - path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII : - MTK_ETH_PATH_GMAC2_RGMII; ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -866,41 +866,41 @@ enum mkt_eth_capabilities { - }; - - /* Supported hardware group on SoCs */ --#define MTK_RGMII BIT(MTK_RGMII_BIT) --#define MTK_TRGMII BIT(MTK_TRGMII_BIT) --#define MTK_SGMII BIT(MTK_SGMII_BIT) --#define MTK_ESW BIT(MTK_ESW_BIT) --#define MTK_GEPHY BIT(MTK_GEPHY_BIT) --#define MTK_MUX BIT(MTK_MUX_BIT) --#define MTK_INFRA BIT(MTK_INFRA_BIT) --#define MTK_SHARED_SGMII BIT(MTK_SHARED_SGMII_BIT) --#define MTK_HWLRO BIT(MTK_HWLRO_BIT) --#define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT) --#define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) --#define MTK_QDMA BIT(MTK_QDMA_BIT) --#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) --#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) --#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) -+#define MTK_RGMII BIT_ULL(MTK_RGMII_BIT) -+#define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT) -+#define MTK_SGMII BIT_ULL(MTK_SGMII_BIT) -+#define MTK_ESW BIT_ULL(MTK_ESW_BIT) -+#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) -+#define MTK_MUX BIT_ULL(MTK_MUX_BIT) -+#define MTK_INFRA BIT_ULL(MTK_INFRA_BIT) -+#define MTK_SHARED_SGMII BIT_ULL(MTK_SHARED_SGMII_BIT) -+#define MTK_HWLRO BIT_ULL(MTK_HWLRO_BIT) -+#define MTK_SHARED_INT BIT_ULL(MTK_SHARED_INT_BIT) -+#define MTK_TRGMII_MT7621_CLK BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT) -+#define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) -+#define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) -+#define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) -+#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ -- BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) -+ BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) - #define MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY \ -- BIT(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) -+ BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) - #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \ -- BIT(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) -+ BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) - #define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \ -- BIT(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) -+ BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) - #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \ -- BIT(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) -+ BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) - - /* Supported path present on SoCs */ --#define MTK_ETH_PATH_GMAC1_RGMII BIT(MTK_ETH_PATH_GMAC1_RGMII_BIT) --#define MTK_ETH_PATH_GMAC1_TRGMII BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT) --#define MTK_ETH_PATH_GMAC1_SGMII BIT(MTK_ETH_PATH_GMAC1_SGMII_BIT) --#define MTK_ETH_PATH_GMAC2_RGMII BIT(MTK_ETH_PATH_GMAC2_RGMII_BIT) --#define MTK_ETH_PATH_GMAC2_SGMII BIT(MTK_ETH_PATH_GMAC2_SGMII_BIT) --#define MTK_ETH_PATH_GMAC2_GEPHY BIT(MTK_ETH_PATH_GMAC2_GEPHY_BIT) --#define MTK_ETH_PATH_GDM1_ESW BIT(MTK_ETH_PATH_GDM1_ESW_BIT) -+#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT) -+#define MTK_ETH_PATH_GMAC1_TRGMII BIT_ULL(MTK_ETH_PATH_GMAC1_TRGMII_BIT) -+#define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT) -+#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT) -+#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) -+#define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT) -+#define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT) - - #define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII) - #define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) -@@ -1045,7 +1045,7 @@ struct mtk_reg_map { - struct mtk_soc_data { - const struct mtk_reg_map *reg_map; - u32 ana_rgc3; -- u32 caps; -+ u64 caps; - u32 required_clks; - bool required_pctl; - u8 offload_version; diff --git a/target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch b/target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch deleted file mode 100644 index 5947d385f2..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch +++ /dev/null @@ -1,132 +0,0 @@ -From a1c9f7d1d24e90294f6a6755b137fcf306851e93 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 25 Jul 2023 01:53:28 +0100 -Subject: [PATCH 104/250] net: ethernet: mtk_eth_soc: convert clock bitmap to - u64 - -The to-be-added MT7988 SoC adds many new clocks which need to be -controlled by the Ethernet driver, which will result in their total -number exceeding 32. -Prepare by converting clock bitmaps into 64-bit types. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/6960a39bb0078cf84d7642a9558e6a91c6cc9df3.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 96 +++++++++++---------- - 1 file changed, 49 insertions(+), 47 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -666,54 +666,56 @@ enum mtk_clks_map { - MTK_CLK_MAX - }; - --#define MT7623_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ -- BIT(MTK_CLK_GP1) | BIT(MTK_CLK_GP2) | \ -- BIT(MTK_CLK_TRGPLL)) --#define MT7622_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ -- BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \ -- BIT(MTK_CLK_GP2) | \ -- BIT(MTK_CLK_SGMII_TX_250M) | \ -- BIT(MTK_CLK_SGMII_RX_250M) | \ -- BIT(MTK_CLK_SGMII_CDR_REF) | \ -- BIT(MTK_CLK_SGMII_CDR_FB) | \ -- BIT(MTK_CLK_SGMII_CK) | \ -- BIT(MTK_CLK_ETH2PLL)) -+#define MT7623_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ -+ BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \ -+ BIT_ULL(MTK_CLK_TRGPLL)) -+#define MT7622_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ -+ BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \ -+ BIT_ULL(MTK_CLK_GP2) | \ -+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ -+ BIT_ULL(MTK_CLK_SGMII_CK) | \ -+ BIT_ULL(MTK_CLK_ETH2PLL)) - #define MT7621_CLKS_BITMAP (0) - #define MT7628_CLKS_BITMAP (0) --#define MT7629_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ -- BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \ -- BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \ -- BIT(MTK_CLK_SGMII_TX_250M) | \ -- BIT(MTK_CLK_SGMII_RX_250M) | \ -- BIT(MTK_CLK_SGMII_CDR_REF) | \ -- BIT(MTK_CLK_SGMII_CDR_FB) | \ -- BIT(MTK_CLK_SGMII2_TX_250M) | \ -- BIT(MTK_CLK_SGMII2_RX_250M) | \ -- BIT(MTK_CLK_SGMII2_CDR_REF) | \ -- BIT(MTK_CLK_SGMII2_CDR_FB) | \ -- BIT(MTK_CLK_SGMII_CK) | \ -- BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP)) --#define MT7981_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ -- BIT(MTK_CLK_WOCPU0) | \ -- BIT(MTK_CLK_SGMII_TX_250M) | \ -- BIT(MTK_CLK_SGMII_RX_250M) | \ -- BIT(MTK_CLK_SGMII_CDR_REF) | \ -- BIT(MTK_CLK_SGMII_CDR_FB) | \ -- BIT(MTK_CLK_SGMII2_TX_250M) | \ -- BIT(MTK_CLK_SGMII2_RX_250M) | \ -- BIT(MTK_CLK_SGMII2_CDR_REF) | \ -- BIT(MTK_CLK_SGMII2_CDR_FB) | \ -- BIT(MTK_CLK_SGMII_CK)) --#define MT7986_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ -- BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \ -- BIT(MTK_CLK_SGMII_TX_250M) | \ -- BIT(MTK_CLK_SGMII_RX_250M) | \ -- BIT(MTK_CLK_SGMII_CDR_REF) | \ -- BIT(MTK_CLK_SGMII_CDR_FB) | \ -- BIT(MTK_CLK_SGMII2_TX_250M) | \ -- BIT(MTK_CLK_SGMII2_RX_250M) | \ -- BIT(MTK_CLK_SGMII2_CDR_REF) | \ -- BIT(MTK_CLK_SGMII2_CDR_FB)) -+#define MT7629_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ -+ BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \ -+ BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_FE) | \ -+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ -+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ -+ BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \ -+ BIT_ULL(MTK_CLK_SGMII_CK) | \ -+ BIT_ULL(MTK_CLK_ETH2PLL) | BIT_ULL(MTK_CLK_SGMIITOP)) -+#define MT7981_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | \ -+ BIT_ULL(MTK_CLK_GP1) | \ -+ BIT_ULL(MTK_CLK_WOCPU0) | \ -+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ -+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ -+ BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \ -+ BIT_ULL(MTK_CLK_SGMII_CK)) -+#define MT7986_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | \ -+ BIT_ULL(MTK_CLK_GP1) | \ -+ BIT_ULL(MTK_CLK_WOCPU1) | BIT_ULL(MTK_CLK_WOCPU0) | \ -+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ -+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ -+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ -+ BIT_ULL(MTK_CLK_SGMII2_CDR_FB)) - - enum mtk_dev_state { - MTK_HW_INIT, -@@ -1046,7 +1048,7 @@ struct mtk_soc_data { - const struct mtk_reg_map *reg_map; - u32 ana_rgc3; - u64 caps; -- u32 required_clks; -+ u64 required_clks; - bool required_pctl; - u8 offload_version; - u8 hash_offset; diff --git a/target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch b/target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch deleted file mode 100644 index 8c24321dd4..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch +++ /dev/null @@ -1,477 +0,0 @@ -From 94f825a7eadfc8b4c8828efdb7705d9703f9c73e Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:57:42 +0100 -Subject: [PATCH 105/250] net: ethernet: mtk_eth_soc: add basic support for - MT7988 SoC - -Introduce support for ethernet chip available in MT7988 SoC to -mtk_eth_soc driver. As a first step support only the first GMAC which -is hard-wired to the internal DSA switch having 4 built-in gigabit -Ethernet PHYs. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/25c8377095b95d186872eeda7aa055da83e8f0ca.1690246605.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_path.c | 14 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 201 +++++++++++++++++-- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 86 +++++++- - 3 files changed, 273 insertions(+), 28 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_path.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c -@@ -43,7 +43,7 @@ static const char *mtk_eth_path_name(u64 - static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) - { - bool updated = true; -- u32 val, mask, set; -+ u32 mask, set, reg; - - switch (path) { - case MTK_ETH_PATH_GMAC1_SGMII: -@@ -59,11 +59,13 @@ static int set_mux_gdm1_to_gmac1_esw(str - break; - } - -- if (updated) { -- val = mtk_r32(eth, MTK_MAC_MISC); -- val = (val & mask) | set; -- mtk_w32(eth, val, MTK_MAC_MISC); -- } -+ if (mtk_is_netsys_v3_or_greater(eth)) -+ reg = MTK_MAC_MISC_V3; -+ else -+ reg = MTK_MAC_MISC; -+ -+ if (updated) -+ mtk_m32(eth, mask, set, reg); - - dev_dbg(eth->dev, "path %s in %s updated = %d\n", - mtk_eth_path_name(path), __func__, updated); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -152,6 +152,54 @@ static const struct mtk_reg_map mt7986_r - .pse_oq_sta = 0x01a0, - }; - -+static const struct mtk_reg_map mt7988_reg_map = { -+ .tx_irq_mask = 0x461c, -+ .tx_irq_status = 0x4618, -+ .pdma = { -+ .rx_ptr = 0x6900, -+ .rx_cnt_cfg = 0x6904, -+ .pcrx_ptr = 0x6908, -+ .glo_cfg = 0x6a04, -+ .rst_idx = 0x6a08, -+ .delay_irq = 0x6a0c, -+ .irq_status = 0x6a20, -+ .irq_mask = 0x6a28, -+ .adma_rx_dbg0 = 0x6a38, -+ .int_grp = 0x6a50, -+ }, -+ .qdma = { -+ .qtx_cfg = 0x4400, -+ .qtx_sch = 0x4404, -+ .rx_ptr = 0x4500, -+ .rx_cnt_cfg = 0x4504, -+ .qcrx_ptr = 0x4508, -+ .glo_cfg = 0x4604, -+ .rst_idx = 0x4608, -+ .delay_irq = 0x460c, -+ .fc_th = 0x4610, -+ .int_grp = 0x4620, -+ .hred = 0x4644, -+ .ctx_ptr = 0x4700, -+ .dtx_ptr = 0x4704, -+ .crx_ptr = 0x4710, -+ .drx_ptr = 0x4714, -+ .fq_head = 0x4720, -+ .fq_tail = 0x4724, -+ .fq_count = 0x4728, -+ .fq_blen = 0x472c, -+ .tx_sch_rate = 0x4798, -+ }, -+ .gdm1_cnt = 0x1c00, -+ .gdma_to_ppe = 0x3333, -+ .ppe_base = 0x2000, -+ .wdma_base = { -+ [0] = 0x4800, -+ [1] = 0x4c00, -+ }, -+ .pse_iq_sta = 0x0180, -+ .pse_oq_sta = 0x01a0, -+}; -+ - /* strings used by ethtool */ - static const struct mtk_ethtool_stats { - char str[ETH_GSTRING_LEN]; -@@ -179,10 +227,54 @@ static const struct mtk_ethtool_stats { - }; - - static const char * const mtk_clks_source_name[] = { -- "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2", "fe", "trgpll", -- "sgmii_tx250m", "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb", -- "sgmii2_tx250m", "sgmii2_rx250m", "sgmii2_cdr_ref", "sgmii2_cdr_fb", -- "sgmii_ck", "eth2pll", "wocpu0", "wocpu1", "netsys0", "netsys1" -+ "ethif", -+ "sgmiitop", -+ "esw", -+ "gp0", -+ "gp1", -+ "gp2", -+ "gp3", -+ "xgp1", -+ "xgp2", -+ "xgp3", -+ "crypto", -+ "fe", -+ "trgpll", -+ "sgmii_tx250m", -+ "sgmii_rx250m", -+ "sgmii_cdr_ref", -+ "sgmii_cdr_fb", -+ "sgmii2_tx250m", -+ "sgmii2_rx250m", -+ "sgmii2_cdr_ref", -+ "sgmii2_cdr_fb", -+ "sgmii_ck", -+ "eth2pll", -+ "wocpu0", -+ "wocpu1", -+ "netsys0", -+ "netsys1", -+ "ethwarp_wocpu2", -+ "ethwarp_wocpu1", -+ "ethwarp_wocpu0", -+ "top_usxgmii0_sel", -+ "top_usxgmii1_sel", -+ "top_sgm0_sel", -+ "top_sgm1_sel", -+ "top_xfi_phy0_xtal_sel", -+ "top_xfi_phy1_xtal_sel", -+ "top_eth_gmii_sel", -+ "top_eth_refck_50m_sel", -+ "top_eth_sys_200m_sel", -+ "top_eth_sys_sel", -+ "top_eth_xgmii_sel", -+ "top_eth_mii_sel", -+ "top_netsys_sel", -+ "top_netsys_500m_sel", -+ "top_netsys_pao_2x_sel", -+ "top_netsys_sync_250m_sel", -+ "top_netsys_ppefb_250m_sel", -+ "top_netsys_warp_sel", - }; - - void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg) -@@ -195,7 +287,7 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne - return __raw_readl(eth->base + reg); - } - --static u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg) -+u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg) - { - u32 val; - -@@ -369,6 +461,19 @@ static void mtk_gmac0_rgmii_adjust(struc - dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); - } - -+static void mtk_setup_bridge_switch(struct mtk_eth *eth) -+{ -+ /* Force Port1 XGMAC Link Up */ -+ mtk_m32(eth, 0, MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID), -+ MTK_XGMAC_STS(MTK_GMAC1_ID)); -+ -+ /* Adjust GSW bridge IPG to 11 */ -+ mtk_m32(eth, GSWTX_IPG_MASK | GSWRX_IPG_MASK, -+ (GSW_IPG_11 << GSWTX_IPG_SHIFT) | -+ (GSW_IPG_11 << GSWRX_IPG_SHIFT), -+ MTK_GSW_CFG); -+} -+ - static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, - phy_interface_t interface) - { -@@ -438,6 +543,8 @@ static void mtk_mac_config(struct phylin - goto init_err; - } - break; -+ case PHY_INTERFACE_MODE_INTERNAL: -+ break; - default: - goto err_phy; - } -@@ -515,6 +622,15 @@ static void mtk_mac_config(struct phylin - return; - } - -+ /* Setup gmac */ -+ if (mtk_is_netsys_v3_or_greater(eth) && -+ mac->interface == PHY_INTERFACE_MODE_INTERNAL) { -+ mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id)); -+ mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id)); -+ -+ mtk_setup_bridge_switch(eth); -+ } -+ - return; - - err_phy: -@@ -725,11 +841,15 @@ static int mtk_mdio_init(struct mtk_eth - } - divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63); - -+ /* Configure MDC Turbo Mode */ -+ if (mtk_is_netsys_v3_or_greater(eth)) -+ mtk_m32(eth, 0, MISC_MDC_TURBO, MTK_MAC_MISC_V3); -+ - /* Configure MDC Divider */ -- val = mtk_r32(eth, MTK_PPSC); -- val &= ~PPSC_MDC_CFG; -- val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; -- mtk_w32(eth, val, MTK_PPSC); -+ val = FIELD_PREP(PPSC_MDC_CFG, divider); -+ if (!mtk_is_netsys_v3_or_greater(eth)) -+ val |= PPSC_MDC_TURBO; -+ mtk_m32(eth, PPSC_MDC_CFG, val, MTK_PPSC); - - dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); - -@@ -1190,10 +1310,19 @@ static void mtk_tx_set_dma_desc_v2(struc - data |= TX_DMA_LS0; - WRITE_ONCE(desc->txd3, data); - -- if (mac->id == MTK_GMAC3_ID) -- data = PSE_GDM3_PORT; -- else -- data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ -+ /* set forward port */ -+ switch (mac->id) { -+ case MTK_GMAC1_ID: -+ data = PSE_GDM1_PORT << TX_DMA_FPORT_SHIFT_V2; -+ break; -+ case MTK_GMAC2_ID: -+ data = PSE_GDM2_PORT << TX_DMA_FPORT_SHIFT_V2; -+ break; -+ case MTK_GMAC3_ID: -+ data = PSE_GDM3_PORT << TX_DMA_FPORT_SHIFT_V2; -+ break; -+ } -+ - data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); - WRITE_ONCE(desc->txd4, data); - -@@ -4360,6 +4489,17 @@ static int mtk_add_mac(struct mtk_eth *e - mac->phylink_config.supported_interfaces); - } - -+ if (mtk_is_netsys_v3_or_greater(mac->hw) && -+ MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW_BIT) && -+ id == MTK_GMAC1_ID) { -+ mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | -+ MAC_SYM_PAUSE | -+ MAC_10000FD; -+ phy_interface_zero(mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_INTERNAL, -+ mac->phylink_config.supported_interfaces); -+ } -+ - phylink = phylink_create(&mac->phylink_config, - of_fwnode_handle(mac->of_node), - phy_mode, &mtk_phylink_ops); -@@ -4880,6 +5020,24 @@ static const struct mtk_soc_data mt7986_ - }, - }; - -+static const struct mtk_soc_data mt7988_data = { -+ .reg_map = &mt7988_reg_map, -+ .ana_rgc3 = 0x128, -+ .caps = MT7988_CAPS, -+ .hw_features = MTK_HW_FEATURES, -+ .required_clks = MT7988_CLKS_BITMAP, -+ .required_pctl = false, -+ .version = 3, -+ .txrx = { -+ .txd_size = sizeof(struct mtk_tx_dma_v2), -+ .rxd_size = sizeof(struct mtk_rx_dma_v2), -+ .rx_irq_done_mask = MTK_RX_DONE_INT_V2, -+ .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, -+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, -+ .dma_len_offset = 8, -+ }, -+}; -+ - static const struct mtk_soc_data rt5350_data = { - .reg_map = &mt7628_reg_map, - .caps = MT7628_CAPS, -@@ -4898,14 +5056,15 @@ static const struct mtk_soc_data rt5350_ - }; - - const struct of_device_id of_mtk_match[] = { -- { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data}, -- { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data}, -- { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, -- { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, -- { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data}, -- { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data}, -- { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data}, -- { .compatible = "ralink,rt5350-eth", .data = &rt5350_data}, -+ { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data }, -+ { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data }, -+ { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data }, -+ { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data }, -+ { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data }, -+ { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data }, -+ { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data }, -+ { .compatible = "mediatek,mt7988-eth", .data = &mt7988_data }, -+ { .compatible = "ralink,rt5350-eth", .data = &rt5350_data }, - {}, - }; - MODULE_DEVICE_TABLE(of, of_mtk_match); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -117,7 +117,8 @@ - #define MTK_CDMP_EG_CTRL 0x404 - - /* GDM Exgress Control Register */ --#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) -+#define MTK_GDMA_FWD_CFG(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ -+ 0x540 : 0x500 + (_x * 0x1000); }) - #define MTK_GDMA_SPECIAL_TAG BIT(24) - #define MTK_GDMA_ICS_EN BIT(22) - #define MTK_GDMA_TCS_EN BIT(21) -@@ -126,6 +127,11 @@ - #define MTK_GDMA_TO_PDMA 0x0 - #define MTK_GDMA_DROP_ALL 0x7777 - -+/* GDM Egress Control Register */ -+#define MTK_GDMA_EG_CTRL(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ -+ 0x544 : 0x504 + (_x * 0x1000); }) -+#define MTK_GDMA_XGDM_SEL BIT(31) -+ - /* Unicast Filter MAC Address Register - Low */ - #define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) - -@@ -389,7 +395,26 @@ - #define PHY_IAC_TIMEOUT HZ - - #define MTK_MAC_MISC 0x1000c -+#define MTK_MAC_MISC_V3 0x10010 - #define MTK_MUX_TO_ESW BIT(0) -+#define MISC_MDC_TURBO BIT(4) -+ -+/* XMAC status registers */ -+#define MTK_XGMAC_STS(x) (((x) == MTK_GMAC3_ID) ? 0x1001C : 0x1000C) -+#define MTK_XGMAC_FORCE_LINK(x) (((x) == MTK_GMAC2_ID) ? BIT(31) : BIT(15)) -+#define MTK_USXGMII_PCS_LINK BIT(8) -+#define MTK_XGMAC_RX_FC BIT(5) -+#define MTK_XGMAC_TX_FC BIT(4) -+#define MTK_USXGMII_PCS_MODE GENMASK(3, 1) -+#define MTK_XGMAC_LINK_STS BIT(0) -+ -+/* GSW bridge registers */ -+#define MTK_GSW_CFG (0x10080) -+#define GSWTX_IPG_MASK GENMASK(19, 16) -+#define GSWTX_IPG_SHIFT 16 -+#define GSWRX_IPG_MASK GENMASK(3, 0) -+#define GSWRX_IPG_SHIFT 0 -+#define GSW_IPG_11 11 - - /* Mac control registers */ - #define MTK_MAC_MCR(x) (0x10100 + (x * 0x100)) -@@ -647,6 +672,11 @@ enum mtk_clks_map { - MTK_CLK_GP0, - MTK_CLK_GP1, - MTK_CLK_GP2, -+ MTK_CLK_GP3, -+ MTK_CLK_XGP1, -+ MTK_CLK_XGP2, -+ MTK_CLK_XGP3, -+ MTK_CLK_CRYPTO, - MTK_CLK_FE, - MTK_CLK_TRGPLL, - MTK_CLK_SGMII_TX_250M, -@@ -663,6 +693,27 @@ enum mtk_clks_map { - MTK_CLK_WOCPU1, - MTK_CLK_NETSYS0, - MTK_CLK_NETSYS1, -+ MTK_CLK_ETHWARP_WOCPU2, -+ MTK_CLK_ETHWARP_WOCPU1, -+ MTK_CLK_ETHWARP_WOCPU0, -+ MTK_CLK_TOP_USXGMII_SBUS_0_SEL, -+ MTK_CLK_TOP_USXGMII_SBUS_1_SEL, -+ MTK_CLK_TOP_SGM_0_SEL, -+ MTK_CLK_TOP_SGM_1_SEL, -+ MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL, -+ MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL, -+ MTK_CLK_TOP_ETH_GMII_SEL, -+ MTK_CLK_TOP_ETH_REFCK_50M_SEL, -+ MTK_CLK_TOP_ETH_SYS_200M_SEL, -+ MTK_CLK_TOP_ETH_SYS_SEL, -+ MTK_CLK_TOP_ETH_XGMII_SEL, -+ MTK_CLK_TOP_ETH_MII_SEL, -+ MTK_CLK_TOP_NETSYS_SEL, -+ MTK_CLK_TOP_NETSYS_500M_SEL, -+ MTK_CLK_TOP_NETSYS_PAO_2X_SEL, -+ MTK_CLK_TOP_NETSYS_SYNC_250M_SEL, -+ MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL, -+ MTK_CLK_TOP_NETSYS_WARP_SEL, - MTK_CLK_MAX - }; - -@@ -716,6 +767,36 @@ enum mtk_clks_map { - BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ - BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ - BIT_ULL(MTK_CLK_SGMII2_CDR_FB)) -+#define MT7988_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_ESW) | \ -+ BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \ -+ BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \ -+ BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \ -+ BIT_ULL(MTK_CLK_CRYPTO) | \ -+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ -+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ -+ BIT_ULL(MTK_CLK_ETHWARP_WOCPU2) | \ -+ BIT_ULL(MTK_CLK_ETHWARP_WOCPU1) | \ -+ BIT_ULL(MTK_CLK_ETHWARP_WOCPU0) | \ -+ BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_0_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_1_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_SGM_0_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_SGM_1_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_ETH_SYS_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_ETH_XGMII_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_ETH_MII_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_NETSYS_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_NETSYS_500M_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_NETSYS_PAO_2X_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_NETSYS_SYNC_250M_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL) | \ -+ BIT_ULL(MTK_CLK_TOP_NETSYS_WARP_SEL)) - - enum mtk_dev_state { - MTK_HW_INIT, -@@ -964,6 +1045,8 @@ enum mkt_eth_capabilities { - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_RSTCTRL_PPE1) - -+#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) -+ - struct mtk_tx_dma_desc_info { - dma_addr_t addr; - u32 size; -@@ -1309,6 +1392,7 @@ void mtk_stats_update_mac(struct mtk_mac - - void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); - u32 mtk_r32(struct mtk_eth *eth, unsigned reg); -+u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg); - - int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); - int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); diff --git a/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch b/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch deleted file mode 100644 index 3dc4662d1a..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 38a7eb76220731eff40602cf433f24880be0a6c2 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Thu, 27 Jul 2023 09:02:26 +0200 -Subject: [PATCH 106/250] net: ethernet: mtk_eth_soc: enable page_pool support - for MT7988 SoC - -In order to recycle pages, enable page_pool allocator for MT7988 SoC. - -Tested-by: Daniel Golle -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/fd4e8693980e47385a543e7b002eec0b88bd09df.1690440675.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1658,7 +1658,7 @@ static void mtk_update_rx_cpu_idx(struct - - static bool mtk_page_pool_enabled(struct mtk_eth *eth) - { -- return eth->soc->version == 2; -+ return mtk_is_netsys_v2_or_greater(eth); - } - - static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, diff --git a/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch b/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch deleted file mode 100644 index 32f26d7d27..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 199e7d5a7f03dd377f3a7a458360dbedd71d50ba Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Thu, 27 Jul 2023 09:07:28 +0200 -Subject: [PATCH 107/250] net: ethernet: mtk_eth_soc: enable nft hw - flowtable_offload for MT7988 SoC - -Enable hw Packet Process Engine (PPE) for MT7988 SoC. - -Tested-by: Daniel Golle -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/5e86341b0220a49620dadc02d77970de5ded9efc.1690441576.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++ - drivers/net/ethernet/mediatek/mtk_ppe.c | 19 +++++++++++++++---- - drivers/net/ethernet/mediatek/mtk_ppe.h | 19 ++++++++++++++++++- - 3 files changed, 36 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5028,6 +5028,9 @@ static const struct mtk_soc_data mt7988_ - .required_clks = MT7988_CLKS_BITMAP, - .required_pctl = false, - .version = 3, -+ .offload_version = 2, -+ .hash_offset = 4, -+ .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -422,13 +422,22 @@ int mtk_foe_entry_set_wdma(struct mtk_et - struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - -- if (mtk_is_netsys_v2_or_greater(eth)) { -+ switch (eth->soc->version) { -+ case 3: -+ *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; -+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | -+ MTK_FOE_IB2_WDMA_WINFO_V2; -+ l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) | -+ FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss); -+ break; -+ case 2: - *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; - *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | - MTK_FOE_IB2_WDMA_WINFO_V2; - l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) | - FIELD_PREP(MTK_FOE_WINFO_BSS, bss); -- } else { -+ break; -+ default: - *ib2 &= ~MTK_FOE_IB2_PORT_MG; - *ib2 |= MTK_FOE_IB2_WDMA_WINFO; - if (wdma_idx) -@@ -436,6 +445,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et - l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) | - FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) | - FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq); -+ break; - } - - return 0; -@@ -950,8 +960,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - mtk_ppe_init_foe_table(ppe); - ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys); - -- val = MTK_PPE_TB_CFG_ENTRY_80B | -- MTK_PPE_TB_CFG_AGE_NON_L4 | -+ val = MTK_PPE_TB_CFG_AGE_NON_L4 | - MTK_PPE_TB_CFG_AGE_UNBIND | - MTK_PPE_TB_CFG_AGE_TCP | - MTK_PPE_TB_CFG_AGE_UDP | -@@ -967,6 +976,8 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - MTK_PPE_ENTRIES_SHIFT); - if (mtk_is_netsys_v2_or_greater(ppe->eth)) - val |= MTK_PPE_TB_CFG_INFO_SEL; -+ if (!mtk_is_netsys_v3_or_greater(ppe->eth)) -+ val |= MTK_PPE_TB_CFG_ENTRY_80B; - ppe_w32(ppe, MTK_PPE_TB_CFG, val); - - ppe_w32(ppe, MTK_PPE_IP_PROTO_CHK, ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -85,6 +85,17 @@ enum { - #define MTK_FOE_WINFO_BSS GENMASK(5, 0) - #define MTK_FOE_WINFO_WCID GENMASK(15, 6) - -+#define MTK_FOE_WINFO_BSS_V3 GENMASK(23, 16) -+#define MTK_FOE_WINFO_WCID_V3 GENMASK(15, 0) -+ -+#define MTK_FOE_WINFO_PAO_USR_INFO GENMASK(15, 0) -+#define MTK_FOE_WINFO_PAO_TID GENMASK(19, 16) -+#define MTK_FOE_WINFO_PAO_IS_FIXEDRATE BIT(20) -+#define MTK_FOE_WINFO_PAO_IS_PRIOR BIT(21) -+#define MTK_FOE_WINFO_PAO_IS_SP BIT(22) -+#define MTK_FOE_WINFO_PAO_HF BIT(23) -+#define MTK_FOE_WINFO_PAO_AMSDU_EN BIT(24) -+ - enum { - MTK_FOE_STATE_INVALID, - MTK_FOE_STATE_UNBIND, -@@ -106,8 +117,13 @@ struct mtk_foe_mac_info { - u16 pppoe_id; - u16 src_mac_lo; - -+ /* netsys_v2 */ - u16 minfo; - u16 winfo; -+ -+ /* netsys_v3 */ -+ u32 w3info; -+ u32 wpao; - }; - - /* software-only entry type */ -@@ -218,6 +234,7 @@ struct mtk_foe_ipv6_6rd { - - #define MTK_FOE_ENTRY_V1_SIZE 80 - #define MTK_FOE_ENTRY_V2_SIZE 96 -+#define MTK_FOE_ENTRY_V3_SIZE 128 - - struct mtk_foe_entry { - u32 ib1; -@@ -228,7 +245,7 @@ struct mtk_foe_entry { - struct mtk_foe_ipv4_dslite dslite; - struct mtk_foe_ipv6 ipv6; - struct mtk_foe_ipv6_6rd ipv6_6rd; -- u32 data[23]; -+ u32 data[31]; - }; - }; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch b/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch deleted file mode 100644 index 876bdd5dd3..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0c024632c1e7ff69914329bfd87bec749b9c0aed Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 2 Aug 2023 04:31:09 +0100 -Subject: [PATCH 108/250] net: ethernet: mtk_eth_soc: support per-flow - accounting on MT7988 - -NETSYS_V3 uses 64 bits for each counters while older SoCs are using -48/40 bits for each counter. -Support reading per-flow byte and package counters on NETSYS_V3. - -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Link: https://lore.kernel.org/r/37a0928fa8c1253b197884c68ce1f54239421ac5.1690946442.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + - drivers/net/ethernet/mediatek/mtk_ppe.c | 21 +++++++++++++------- - drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 2 ++ - 3 files changed, 17 insertions(+), 7 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5030,6 +5030,7 @@ static const struct mtk_soc_data mt7988_ - .version = 3, - .offload_version = 2, - .hash_offset = 4, -+ .has_accounting = true, - .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -91,7 +91,6 @@ static int mtk_ppe_mib_wait_busy(struct - - static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) - { -- u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; - u32 val, cnt_r0, cnt_r1, cnt_r2; - int ret; - -@@ -106,12 +105,20 @@ static int mtk_mib_entry_read(struct mtk - cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); - cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); - -- byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); -- byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); -- pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); -- pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); -- *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; -- *packets = (pkt_cnt_high << 16) | pkt_cnt_low; -+ if (mtk_is_netsys_v3_or_greater(ppe->eth)) { -+ /* 64 bit for each counter */ -+ u32 cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3); -+ *bytes = ((u64)cnt_r1 << 32) | cnt_r0; -+ *packets = ((u64)cnt_r3 << 32) | cnt_r2; -+ } else { -+ /* 48 bit byte counter, 40 bit packet counter */ -+ u32 byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); -+ u32 byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); -+ u32 pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); -+ u32 pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); -+ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; -+ *packets = (pkt_cnt_high << 16) | pkt_cnt_low; -+ } - - return 0; - } ---- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -@@ -163,6 +163,8 @@ enum { - #define MTK_PPE_MIB_SER_R2 0x348 - #define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) - -+#define MTK_PPE_MIB_SER_R3 0x34c -+ - #define MTK_PPE_MIB_CACHE_CTL 0x350 - #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) - #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) diff --git a/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch b/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch deleted file mode 100644 index 6f1639a572..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 3b12f42772c26869d60398c1710aa27b27cd945c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 21 Aug 2023 17:12:44 +0100 -Subject: [PATCH 109/250] net: ethernet: mtk_eth_soc: fix NULL pointer on hw - reset - -When a hardware reset is triggered on devices not initializing WED the -calls to mtk_wed_fe_reset and mtk_wed_fe_reset_complete dereference a -pointer on uninitialized stack memory. -Break out of both functions in case a hw_list entry is 0. - -Fixes: 08a764a7c51b ("net: ethernet: mtk_wed: add reset/reset_complete callbacks") -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Acked-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/5465c1609b464cc7407ae1530c40821dcdf9d3e6.1692634266.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_wed.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -214,9 +214,13 @@ void mtk_wed_fe_reset(void) - - for (i = 0; i < ARRAY_SIZE(hw_list); i++) { - struct mtk_wed_hw *hw = hw_list[i]; -- struct mtk_wed_device *dev = hw->wed_dev; -+ struct mtk_wed_device *dev; - int err; - -+ if (!hw) -+ break; -+ -+ dev = hw->wed_dev; - if (!dev || !dev->wlan.reset) - continue; - -@@ -237,8 +241,12 @@ void mtk_wed_fe_reset_complete(void) - - for (i = 0; i < ARRAY_SIZE(hw_list); i++) { - struct mtk_wed_hw *hw = hw_list[i]; -- struct mtk_wed_device *dev = hw->wed_dev; -+ struct mtk_wed_device *dev; -+ -+ if (!hw) -+ break; - -+ dev = hw->wed_dev; - if (!dev || !dev->wlan.reset_complete) - continue; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch b/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch deleted file mode 100644 index 2190761fdd..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 489aea123d74a846ce746bfdb3efe1e7ad512e0d Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:31:24 +0100 -Subject: [PATCH 110/250] net: ethernet: mtk_eth_soc: fix register definitions - for MT7988 - -More register macros need to be adjusted for the 3rd GMAC on MT7988. -Account for added bit in SYSCFG0_SGMII_MASK. - -Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Link: https://lore.kernel.org/r/1c8da012e2ca80939906d85f314138c552139f0f.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -133,10 +133,12 @@ - #define MTK_GDMA_XGDM_SEL BIT(31) - - /* Unicast Filter MAC Address Register - Low */ --#define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) -+#define MTK_GDMA_MAC_ADRL(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ -+ 0x548 : 0x508 + (_x * 0x1000); }) - - /* Unicast Filter MAC Address Register - High */ --#define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000)) -+#define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ -+ 0x54C : 0x50C + (_x * 0x1000); }) - - /* FE global misc reg*/ - #define MTK_FE_GLO_MISC 0x124 -@@ -503,7 +505,7 @@ - #define ETHSYS_SYSCFG0 0x14 - #define SYSCFG0_GE_MASK 0x3 - #define SYSCFG0_GE_MODE(x, y) (x << (12 + (y * 2))) --#define SYSCFG0_SGMII_MASK GENMASK(9, 8) -+#define SYSCFG0_SGMII_MASK GENMASK(9, 7) - #define SYSCFG0_SGMII_GMAC1 ((2 << 8) & SYSCFG0_SGMII_MASK) - #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) - #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) diff --git a/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch b/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch deleted file mode 100644 index 05a18364d6..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 15a84d1c44ae8c1451c265ee60500588a24e8cd6 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:32:03 +0100 -Subject: [PATCH 111/250] net: ethernet: mtk_eth_soc: add reset bits for MT7988 - -Add bits needed to reset the frame engine on MT7988. - -Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/89b6c38380e7a3800c1362aa7575600717bc7543.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 76 +++++++++++++++------ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 16 +++-- - 2 files changed, 68 insertions(+), 24 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3594,19 +3594,34 @@ static void mtk_hw_reset(struct mtk_eth - { - u32 val; - -- if (mtk_is_netsys_v2_or_greater(eth)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); -+ -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ val = RSTCTRL_PPE0_V3; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= RSTCTRL_PPE1_V3; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ val |= RSTCTRL_PPE2; -+ -+ val |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; -+ } else if (mtk_is_netsys_v2_or_greater(eth)) { - val = RSTCTRL_PPE0_V2; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= RSTCTRL_PPE1; - } else { - val = RSTCTRL_PPE0; - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val |= RSTCTRL_PPE1; -- - ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); - -- if (mtk_is_netsys_v2_or_greater(eth)) -+ if (mtk_is_netsys_v3_or_greater(eth)) -+ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, -+ 0x6f8ff); -+ else if (mtk_is_netsys_v2_or_greater(eth)) - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, - 0x3ffffff); - } -@@ -3632,13 +3647,21 @@ static void mtk_hw_warm_reset(struct mtk - return; - } - -- if (mtk_is_netsys_v2_or_greater(eth)) -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ rst_mask |= RSTCTRL_PPE1_V3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ rst_mask |= RSTCTRL_PPE2; -+ -+ rst_mask |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; -+ } else if (mtk_is_netsys_v2_or_greater(eth)) { - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; -- else -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ rst_mask |= RSTCTRL_PPE1; -+ } else { - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; -- -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- rst_mask |= RSTCTRL_PPE1; -+ } - - regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); - -@@ -3990,11 +4013,17 @@ static void mtk_prepare_for_reset(struct - u32 val; - int i; - -- /* disabe FE P3 and P4 */ -- val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3; -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val |= MTK_FE_LINK_DOWN_P4; -- mtk_w32(eth, val, MTK_FE_GLO_CFG); -+ /* set FE PPE ports link down */ -+ for (i = MTK_GMAC1_ID; -+ i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); -+ i += 2) { -+ val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) | MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ val |= MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); -+ mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); -+ } - - /* adjust PPE configurations to prepare for reset */ - for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) -@@ -4055,11 +4084,18 @@ static void mtk_pending_work(struct work - } - } - -- /* enabe FE P3 and P4 */ -- val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3; -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val &= ~MTK_FE_LINK_DOWN_P4; -- mtk_w32(eth, val, MTK_FE_GLO_CFG); -+ /* set FE PPE ports link up */ -+ for (i = MTK_GMAC1_ID; -+ i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); -+ i += 2) { -+ val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) & ~MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); -+ -+ mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); -+ } - - clear_bit(MTK_RESETTING, ð->state); - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -76,9 +76,8 @@ - #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 - - /* Frame Engine Global Configuration */ --#define MTK_FE_GLO_CFG 0x00 --#define MTK_FE_LINK_DOWN_P3 BIT(11) --#define MTK_FE_LINK_DOWN_P4 BIT(12) -+#define MTK_FE_GLO_CFG(x) (((x) == MTK_GMAC3_ID) ? 0x24 : 0x00) -+#define MTK_FE_LINK_DOWN_P(x) BIT(((x) + 8) % 16) - - /* Frame Engine Global Reset Register */ - #define MTK_RST_GL 0x04 -@@ -522,9 +521,15 @@ - /* ethernet reset control register */ - #define ETHSYS_RSTCTRL 0x34 - #define RSTCTRL_FE BIT(6) -+#define RSTCTRL_WDMA0 BIT(24) -+#define RSTCTRL_WDMA1 BIT(25) -+#define RSTCTRL_WDMA2 BIT(26) - #define RSTCTRL_PPE0 BIT(31) - #define RSTCTRL_PPE0_V2 BIT(30) - #define RSTCTRL_PPE1 BIT(31) -+#define RSTCTRL_PPE0_V3 BIT(29) -+#define RSTCTRL_PPE1_V3 BIT(30) -+#define RSTCTRL_PPE2 BIT(31) - #define RSTCTRL_ETH BIT(23) - - /* ethernet reset check idle register */ -@@ -931,6 +936,7 @@ enum mkt_eth_capabilities { - MTK_QDMA_BIT, - MTK_SOC_MT7628_BIT, - MTK_RSTCTRL_PPE1_BIT, -+ MTK_RSTCTRL_PPE2_BIT, - MTK_U3_COPHY_V2_BIT, - - /* MUX BITS*/ -@@ -965,6 +971,7 @@ enum mkt_eth_capabilities { - #define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) - #define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) - #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) -+#define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) - #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ -@@ -1047,7 +1054,8 @@ enum mkt_eth_capabilities { - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_RSTCTRL_PPE1) - --#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) -+#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ -+ MTK_RSTCTRL_PPE2) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; diff --git a/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch b/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch deleted file mode 100644 index 74ac8dc898..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch +++ /dev/null @@ -1,254 +0,0 @@ -From 25ce45fe40b574e5d7ffa407f7f2db03e7d5a910 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:32:54 +0100 -Subject: [PATCH 112/250] net: ethernet: mtk_eth_soc: add support for in-SoC - SRAM - -MT7981, MT7986 and MT7988 come with in-SoC SRAM dedicated for Ethernet -DMA rings. Support using the SRAM without breaking existing device tree -bindings, ie. only new SoC starting from MT7988 will have the SRAM -declared as additional resource in device tree. For MT7981 and MT7986 -an offset on top of the main I/O base is used. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/e45e0f230c63ad58869e8fe35b95a2fb8925b625.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 88 ++++++++++++++++----- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++- - 2 files changed, 78 insertions(+), 22 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1118,10 +1118,13 @@ static int mtk_init_fq_dma(struct mtk_et - dma_addr_t dma_addr; - int i; - -- eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, -- cnt * soc->txrx.txd_size, -- ð->phy_scratch_ring, -- GFP_KERNEL); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) -+ eth->scratch_ring = eth->sram_base; -+ else -+ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, -+ cnt * soc->txrx.txd_size, -+ ð->phy_scratch_ring, -+ GFP_KERNEL); - if (unlikely(!eth->scratch_ring)) - return -ENOMEM; - -@@ -2429,8 +2432,14 @@ static int mtk_tx_alloc(struct mtk_eth * - if (!ring->buf) - goto no_tx_mem; - -- ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, -- &ring->phys, GFP_KERNEL); -+ if (MTK_HAS_CAPS(soc->caps, MTK_SRAM)) { -+ ring->dma = eth->sram_base + ring_size * sz; -+ ring->phys = eth->phy_scratch_ring + ring_size * (dma_addr_t)sz; -+ } else { -+ ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, -+ &ring->phys, GFP_KERNEL); -+ } -+ - if (!ring->dma) - goto no_tx_mem; - -@@ -2529,8 +2538,7 @@ static void mtk_tx_clean(struct mtk_eth - kfree(ring->buf); - ring->buf = NULL; - } -- -- if (ring->dma) { -+ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { - dma_free_coherent(eth->dma_dev, - ring->dma_size * soc->txrx.txd_size, - ring->dma, ring->phys); -@@ -2549,9 +2557,14 @@ static int mtk_rx_alloc(struct mtk_eth * - { - const struct mtk_reg_map *reg_map = eth->soc->reg_map; - struct mtk_rx_ring *ring; -- int rx_data_len, rx_dma_size; -+ int rx_data_len, rx_dma_size, tx_ring_size; - int i; - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -+ tx_ring_size = MTK_QDMA_RING_SIZE; -+ else -+ tx_ring_size = MTK_DMA_SIZE; -+ - if (rx_flag == MTK_RX_FLAGS_QDMA) { - if (ring_no) - return -EINVAL; -@@ -2586,9 +2599,20 @@ static int mtk_rx_alloc(struct mtk_eth * - ring->page_pool = pp; - } - -- ring->dma = dma_alloc_coherent(eth->dma_dev, -- rx_dma_size * eth->soc->txrx.rxd_size, -- &ring->phys, GFP_KERNEL); -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || -+ rx_flag != MTK_RX_FLAGS_NORMAL) { -+ ring->dma = dma_alloc_coherent(eth->dma_dev, -+ rx_dma_size * eth->soc->txrx.rxd_size, -+ &ring->phys, GFP_KERNEL); -+ } else { -+ struct mtk_tx_ring *tx_ring = ð->tx_ring; -+ -+ ring->dma = tx_ring->dma + tx_ring_size * -+ eth->soc->txrx.txd_size * (ring_no + 1); -+ ring->phys = tx_ring->phys + tx_ring_size * -+ eth->soc->txrx.txd_size * (ring_no + 1); -+ } -+ - if (!ring->dma) - return -ENOMEM; - -@@ -2673,7 +2697,7 @@ static int mtk_rx_alloc(struct mtk_eth * - return 0; - } - --static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring) -+static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) - { - int i; - -@@ -2696,7 +2720,7 @@ static void mtk_rx_clean(struct mtk_eth - ring->data = NULL; - } - -- if (ring->dma) { -+ if (!in_sram && ring->dma) { - dma_free_coherent(eth->dma_dev, - ring->dma_size * eth->soc->txrx.rxd_size, - ring->dma, ring->phys); -@@ -3059,7 +3083,7 @@ static void mtk_dma_free(struct mtk_eth - for (i = 0; i < MTK_MAX_DEVS; i++) - if (eth->netdev[i]) - netdev_reset_queue(eth->netdev[i]); -- if (eth->scratch_ring) { -+ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { - dma_free_coherent(eth->dma_dev, - MTK_QDMA_RING_SIZE * soc->txrx.txd_size, - eth->scratch_ring, eth->phy_scratch_ring); -@@ -3067,13 +3091,13 @@ static void mtk_dma_free(struct mtk_eth - eth->phy_scratch_ring = 0; - } - mtk_tx_clean(eth); -- mtk_rx_clean(eth, ð->rx_ring[0]); -- mtk_rx_clean(eth, ð->rx_ring_qdma); -+ mtk_rx_clean(eth, ð->rx_ring[0], MTK_HAS_CAPS(soc->caps, MTK_SRAM)); -+ mtk_rx_clean(eth, ð->rx_ring_qdma, false); - - if (eth->hwlro) { - mtk_hwlro_rx_uninit(eth); - for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) -- mtk_rx_clean(eth, ð->rx_ring[i]); -+ mtk_rx_clean(eth, ð->rx_ring[i], false); - } - - kfree(eth->scratch_head); -@@ -4641,7 +4665,7 @@ static int mtk_sgmii_init(struct mtk_eth - - static int mtk_probe(struct platform_device *pdev) - { -- struct resource *res = NULL; -+ struct resource *res = NULL, *res_sram; - struct device_node *mac_np; - struct mtk_eth *eth; - int err, i; -@@ -4661,6 +4685,20 @@ static int mtk_probe(struct platform_dev - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) - eth->ip_align = NET_IP_ALIGN; - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { -+ /* SRAM is actual memory and supports transparent access just like DRAM. -+ * Hence we don't require __iomem being set and don't need to use accessor -+ * functions to read from or write to SRAM. -+ */ -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ eth->sram_base = (void __force *)devm_platform_ioremap_resource(pdev, 1); -+ if (IS_ERR(eth->sram_base)) -+ return PTR_ERR(eth->sram_base); -+ } else { -+ eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET; -+ } -+ } -+ - spin_lock_init(ð->page_lock); - spin_lock_init(ð->tx_irq_lock); - spin_lock_init(ð->rx_irq_lock); -@@ -4724,6 +4762,18 @@ static int mtk_probe(struct platform_dev - err = -EINVAL; - goto err_destroy_sgmii; - } -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ res_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (!res_sram) { -+ err = -EINVAL; -+ goto err_destroy_sgmii; -+ } -+ eth->phy_scratch_ring = res_sram->start; -+ } else { -+ eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET; -+ } -+ } - } - - if (eth->soc->offload_version) { ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -139,6 +139,9 @@ - #define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ - 0x54C : 0x50C + (_x * 0x1000); }) - -+/* Internal SRAM offset */ -+#define MTK_ETH_SRAM_OFFSET 0x40000 -+ - /* FE global misc reg*/ - #define MTK_FE_GLO_MISC 0x124 - -@@ -938,6 +941,7 @@ enum mkt_eth_capabilities { - MTK_RSTCTRL_PPE1_BIT, - MTK_RSTCTRL_PPE2_BIT, - MTK_U3_COPHY_V2_BIT, -+ MTK_SRAM_BIT, - - /* MUX BITS*/ - MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, -@@ -973,6 +977,7 @@ enum mkt_eth_capabilities { - #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) - #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) - #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) -+#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ - BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) -@@ -1048,14 +1053,14 @@ enum mkt_eth_capabilities { - #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ -- MTK_RSTCTRL_PPE1) -+ MTK_RSTCTRL_PPE1 | MTK_SRAM) - - #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ -- MTK_RSTCTRL_PPE1) -+ MTK_RSTCTRL_PPE1 | MTK_SRAM) - - #define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ -- MTK_RSTCTRL_PPE2) -+ MTK_RSTCTRL_PPE2 | MTK_SRAM) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; -@@ -1215,6 +1220,7 @@ struct mtk_eth { - struct device *dev; - struct device *dma_dev; - void __iomem *base; -+ void *sram_base; - spinlock_t page_lock; - spinlock_t tx_irq_lock; - spinlock_t rx_irq_lock; diff --git a/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch b/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch deleted file mode 100644 index 1584dfd07c..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 0b0d606eb9650fa01dd5621e072aa29a10544399 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:33:12 +0100 -Subject: [PATCH 113/250] net: ethernet: mtk_eth_soc: support 36-bit DMA - addressing on MT7988 - -Systems having 4 GiB of RAM and more require DMA addressing beyond the -current 32-bit limit. Starting from MT7988 the hardware now supports -36-bit DMA addressing, let's use that new capability in the driver to -avoid running into swiotlb on systems with 4 GiB of RAM or more. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/95b919c98876c9e49761e44662e7c937479eecb8.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 +++++++++++++++++++-- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 22 +++++++++++++-- - 2 files changed, 48 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1311,6 +1311,10 @@ static void mtk_tx_set_dma_desc_v2(struc - data = TX_DMA_PLEN0(info->size); - if (info->last) - data |= TX_DMA_LS0; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ data |= TX_DMA_PREP_ADDR64(info->addr); -+ - WRITE_ONCE(desc->txd3, data); - - /* set forward port */ -@@ -1980,6 +1984,7 @@ static int mtk_poll_rx(struct napi_struc - bool xdp_flush = false; - int idx; - struct sk_buff *skb; -+ u64 addr64 = 0; - u8 *data, *new_data; - struct mtk_rx_dma_v2 *rxd, trxd; - int done = 0, bytes = 0; -@@ -2095,7 +2100,10 @@ static int mtk_poll_rx(struct napi_struc - goto release_desc; - } - -- dma_unmap_single(eth->dma_dev, trxd.rxd1, -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ addr64 = RX_DMA_GET_ADDR64(trxd.rxd2); -+ -+ dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64), - ring->buf_size, DMA_FROM_DEVICE); - - skb = build_skb(data, ring->frag_size); -@@ -2161,6 +2169,9 @@ release_desc: - else - rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); -+ - ring->calc_idx = idx; - done++; - } -@@ -2653,6 +2664,9 @@ static int mtk_rx_alloc(struct mtk_eth * - else - rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); -+ - rxd->rxd3 = 0; - rxd->rxd4 = 0; - if (mtk_is_netsys_v2_or_greater(eth)) { -@@ -2699,6 +2713,7 @@ static int mtk_rx_alloc(struct mtk_eth * - - static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) - { -+ u64 addr64 = 0; - int i; - - if (ring->data && ring->dma) { -@@ -2712,7 +2727,10 @@ static void mtk_rx_clean(struct mtk_eth - if (!rxd->rxd1) - continue; - -- dma_unmap_single(eth->dma_dev, rxd->rxd1, -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ addr64 = RX_DMA_GET_ADDR64(rxd->rxd2); -+ -+ dma_unmap_single(eth->dma_dev, ((u64)rxd->rxd1 | addr64), - ring->buf_size, DMA_FROM_DEVICE); - mtk_rx_put_buff(ring, ring->data[i], false); - } -@@ -4699,6 +4717,14 @@ static int mtk_probe(struct platform_dev - } - } - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { -+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); -+ if (err) { -+ dev_err(&pdev->dev, "Wrong DMA config\n"); -+ return -EINVAL; -+ } -+ } -+ - spin_lock_init(ð->page_lock); - spin_lock_init(ð->tx_irq_lock); - spin_lock_init(ð->rx_irq_lock); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -331,6 +331,14 @@ - #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) - #define TX_DMA_SWC BIT(14) - #define TX_DMA_PQID GENMASK(3, 0) -+#define TX_DMA_ADDR64_MASK GENMASK(3, 0) -+#if IS_ENABLED(CONFIG_64BIT) -+# define TX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(TX_DMA_ADDR64_MASK, (x))) << 32) -+# define TX_DMA_PREP_ADDR64(x) FIELD_PREP(TX_DMA_ADDR64_MASK, ((x) >> 32)) -+#else -+# define TX_DMA_GET_ADDR64(x) (0) -+# define TX_DMA_PREP_ADDR64(x) (0) -+#endif - - /* PDMA on MT7628 */ - #define TX_DMA_DONE BIT(31) -@@ -343,6 +351,14 @@ - #define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) - #define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) - #define RX_DMA_VTAG BIT(15) -+#define RX_DMA_ADDR64_MASK GENMASK(3, 0) -+#if IS_ENABLED(CONFIG_64BIT) -+# define RX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(RX_DMA_ADDR64_MASK, (x))) << 32) -+# define RX_DMA_PREP_ADDR64(x) FIELD_PREP(RX_DMA_ADDR64_MASK, ((x) >> 32)) -+#else -+# define RX_DMA_GET_ADDR64(x) (0) -+# define RX_DMA_PREP_ADDR64(x) (0) -+#endif - - /* QDMA descriptor rxd3 */ - #define RX_DMA_VID(x) ((x) & VLAN_VID_MASK) -@@ -942,6 +958,7 @@ enum mkt_eth_capabilities { - MTK_RSTCTRL_PPE2_BIT, - MTK_U3_COPHY_V2_BIT, - MTK_SRAM_BIT, -+ MTK_36BIT_DMA_BIT, - - /* MUX BITS*/ - MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, -@@ -978,6 +995,7 @@ enum mkt_eth_capabilities { - #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) - #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) - #define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) -+#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ - BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) -@@ -1059,8 +1077,8 @@ enum mkt_eth_capabilities { - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_RSTCTRL_PPE1 | MTK_SRAM) - --#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ -- MTK_RSTCTRL_PPE2 | MTK_SRAM) -+#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_QDMA | \ -+ MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; diff --git a/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch b/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch deleted file mode 100644 index 5b27458eb8..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch +++ /dev/null @@ -1,44 +0,0 @@ -From e10a35abb3da12b812cfb6fc6137926a0c81e39a Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 10 Sep 2023 22:40:30 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix uninitialized variable - -Variable dma_addr in function mtk_poll_rx can be uninitialized on -some of the error paths. In practise this doesn't matter, even random -data present in uninitialized stack memory can safely be used in the -way it happens in the error path. - -However, in order to make Smatch happy make sure the variable is -always initialized. - -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1988,11 +1988,11 @@ static int mtk_poll_rx(struct napi_struc - u8 *data, *new_data; - struct mtk_rx_dma_v2 *rxd, trxd; - int done = 0, bytes = 0; -+ dma_addr_t dma_addr = DMA_MAPPING_ERROR; - - while (done < budget) { - unsigned int pktlen, *rxdcsum; - struct net_device *netdev; -- dma_addr_t dma_addr; - u32 hash, reason; - int mac = 0; - -@@ -2169,7 +2169,8 @@ release_desc: - else - rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA) && -+ likely(dma_addr != DMA_MAPPING_ERROR)) - rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); - - ring->calc_idx = idx; diff --git a/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch b/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch deleted file mode 100644 index ac3e3a3e67..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 5a124b1fd3e6cb15a943f0cdfe96aa8f6d3d2f39 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Sat, 9 Sep 2023 20:41:56 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix pse_port configuration for - MT7988 - -MT7988 SoC support 3 NICs. Fix pse_port configuration in -mtk_flow_set_output_device routine if the traffic is offloaded to eth2. -Rely on mtk_pse_port definitions. - -Fixes: 88efedf517e6 ("net: ethernet: mtk_eth_soc: enable nft hw flowtable_offload for MT7988 SoC") -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -214,9 +214,11 @@ mtk_flow_set_output_device(struct mtk_et - dsa_port = mtk_flow_get_dsa_port(&dev); - - if (dev == eth->netdev[0]) -- pse_port = 1; -+ pse_port = PSE_GDM1_PORT; - else if (dev == eth->netdev[1]) -- pse_port = 2; -+ pse_port = PSE_GDM2_PORT; -+ else if (dev == eth->netdev[2]) -+ pse_port = PSE_GDM3_PORT; - else - return -EOPNOTSUPP; - diff --git a/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch b/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch deleted file mode 100644 index 46da5b283f..0000000000 --- a/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch +++ /dev/null @@ -1,271 +0,0 @@ -From: Felix Fietkau -Date: Mon, 20 Mar 2023 11:44:30 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add code for offloading flows - from wlan devices - -WED version 2 (on MT7986 and later) can offload flows originating from wireless -devices. In order to make that work, ndo_setup_tc needs to be implemented on -the netdevs. This adds the required code to offload flows coming in from WED, -while keeping track of the incoming wed index used for selecting the correct -PPE device. - -Signed-off-by: Felix Fietkau ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + - .../net/ethernet/mediatek/mtk_ppe_offload.c | 37 ++++--- - drivers/net/ethernet/mediatek/mtk_wed.c | 101 ++++++++++++++++++ - include/linux/soc/mediatek/mtk_wed.h | 6 ++ - 4 files changed, 133 insertions(+), 14 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1435,6 +1435,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk - int mtk_eth_offload_init(struct mtk_eth *eth); - int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, - void *type_data); -+int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls, -+ int ppe_index); -+void mtk_flow_offload_cleanup(struct mtk_eth *eth, struct list_head *list); - void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); - - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -237,7 +237,8 @@ out: - } - - static int --mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) -+mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f, -+ int ppe_index) - { - struct flow_rule *rule = flow_cls_offload_flow_rule(f); - struct flow_action_entry *act; -@@ -454,6 +455,7 @@ mtk_flow_offload_replace(struct mtk_eth - entry->cookie = f->cookie; - memcpy(&entry->data, &foe, sizeof(entry->data)); - entry->wed_index = wed_index; -+ entry->ppe_index = ppe_index; - - err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry); - if (err < 0) -@@ -522,25 +524,15 @@ mtk_flow_offload_stats(struct mtk_eth *e - - static DEFINE_MUTEX(mtk_flow_offload_mutex); - --static int --mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) -+int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls, -+ int ppe_index) - { -- struct flow_cls_offload *cls = type_data; -- struct net_device *dev = cb_priv; -- struct mtk_mac *mac = netdev_priv(dev); -- struct mtk_eth *eth = mac->hw; - int err; - -- if (!tc_can_offload(dev)) -- return -EOPNOTSUPP; -- -- if (type != TC_SETUP_CLSFLOWER) -- return -EOPNOTSUPP; -- - mutex_lock(&mtk_flow_offload_mutex); - switch (cls->command) { - case FLOW_CLS_REPLACE: -- err = mtk_flow_offload_replace(eth, cls); -+ err = mtk_flow_offload_replace(eth, cls, ppe_index); - break; - case FLOW_CLS_DESTROY: - err = mtk_flow_offload_destroy(eth, cls); -@@ -558,6 +550,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ - } - - static int -+mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) -+{ -+ struct flow_cls_offload *cls = type_data; -+ struct net_device *dev = cb_priv; -+ struct mtk_mac *mac = netdev_priv(dev); -+ struct mtk_eth *eth = mac->hw; -+ -+ if (!tc_can_offload(dev)) -+ return -EOPNOTSUPP; -+ -+ if (type != TC_SETUP_CLSFLOWER) -+ return -EOPNOTSUPP; -+ -+ return mtk_flow_offload_cmd(eth, cls, 0); -+} -+ -+static int - mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f) - { - struct mtk_mac *mac = netdev_priv(dev); ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -13,6 +13,8 @@ - #include - #include - #include -+#include -+#include - #include "mtk_eth_soc.h" - #include "mtk_wed_regs.h" - #include "mtk_wed.h" -@@ -41,6 +43,11 @@ - static struct mtk_wed_hw *hw_list[2]; - static DEFINE_MUTEX(hw_lock); - -+struct mtk_wed_flow_block_priv { -+ struct mtk_wed_hw *hw; -+ struct net_device *dev; -+}; -+ - static void - wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) - { -@@ -1753,6 +1760,99 @@ out: - mutex_unlock(&hw_lock); - } - -+static int -+mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) -+{ -+ struct mtk_wed_flow_block_priv *priv = cb_priv; -+ struct flow_cls_offload *cls = type_data; -+ struct mtk_wed_hw *hw = priv->hw; -+ -+ if (!tc_can_offload(priv->dev)) -+ return -EOPNOTSUPP; -+ -+ if (type != TC_SETUP_CLSFLOWER) -+ return -EOPNOTSUPP; -+ -+ return mtk_flow_offload_cmd(hw->eth, cls, hw->index); -+} -+ -+static int -+mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev, -+ struct flow_block_offload *f) -+{ -+ struct mtk_wed_flow_block_priv *priv; -+ static LIST_HEAD(block_cb_list); -+ struct flow_block_cb *block_cb; -+ struct mtk_eth *eth = hw->eth; -+ flow_setup_cb_t *cb; -+ -+ if (!eth->soc->offload_version) -+ return -EOPNOTSUPP; -+ -+ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) -+ return -EOPNOTSUPP; -+ -+ cb = mtk_wed_setup_tc_block_cb; -+ f->driver_block_list = &block_cb_list; -+ -+ switch (f->command) { -+ case FLOW_BLOCK_BIND: -+ block_cb = flow_block_cb_lookup(f->block, cb, dev); -+ if (block_cb) { -+ flow_block_cb_incref(block_cb); -+ return 0; -+ } -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->hw = hw; -+ priv->dev = dev; -+ block_cb = flow_block_cb_alloc(cb, dev, priv, NULL); -+ if (IS_ERR(block_cb)) { -+ kfree(priv); -+ return PTR_ERR(block_cb); -+ } -+ -+ flow_block_cb_incref(block_cb); -+ flow_block_cb_add(block_cb, f); -+ list_add_tail(&block_cb->driver_list, &block_cb_list); -+ return 0; -+ case FLOW_BLOCK_UNBIND: -+ block_cb = flow_block_cb_lookup(f->block, cb, dev); -+ if (!block_cb) -+ return -ENOENT; -+ -+ if (!flow_block_cb_decref(block_cb)) { -+ flow_block_cb_remove(block_cb, f); -+ list_del(&block_cb->driver_list); -+ kfree(block_cb->cb_priv); -+ } -+ return 0; -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+static int -+mtk_wed_setup_tc(struct mtk_wed_device *wed, struct net_device *dev, -+ enum tc_setup_type type, void *type_data) -+{ -+ struct mtk_wed_hw *hw = wed->hw; -+ -+ if (hw->version < 2) -+ return -EOPNOTSUPP; -+ -+ switch (type) { -+ case TC_SETUP_BLOCK: -+ case TC_SETUP_FT: -+ return mtk_wed_setup_tc_block(hw, dev, type_data); -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ - void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, - void __iomem *wdma, phys_addr_t wdma_phy, - int index) -@@ -1772,6 +1872,7 @@ void mtk_wed_add_hw(struct device_node * - .irq_set_mask = mtk_wed_irq_set_mask, - .detach = mtk_wed_detach, - .ppe_check = mtk_wed_ppe_check, -+ .setup_tc = mtk_wed_setup_tc, - }; - struct device_node *eth_np = eth->dev->of_node; - struct platform_device *pdev; ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - - #define MTK_WED_TX_QUEUES 2 - #define MTK_WED_RX_QUEUES 2 -@@ -180,6 +181,8 @@ struct mtk_wed_ops { - - u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask); - void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); -+ int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev, -+ enum tc_setup_type type, void *type_data); - }; - - extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; -@@ -238,6 +241,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - (_dev)->ops->msg_update(_dev, _id, _msg, _len) - #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev) - #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) -+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \ -+ (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data) - #else - static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) - { -@@ -256,6 +261,7 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV - #define mtk_wed_device_stop(_dev) do {} while (0) - #define mtk_wed_device_dma_reset(_dev) do {} while (0) -+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP - #endif - - #endif diff --git a/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch b/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch deleted file mode 100644 index b1796641a3..0000000000 --- a/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Felix Fietkau -Date: Mon, 20 Mar 2023 15:37:55 +0100 -Subject: [PATCH] net: ethernet: mediatek: mtk_ppe: prefer newly added l2 - flows over existing ones - -When a device is roaming between interfaces and a new flow entry is created, -we should assume that its output device is more up to date than whatever -entry existed already. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -656,10 +656,20 @@ void mtk_foe_entry_clear(struct mtk_ppe - static int - mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) - { -+ struct mtk_flow_entry *prev; -+ - entry->type = MTK_FLOW_TYPE_L2; - -- return rhashtable_insert_fast(&ppe->l2_flows, &entry->l2_node, -- mtk_flow_l2_ht_params); -+ prev = rhashtable_lookup_get_insert_fast(&ppe->l2_flows, &entry->l2_node, -+ mtk_flow_l2_ht_params); -+ if (likely(!prev)) -+ return 0; -+ -+ if (IS_ERR(prev)) -+ return PTR_ERR(prev); -+ -+ return rhashtable_replace_fast(&ppe->l2_flows, &prev->l2_node, -+ &entry->l2_node, mtk_flow_l2_ht_params); - } - - int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) diff --git a/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch b/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch deleted file mode 100644 index a224b62624..0000000000 --- a/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Lorenzo Bianconi -Date: Sun, 27 Aug 2023 19:31:41 +0200 -Subject: [PATCH] net: ethernet: mtk_wed: add some more info in wed_txinfo_show - handler - -Add some new info in Wireless Ethernet Dispatcher wed_txinfo_show -debugfs handler useful during debugging. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/3390292655d568180b73d2a25576f61aa63310e5.1693157377.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -@@ -127,8 +127,17 @@ wed_txinfo_show(struct seq_file *s, void - DUMP_WDMA_RING(WDMA_RING_RX(0)), - DUMP_WDMA_RING(WDMA_RING_RX(1)), - -- DUMP_STR("TX FREE"), -+ DUMP_STR("WED TX FREE"), - DUMP_WED(WED_RX_MIB(0)), -+ DUMP_WED_RING(WED_RING_RX(0)), -+ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)), -+ DUMP_WED(WED_RX_MIB(1)), -+ DUMP_WED_RING(WED_RING_RX(1)), -+ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)), -+ -+ DUMP_STR("WED WPDMA TX FREE"), -+ DUMP_WED_RING(WED_WPDMA_RING_RX(0)), -+ DUMP_WED_RING(WED_WPDMA_RING_RX(1)), - }; - struct mtk_wed_hw *hw = s->private; - struct mtk_wed_device *dev = hw->wed_dev; ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -266,6 +266,8 @@ struct mtk_wdma_desc { - - #define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) - #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_MIB(_n) (0x5e0 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_COHERENT_MIB(_n) (0x5f0 + (_n) * 4) - - #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) - #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) diff --git a/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch b/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch deleted file mode 100644 index df6edfdf94..0000000000 --- a/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch +++ /dev/null @@ -1,47 +0,0 @@ -From: Lorenzo Bianconi -Date: Sun, 27 Aug 2023 19:33:47 +0200 -Subject: [PATCH] net: ethernet: mtk_wed: minor change in wed_{tx,rx}info_show - -No functional changes, just cosmetic ones. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/71e046c72a978745f0435af265dda610aa9bfbcf.1693157578.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -@@ -84,7 +84,6 @@ dump_wed_regs(struct seq_file *s, struct - } - } - -- - static int - wed_txinfo_show(struct seq_file *s, void *data) - { -@@ -142,10 +141,8 @@ wed_txinfo_show(struct seq_file *s, void - struct mtk_wed_hw *hw = s->private; - struct mtk_wed_device *dev = hw->wed_dev; - -- if (!dev) -- return 0; -- -- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); -+ if (dev) -+ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); - - return 0; - } -@@ -217,10 +214,8 @@ wed_rxinfo_show(struct seq_file *s, void - struct mtk_wed_hw *hw = s->private; - struct mtk_wed_device *dev = hw->wed_dev; - -- if (!dev) -- return 0; -- -- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); -+ if (dev) -+ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch b/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch deleted file mode 100644 index c0320ad6f9..0000000000 --- a/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch +++ /dev/null @@ -1,150 +0,0 @@ -From cfbd6de588ef659c198083205dc954a6d3ed2aec Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 29 Dec 2022 17:33:35 +0100 -Subject: [PATCH 4/5] net: dsa: qca8k: introduce single mii read/write lo/hi - -It may be useful to read/write just the lo or hi half of a reg. - -This is especially useful for phy poll with the use of mdio master. -The mdio master reg is composed by the first 16 bit related to setup and -the other half with the returned data or data to write. - -Refactor the mii function to permit single mii read/write of lo or hi -half of the reg. - -Tested-by: Ronald Wahl -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 106 ++++++++++++++++++++++++------- - 1 file changed, 84 insertions(+), 22 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -37,42 +37,104 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u - } - - static int --qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) -+qca8k_mii_write_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) - { - int ret; -+ u16 lo; - -- ret = bus->read(bus, phy_id, regnum); -- if (ret >= 0) { -- *val = ret; -- ret = bus->read(bus, phy_id, regnum + 1); -- *val |= ret << 16; -- } -+ lo = val & 0xffff; -+ ret = bus->write(bus, phy_id, regnum, lo); -+ if (ret < 0) -+ dev_err_ratelimited(&bus->dev, -+ "failed to write qca8k 32bit lo register\n"); -+ -+ return ret; -+} - -- if (ret < 0) { -+static int -+qca8k_mii_write_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) -+{ -+ int ret; -+ u16 hi; -+ -+ hi = (u16)(val >> 16); -+ ret = bus->write(bus, phy_id, regnum, hi); -+ if (ret < 0) - dev_err_ratelimited(&bus->dev, -- "failed to read qca8k 32bit register\n"); -- *val = 0; -- return ret; -- } -+ "failed to write qca8k 32bit hi register\n"); - -+ return ret; -+} -+ -+static int -+qca8k_mii_read_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) -+{ -+ int ret; -+ -+ ret = bus->read(bus, phy_id, regnum); -+ if (ret < 0) -+ goto err; -+ -+ *val = ret & 0xffff; - return 0; -+ -+err: -+ dev_err_ratelimited(&bus->dev, -+ "failed to read qca8k 32bit lo register\n"); -+ *val = 0; -+ -+ return ret; - } - --static void --qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) -+static int -+qca8k_mii_read_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) - { -- u16 lo, hi; - int ret; - -- lo = val & 0xffff; -- hi = (u16)(val >> 16); -+ ret = bus->read(bus, phy_id, regnum); -+ if (ret < 0) -+ goto err; - -- ret = bus->write(bus, phy_id, regnum, lo); -- if (ret >= 0) -- ret = bus->write(bus, phy_id, regnum + 1, hi); -+ *val = ret << 16; -+ return 0; -+ -+err: -+ dev_err_ratelimited(&bus->dev, -+ "failed to read qca8k 32bit hi register\n"); -+ *val = 0; -+ -+ return ret; -+} -+ -+static int -+qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) -+{ -+ u32 hi, lo; -+ int ret; -+ -+ *val = 0; -+ -+ ret = qca8k_mii_read_lo(bus, phy_id, regnum, &lo); - if (ret < 0) -- dev_err_ratelimited(&bus->dev, -- "failed to write qca8k 32bit register\n"); -+ goto err; -+ -+ ret = qca8k_mii_read_hi(bus, phy_id, regnum + 1, &hi); -+ if (ret < 0) -+ goto err; -+ -+ *val = lo | hi; -+ -+err: -+ return ret; -+} -+ -+static void -+qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) -+{ -+ if (qca8k_mii_write_lo(bus, phy_id, regnum, val) < 0) -+ return; -+ -+ qca8k_mii_write_hi(bus, phy_id, regnum + 1, val); - } - - static int diff --git a/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch b/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch deleted file mode 100644 index dcafad0fd5..0000000000 --- a/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch +++ /dev/null @@ -1,73 +0,0 @@ -From a4165830ca237f2b3318faf62562bce8ce12a389 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 29 Dec 2022 17:33:36 +0100 -Subject: [PATCH 5/5] net: dsa: qca8k: improve mdio master read/write by using - single lo/hi - -Improve mdio master read/write by using singe mii read/write lo/hi. - -In a read and write we need to poll the mdio master regs in a busy loop -to check for a specific bit present in the upper half of the reg. We can -ignore the other half since it won't contain useful data. This will save -an additional useless read for each read and write operation. - -In a read operation the returned data is present in the mdio master reg -lower half. We can ignore the other half since it won't contain useful -data. This will save an additional useless read for each read operation. - -In a read operation it's needed to just set the hi half of the mdio -master reg as the lo half will be replaced by the result. This will save -an additional useless write for each read operation. - -Tested-by: Ronald Wahl -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -754,9 +754,9 @@ qca8k_mdio_busy_wait(struct mii_bus *bus - - qca8k_split_addr(reg, &r1, &r2, &page); - -- ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, -+ ret = read_poll_timeout(qca8k_mii_read_hi, ret1, !(val & mask), 0, - QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, -- bus, 0x10 | r2, r1, &val); -+ bus, 0x10 | r2, r1 + 1, &val); - - /* Check if qca8k_read has failed for a different reason - * before returnting -ETIMEDOUT -@@ -798,7 +798,7 @@ qca8k_mdio_write(struct qca8k_priv *priv - - exit: - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); -+ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); - - mutex_unlock(&bus->mdio_lock); - -@@ -828,18 +828,18 @@ qca8k_mdio_read(struct qca8k_priv *priv, - if (ret) - goto exit; - -- qca8k_mii_write32(bus, 0x10 | r2, r1, val); -+ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, val); - - ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY); - if (ret) - goto exit; - -- ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); -+ ret = qca8k_mii_read_lo(bus, 0x10 | r2, r1, &val); - - exit: - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); -+ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); - - mutex_unlock(&bus->mdio_lock); - diff --git a/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch b/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch deleted file mode 100644 index 9331fd536d..0000000000 --- a/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e03cea60c3db8c6b011cc36ecef9281dff8377f3 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 25 Jan 2023 21:35:16 +0100 -Subject: [PATCH] net: dsa: qca8k: add QCA8K_ATU_TABLE_SIZE define for fdb - access - -Add and use QCA8K_ATU_TABLE_SIZE instead of hardcoding the ATU size with -a pure number and using sizeof on the array. - -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-common.c | 10 ++++++---- - drivers/net/dsa/qca/qca8k.h | 2 ++ - 2 files changed, 8 insertions(+), 4 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-common.c -+++ b/drivers/net/dsa/qca/qca8k-common.c -@@ -150,11 +150,12 @@ static int qca8k_busy_wait(struct qca8k_ - - static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) - { -- u32 reg[3]; -+ u32 reg[QCA8K_ATU_TABLE_SIZE]; - int ret; - - /* load the ARL table into an array */ -- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); -+ ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); - if (ret) - return ret; - -@@ -178,7 +179,7 @@ static int qca8k_fdb_read(struct qca8k_p - static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, - const u8 *mac, u8 aging) - { -- u32 reg[3] = { 0 }; -+ u32 reg[QCA8K_ATU_TABLE_SIZE] = { 0 }; - - /* vid - 83:72 */ - reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid); -@@ -195,7 +196,8 @@ static void qca8k_fdb_write(struct qca8k - reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); - - /* load the array into the ARL table */ -- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); -+ qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); - } - - static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -148,6 +148,8 @@ - #define QCA8K_REG_IPV4_PRI_ADDR_MASK 0x474 - - /* Lookup registers */ -+#define QCA8K_ATU_TABLE_SIZE 3 /* 12 bytes wide table / sizeof(u32) */ -+ - #define QCA8K_REG_ATU_DATA0 0x600 - #define QCA8K_ATU_ADDR2_MASK GENMASK(31, 24) - #define QCA8K_ATU_ADDR3_MASK GENMASK(23, 16) diff --git a/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch b/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch deleted file mode 100644 index b8f8071b0a..0000000000 --- a/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch +++ /dev/null @@ -1,261 +0,0 @@ -From c766e077d927e1775902c18827205ea2ade3a35d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 25 Jan 2023 21:35:17 +0100 -Subject: [PATCH] net: dsa: qca8k: convert to regmap read/write API - -Convert qca8k to regmap read/write bulk API. The mgmt eth can write up -to 32 bytes of data at times. Currently we use a custom function to do -it but regmap now supports declaration of read/write bulk even without a -bus. - -Drop the custom function and rework the regmap function to this new -implementation. - -Rework the qca8k_fdb_read/write function to use the new -regmap_bulk_read/write as the old qca8k_bulk_read/write are now dropped. - -Cc: Mark Brown -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 92 ++++++++++++++++++++++++------ - drivers/net/dsa/qca/qca8k-common.c | 47 ++------------- - drivers/net/dsa/qca/qca8k.h | 3 - - 3 files changed, 77 insertions(+), 65 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -425,16 +425,12 @@ qca8k_regmap_update_bits_eth(struct qca8 - } - - static int --qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) -+qca8k_read_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t *val) - { -- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - int ret; - -- if (!qca8k_read_eth(priv, reg, val, sizeof(*val))) -- return 0; -- - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -451,16 +447,12 @@ exit: - } - - static int --qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) -+qca8k_write_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t val) - { -- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - int ret; - -- if (!qca8k_write_eth(priv, reg, &val, sizeof(val))) -- return 0; -- - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -477,17 +469,14 @@ exit: - } - - static int --qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) -+qca8k_regmap_update_bits_mii(struct qca8k_priv *priv, uint32_t reg, -+ uint32_t mask, uint32_t write_val) - { -- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 val; - int ret; - -- if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) -- return 0; -- - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -510,17 +499,84 @@ exit: - return ret; - } - -+static int -+qca8k_bulk_read(void *ctx, const void *reg_buf, size_t reg_len, -+ void *val_buf, size_t val_len) -+{ -+ int i, count = val_len / sizeof(u32), ret; -+ u32 reg = *(u32 *)reg_buf & U16_MAX; -+ struct qca8k_priv *priv = ctx; -+ -+ if (priv->mgmt_master && -+ !qca8k_read_eth(priv, reg, val_buf, val_len)) -+ return 0; -+ -+ /* loop count times and increment reg of 4 */ -+ for (i = 0; i < count; i++, reg += sizeof(u32)) { -+ ret = qca8k_read_mii(priv, reg, val_buf + i); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+qca8k_bulk_gather_write(void *ctx, const void *reg_buf, size_t reg_len, -+ const void *val_buf, size_t val_len) -+{ -+ int i, count = val_len / sizeof(u32), ret; -+ u32 reg = *(u32 *)reg_buf & U16_MAX; -+ struct qca8k_priv *priv = ctx; -+ u32 *val = (u32 *)val_buf; -+ -+ if (priv->mgmt_master && -+ !qca8k_write_eth(priv, reg, val, val_len)) -+ return 0; -+ -+ /* loop count times, increment reg of 4 and increment val ptr to -+ * the next value -+ */ -+ for (i = 0; i < count; i++, reg += sizeof(u32), val++) { -+ ret = qca8k_write_mii(priv, reg, *val); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+qca8k_bulk_write(void *ctx, const void *data, size_t bytes) -+{ -+ return qca8k_bulk_gather_write(ctx, data, sizeof(u16), data + sizeof(u16), -+ bytes - sizeof(u16)); -+} -+ -+static int -+qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) -+{ -+ struct qca8k_priv *priv = ctx; -+ -+ if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) -+ return 0; -+ -+ return qca8k_regmap_update_bits_mii(priv, reg, mask, write_val); -+} -+ - static struct regmap_config qca8k_regmap_config = { - .reg_bits = 16, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0x16ac, /* end MIB - Port6 range */ -- .reg_read = qca8k_regmap_read, -- .reg_write = qca8k_regmap_write, -+ .read = qca8k_bulk_read, -+ .write = qca8k_bulk_write, - .reg_update_bits = qca8k_regmap_update_bits, - .rd_table = &qca8k_readable_table, - .disable_locking = true, /* Locking is handled by qca8k read/write */ - .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ -+ .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ -+ .max_raw_write = 32, - }; - - static int -@@ -2112,8 +2168,6 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, - - static const struct qca8k_info_ops qca8xxx_ops = { - .autocast_mib = qca8k_get_ethtool_stats_eth, -- .read_eth = qca8k_read_eth, -- .write_eth = qca8k_write_eth, - }; - - static const struct qca8k_match_data qca8327 = { ---- a/drivers/net/dsa/qca/qca8k-common.c -+++ b/drivers/net/dsa/qca/qca8k-common.c -@@ -101,45 +101,6 @@ const struct regmap_access_table qca8k_r - .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), - }; - --/* TODO: remove these extra ops when we can support regmap bulk read/write */ --static int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len) --{ -- int i, count = len / sizeof(u32), ret; -- -- if (priv->mgmt_master && priv->info->ops->read_eth && -- !priv->info->ops->read_eth(priv, reg, val, len)) -- return 0; -- -- for (i = 0; i < count; i++) { -- ret = regmap_read(priv->regmap, reg + (i * 4), val + i); -- if (ret < 0) -- return ret; -- } -- -- return 0; --} -- --/* TODO: remove these extra ops when we can support regmap bulk read/write */ --static int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len) --{ -- int i, count = len / sizeof(u32), ret; -- u32 tmp; -- -- if (priv->mgmt_master && priv->info->ops->write_eth && -- !priv->info->ops->write_eth(priv, reg, val, len)) -- return 0; -- -- for (i = 0; i < count; i++) { -- tmp = val[i]; -- -- ret = regmap_write(priv->regmap, reg + (i * 4), tmp); -- if (ret < 0) -- return ret; -- } -- -- return 0; --} -- - static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) - { - u32 val; -@@ -154,8 +115,8 @@ static int qca8k_fdb_read(struct qca8k_p - int ret; - - /* load the ARL table into an array */ -- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, -- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); -+ ret = regmap_bulk_read(priv->regmap, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE); - if (ret) - return ret; - -@@ -196,8 +157,8 @@ static void qca8k_fdb_write(struct qca8k - reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); - - /* load the array into the ARL table */ -- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, -- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); -+ regmap_bulk_write(priv->regmap, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE); - } - - static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -330,9 +330,6 @@ struct qca8k_priv; - - struct qca8k_info_ops { - int (*autocast_mib)(struct dsa_switch *ds, int port, u64 *data); -- /* TODO: remove these extra ops when we can support regmap bulk read/write */ -- int (*read_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); -- int (*write_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); - }; - - struct qca8k_match_data { diff --git a/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch b/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch deleted file mode 100644 index 3619440f07..0000000000 --- a/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 2c39dd025da489cf87d26469d9f5ff19715324a0 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 24 Jul 2023 05:25:28 +0200 -Subject: [PATCH 1/4] net: dsa: qca8k: enable use_single_write for qca8xxx - -The qca8xxx switch supports 2 way to write reg values, a slow way using -mdio and a fast way by sending specially crafted mgmt packet to -read/write reg. - -The fast way can support up to 32 bytes of data as eth packet are used -to send/receive. - -This correctly works for almost the entire regmap of the switch but with -the use of some kernel selftests for dsa drivers it was found a funny -and interesting hw defect/limitation. - -For some specific reg, bulk write won't work and will result in writing -only part of the requested regs resulting in half data written. This was -especially hard to track and discover due to the total strangeness of -the problem and also by the specific regs where this occurs. - -This occurs in the specific regs of the ATU table, where multiple entry -needs to be written to compose the entire entry. -It was discovered that with a bulk write of 12 bytes on -QCA8K_REG_ATU_DATA0 only QCA8K_REG_ATU_DATA0 and QCA8K_REG_ATU_DATA2 -were written, but QCA8K_REG_ATU_DATA1 was always zero. -Tcpdump was used to make sure the specially crafted packet was correct -and this was confirmed. - -The problem was hard to track as the lack of QCA8K_REG_ATU_DATA1 -resulted in an entry somehow possible as the first bytes of the mac -address are set in QCA8K_REG_ATU_DATA0 and the entry type is set in -QCA8K_REG_ATU_DATA2. - -Funlly enough writing QCA8K_REG_ATU_DATA1 results in the same problem -with QCA8K_REG_ATU_DATA2 empty and QCA8K_REG_ATU_DATA1 and -QCA8K_REG_ATU_FUNC correctly written. -A speculation on the problem might be that there are some kind of -indirection internally when accessing these regs and they can't be -accessed all together, due to the fact that it's really a table mapped -somewhere in the switch SRAM. - -Even more funny is the fact that every other reg was tested with all -kind of combination and they are not affected by this problem. Read -operation was also tested and always worked so it's not affected by this -problem. - -The problem is not present if we limit writing a single reg at times. - -To handle this hardware defect, enable use_single_write so that bulk -api can correctly split the write in multiple different operation -effectively reverting to a non-bulk write. - -Cc: Mark Brown -Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") -Signed-off-by: Christian Marangi -Cc: stable@vger.kernel.org -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -575,8 +575,11 @@ static struct regmap_config qca8k_regmap - .rd_table = &qca8k_readable_table, - .disable_locking = true, /* Locking is handled by qca8k read/write */ - .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ -- .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ -- .max_raw_write = 32, -+ .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */ -+ /* ATU regs suffer from a bug where some data are not correctly -+ * written. Disable bulk write to correctly write ATU entry. -+ */ -+ .use_single_write = true, - }; - - static int diff --git a/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch b/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch deleted file mode 100644 index d31789370e..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 23cfc7172e5297d0bee49ac6f6f8248d1cf0820d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:10 +0200 -Subject: [PATCH 1/4] net: dsa: qca8k: make learning configurable and keep off - if standalone - -Address learning should initially be turned off by the driver for port -operation in standalone mode, then the DSA core handles changes to it -via ds->ops->port_bridge_flags(). - -Currently this is not the case for qca8k where learning is enabled -unconditionally in qca8k_setup for every user port. - -Handle ports configured in standalone mode by making the learning -configurable and not enabling it by default. - -Implement .port_pre_bridge_flags and .port_bridge_flags dsa ops to -enable learning for bridge that request it and tweak -.port_stp_state_set to correctly disable learning when port is -configured in standalone mode. - -Signed-off-by: Christian Marangi -Reviewed-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230730074113.21889-2-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++-- - drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++ - drivers/net/dsa/qca/qca8k.h | 6 ++++ - 3 files changed, 58 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1905,9 +1905,8 @@ qca8k_setup(struct dsa_switch *ds) - if (ret) - return ret; - -- /* Enable ARP Auto-learning by default */ -- ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_LEARN); -+ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), -+ QCA8K_PORT_LOOKUP_LEARN); - if (ret) - return ret; - -@@ -2013,6 +2012,8 @@ static const struct dsa_switch_ops qca8k - .port_change_mtu = qca8k_port_change_mtu, - .port_max_mtu = qca8k_port_max_mtu, - .port_stp_state_set = qca8k_port_stp_state_set, -+ .port_pre_bridge_flags = qca8k_port_pre_bridge_flags, -+ .port_bridge_flags = qca8k_port_bridge_flags, - .port_bridge_join = qca8k_port_bridge_join, - .port_bridge_leave = qca8k_port_bridge_leave, - .port_fast_age = qca8k_port_fast_age, ---- a/drivers/net/dsa/qca/qca8k-common.c -+++ b/drivers/net/dsa/qca/qca8k-common.c -@@ -565,9 +565,26 @@ int qca8k_get_mac_eee(struct dsa_switch - return 0; - } - -+static int qca8k_port_configure_learning(struct dsa_switch *ds, int port, -+ bool learning) -+{ -+ struct qca8k_priv *priv = ds->priv; -+ -+ if (learning) -+ return regmap_set_bits(priv->regmap, -+ QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_LEARN); -+ else -+ return regmap_clear_bits(priv->regmap, -+ QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_LEARN); -+} -+ - void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) - { -+ struct dsa_port *dp = dsa_to_port(ds, port); - struct qca8k_priv *priv = ds->priv; -+ bool learning = false; - u32 stp_state; - - switch (state) { -@@ -582,8 +599,11 @@ void qca8k_port_stp_state_set(struct dsa - break; - case BR_STATE_LEARNING: - stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING; -+ learning = dp->learning; - break; - case BR_STATE_FORWARDING: -+ learning = dp->learning; -+ fallthrough; - default: - stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD; - break; -@@ -591,6 +611,34 @@ void qca8k_port_stp_state_set(struct dsa - - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), - QCA8K_PORT_LOOKUP_STATE_MASK, stp_state); -+ -+ qca8k_port_configure_learning(ds, port, learning); -+} -+ -+int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack) -+{ -+ if (flags.mask & ~BR_LEARNING) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack) -+{ -+ int ret; -+ -+ if (flags.mask & BR_LEARNING) { -+ ret = qca8k_port_configure_learning(ds, port, -+ flags.val & BR_LEARNING); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; - } - - int qca8k_port_bridge_join(struct dsa_switch *ds, int port, ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -448,6 +448,12 @@ int qca8k_get_mac_eee(struct dsa_switch - - /* Common bridge function */ - void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); -+int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack); -+int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack); - int qca8k_port_bridge_join(struct dsa_switch *ds, int port, - struct dsa_bridge bridge, - bool *tx_fwd_offload, diff --git a/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch b/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch deleted file mode 100644 index 4b457f67de..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 18e8feae4a807994e4906d659116d249bfecd4c5 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:11 +0200 -Subject: [PATCH 2/4] net: dsa: qca8k: limit user ports access to the first CPU - port on setup - -In preparation for multi-CPU support, set CPU port LOOKUP MEMBER outside -the port loop and setup the LOOKUP MEMBER mask for user ports only to -the first CPU port. - -This is to handle flooding condition where every CPU port is set as -target and prevent packet duplication for unknown frames from user ports. - -Secondary CPU port LOOKUP MEMBER mask will be setup later when -port_change_master will be implemented. - -Signed-off-by: Christian Marangi -Reviewed-by: Simon Horman -Reviewed-by: Florian Fainelli -Reviewed-by: Vladimir Oltean -Link: https://lore.kernel.org/r/20230730074113.21889-3-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1885,18 +1885,16 @@ qca8k_setup(struct dsa_switch *ds) - if (ret) - return ret; - -+ /* CPU port gets connected to all user ports of the switch */ -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), -+ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); -+ if (ret) -+ return ret; -+ - /* Setup connection between CPU port & user ports - * Configure specific switch configuration for ports - */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) { -- /* CPU port gets connected to all user ports of the switch */ -- if (dsa_is_cpu_port(ds, i)) { -- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); -- if (ret) -- return ret; -- } -- - /* Individual user ports get connected to CPU port only */ - if (dsa_is_user_port(ds, i)) { - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), diff --git a/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch b/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch deleted file mode 100644 index f556628b5b..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch +++ /dev/null @@ -1,111 +0,0 @@ -From a9108b0712bf018dc69020864b21485b71b17dfc Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:12 +0200 -Subject: [PATCH 3/4] net: dsa: qca8k: move qca8xxx hol fixup to separate - function - -Move qca8xxx hol fixup to separate function to tidy things up and to -permit using a more efficent loop in future patch. - -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230730074113.21889-4-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 78 +++++++++++++++++--------------- - 1 file changed, 42 insertions(+), 36 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1795,6 +1795,46 @@ static int qca8k_connect_tag_protocol(st - return 0; - } - -+static void qca8k_setup_hol_fixup(struct qca8k_priv *priv, int port) -+{ -+ u32 mask; -+ -+ switch (port) { -+ /* The 2 CPU port and port 5 requires some different -+ * priority than any other ports. -+ */ -+ case 0: -+ case 5: -+ case 6: -+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | -+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); -+ break; -+ default: -+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | -+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); -+ } -+ regmap_write(priv->regmap, QCA8K_REG_PORT_HOL_CTRL0(port), mask); -+ -+ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | -+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_WRED_EN; -+ regmap_update_bits(priv->regmap, QCA8K_REG_PORT_HOL_CTRL1(port), -+ QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | -+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_WRED_EN, -+ mask); -+} -+ - static int - qca8k_setup(struct dsa_switch *ds) - { -@@ -1930,42 +1970,8 @@ qca8k_setup(struct dsa_switch *ds) - * missing settings to improve switch stability under load condition. - * This problem is limited to qca8337 and other qca8k switch are not affected. - */ -- if (priv->switch_id == QCA8K_ID_QCA8337) { -- switch (i) { -- /* The 2 CPU port and port 5 requires some different -- * priority than any other ports. -- */ -- case 0: -- case 5: -- case 6: -- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | -- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); -- break; -- default: -- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | -- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); -- } -- qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); -- -- mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | -- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_WRED_EN; -- qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), -- QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | -- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_WRED_EN, -- mask); -- } -+ if (priv->switch_id == QCA8K_ID_QCA8337) -+ qca8k_setup_hol_fixup(priv, i); - } - - /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ diff --git a/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch b/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch deleted file mode 100644 index faa0142ca9..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 01e6f8ad8d26ced14b0cf288c42e55d03a7c5070 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:13 +0200 -Subject: [PATCH 4/4] net: dsa: qca8k: use dsa_for_each macro instead of for - loop - -Convert for loop to dsa_for_each macro to save some redundant write on -unconnected/unused port and tidy things up. - -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230730074113.21889-5-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 107 ++++++++++++++++--------------- - 1 file changed, 54 insertions(+), 53 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1839,7 +1839,8 @@ static int - qca8k_setup(struct dsa_switch *ds) - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; -- int cpu_port, ret, i; -+ struct dsa_port *dp; -+ int cpu_port, ret; - u32 mask; - - cpu_port = qca8k_find_cpu_port(ds); -@@ -1890,27 +1891,27 @@ qca8k_setup(struct dsa_switch *ds) - dev_warn(priv->dev, "mib init failed"); - - /* Initial setup of all ports */ -- for (i = 0; i < QCA8K_NUM_PORTS; i++) { -+ dsa_switch_for_each_port(dp, ds) { - /* Disable forwarding by default on all ports */ -- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(dp->index), - QCA8K_PORT_LOOKUP_MEMBER, 0); - if (ret) - return ret; -+ } - -- /* Enable QCA header mode on all cpu ports */ -- if (dsa_is_cpu_port(ds, i)) { -- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), -- FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | -- FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); -- if (ret) { -- dev_err(priv->dev, "failed enabling QCA header mode"); -- return ret; -- } -+ /* Disable MAC by default on all user ports */ -+ dsa_switch_for_each_user_port(dp, ds) -+ qca8k_port_set_status(priv, dp->index, 0); -+ -+ /* Enable QCA header mode on all cpu ports */ -+ dsa_switch_for_each_cpu_port(dp, ds) { -+ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(dp->index), -+ FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | -+ FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); -+ if (ret) { -+ dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); -+ return ret; - } -- -- /* Disable MAC by default on all user ports */ -- if (dsa_is_user_port(ds, i)) -- qca8k_port_set_status(priv, i, 0); - } - - /* Forward all unknown frames to CPU port for Linux processing -@@ -1932,48 +1933,48 @@ qca8k_setup(struct dsa_switch *ds) - return ret; - - /* Setup connection between CPU port & user ports -- * Configure specific switch configuration for ports -+ * Individual user ports get connected to CPU port only - */ -- for (i = 0; i < QCA8K_NUM_PORTS; i++) { -- /* Individual user ports get connected to CPU port only */ -- if (dsa_is_user_port(ds, i)) { -- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_MEMBER, -- BIT(cpu_port)); -- if (ret) -- return ret; -- -- ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_LEARN); -- if (ret) -- return ret; -- -- /* For port based vlans to work we need to set the -- * default egress vid -- */ -- ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), -- QCA8K_EGREES_VLAN_PORT_MASK(i), -- QCA8K_EGREES_VLAN_PORT(i, QCA8K_PORT_VID_DEF)); -- if (ret) -- return ret; -- -- ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), -- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | -- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); -- if (ret) -- return ret; -- } -+ dsa_switch_for_each_user_port(dp, ds) { -+ u8 port = dp->index; - -- /* The port 5 of the qca8337 have some problem in flood condition. The -- * original legacy driver had some specific buffer and priority settings -- * for the different port suggested by the QCA switch team. Add this -- * missing settings to improve switch stability under load condition. -- * This problem is limited to qca8337 and other qca8k switch are not affected. -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_MEMBER, -+ BIT(cpu_port)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_LEARN); -+ if (ret) -+ return ret; -+ -+ /* For port based vlans to work we need to set the -+ * default egress vid - */ -- if (priv->switch_id == QCA8K_ID_QCA8337) -- qca8k_setup_hol_fixup(priv, i); -+ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), -+ QCA8K_EGREES_VLAN_PORT_MASK(port), -+ QCA8K_EGREES_VLAN_PORT(port, QCA8K_PORT_VID_DEF)); -+ if (ret) -+ return ret; -+ -+ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), -+ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | -+ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); -+ if (ret) -+ return ret; - } - -+ /* The port 5 of the qca8337 have some problem in flood condition. The -+ * original legacy driver had some specific buffer and priority settings -+ * for the different port suggested by the QCA switch team. Add this -+ * missing settings to improve switch stability under load condition. -+ * This problem is limited to qca8337 and other qca8k switch are not affected. -+ */ -+ if (priv->switch_id == QCA8K_ID_QCA8337) -+ dsa_switch_for_each_available_port(dp, ds) -+ qca8k_setup_hol_fixup(priv, dp->index); -+ - /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ - if (priv->switch_id == QCA8K_ID_QCA8327) { - mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | diff --git a/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch b/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch deleted file mode 100644 index 632f422d1f..0000000000 --- a/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 5652d1741574eb89cc02576e50ee3e348bd6dd77 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Wed, 4 Oct 2023 11:19:03 +0200 -Subject: [PATCH 1/2] net: dsa: qca8k: fix regmap bulk read/write methods on - big endian systems -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Commit c766e077d927 ("net: dsa: qca8k: convert to regmap read/write -API") introduced bulk read/write methods to qca8k's regmap. - -The regmap bulk read/write methods get the register address in a buffer -passed as a void pointer parameter (the same buffer contains also the -read/written values). The register address occupies only as many bytes -as it requires at the beginning of this buffer. For example if the -.reg_bits member in regmap_config is 16 (as is the case for this -driver), the register address occupies only the first 2 bytes in this -buffer, so it can be cast to u16. - -But the original commit implementing these bulk read/write methods cast -the buffer to u32: - u32 reg = *(u32 *)reg_buf & U16_MAX; -taking the first 4 bytes. This works on little endian systems where the -first 2 bytes of the buffer correspond to the low 16-bits, but it -obviously cannot work on big endian systems. - -Fix this by casting the beginning of the buffer to u16 as - u32 reg = *(u16 *)reg_buf; - -Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") -Signed-off-by: Marek Behún -Tested-by: Christian Marangi -Reviewed-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -504,8 +504,8 @@ qca8k_bulk_read(void *ctx, const void *r - void *val_buf, size_t val_len) - { - int i, count = val_len / sizeof(u32), ret; -- u32 reg = *(u32 *)reg_buf & U16_MAX; - struct qca8k_priv *priv = ctx; -+ u32 reg = *(u16 *)reg_buf; - - if (priv->mgmt_master && - !qca8k_read_eth(priv, reg, val_buf, val_len)) -@@ -526,8 +526,8 @@ qca8k_bulk_gather_write(void *ctx, const - const void *val_buf, size_t val_len) - { - int i, count = val_len / sizeof(u32), ret; -- u32 reg = *(u32 *)reg_buf & U16_MAX; - struct qca8k_priv *priv = ctx; -+ u32 reg = *(u16 *)reg_buf; - u32 *val = (u32 *)val_buf; - - if (priv->mgmt_master && diff --git a/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch b/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch deleted file mode 100644 index 8010076fc0..0000000000 --- a/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch +++ /dev/null @@ -1,514 +0,0 @@ -From patchwork Thu Mar 9 10:57:44 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: Daniel Golle -X-Patchwork-Id: 13167235 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -Date: Thu, 9 Mar 2023 10:57:44 +0000 -From: Daniel Golle -To: netdev@vger.kernel.org, linux-mediatek@lists.infradead.org, - linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, - Russell King , - Heiner Kallweit , - Lorenzo Bianconi , - Mark Lee , - John Crispin , Felix Fietkau , - AngeloGioacchino Del Regno - , - Matthias Brugger , - DENG Qingfang , - Landen Chao , - Sean Wang , - Paolo Abeni , - Jakub Kicinski , - Eric Dumazet , - "David S. Miller" , - Vladimir Oltean , - Florian Fainelli , - Andrew Lunn , - Vladimir Oltean -Cc: =?iso-8859-1?q?Bj=F8rn?= Mork , - Frank Wunderlich , - Alexander Couzens -Subject: [PATCH net-next v13 11/16] net: dsa: mt7530: use external PCS driver -Message-ID: - <2ac2ee40d3b0e705461b50613fda6a7edfdbc4b3.1678357225.git.daniel@makrotopia.org> -References: -MIME-Version: 1.0 -Content-Disposition: inline -In-Reply-To: -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org - -Implement regmap access wrappers, for now only to be used by the -pcs-mtk driver. -Make use of external PCS driver and drop the reduntant implementation -in mt7530.c. -As a nice side effect the SGMII registers can now also more easily be -inspected for debugging via /sys/kernel/debug/regmap. - -Reviewed-by: Russell King (Oracle) -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Tested-by: Frank Wunderlich ---- - drivers/net/dsa/Kconfig | 1 + - drivers/net/dsa/mt7530.c | 277 ++++++++++----------------------------- - drivers/net/dsa/mt7530.h | 47 +------ - 3 files changed, 71 insertions(+), 254 deletions(-) - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -37,6 +37,7 @@ config NET_DSA_MT7530 - tristate "MediaTek MT753x and MT7621 Ethernet switch support" - select NET_DSA_TAG_MTK - select MEDIATEK_GE_PHY -+ select PCS_MTK_LYNXI - help - This enables support for the MediaTek MT7530, MT7531, and MT7621 - Ethernet switch chips. ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2615,128 +2616,11 @@ static int mt7531_rgmii_setup(struct mt7 - return 0; - } - --static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -- phy_interface_t interface, int speed, int duplex) --{ -- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; -- int port = pcs_to_mt753x_pcs(pcs)->port; -- unsigned int val; -- -- /* For adjusting speed and duplex of SGMII force mode. */ -- if (interface != PHY_INTERFACE_MODE_SGMII || -- phylink_autoneg_inband(mode)) -- return; -- -- /* SGMII force mode setting */ -- val = mt7530_read(priv, MT7531_SGMII_MODE(port)); -- val &= ~MT7531_SGMII_IF_MODE_MASK; -- -- switch (speed) { -- case SPEED_10: -- val |= MT7531_SGMII_FORCE_SPEED_10; -- break; -- case SPEED_100: -- val |= MT7531_SGMII_FORCE_SPEED_100; -- break; -- case SPEED_1000: -- val |= MT7531_SGMII_FORCE_SPEED_1000; -- break; -- } -- -- /* MT7531 SGMII 1G force mode can only work in full duplex mode, -- * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. -- * -- * The speed check is unnecessary as the MAC capabilities apply -- * this restriction. --rmk -- */ -- if ((speed == SPEED_10 || speed == SPEED_100) && -- duplex != DUPLEX_FULL) -- val |= MT7531_SGMII_FORCE_HALF_DUPLEX; -- -- mt7530_write(priv, MT7531_SGMII_MODE(port), val); --} -- - static bool mt753x_is_mac_port(u32 port) - { - return (port == 5 || port == 6); - } - --static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port, -- phy_interface_t interface) --{ -- u32 val; -- -- if (!mt753x_is_mac_port(port)) -- return -EINVAL; -- -- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), -- MT7531_SGMII_PHYA_PWD); -- -- val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); -- val &= ~MT7531_RG_TPHY_SPEED_MASK; -- /* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B -- * encoding. -- */ -- val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ? -- MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G; -- mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); -- -- mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); -- -- /* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex -- * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. -- */ -- mt7530_rmw(priv, MT7531_SGMII_MODE(port), -- MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS, -- MT7531_SGMII_FORCE_SPEED_1000); -- -- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); -- -- return 0; --} -- --static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, -- phy_interface_t interface) --{ -- if (!mt753x_is_mac_port(port)) -- return -EINVAL; -- -- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), -- MT7531_SGMII_PHYA_PWD); -- -- mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port), -- MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G); -- -- mt7530_set(priv, MT7531_SGMII_MODE(port), -- MT7531_SGMII_REMOTE_FAULT_DIS | -- MT7531_SGMII_SPEED_DUPLEX_AN); -- -- mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port), -- MT7531_SGMII_TX_CONFIG_MASK, 1); -- -- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); -- -- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART); -- -- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); -- -- return 0; --} -- --static void mt7531_pcs_an_restart(struct phylink_pcs *pcs) --{ -- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; -- int port = pcs_to_mt753x_pcs(pcs)->port; -- u32 val; -- -- /* Only restart AN when AN is enabled */ -- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -- if (val & MT7531_SGMII_AN_ENABLE) { -- val |= MT7531_SGMII_AN_RESTART; -- mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); -- } --} -- - static int - mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, - phy_interface_t interface) -@@ -2759,11 +2643,11 @@ mt7531_mac_config(struct dsa_switch *ds, - phydev = dp->slave->phydev; - return mt7531_rgmii_setup(priv, port, interface, phydev); - case PHY_INTERFACE_MODE_SGMII: -- return mt7531_sgmii_setup_mode_an(priv, port, interface); - case PHY_INTERFACE_MODE_NA: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_2500BASEX: -- return mt7531_sgmii_setup_mode_force(priv, port, interface); -+ /* handled in SGMII PCS driver */ -+ return 0; - default: - return -EINVAL; - } -@@ -2788,11 +2672,11 @@ mt753x_phylink_mac_select_pcs(struct dsa - - switch (interface) { - case PHY_INTERFACE_MODE_TRGMII: -+ return &priv->pcs[port].pcs; - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_2500BASEX: -- return &priv->pcs[port].pcs; -- -+ return priv->ports[port].sgmii_pcs; - default: - return NULL; - } -@@ -3033,86 +2917,6 @@ static void mt7530_pcs_get_state(struct - state->pause |= MLO_PAUSE_TX; - } - --static int --mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port, -- struct phylink_link_state *state) --{ -- u32 status, val; -- u16 config_reg; -- -- status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -- state->link = !!(status & MT7531_SGMII_LINK_STATUS); -- state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE); -- if (state->interface == PHY_INTERFACE_MODE_SGMII && -- (status & MT7531_SGMII_AN_ENABLE)) { -- val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port)); -- config_reg = val >> 16; -- -- switch (config_reg & LPA_SGMII_SPD_MASK) { -- case LPA_SGMII_1000: -- state->speed = SPEED_1000; -- break; -- case LPA_SGMII_100: -- state->speed = SPEED_100; -- break; -- case LPA_SGMII_10: -- state->speed = SPEED_10; -- break; -- default: -- dev_err(priv->dev, "invalid sgmii PHY speed\n"); -- state->link = false; -- return -EINVAL; -- } -- -- if (config_reg & LPA_SGMII_FULL_DUPLEX) -- state->duplex = DUPLEX_FULL; -- else -- state->duplex = DUPLEX_HALF; -- } -- -- return 0; --} -- --static void --mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port, -- struct phylink_link_state *state) --{ -- unsigned int val; -- -- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -- state->link = !!(val & MT7531_SGMII_LINK_STATUS); -- if (!state->link) -- return; -- -- state->an_complete = state->link; -- -- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -- state->speed = SPEED_2500; -- else -- state->speed = SPEED_1000; -- -- state->duplex = DUPLEX_FULL; -- state->pause = MLO_PAUSE_NONE; --} -- --static void mt7531_pcs_get_state(struct phylink_pcs *pcs, -- struct phylink_link_state *state) --{ -- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; -- int port = pcs_to_mt753x_pcs(pcs)->port; -- -- if (state->interface == PHY_INTERFACE_MODE_SGMII) { -- mt7531_sgmii_pcs_get_state_an(priv, port, state); -- return; -- } else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) || -- (state->interface == PHY_INTERFACE_MODE_2500BASEX)) { -- mt7531_sgmii_pcs_get_state_inband(priv, port, state); -- return; -- } -- -- state->link = false; --} -- - static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertising, -@@ -3132,18 +2936,57 @@ static const struct phylink_pcs_ops mt75 - .pcs_an_restart = mt7530_pcs_an_restart, - }; - --static const struct phylink_pcs_ops mt7531_pcs_ops = { -- .pcs_validate = mt753x_pcs_validate, -- .pcs_get_state = mt7531_pcs_get_state, -- .pcs_config = mt753x_pcs_config, -- .pcs_an_restart = mt7531_pcs_an_restart, -- .pcs_link_up = mt7531_pcs_link_up, -+static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) -+{ -+ struct mt7530_priv *priv = context; -+ -+ *val = mt7530_read(priv, reg); -+ return 0; -+}; -+ -+static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) -+{ -+ struct mt7530_priv *priv = context; -+ -+ mt7530_write(priv, reg, val); -+ return 0; -+}; -+ -+static int mt7530_regmap_update_bits(void *context, unsigned int reg, -+ unsigned int mask, unsigned int val) -+{ -+ struct mt7530_priv *priv = context; -+ -+ mt7530_rmw(priv, reg, mask, val); -+ return 0; -+}; -+ -+static const struct regmap_bus mt7531_regmap_bus = { -+ .reg_write = mt7530_regmap_write, -+ .reg_read = mt7530_regmap_read, -+ .reg_update_bits = mt7530_regmap_update_bits, -+}; -+ -+#define MT7531_PCS_REGMAP_CONFIG(_name, _reg_base) \ -+ { \ -+ .name = _name, \ -+ .reg_bits = 16, \ -+ .val_bits = 32, \ -+ .reg_stride = 4, \ -+ .reg_base = _reg_base, \ -+ .max_register = 0x17c, \ -+ } -+ -+static const struct regmap_config mt7531_pcs_config[] = { -+ MT7531_PCS_REGMAP_CONFIG("port5", MT7531_SGMII_REG_BASE(5)), -+ MT7531_PCS_REGMAP_CONFIG("port6", MT7531_SGMII_REG_BASE(6)), - }; - - static int - mt753x_setup(struct dsa_switch *ds) - { - struct mt7530_priv *priv = ds->priv; -+ struct regmap *regmap; - int i, ret; - - /* Initialise the PCS devices */ -@@ -3151,8 +2994,6 @@ mt753x_setup(struct dsa_switch *ds) - priv->pcs[i].pcs.ops = priv->info->pcs_ops; - priv->pcs[i].priv = priv; - priv->pcs[i].port = i; -- if (mt753x_is_mac_port(i)) -- priv->pcs[i].pcs.poll = 1; - } - - ret = priv->info->sw_setup(ds); -@@ -3167,6 +3008,16 @@ mt753x_setup(struct dsa_switch *ds) - if (ret && priv->irq) - mt7530_free_irq_common(priv); - -+ if (priv->id == ID_MT7531) -+ for (i = 0; i < 2; i++) { -+ regmap = devm_regmap_init(ds->dev, -+ &mt7531_regmap_bus, priv, -+ &mt7531_pcs_config[i]); -+ priv->ports[5 + i].sgmii_pcs = -+ mtk_pcs_lynxi_create(ds->dev, regmap, -+ MT7531_PHYA_CTRL_SIGNAL3, 0); -+ } -+ - return ret; - } - -@@ -3258,7 +3109,7 @@ static const struct mt753x_info mt753x_t - }, - [ID_MT7531] = { - .id = ID_MT7531, -- .pcs_ops = &mt7531_pcs_ops, -+ .pcs_ops = &mt7530_pcs_ops, - .sw_setup = mt7531_setup, - .phy_read = mt7531_ind_phy_read, - .phy_write = mt7531_ind_phy_write, -@@ -3366,7 +3217,7 @@ static void - mt7530_remove(struct mdio_device *mdiodev) - { - struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -- int ret = 0; -+ int ret = 0, i; - - if (!priv) - return; -@@ -3385,6 +3236,10 @@ mt7530_remove(struct mdio_device *mdiode - mt7530_free_irq(priv); - - dsa_unregister_switch(priv->ds); -+ -+ for (i = 0; i < 2; ++i) -+ mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); -+ - mutex_destroy(&priv->reg_mutex); - } - ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -371,47 +371,8 @@ enum mt7530_vlan_port_acc_frm { - CCR_TX_OCT_CNT_BAD) - - /* MT7531 SGMII register group */ --#define MT7531_SGMII_REG_BASE 0x5000 --#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \ -- ((p) - 5) * 0x1000 + (r)) -- --/* Register forSGMII PCS_CONTROL_1 */ --#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00) --#define MT7531_SGMII_LINK_STATUS BIT(18) --#define MT7531_SGMII_AN_ENABLE BIT(12) --#define MT7531_SGMII_AN_RESTART BIT(9) --#define MT7531_SGMII_AN_COMPLETE BIT(21) -- --/* Register for SGMII PCS_SPPED_ABILITY */ --#define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08) --#define MT7531_SGMII_TX_CONFIG_MASK GENMASK(15, 0) --#define MT7531_SGMII_TX_CONFIG BIT(0) -- --/* Register for SGMII_MODE */ --#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20) --#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8) --#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1) --#define MT7531_SGMII_FORCE_DUPLEX BIT(4) --#define MT7531_SGMII_FORCE_SPEED_MASK GENMASK(3, 2) --#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3) --#define MT7531_SGMII_FORCE_SPEED_100 BIT(2) --#define MT7531_SGMII_FORCE_SPEED_10 0 --#define MT7531_SGMII_SPEED_DUPLEX_AN BIT(1) -- --enum mt7531_sgmii_force_duplex { -- MT7531_SGMII_FORCE_FULL_DUPLEX = 0, -- MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10, --}; -- --/* Fields of QPHY_PWR_STATE_CTRL */ --#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8) --#define MT7531_SGMII_PHYA_PWD BIT(4) -- --/* Values of SGMII SPEED */ --#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128) --#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3)) --#define MT7531_RG_TPHY_SPEED_1_25G 0x0 --#define MT7531_RG_TPHY_SPEED_3_125G BIT(2) -+#define MT7531_SGMII_REG_BASE(p) (0x5000 + ((p) - 5) * 0x1000) -+#define MT7531_PHYA_CTRL_SIGNAL3 0x128 - - /* Register for system reset */ - #define MT7530_SYS_CTRL 0x7000 -@@ -710,13 +671,13 @@ struct mt7530_fdb { - * @pm: The matrix used to show all connections with the port. - * @pvid: The VLAN specified is to be considered a PVID at ingress. Any - * untagged frames will be assigned to the related VLAN. -- * @vlan_filtering: The flags indicating whether the port that can recognize -- * VLAN-tagged frames. -+ * @sgmii_pcs: Pointer to PCS instance for SerDes ports - */ - struct mt7530_port { - bool enable; - u32 pm; - u16 pvid; -+ struct phylink_pcs *sgmii_pcs; - }; - - /* Port 5 interface select definitions */ diff --git a/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch b/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch deleted file mode 100644 index 4d024b063a..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c3552d3f85f06cf4b4818bd84c4fcc09d8d45165 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:19 +0100 -Subject: [PATCH 01/13] net: dsa: mt7530: make some noise if register read - fails - -Simply returning the negative error value instead of the read value -doesn't seem like a good idea. Return 0 instead and add WARN_ON_ONCE(1) -so this kind of error will not go unnoticed. - -Suggested-by: Andrew Lunn -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -224,9 +224,10 @@ mt7530_mii_read(struct mt7530_priv *priv - /* MT7530 uses 31 as the pseudo port */ - ret = bus->write(bus, 0x1f, 0x1f, page); - if (ret < 0) { -+ WARN_ON_ONCE(1); - dev_err(&bus->dev, - "failed to read mt7530 register\n"); -- return ret; -+ return 0; - } - - lo = bus->read(bus, 0x1f, r); diff --git a/target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch b/target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch deleted file mode 100644 index 5667449296..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch +++ /dev/null @@ -1,111 +0,0 @@ -From b896355fc4988216d4f38582d07add9252a795ae Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:30 +0100 -Subject: [PATCH 02/13] net: dsa: mt7530: refactor SGMII PCS creation - -Instead of macro templates use a dedidated function and allocated -regmap_config when creating the regmaps for the pcs-mtk-lynxi -instances. -This is in preparation to switching to use unlocked regmap accessors -and have regmap's locking API handle locking for us. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 74 +++++++++++++++++++++++++++------------- - 1 file changed, 50 insertions(+), 24 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2968,26 +2968,56 @@ static const struct regmap_bus mt7531_re - .reg_update_bits = mt7530_regmap_update_bits, - }; - --#define MT7531_PCS_REGMAP_CONFIG(_name, _reg_base) \ -- { \ -- .name = _name, \ -- .reg_bits = 16, \ -- .val_bits = 32, \ -- .reg_stride = 4, \ -- .reg_base = _reg_base, \ -- .max_register = 0x17c, \ -+static int -+mt7531_create_sgmii(struct mt7530_priv *priv) -+{ -+ struct regmap_config *mt7531_pcs_config[2]; -+ struct phylink_pcs *pcs; -+ struct regmap *regmap; -+ int i, ret = 0; -+ -+ for (i = 0; i < 2; i++) { -+ mt7531_pcs_config[i] = devm_kzalloc(priv->dev, -+ sizeof(struct regmap_config), -+ GFP_KERNEL); -+ if (!mt7531_pcs_config[i]) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ mt7531_pcs_config[i]->name = i ? "port6" : "port5"; -+ mt7531_pcs_config[i]->reg_bits = 16; -+ mt7531_pcs_config[i]->val_bits = 32; -+ mt7531_pcs_config[i]->reg_stride = 4; -+ mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); -+ mt7531_pcs_config[i]->max_register = 0x17c; -+ -+ regmap = devm_regmap_init(priv->dev, -+ &mt7531_regmap_bus, priv, -+ mt7531_pcs_config[i]); -+ if (IS_ERR(regmap)) { -+ ret = PTR_ERR(regmap); -+ break; -+ } -+ pcs = mtk_pcs_lynxi_create(priv->dev, regmap, -+ MT7531_PHYA_CTRL_SIGNAL3, 0); -+ if (!pcs) { -+ ret = -ENXIO; -+ break; -+ } -+ priv->ports[5 + i].sgmii_pcs = pcs; - } - --static const struct regmap_config mt7531_pcs_config[] = { -- MT7531_PCS_REGMAP_CONFIG("port5", MT7531_SGMII_REG_BASE(5)), -- MT7531_PCS_REGMAP_CONFIG("port6", MT7531_SGMII_REG_BASE(6)), --}; -+ if (ret && i) -+ mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs); -+ -+ return ret; -+} - - static int - mt753x_setup(struct dsa_switch *ds) - { - struct mt7530_priv *priv = ds->priv; -- struct regmap *regmap; - int i, ret; - - /* Initialise the PCS devices */ -@@ -3009,15 +3039,11 @@ mt753x_setup(struct dsa_switch *ds) - if (ret && priv->irq) - mt7530_free_irq_common(priv); - -- if (priv->id == ID_MT7531) -- for (i = 0; i < 2; i++) { -- regmap = devm_regmap_init(ds->dev, -- &mt7531_regmap_bus, priv, -- &mt7531_pcs_config[i]); -- priv->ports[5 + i].sgmii_pcs = -- mtk_pcs_lynxi_create(ds->dev, regmap, -- MT7531_PHYA_CTRL_SIGNAL3, 0); -- } -+ if (priv->id == ID_MT7531) { -+ ret = mt7531_create_sgmii(priv); -+ if (ret && priv->irq) -+ mt7530_free_irq_common(priv); -+ } - - return ret; - } diff --git a/target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch b/target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch deleted file mode 100644 index 3b4689fb19..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 33396408776385f3d2f6069646169a6b5b28e3b3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:40 +0100 -Subject: [PATCH 03/13] net: dsa: mt7530: use unlocked regmap accessors - -Instead of wrapping the locked register accessor functions, use the -unlocked variants and add locking wrapper functions to let regmap -handle the locking. - -This is a preparation towards being able to always use regmap to -access switch registers instead of open-coded accessor functions. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 23 ++++++++++++++--------- - 1 file changed, 14 insertions(+), 9 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2941,7 +2941,7 @@ static int mt7530_regmap_read(void *cont - { - struct mt7530_priv *priv = context; - -- *val = mt7530_read(priv, reg); -+ *val = mt7530_mii_read(priv, reg); - return 0; - }; - -@@ -2949,23 +2949,25 @@ static int mt7530_regmap_write(void *con - { - struct mt7530_priv *priv = context; - -- mt7530_write(priv, reg, val); -+ mt7530_mii_write(priv, reg, val); - return 0; - }; - --static int mt7530_regmap_update_bits(void *context, unsigned int reg, -- unsigned int mask, unsigned int val) -+static void -+mt7530_mdio_regmap_lock(void *mdio_lock) - { -- struct mt7530_priv *priv = context; -+ mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED); -+} - -- mt7530_rmw(priv, reg, mask, val); -- return 0; --}; -+static void -+mt7530_mdio_regmap_unlock(void *mdio_lock) -+{ -+ mutex_unlock(mdio_lock); -+} - - static const struct regmap_bus mt7531_regmap_bus = { - .reg_write = mt7530_regmap_write, - .reg_read = mt7530_regmap_read, -- .reg_update_bits = mt7530_regmap_update_bits, - }; - - static int -@@ -2991,6 +2993,9 @@ mt7531_create_sgmii(struct mt7530_priv * - mt7531_pcs_config[i]->reg_stride = 4; - mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); - mt7531_pcs_config[i]->max_register = 0x17c; -+ mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock; -+ mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; -+ mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; - - regmap = devm_regmap_init(priv->dev, - &mt7531_regmap_bus, priv, diff --git a/target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch b/target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch deleted file mode 100644 index 04033f14f4..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 743cba4345cb366248f9d375c6a9e50243dc0677 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:52 +0100 -Subject: [PATCH 04/13] net: dsa: mt7530: use regmap to access switch register - space - -Use regmap API to access the switch register space. - -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 99 ++++++++++++++++++++++++---------------- - drivers/net/dsa/mt7530.h | 2 + - 2 files changed, 62 insertions(+), 39 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -183,9 +183,9 @@ core_clear(struct mt7530_priv *priv, u32 - } - - static int --mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val) -+mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) - { -- struct mii_bus *bus = priv->bus; -+ struct mii_bus *bus = context; - u16 page, r, lo, hi; - int ret; - -@@ -197,24 +197,34 @@ mt7530_mii_write(struct mt7530_priv *pri - /* MT7530 uses 31 as the pseudo port */ - ret = bus->write(bus, 0x1f, 0x1f, page); - if (ret < 0) -- goto err; -+ return ret; - - ret = bus->write(bus, 0x1f, r, lo); - if (ret < 0) -- goto err; -+ return ret; - - ret = bus->write(bus, 0x1f, 0x10, hi); --err: -+ return ret; -+} -+ -+static int -+mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ int ret; -+ -+ ret = regmap_write(priv->regmap, reg, val); -+ - if (ret < 0) -- dev_err(&bus->dev, -+ dev_err(priv->dev, - "failed to write mt7530 register\n"); -+ - return ret; - } - --static u32 --mt7530_mii_read(struct mt7530_priv *priv, u32 reg) -+static int -+mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) - { -- struct mii_bus *bus = priv->bus; -+ struct mii_bus *bus = context; - u16 page, r, lo, hi; - int ret; - -@@ -223,17 +233,32 @@ mt7530_mii_read(struct mt7530_priv *priv - - /* MT7530 uses 31 as the pseudo port */ - ret = bus->write(bus, 0x1f, 0x1f, page); -- if (ret < 0) { -+ if (ret < 0) -+ return ret; -+ -+ lo = bus->read(bus, 0x1f, r); -+ hi = bus->read(bus, 0x1f, 0x10); -+ -+ *val = (hi << 16) | (lo & 0xffff); -+ -+ return 0; -+} -+ -+static u32 -+mt7530_mii_read(struct mt7530_priv *priv, u32 reg) -+{ -+ int ret; -+ u32 val; -+ -+ ret = regmap_read(priv->regmap, reg, &val); -+ if (ret) { - WARN_ON_ONCE(1); -- dev_err(&bus->dev, -+ dev_err(priv->dev, - "failed to read mt7530 register\n"); - return 0; - } - -- lo = bus->read(bus, 0x1f, r); -- hi = bus->read(bus, 0x1f, 0x10); -- -- return (hi << 16) | (lo & 0xffff); -+ return val; - } - - static void -@@ -283,14 +308,10 @@ mt7530_rmw(struct mt7530_priv *priv, u32 - u32 mask, u32 set) - { - struct mii_bus *bus = priv->bus; -- u32 val; - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- val = mt7530_mii_read(priv, reg); -- val &= ~mask; -- val |= set; -- mt7530_mii_write(priv, reg, val); -+ regmap_update_bits(priv->regmap, reg, mask, set); - - mutex_unlock(&bus->mdio_lock); - } -@@ -298,7 +319,7 @@ mt7530_rmw(struct mt7530_priv *priv, u32 - static void - mt7530_set(struct mt7530_priv *priv, u32 reg, u32 val) - { -- mt7530_rmw(priv, reg, 0, val); -+ mt7530_rmw(priv, reg, val, val); - } - - static void -@@ -2937,22 +2958,6 @@ static const struct phylink_pcs_ops mt75 - .pcs_an_restart = mt7530_pcs_an_restart, - }; - --static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) --{ -- struct mt7530_priv *priv = context; -- -- *val = mt7530_mii_read(priv, reg); -- return 0; --}; -- --static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) --{ -- struct mt7530_priv *priv = context; -- -- mt7530_mii_write(priv, reg, val); -- return 0; --}; -- - static void - mt7530_mdio_regmap_lock(void *mdio_lock) - { -@@ -2965,7 +2970,7 @@ mt7530_mdio_regmap_unlock(void *mdio_loc - mutex_unlock(mdio_lock); - } - --static const struct regmap_bus mt7531_regmap_bus = { -+static const struct regmap_bus mt7530_regmap_bus = { - .reg_write = mt7530_regmap_write, - .reg_read = mt7530_regmap_read, - }; -@@ -2998,7 +3003,7 @@ mt7531_create_sgmii(struct mt7530_priv * - mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; - - regmap = devm_regmap_init(priv->dev, -- &mt7531_regmap_bus, priv, -+ &mt7530_regmap_bus, priv->bus, - mt7531_pcs_config[i]); - if (IS_ERR(regmap)) { - ret = PTR_ERR(regmap); -@@ -3163,6 +3168,7 @@ MODULE_DEVICE_TABLE(of, mt7530_of_match) - static int - mt7530_probe(struct mdio_device *mdiodev) - { -+ static struct regmap_config *regmap_config; - struct mt7530_priv *priv; - struct device_node *dn; - -@@ -3242,6 +3248,21 @@ mt7530_probe(struct mdio_device *mdiodev - mutex_init(&priv->reg_mutex); - dev_set_drvdata(&mdiodev->dev, priv); - -+ regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), -+ GFP_KERNEL); -+ if (!regmap_config) -+ return -ENOMEM; -+ -+ regmap_config->reg_bits = 16; -+ regmap_config->val_bits = 32; -+ regmap_config->reg_stride = 4; -+ regmap_config->max_register = MT7530_CREV; -+ regmap_config->disable_locking = true; -+ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, -+ priv->bus, regmap_config); -+ if (IS_ERR(priv->regmap)) -+ return PTR_ERR(priv->regmap); -+ - return dsa_register_switch(priv->ds); - } - ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -754,6 +754,7 @@ struct mt753x_info { - * @dev: The device pointer - * @ds: The pointer to the dsa core structure - * @bus: The bus used for the device and built-in PHY -+ * @regmap: The regmap instance representing all switch registers - * @rstc: The pointer to reset control used by MCM - * @core_pwr: The power supplied into the core - * @io_pwr: The power supplied into the I/O -@@ -774,6 +775,7 @@ struct mt7530_priv { - struct device *dev; - struct dsa_switch *ds; - struct mii_bus *bus; -+ struct regmap *regmap; - struct reset_control *rstc; - struct regulator *core_pwr; - struct regulator *io_pwr; diff --git a/target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch b/target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch deleted file mode 100644 index 6c5bebdd80..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch +++ /dev/null @@ -1,54 +0,0 @@ -From f3cf1d06e2aef644b426c23b4bb570780b1f8d47 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:04 +0100 -Subject: [PATCH 05/13] net: dsa: mt7530: move SGMII PCS creation to - mt7530_probe function - -Move creating the SGMII PCS from mt753x_setup() to the more appropriate -mt7530_probe() function. -This is done also in preparation of moving all functions related to -MDIO-connected MT753x switches to a separate module. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -3049,12 +3049,6 @@ mt753x_setup(struct dsa_switch *ds) - if (ret && priv->irq) - mt7530_free_irq_common(priv); - -- if (priv->id == ID_MT7531) { -- ret = mt7531_create_sgmii(priv); -- if (ret && priv->irq) -- mt7530_free_irq_common(priv); -- } -- - return ret; - } - -@@ -3171,6 +3165,7 @@ mt7530_probe(struct mdio_device *mdiodev - static struct regmap_config *regmap_config; - struct mt7530_priv *priv; - struct device_node *dn; -+ int ret; - - dn = mdiodev->dev.of_node; - -@@ -3263,6 +3258,12 @@ mt7530_probe(struct mdio_device *mdiodev - if (IS_ERR(priv->regmap)) - return PTR_ERR(priv->regmap); - -+ if (priv->id == ID_MT7531) { -+ ret = mt7531_create_sgmii(priv); -+ if (ret) -+ return ret; -+ } -+ - return dsa_register_switch(priv->ds); - } - diff --git a/target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch b/target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch deleted file mode 100644 index a8933d2cf4..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch +++ /dev/null @@ -1,273 +0,0 @@ -From e4729ae7c095c0c87794bff47ea43e35d69de986 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:16 +0100 -Subject: [PATCH 06/13] net: dsa: mt7530: introduce mutex helpers - -As the MDIO bus lock only needs to be involved if actually operating -on an MDIO-connected switch we will need to skip locking for built-in -switches which are accessed via MMIO. -Create helper functions which simplify that upcoming change. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 73 ++++++++++++++++++++-------------------- - 1 file changed, 36 insertions(+), 37 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -143,31 +143,40 @@ err: - } - - static void --core_write(struct mt7530_priv *priv, u32 reg, u32 val) -+mt7530_mutex_lock(struct mt7530_priv *priv) - { -- struct mii_bus *bus = priv->bus; -+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+} - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+static void -+mt7530_mutex_unlock(struct mt7530_priv *priv) -+{ -+ mutex_unlock(&priv->bus->mdio_lock); -+} -+ -+static void -+core_write(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ mt7530_mutex_lock(priv); - - core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); - -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - } - - static void - core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) - { -- struct mii_bus *bus = priv->bus; - u32 val; - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - val = core_read_mmd_indirect(priv, reg, MDIO_MMD_VEND2); - val &= ~mask; - val |= set; - core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); - -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - } - - static void -@@ -264,13 +273,11 @@ mt7530_mii_read(struct mt7530_priv *priv - static void - mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val) - { -- struct mii_bus *bus = priv->bus; -- -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - mt7530_mii_write(priv, reg, val); - -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - } - - static u32 -@@ -282,14 +289,13 @@ _mt7530_unlocked_read(struct mt7530_dumm - static u32 - _mt7530_read(struct mt7530_dummy_poll *p) - { -- struct mii_bus *bus = p->priv->bus; - u32 val; - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(p->priv); - - val = mt7530_mii_read(p->priv, p->reg); - -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(p->priv); - - return val; - } -@@ -307,13 +313,11 @@ static void - mt7530_rmw(struct mt7530_priv *priv, u32 reg, - u32 mask, u32 set) - { -- struct mii_bus *bus = priv->bus; -- -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - regmap_update_bits(priv->regmap, reg, mask, set); - -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - } - - static void -@@ -645,14 +649,13 @@ static int - mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, - int regnum) - { -- struct mii_bus *bus = priv->bus; - struct mt7530_dummy_poll p; - u32 reg, val; - int ret; - - INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, - !(val & MT7531_PHY_ACS_ST), 20, 100000); -@@ -685,7 +688,7 @@ mt7531_ind_c45_phy_read(struct mt7530_pr - - ret = val & MT7531_MDIO_RW_DATA_MASK; - out: -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - - return ret; - } -@@ -694,14 +697,13 @@ static int - mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, - int regnum, u32 data) - { -- struct mii_bus *bus = priv->bus; - struct mt7530_dummy_poll p; - u32 val, reg; - int ret; - - INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, - !(val & MT7531_PHY_ACS_ST), 20, 100000); -@@ -733,7 +735,7 @@ mt7531_ind_c45_phy_write(struct mt7530_p - } - - out: -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - - return ret; - } -@@ -741,14 +743,13 @@ out: - static int - mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum) - { -- struct mii_bus *bus = priv->bus; - struct mt7530_dummy_poll p; - int ret; - u32 val; - - INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, - !(val & MT7531_PHY_ACS_ST), 20, 100000); -@@ -771,7 +772,7 @@ mt7531_ind_c22_phy_read(struct mt7530_pr - - ret = val & MT7531_MDIO_RW_DATA_MASK; - out: -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - - return ret; - } -@@ -780,14 +781,13 @@ static int - mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, - u16 data) - { -- struct mii_bus *bus = priv->bus; - struct mt7530_dummy_poll p; - int ret; - u32 reg; - - INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, - !(reg & MT7531_PHY_ACS_ST), 20, 100000); -@@ -809,7 +809,7 @@ mt7531_ind_c22_phy_write(struct mt7530_p - } - - out: -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - - return ret; - } -@@ -1125,7 +1125,6 @@ static int - mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) - { - struct mt7530_priv *priv = ds->priv; -- struct mii_bus *bus = priv->bus; - int length; - u32 val; - -@@ -1136,7 +1135,7 @@ mt7530_port_change_mtu(struct dsa_switch - if (!dsa_is_cpu_port(ds, port)) - return 0; - -- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - - val = mt7530_mii_read(priv, MT7530_GMACCR); - val &= ~MAX_RX_PKT_LEN_MASK; -@@ -1157,7 +1156,7 @@ mt7530_port_change_mtu(struct dsa_switch - - mt7530_mii_write(priv, MT7530_GMACCR, val); - -- mutex_unlock(&bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - - return 0; - } -@@ -1958,10 +1957,10 @@ mt7530_irq_thread_fn(int irq, void *dev_ - u32 val; - int p; - -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - val = mt7530_mii_read(priv, MT7530_SYS_INT_STS); - mt7530_mii_write(priv, MT7530_SYS_INT_STS, val); -- mutex_unlock(&priv->bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - - for (p = 0; p < MT7530_NUM_PHYS; p++) { - if (BIT(p) & val) { -@@ -1997,7 +1996,7 @@ mt7530_irq_bus_lock(struct irq_data *d) - { - struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); - -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mt7530_mutex_lock(priv); - } - - static void -@@ -2006,7 +2005,7 @@ mt7530_irq_bus_sync_unlock(struct irq_da - struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); - - mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); -- mutex_unlock(&priv->bus->mdio_lock); -+ mt7530_mutex_unlock(priv); - } - - static struct irq_chip mt7530_irq_chip = { diff --git a/target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch b/target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch deleted file mode 100644 index 6c68dc0c4f..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0d7ae94a0c581f86939bebec0b6ccd66e640d1d8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:28 +0100 -Subject: [PATCH 07/13] net: dsa: mt7530: move p5_intf_modes() function to - mt7530.c - -In preparation of splitting mt7530.c into a driver for MDIO-connected -as well as MDIO-accessed built-in switches on one hand and MMIO-accessed -built-in switches move the p5_inft_modes() function from mt7530.h to -mt7530.c. The function is only needed there and will trigger a compiler -warning about a defined but unused function otherwise when including -mt7530.h in the to-be-introduced bus-specific drivers. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 18 ++++++++++++++++++ - drivers/net/dsa/mt7530.h | 18 ------------------ - 2 files changed, 18 insertions(+), 18 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -950,6 +950,24 @@ mt7530_set_ageing_time(struct dsa_switch - return 0; - } - -+static const char *p5_intf_modes(unsigned int p5_interface) -+{ -+ switch (p5_interface) { -+ case P5_DISABLED: -+ return "DISABLED"; -+ case P5_INTF_SEL_PHY_P0: -+ return "PHY P0"; -+ case P5_INTF_SEL_PHY_P4: -+ return "PHY P4"; -+ case P5_INTF_SEL_GMAC5: -+ return "GMAC5"; -+ case P5_INTF_SEL_GMAC5_SGMII: -+ return "GMAC5_SGMII"; -+ default: -+ return "unknown"; -+ } -+} -+ - static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface) - { - struct mt7530_priv *priv = ds->priv; ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -689,24 +689,6 @@ enum p5_interface_select { - P5_INTF_SEL_GMAC5_SGMII, - }; - --static const char *p5_intf_modes(unsigned int p5_interface) --{ -- switch (p5_interface) { -- case P5_DISABLED: -- return "DISABLED"; -- case P5_INTF_SEL_PHY_P0: -- return "PHY P0"; -- case P5_INTF_SEL_PHY_P4: -- return "PHY P4"; -- case P5_INTF_SEL_GMAC5: -- return "GMAC5"; -- case P5_INTF_SEL_GMAC5_SGMII: -- return "GMAC5_SGMII"; -- default: -- return "unknown"; -- } --} -- - struct mt7530_priv; - - struct mt753x_pcs { diff --git a/target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch b/target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch deleted file mode 100644 index dc4fcb6aa1..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 4d632005c90e253c000d0db73b7cdb9d8dc2e2dd Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:39 +0100 -Subject: [PATCH 08/13] net: dsa: mt7530: introduce mt7530_probe_common helper - function - -Move commonly used parts from mt7530_probe into new mt7530_probe_common -helper function which will be used by both, mt7530_probe and the -to-be-introduced mt7988_probe. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 98 ++++++++++++++++++++++------------------ - 1 file changed, 54 insertions(+), 44 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -3177,44 +3177,21 @@ static const struct of_device_id mt7530_ - MODULE_DEVICE_TABLE(of, mt7530_of_match); - - static int --mt7530_probe(struct mdio_device *mdiodev) -+mt7530_probe_common(struct mt7530_priv *priv) - { -- static struct regmap_config *regmap_config; -- struct mt7530_priv *priv; -- struct device_node *dn; -- int ret; -+ struct device *dev = priv->dev; - -- dn = mdiodev->dev.of_node; -- -- priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); -- if (!priv) -- return -ENOMEM; -- -- priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); -+ priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL); - if (!priv->ds) - return -ENOMEM; - -- priv->ds->dev = &mdiodev->dev; -+ priv->ds->dev = dev; - priv->ds->num_ports = MT7530_NUM_PORTS; - -- /* Use medatek,mcm property to distinguish hardware type that would -- * casues a little bit differences on power-on sequence. -- */ -- priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); -- if (priv->mcm) { -- dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); -- -- priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); -- if (IS_ERR(priv->rstc)) { -- dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -- return PTR_ERR(priv->rstc); -- } -- } -- - /* Get the hardware identifier from the devicetree node. - * We will need it for some of the clock and regulator setup. - */ -- priv->info = of_device_get_match_data(&mdiodev->dev); -+ priv->info = of_device_get_match_data(dev); - if (!priv->info) - return -EINVAL; - -@@ -3228,23 +3205,53 @@ mt7530_probe(struct mdio_device *mdiodev - return -EINVAL; - - priv->id = priv->info->id; -+ priv->dev = dev; -+ priv->ds->priv = priv; -+ priv->ds->ops = &mt7530_switch_ops; -+ mutex_init(&priv->reg_mutex); -+ dev_set_drvdata(dev, priv); - -- if (priv->id == ID_MT7530) { -- priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); -- if (IS_ERR(priv->core_pwr)) -- return PTR_ERR(priv->core_pwr); -+ return 0; -+} - -- priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); -- if (IS_ERR(priv->io_pwr)) -- return PTR_ERR(priv->io_pwr); -- } -+static int -+mt7530_probe(struct mdio_device *mdiodev) -+{ -+ static struct regmap_config *regmap_config; -+ struct mt7530_priv *priv; -+ struct device_node *dn; -+ int ret; -+ -+ dn = mdiodev->dev.of_node; -+ -+ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; - -- /* Not MCM that indicates switch works as the remote standalone -+ priv->bus = mdiodev->bus; -+ priv->dev = &mdiodev->dev; -+ -+ ret = mt7530_probe_common(priv); -+ if (ret) -+ return ret; -+ -+ /* Use medatek,mcm property to distinguish hardware type that would -+ * cause a little bit differences on power-on sequence. -+ * Not MCM that indicates switch works as the remote standalone - * integrated circuit so the GPIO pin would be used to complete - * the reset, otherwise memory-mapped register accessing used - * through syscon provides in the case of MCM. - */ -- if (!priv->mcm) { -+ priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); -+ if (priv->mcm) { -+ dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); -+ -+ priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); -+ if (IS_ERR(priv->rstc)) { -+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -+ return PTR_ERR(priv->rstc); -+ } -+ } else { - priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", - GPIOD_OUT_LOW); - if (IS_ERR(priv->reset)) { -@@ -3253,12 +3260,15 @@ mt7530_probe(struct mdio_device *mdiodev - } - } - -- priv->bus = mdiodev->bus; -- priv->dev = &mdiodev->dev; -- priv->ds->priv = priv; -- priv->ds->ops = &mt7530_switch_ops; -- mutex_init(&priv->reg_mutex); -- dev_set_drvdata(&mdiodev->dev, priv); -+ if (priv->id == ID_MT7530) { -+ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); -+ if (IS_ERR(priv->core_pwr)) -+ return PTR_ERR(priv->core_pwr); -+ -+ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); -+ if (IS_ERR(priv->io_pwr)) -+ return PTR_ERR(priv->io_pwr); -+ } - - regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), - GFP_KERNEL); diff --git a/target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch b/target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch deleted file mode 100644 index 5df859d2df..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 69b838d2629e6b82bcd9e0ab3c1c03f46e5e01d3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:50 +0100 -Subject: [PATCH 09/13] net: dsa: mt7530: introduce mt7530_remove_common helper - function - -Move commonly used parts from mt7530_remove into new -mt7530_remove_common helper function which will be used by both, -mt7530_remove and the to-be-introduced mt7988_remove. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 18 ++++++++++++------ - 1 file changed, 12 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -3295,6 +3295,17 @@ mt7530_probe(struct mdio_device *mdiodev - } - - static void -+mt7530_remove_common(struct mt7530_priv *priv) -+{ -+ if (priv->irq) -+ mt7530_free_irq(priv); -+ -+ dsa_unregister_switch(priv->ds); -+ -+ mutex_destroy(&priv->reg_mutex); -+} -+ -+static void - mt7530_remove(struct mdio_device *mdiodev) - { - struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -@@ -3313,15 +3324,10 @@ mt7530_remove(struct mdio_device *mdiode - dev_err(priv->dev, "Failed to disable io pwr: %d\n", - ret); - -- if (priv->irq) -- mt7530_free_irq(priv); -- -- dsa_unregister_switch(priv->ds); -+ mt7530_remove_common(priv); - - for (i = 0; i < 2; ++i) - mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); -- -- mutex_destroy(&priv->reg_mutex); - } - - static void mt7530_shutdown(struct mdio_device *mdiodev) diff --git a/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch deleted file mode 100644 index d203711884..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch +++ /dev/null @@ -1,691 +0,0 @@ -From 8eceed6dbd74067dbf4d8e39f14734f4d2f35176 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:19:13 +0100 -Subject: [PATCH 10/13] net: dsa: mt7530: introduce separate MDIO driver - -Split MT7530 switch driver into a common part and a part specific -for MDIO connected switches and multi-chip modules. -Move MDIO-specific functions to newly introduced mt7530-mdio.c while -keeping the common parts in mt7530.c. -Introduce new Kconfig symbol CONFIG_NET_DSA_MT7530_MDIO which is -implied by CONFIG_NET_DSA_MT7530. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 1 + - drivers/net/dsa/Kconfig | 16 +- - drivers/net/dsa/Makefile | 1 + - drivers/net/dsa/mt7530-mdio.c | 271 ++++++++++++++++++++++++++++++++++ - drivers/net/dsa/mt7530.c | 264 +-------------------------------- - drivers/net/dsa/mt7530.h | 6 + - 6 files changed, 301 insertions(+), 258 deletions(-) - create mode 100644 drivers/net/dsa/mt7530-mdio.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -13062,6 +13062,7 @@ M: Landen Chao - L: netdev@vger.kernel.org - S: Maintained -+F: drivers/net/dsa/mt7530-mdio.c - F: drivers/net/dsa/mt7530.* - F: net/dsa/tag_mtk.c - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -37,10 +37,22 @@ config NET_DSA_MT7530 - tristate "MediaTek MT753x and MT7621 Ethernet switch support" - select NET_DSA_TAG_MTK - select MEDIATEK_GE_PHY -+ imply NET_DSA_MT7530_MDIO -+ help -+ This enables support for the MediaTek MT7530 and MT7531 Ethernet -+ switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT, -+ MT7621ST and MT7623AI SoCs, and built-in switch in MT7988 SoC are -+ supported as well. -+ -+config NET_DSA_MT7530_MDIO -+ tristate "MediaTek MT7530 MDIO interface driver" -+ depends on NET_DSA_MT7530 - select PCS_MTK_LYNXI - help -- This enables support for the MediaTek MT7530, MT7531, and MT7621 -- Ethernet switch chips. -+ This enables support for the MediaTek MT7530 and MT7531 switch -+ chips which are connected via MDIO, as well as multi-chip -+ module MT7530 which can be found in the MT7621AT, MT7621DAT, -+ MT7621ST and MT7623AI SoCs. - - config NET_DSA_MV88E6060 - tristate "Marvell 88E6060 ethernet switch chip support" ---- a/drivers/net/dsa/Makefile -+++ b/drivers/net/dsa/Makefile -@@ -7,6 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdi - endif - obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o - obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o -+obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o - obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o - obj-$(CONFIG_NET_DSA_RZN1_A5PSW) += rzn1_a5psw.o - obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o ---- /dev/null -+++ b/drivers/net/dsa/mt7530-mdio.c -@@ -0,0 +1,271 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mt7530.h" -+ -+static int -+mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) -+{ -+ struct mii_bus *bus = context; -+ u16 page, r, lo, hi; -+ int ret; -+ -+ page = (reg >> 6) & 0x3ff; -+ r = (reg >> 2) & 0xf; -+ lo = val & 0xffff; -+ hi = val >> 16; -+ -+ /* MT7530 uses 31 as the pseudo port */ -+ ret = bus->write(bus, 0x1f, 0x1f, page); -+ if (ret < 0) -+ return ret; -+ -+ ret = bus->write(bus, 0x1f, r, lo); -+ if (ret < 0) -+ return ret; -+ -+ ret = bus->write(bus, 0x1f, 0x10, hi); -+ return ret; -+} -+ -+static int -+mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) -+{ -+ struct mii_bus *bus = context; -+ u16 page, r, lo, hi; -+ int ret; -+ -+ page = (reg >> 6) & 0x3ff; -+ r = (reg >> 2) & 0xf; -+ -+ /* MT7530 uses 31 as the pseudo port */ -+ ret = bus->write(bus, 0x1f, 0x1f, page); -+ if (ret < 0) -+ return ret; -+ -+ lo = bus->read(bus, 0x1f, r); -+ hi = bus->read(bus, 0x1f, 0x10); -+ -+ *val = (hi << 16) | (lo & 0xffff); -+ -+ return 0; -+} -+ -+static void -+mt7530_mdio_regmap_lock(void *mdio_lock) -+{ -+ mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED); -+} -+ -+static void -+mt7530_mdio_regmap_unlock(void *mdio_lock) -+{ -+ mutex_unlock(mdio_lock); -+} -+ -+static const struct regmap_bus mt7530_regmap_bus = { -+ .reg_write = mt7530_regmap_write, -+ .reg_read = mt7530_regmap_read, -+}; -+ -+static int -+mt7531_create_sgmii(struct mt7530_priv *priv) -+{ -+ struct regmap_config *mt7531_pcs_config[2]; -+ struct phylink_pcs *pcs; -+ struct regmap *regmap; -+ int i, ret = 0; -+ -+ for (i = 0; i < 2; i++) { -+ mt7531_pcs_config[i] = devm_kzalloc(priv->dev, -+ sizeof(struct regmap_config), -+ GFP_KERNEL); -+ if (!mt7531_pcs_config[i]) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ mt7531_pcs_config[i]->name = i ? "port6" : "port5"; -+ mt7531_pcs_config[i]->reg_bits = 16; -+ mt7531_pcs_config[i]->val_bits = 32; -+ mt7531_pcs_config[i]->reg_stride = 4; -+ mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); -+ mt7531_pcs_config[i]->max_register = 0x17c; -+ mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock; -+ mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; -+ mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; -+ -+ regmap = devm_regmap_init(priv->dev, -+ &mt7530_regmap_bus, priv->bus, -+ mt7531_pcs_config[i]); -+ if (IS_ERR(regmap)) { -+ ret = PTR_ERR(regmap); -+ break; -+ } -+ pcs = mtk_pcs_lynxi_create(priv->dev, regmap, -+ MT7531_PHYA_CTRL_SIGNAL3, 0); -+ if (!pcs) { -+ ret = -ENXIO; -+ break; -+ } -+ priv->ports[5 + i].sgmii_pcs = pcs; -+ } -+ -+ if (ret && i) -+ mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs); -+ -+ return ret; -+} -+ -+static const struct of_device_id mt7530_of_match[] = { -+ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, -+ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, -+ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, mt7530_of_match); -+ -+static int -+mt7530_probe(struct mdio_device *mdiodev) -+{ -+ static struct regmap_config *regmap_config; -+ struct mt7530_priv *priv; -+ struct device_node *dn; -+ int ret; -+ -+ dn = mdiodev->dev.of_node; -+ -+ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->bus = mdiodev->bus; -+ priv->dev = &mdiodev->dev; -+ -+ ret = mt7530_probe_common(priv); -+ if (ret) -+ return ret; -+ -+ /* Use medatek,mcm property to distinguish hardware type that would -+ * cause a little bit differences on power-on sequence. -+ * Not MCM that indicates switch works as the remote standalone -+ * integrated circuit so the GPIO pin would be used to complete -+ * the reset, otherwise memory-mapped register accessing used -+ * through syscon provides in the case of MCM. -+ */ -+ priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); -+ if (priv->mcm) { -+ dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); -+ -+ priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); -+ if (IS_ERR(priv->rstc)) { -+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -+ return PTR_ERR(priv->rstc); -+ } -+ } else { -+ priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(priv->reset)) { -+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -+ return PTR_ERR(priv->reset); -+ } -+ } -+ -+ if (priv->id == ID_MT7530) { -+ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); -+ if (IS_ERR(priv->core_pwr)) -+ return PTR_ERR(priv->core_pwr); -+ -+ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); -+ if (IS_ERR(priv->io_pwr)) -+ return PTR_ERR(priv->io_pwr); -+ } -+ -+ regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), -+ GFP_KERNEL); -+ if (!regmap_config) -+ return -ENOMEM; -+ -+ regmap_config->reg_bits = 16; -+ regmap_config->val_bits = 32; -+ regmap_config->reg_stride = 4; -+ regmap_config->max_register = MT7530_CREV; -+ regmap_config->disable_locking = true; -+ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, -+ priv->bus, regmap_config); -+ if (IS_ERR(priv->regmap)) -+ return PTR_ERR(priv->regmap); -+ -+ if (priv->id == ID_MT7531) { -+ ret = mt7531_create_sgmii(priv); -+ if (ret) -+ return ret; -+ } -+ -+ return dsa_register_switch(priv->ds); -+} -+ -+static void -+mt7530_remove(struct mdio_device *mdiodev) -+{ -+ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -+ int ret = 0, i; -+ -+ if (!priv) -+ return; -+ -+ ret = regulator_disable(priv->core_pwr); -+ if (ret < 0) -+ dev_err(priv->dev, -+ "Failed to disable core power: %d\n", ret); -+ -+ ret = regulator_disable(priv->io_pwr); -+ if (ret < 0) -+ dev_err(priv->dev, "Failed to disable io pwr: %d\n", -+ ret); -+ -+ mt7530_remove_common(priv); -+ -+ for (i = 0; i < 2; ++i) -+ mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); -+} -+ -+static void mt7530_shutdown(struct mdio_device *mdiodev) -+{ -+ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -+ -+ if (!priv) -+ return; -+ -+ dsa_switch_shutdown(priv->ds); -+ -+ dev_set_drvdata(&mdiodev->dev, NULL); -+} -+ -+static struct mdio_driver mt7530_mdio_driver = { -+ .probe = mt7530_probe, -+ .remove = mt7530_remove, -+ .shutdown = mt7530_shutdown, -+ .mdiodrv.driver = { -+ .name = "mt7530-mdio", -+ .of_match_table = mt7530_of_match, -+ }, -+}; -+ -+mdio_module_driver(mt7530_mdio_driver); -+ -+MODULE_AUTHOR("Sean Wang "); -+MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MDIO)"); -+MODULE_LICENSE("GPL"); ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -192,31 +191,6 @@ core_clear(struct mt7530_priv *priv, u32 - } - - static int --mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) --{ -- struct mii_bus *bus = context; -- u16 page, r, lo, hi; -- int ret; -- -- page = (reg >> 6) & 0x3ff; -- r = (reg >> 2) & 0xf; -- lo = val & 0xffff; -- hi = val >> 16; -- -- /* MT7530 uses 31 as the pseudo port */ -- ret = bus->write(bus, 0x1f, 0x1f, page); -- if (ret < 0) -- return ret; -- -- ret = bus->write(bus, 0x1f, r, lo); -- if (ret < 0) -- return ret; -- -- ret = bus->write(bus, 0x1f, 0x10, hi); -- return ret; --} -- --static int - mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val) - { - int ret; -@@ -230,29 +204,6 @@ mt7530_mii_write(struct mt7530_priv *pri - return ret; - } - --static int --mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) --{ -- struct mii_bus *bus = context; -- u16 page, r, lo, hi; -- int ret; -- -- page = (reg >> 6) & 0x3ff; -- r = (reg >> 2) & 0xf; -- -- /* MT7530 uses 31 as the pseudo port */ -- ret = bus->write(bus, 0x1f, 0x1f, page); -- if (ret < 0) -- return ret; -- -- lo = bus->read(bus, 0x1f, r); -- hi = bus->read(bus, 0x1f, 0x10); -- -- *val = (hi << 16) | (lo & 0xffff); -- -- return 0; --} -- - static u32 - mt7530_mii_read(struct mt7530_priv *priv, u32 reg) - { -@@ -2975,72 +2926,6 @@ static const struct phylink_pcs_ops mt75 - .pcs_an_restart = mt7530_pcs_an_restart, - }; - --static void --mt7530_mdio_regmap_lock(void *mdio_lock) --{ -- mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED); --} -- --static void --mt7530_mdio_regmap_unlock(void *mdio_lock) --{ -- mutex_unlock(mdio_lock); --} -- --static const struct regmap_bus mt7530_regmap_bus = { -- .reg_write = mt7530_regmap_write, -- .reg_read = mt7530_regmap_read, --}; -- --static int --mt7531_create_sgmii(struct mt7530_priv *priv) --{ -- struct regmap_config *mt7531_pcs_config[2]; -- struct phylink_pcs *pcs; -- struct regmap *regmap; -- int i, ret = 0; -- -- for (i = 0; i < 2; i++) { -- mt7531_pcs_config[i] = devm_kzalloc(priv->dev, -- sizeof(struct regmap_config), -- GFP_KERNEL); -- if (!mt7531_pcs_config[i]) { -- ret = -ENOMEM; -- break; -- } -- -- mt7531_pcs_config[i]->name = i ? "port6" : "port5"; -- mt7531_pcs_config[i]->reg_bits = 16; -- mt7531_pcs_config[i]->val_bits = 32; -- mt7531_pcs_config[i]->reg_stride = 4; -- mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); -- mt7531_pcs_config[i]->max_register = 0x17c; -- mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock; -- mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; -- mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; -- -- regmap = devm_regmap_init(priv->dev, -- &mt7530_regmap_bus, priv->bus, -- mt7531_pcs_config[i]); -- if (IS_ERR(regmap)) { -- ret = PTR_ERR(regmap); -- break; -- } -- pcs = mtk_pcs_lynxi_create(priv->dev, regmap, -- MT7531_PHYA_CTRL_SIGNAL3, 0); -- if (!pcs) { -- ret = -ENXIO; -- break; -- } -- priv->ports[5 + i].sgmii_pcs = pcs; -- } -- -- if (ret && i) -- mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs); -- -- return ret; --} -- - static int - mt753x_setup(struct dsa_switch *ds) - { -@@ -3099,7 +2984,7 @@ static int mt753x_set_mac_eee(struct dsa - return 0; - } - --static const struct dsa_switch_ops mt7530_switch_ops = { -+const struct dsa_switch_ops mt7530_switch_ops = { - .get_tag_protocol = mtk_get_tag_protocol, - .setup = mt753x_setup, - .get_strings = mt7530_get_strings, -@@ -3133,8 +3018,9 @@ static const struct dsa_switch_ops mt753 - .get_mac_eee = mt753x_get_mac_eee, - .set_mac_eee = mt753x_set_mac_eee, - }; -+EXPORT_SYMBOL_GPL(mt7530_switch_ops); - --static const struct mt753x_info mt753x_table[] = { -+const struct mt753x_info mt753x_table[] = { - [ID_MT7621] = { - .id = ID_MT7621, - .pcs_ops = &mt7530_pcs_ops, -@@ -3167,16 +3053,9 @@ static const struct mt753x_info mt753x_t - .mac_port_config = mt7531_mac_config, - }, - }; -+EXPORT_SYMBOL_GPL(mt753x_table); - --static const struct of_device_id mt7530_of_match[] = { -- { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, -- { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, -- { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, -- { /* sentinel */ }, --}; --MODULE_DEVICE_TABLE(of, mt7530_of_match); -- --static int -+int - mt7530_probe_common(struct mt7530_priv *priv) - { - struct device *dev = priv->dev; -@@ -3213,88 +3092,9 @@ mt7530_probe_common(struct mt7530_priv * - - return 0; - } -+EXPORT_SYMBOL_GPL(mt7530_probe_common); - --static int --mt7530_probe(struct mdio_device *mdiodev) --{ -- static struct regmap_config *regmap_config; -- struct mt7530_priv *priv; -- struct device_node *dn; -- int ret; -- -- dn = mdiodev->dev.of_node; -- -- priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); -- if (!priv) -- return -ENOMEM; -- -- priv->bus = mdiodev->bus; -- priv->dev = &mdiodev->dev; -- -- ret = mt7530_probe_common(priv); -- if (ret) -- return ret; -- -- /* Use medatek,mcm property to distinguish hardware type that would -- * cause a little bit differences on power-on sequence. -- * Not MCM that indicates switch works as the remote standalone -- * integrated circuit so the GPIO pin would be used to complete -- * the reset, otherwise memory-mapped register accessing used -- * through syscon provides in the case of MCM. -- */ -- priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); -- if (priv->mcm) { -- dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); -- -- priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); -- if (IS_ERR(priv->rstc)) { -- dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -- return PTR_ERR(priv->rstc); -- } -- } else { -- priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", -- GPIOD_OUT_LOW); -- if (IS_ERR(priv->reset)) { -- dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -- return PTR_ERR(priv->reset); -- } -- } -- -- if (priv->id == ID_MT7530) { -- priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); -- if (IS_ERR(priv->core_pwr)) -- return PTR_ERR(priv->core_pwr); -- -- priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); -- if (IS_ERR(priv->io_pwr)) -- return PTR_ERR(priv->io_pwr); -- } -- -- regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), -- GFP_KERNEL); -- if (!regmap_config) -- return -ENOMEM; -- -- regmap_config->reg_bits = 16; -- regmap_config->val_bits = 32; -- regmap_config->reg_stride = 4; -- regmap_config->max_register = MT7530_CREV; -- regmap_config->disable_locking = true; -- priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, -- priv->bus, regmap_config); -- if (IS_ERR(priv->regmap)) -- return PTR_ERR(priv->regmap); -- -- if (priv->id == ID_MT7531) { -- ret = mt7531_create_sgmii(priv); -- if (ret) -- return ret; -- } -- -- return dsa_register_switch(priv->ds); --} -- --static void -+void - mt7530_remove_common(struct mt7530_priv *priv) - { - if (priv->irq) -@@ -3304,55 +3104,7 @@ mt7530_remove_common(struct mt7530_priv - - mutex_destroy(&priv->reg_mutex); - } -- --static void --mt7530_remove(struct mdio_device *mdiodev) --{ -- struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -- int ret = 0, i; -- -- if (!priv) -- return; -- -- ret = regulator_disable(priv->core_pwr); -- if (ret < 0) -- dev_err(priv->dev, -- "Failed to disable core power: %d\n", ret); -- -- ret = regulator_disable(priv->io_pwr); -- if (ret < 0) -- dev_err(priv->dev, "Failed to disable io pwr: %d\n", -- ret); -- -- mt7530_remove_common(priv); -- -- for (i = 0; i < 2; ++i) -- mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); --} -- --static void mt7530_shutdown(struct mdio_device *mdiodev) --{ -- struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -- -- if (!priv) -- return; -- -- dsa_switch_shutdown(priv->ds); -- -- dev_set_drvdata(&mdiodev->dev, NULL); --} -- --static struct mdio_driver mt7530_mdio_driver = { -- .probe = mt7530_probe, -- .remove = mt7530_remove, -- .shutdown = mt7530_shutdown, -- .mdiodrv.driver = { -- .name = "mt7530", -- .of_match_table = mt7530_of_match, -- }, --}; -- --mdio_module_driver(mt7530_mdio_driver); -+EXPORT_SYMBOL_GPL(mt7530_remove_common); - - MODULE_AUTHOR("Sean Wang "); - MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch"); ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -814,4 +814,10 @@ static inline void INIT_MT7530_DUMMY_POL - p->reg = reg; - } - -+int mt7530_probe_common(struct mt7530_priv *priv); -+void mt7530_remove_common(struct mt7530_priv *priv); -+ -+extern const struct dsa_switch_ops mt7530_switch_ops; -+extern const struct mt753x_info mt753x_table[]; -+ - #endif /* __MT7530_H */ diff --git a/target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch b/target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch deleted file mode 100644 index 01011ed1a0..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch +++ /dev/null @@ -1,47 +0,0 @@ -From a52cadbf76593f8fcb2f4f62cb006e3f2a22ad06 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:19:28 +0100 -Subject: [PATCH 11/13] net: dsa: mt7530: skip locking if MDIO bus isn't - present - -As MT7530 and MT7531 internally use 32-bit wide registers, each access -to any register of the switch requires several operations on the MDIO -bus. Hence if there is congruent access, e.g. due to PCS or PHY -polling, this can mess up and interfere with another ongoing register -access sequence. - -However, the MDIO bus mutex is only relevant for MDIO-connected -switches. Prepare switches which have there registers directly mapped -into the SoCs register space via MMIO which do not require such -locking. There we can simply use regmap's default locking mechanism. - -Hence guard mutex operations to only be performed in case of MDIO -connected switches. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -144,13 +144,15 @@ err: - static void - mt7530_mutex_lock(struct mt7530_priv *priv) - { -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ if (priv->bus) -+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); - } - - static void - mt7530_mutex_unlock(struct mt7530_priv *priv) - { -- mutex_unlock(&priv->bus->mdio_lock); -+ if (priv->bus) -+ mutex_unlock(&priv->bus->mdio_lock); - } - - static void diff --git a/target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch deleted file mode 100644 index 63bf0e77fa..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch +++ /dev/null @@ -1,421 +0,0 @@ -From b361015763fedea439f13b336b15ef7bdf1f7d4f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:19:40 +0100 -Subject: [PATCH 12/13] net: dsa: mt7530: introduce driver for MT7988 built-in - switch - -Add driver for the built-in Gigabit Ethernet switch which can be found -in the MediaTek MT7988 SoC. - -The switch shares most of its design with MT7530 and MT7531, but has -it's registers mapped into the SoCs register space rather than being -connected externally or internally via MDIO. - -Introduce a new platform driver to support that. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 2 + - drivers/net/dsa/Kconfig | 12 +++ - drivers/net/dsa/Makefile | 1 + - drivers/net/dsa/mt7530-mmio.c | 101 +++++++++++++++++++++++++ - drivers/net/dsa/mt7530.c | 135 +++++++++++++++++++++++++++++++++- - drivers/net/dsa/mt7530.h | 12 +-- - 6 files changed, 253 insertions(+), 10 deletions(-) - create mode 100644 drivers/net/dsa/mt7530-mmio.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -13060,9 +13060,11 @@ MEDIATEK SWITCH DRIVER - M: Sean Wang - M: Landen Chao - M: DENG Qingfang -+M: Daniel Golle - L: netdev@vger.kernel.org - S: Maintained - F: drivers/net/dsa/mt7530-mdio.c -+F: drivers/net/dsa/mt7530-mmio.c - F: drivers/net/dsa/mt7530.* - F: net/dsa/tag_mtk.c - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -38,6 +38,7 @@ config NET_DSA_MT7530 - select NET_DSA_TAG_MTK - select MEDIATEK_GE_PHY - imply NET_DSA_MT7530_MDIO -+ imply NET_DSA_MT7530_MMIO - help - This enables support for the MediaTek MT7530 and MT7531 Ethernet - switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT, -@@ -54,6 +55,17 @@ config NET_DSA_MT7530_MDIO - module MT7530 which can be found in the MT7621AT, MT7621DAT, - MT7621ST and MT7623AI SoCs. - -+config NET_DSA_MT7530_MMIO -+ tristate "MediaTek MT7530 MMIO interface driver" -+ depends on NET_DSA_MT7530 -+ depends on HAS_IOMEM -+ help -+ This enables support for the built-in Ethernet switch found -+ in the MediaTek MT7988 SoC. -+ The switch is a similar design as MT7531, but the switch registers -+ are directly mapped into the SoCs register space rather than being -+ accessible via MDIO. -+ - config NET_DSA_MV88E6060 - tristate "Marvell 88E6060 ethernet switch chip support" - select NET_DSA_TAG_TRAILER ---- a/drivers/net/dsa/Makefile -+++ b/drivers/net/dsa/Makefile -@@ -8,6 +8,7 @@ endif - obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o - obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o - obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o -+obj-$(CONFIG_NET_DSA_MT7530_MMIO) += mt7530-mmio.o - obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o - obj-$(CONFIG_NET_DSA_RZN1_A5PSW) += rzn1_a5psw.o - obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o ---- /dev/null -+++ b/drivers/net/dsa/mt7530-mmio.c -@@ -0,0 +1,101 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mt7530.h" -+ -+static const struct of_device_id mt7988_of_match[] = { -+ { .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], }, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, mt7988_of_match); -+ -+static int -+mt7988_probe(struct platform_device *pdev) -+{ -+ static struct regmap_config *sw_regmap_config; -+ struct mt7530_priv *priv; -+ void __iomem *base_addr; -+ int ret; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->bus = NULL; -+ priv->dev = &pdev->dev; -+ -+ ret = mt7530_probe_common(priv); -+ if (ret) -+ return ret; -+ -+ priv->rstc = devm_reset_control_get(&pdev->dev, NULL); -+ if (IS_ERR(priv->rstc)) { -+ dev_err(&pdev->dev, "Couldn't get our reset line\n"); -+ return PTR_ERR(priv->rstc); -+ } -+ -+ base_addr = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base_addr)) { -+ dev_err(&pdev->dev, "cannot request I/O memory space\n"); -+ return -ENXIO; -+ } -+ -+ sw_regmap_config = devm_kzalloc(&pdev->dev, sizeof(*sw_regmap_config), GFP_KERNEL); -+ if (!sw_regmap_config) -+ return -ENOMEM; -+ -+ sw_regmap_config->name = "switch"; -+ sw_regmap_config->reg_bits = 16; -+ sw_regmap_config->val_bits = 32; -+ sw_regmap_config->reg_stride = 4; -+ sw_regmap_config->max_register = MT7530_CREV; -+ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base_addr, sw_regmap_config); -+ if (IS_ERR(priv->regmap)) -+ return PTR_ERR(priv->regmap); -+ -+ return dsa_register_switch(priv->ds); -+} -+ -+static int -+mt7988_remove(struct platform_device *pdev) -+{ -+ struct mt7530_priv *priv = platform_get_drvdata(pdev); -+ -+ if (priv) -+ mt7530_remove_common(priv); -+ -+ return 0; -+} -+ -+static void mt7988_shutdown(struct platform_device *pdev) -+{ -+ struct mt7530_priv *priv = platform_get_drvdata(pdev); -+ -+ if (!priv) -+ return; -+ -+ dsa_switch_shutdown(priv->ds); -+ -+ dev_set_drvdata(&pdev->dev, NULL); -+} -+ -+static struct platform_driver mt7988_platform_driver = { -+ .probe = mt7988_probe, -+ .remove = mt7988_remove, -+ .shutdown = mt7988_shutdown, -+ .driver = { -+ .name = "mt7530-mmio", -+ .of_match_table = mt7988_of_match, -+ }, -+}; -+module_platform_driver(mt7988_platform_driver); -+ -+MODULE_AUTHOR("Daniel Golle "); -+MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MMIO)"); -+MODULE_LICENSE("GPL"); ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2005,6 +2005,47 @@ static const struct irq_domain_ops mt753 - }; - - static void -+mt7988_irq_mask(struct irq_data *d) -+{ -+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); -+ -+ priv->irq_enable &= ~BIT(d->hwirq); -+ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); -+} -+ -+static void -+mt7988_irq_unmask(struct irq_data *d) -+{ -+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); -+ -+ priv->irq_enable |= BIT(d->hwirq); -+ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); -+} -+ -+static struct irq_chip mt7988_irq_chip = { -+ .name = KBUILD_MODNAME, -+ .irq_mask = mt7988_irq_mask, -+ .irq_unmask = mt7988_irq_unmask, -+}; -+ -+static int -+mt7988_irq_map(struct irq_domain *domain, unsigned int irq, -+ irq_hw_number_t hwirq) -+{ -+ irq_set_chip_data(irq, domain->host_data); -+ irq_set_chip_and_handler(irq, &mt7988_irq_chip, handle_simple_irq); -+ irq_set_nested_thread(irq, true); -+ irq_set_noprobe(irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops mt7988_irq_domain_ops = { -+ .map = mt7988_irq_map, -+ .xlate = irq_domain_xlate_onecell, -+}; -+ -+static void - mt7530_setup_mdio_irq(struct mt7530_priv *priv) - { - struct dsa_switch *ds = priv->ds; -@@ -2038,8 +2079,15 @@ mt7530_setup_irq(struct mt7530_priv *pri - return priv->irq ? : -EINVAL; - } - -- priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, -- &mt7530_irq_domain_ops, priv); -+ if (priv->id == ID_MT7988) -+ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, -+ &mt7988_irq_domain_ops, -+ priv); -+ else -+ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, -+ &mt7530_irq_domain_ops, -+ priv); -+ - if (!priv->irq_domain) { - dev_err(dev, "failed to create IRQ domain\n"); - return -ENOMEM; -@@ -2538,6 +2586,25 @@ static void mt7531_mac_port_get_caps(str - } - } - -+static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port, -+ struct phylink_config *config) -+{ -+ phy_interface_zero(config->supported_interfaces); -+ -+ switch (port) { -+ case 0 ... 4: /* Internal phy */ -+ __set_bit(PHY_INTERFACE_MODE_INTERNAL, -+ config->supported_interfaces); -+ break; -+ -+ case 6: -+ __set_bit(PHY_INTERFACE_MODE_INTERNAL, -+ config->supported_interfaces); -+ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -+ MAC_10000FD; -+ } -+} -+ - static int - mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) - { -@@ -2614,6 +2681,17 @@ static bool mt753x_is_mac_port(u32 port) - } - - static int -+mt7988_mac_config(struct dsa_switch *ds, int port, unsigned int mode, -+ phy_interface_t interface) -+{ -+ if (dsa_is_cpu_port(ds, port) && -+ interface == PHY_INTERFACE_MODE_INTERNAL) -+ return 0; -+ -+ return -EINVAL; -+} -+ -+static int - mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, - phy_interface_t interface) - { -@@ -2683,7 +2761,8 @@ mt753x_phylink_mac_config(struct dsa_swi - - switch (port) { - case 0 ... 4: /* Internal phy */ -- if (state->interface != PHY_INTERFACE_MODE_GMII) -+ if (state->interface != PHY_INTERFACE_MODE_GMII && -+ state->interface != PHY_INTERFACE_MODE_INTERNAL) - goto unsupported; - break; - case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -@@ -2761,7 +2840,8 @@ static void mt753x_phylink_mac_link_up(s - /* MT753x MAC works in 1G full duplex mode for all up-clocked - * variants. - */ -- if (interface == PHY_INTERFACE_MODE_TRGMII || -+ if (interface == PHY_INTERFACE_MODE_INTERNAL || -+ interface == PHY_INTERFACE_MODE_TRGMII || - (phy_interface_mode_is_8023z(interface))) { - speed = SPEED_1000; - duplex = DUPLEX_FULL; -@@ -2841,6 +2921,21 @@ mt7531_cpu_port_config(struct dsa_switch - return 0; - } - -+static int -+mt7988_cpu_port_config(struct dsa_switch *ds, int port) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ mt7530_write(priv, MT7530_PMCR_P(port), -+ PMCR_CPU_PORT_SETTING(priv->id)); -+ -+ mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, -+ PHY_INTERFACE_MODE_INTERNAL, NULL, -+ SPEED_10000, DUPLEX_FULL, true, true); -+ -+ return 0; -+} -+ - static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, - struct phylink_config *config) - { -@@ -2986,6 +3081,27 @@ static int mt753x_set_mac_eee(struct dsa - return 0; - } - -+static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface) -+{ -+ return 0; -+} -+ -+static int mt7988_setup(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ /* Reset the switch */ -+ reset_control_assert(priv->rstc); -+ usleep_range(20, 50); -+ reset_control_deassert(priv->rstc); -+ usleep_range(20, 50); -+ -+ /* Reset the switch PHYs */ -+ mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_PHY_RST); -+ -+ return mt7531_setup_common(ds); -+} -+ - const struct dsa_switch_ops mt7530_switch_ops = { - .get_tag_protocol = mtk_get_tag_protocol, - .setup = mt753x_setup, -@@ -3054,6 +3170,17 @@ const struct mt753x_info mt753x_table[] - .mac_port_get_caps = mt7531_mac_port_get_caps, - .mac_port_config = mt7531_mac_config, - }, -+ [ID_MT7988] = { -+ .id = ID_MT7988, -+ .pcs_ops = &mt7530_pcs_ops, -+ .sw_setup = mt7988_setup, -+ .phy_read = mt7531_ind_phy_read, -+ .phy_write = mt7531_ind_phy_write, -+ .pad_setup = mt7988_pad_setup, -+ .cpu_port_config = mt7988_cpu_port_config, -+ .mac_port_get_caps = mt7988_mac_port_get_caps, -+ .mac_port_config = mt7988_mac_config, -+ }, - }; - EXPORT_SYMBOL_GPL(mt753x_table); - ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -18,6 +18,7 @@ enum mt753x_id { - ID_MT7530 = 0, - ID_MT7621 = 1, - ID_MT7531 = 2, -+ ID_MT7988 = 3, - }; - - #define NUM_TRGMII_CTRL 5 -@@ -54,11 +55,11 @@ enum mt753x_id { - #define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16) - #define MT7531_CPU_PMAP_MASK GENMASK(7, 0) - --#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \ -+#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ - MT7531_CFC : MT7530_MFC) --#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \ -+#define MT753X_MIRROR_EN(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ - MT7531_MIRROR_EN : MIRROR_EN) --#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \ -+#define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ - MT7531_MIRROR_MASK : MIRROR_MASK) - - /* Registers for BPDU and PAE frame control*/ -@@ -302,9 +303,8 @@ enum mt7530_vlan_port_acc_frm { - MT7531_FORCE_DPX | \ - MT7531_FORCE_RX_FC | \ - MT7531_FORCE_TX_FC) --#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \ -- MT7531_FORCE_MODE : \ -- PMCR_FORCE_MODE) -+#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ -+ MT7531_FORCE_MODE : PMCR_FORCE_MODE) - #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ - PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ - PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ diff --git a/target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch b/target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch deleted file mode 100644 index 5b5f25e7af..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch +++ /dev/null @@ -1,118 +0,0 @@ -From eb1dd407b4be7ca38166a38c56c8edf52c6a399f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 16 Apr 2023 13:08:14 +0100 -Subject: [PATCH 13/13] net: dsa: mt7530: fix support for MT7531BE -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There are two variants of the MT7531 switch IC which got different -features (and pins) regarding port 5: - * MT7531AE: SGMII/1000Base-X/2500Base-X SerDes PCS - * MT7531BE: RGMII - -Moving the creation of the SerDes PCS from mt753x_setup to mt7530_probe -with commit 6de285229773 ("net: dsa: mt7530: move SGMII PCS creation -to mt7530_probe function") works fine for MT7531AE which got two -instances of mtk-pcs-lynxi, however, MT7531BE requires mt7531_pll_setup -to setup clocks before the single PCS on port 6 (usually used as CPU -port) starts to work and hence the PCS creation failed on MT7531BE. - -Fix this by introducing a pointer to mt7531_create_sgmii function in -struct mt7530_priv and call it again at the end of mt753x_setup like it -was before commit 6de285229773 ("net: dsa: mt7530: move SGMII PCS -creation to mt7530_probe function"). - -Fixes: 6de285229773 ("net: dsa: mt7530: move SGMII PCS creation to mt7530_probe function") -Signed-off-by: Daniel Golle -Acked-by: Arınç ÜNAL -Link: https://lore.kernel.org/r/ZDvlLhhqheobUvOK@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mt7530-mdio.c | 16 ++++++++-------- - drivers/net/dsa/mt7530.c | 6 ++++++ - drivers/net/dsa/mt7530.h | 4 ++-- - 3 files changed, 16 insertions(+), 10 deletions(-) - ---- a/drivers/net/dsa/mt7530-mdio.c -+++ b/drivers/net/dsa/mt7530-mdio.c -@@ -81,14 +81,17 @@ static const struct regmap_bus mt7530_re - }; - - static int --mt7531_create_sgmii(struct mt7530_priv *priv) -+mt7531_create_sgmii(struct mt7530_priv *priv, bool dual_sgmii) - { -- struct regmap_config *mt7531_pcs_config[2]; -+ struct regmap_config *mt7531_pcs_config[2] = {}; - struct phylink_pcs *pcs; - struct regmap *regmap; - int i, ret = 0; - -- for (i = 0; i < 2; i++) { -+ /* MT7531AE has two SGMII units for port 5 and port 6 -+ * MT7531BE has only one SGMII unit for port 6 -+ */ -+ for (i = dual_sgmii ? 0 : 1; i < 2; i++) { - mt7531_pcs_config[i] = devm_kzalloc(priv->dev, - sizeof(struct regmap_config), - GFP_KERNEL); -@@ -208,11 +211,8 @@ mt7530_probe(struct mdio_device *mdiodev - if (IS_ERR(priv->regmap)) - return PTR_ERR(priv->regmap); - -- if (priv->id == ID_MT7531) { -- ret = mt7531_create_sgmii(priv); -- if (ret) -- return ret; -- } -+ if (priv->id == ID_MT7531) -+ priv->create_sgmii = mt7531_create_sgmii; - - return dsa_register_switch(priv->ds); - } ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -3048,6 +3048,12 @@ mt753x_setup(struct dsa_switch *ds) - if (ret && priv->irq) - mt7530_free_irq_common(priv); - -+ if (priv->create_sgmii) { -+ ret = priv->create_sgmii(priv, mt7531_dual_sgmii_supported(priv)); -+ if (ret && priv->irq) -+ mt7530_free_irq(priv); -+ } -+ - return ret; - } - ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -748,10 +748,10 @@ struct mt753x_info { - * registers - * @p6_interface Holding the current port 6 interface - * @p5_intf_sel: Holding the current port 5 interface select -- * - * @irq: IRQ number of the switch - * @irq_domain: IRQ domain of the switch irq_chip - * @irq_enable: IRQ enable bits, synced to SYS_INT_EN -+ * @create_sgmii: Pointer to function creating SGMII PCS instance(s) - */ - struct mt7530_priv { - struct device *dev; -@@ -770,7 +770,6 @@ struct mt7530_priv { - unsigned int p5_intf_sel; - u8 mirror_rx; - u8 mirror_tx; -- - struct mt7530_port ports[MT7530_NUM_PORTS]; - struct mt753x_pcs pcs[MT7530_NUM_PORTS]; - /* protect among processes for registers access*/ -@@ -778,6 +777,7 @@ struct mt7530_priv { - int irq; - struct irq_domain *irq_domain; - u32 irq_enable; -+ int (*create_sgmii)(struct mt7530_priv *priv, bool dual_sgmii); - }; - - struct mt7530_hw_vlan_entry { diff --git a/target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch deleted file mode 100644 index 4cdd67cdcc..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ /dev/null @@ -1,1724 +0,0 @@ -From 70479a40954cf353e87a486997a3477108c75aa9 Mon Sep 17 00:00:00 2001 -From: Frank -Date: Fri, 28 Oct 2022 17:26:21 +0800 -Subject: [PATCH] net: phy: Add driver for Motorcomm yt8521 gigabit ethernet - phy - -Add a driver for the motorcomm yt8521 gigabit ethernet phy. We have verified - the driver on StarFive VisionFive development board, which is developed by - Shanghai StarFive Technology Co., Ltd.. On the board, yt8521 gigabit ethernet - phy works in utp mode, RGMII interface, supports 1000M/100M/10M speeds, and - wol(magic package). - -Signed-off-by: Frank -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 1 + - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 1635 ++++++++++++++++++++++++++++++++++- - 3 files changed, 1635 insertions(+), 3 deletions(-) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -13964,6 +13964,7 @@ F: include/uapi/linux/meye.h - - MOTORCOMM PHY DRIVER - M: Peter Geis -+M: Frank - L: netdev@vger.kernel.org - S: Maintained - F: drivers/net/phy/motorcomm.c ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -257,7 +257,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511 gigabit PHY. -+ Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,15 +1,106 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Driver for Motorcomm PHYs -+ * Motorcomm 8511/8521 PHY driver. - * - * Author: Peter Geis -+ * Author: Frank - */ - -+#include - #include - #include - #include - - #define PHY_ID_YT8511 0x0000010a -+#define PHY_ID_YT8521 0x0000011A -+ -+/* YT8521 Register Overview -+ * UTP Register space | FIBER Register space -+ * ------------------------------------------------------------ -+ * | UTP MII | FIBER MII | -+ * | UTP MMD | | -+ * | UTP Extended | FIBER Extended | -+ * ------------------------------------------------------------ -+ * | Common Extended | -+ * ------------------------------------------------------------ -+ */ -+ -+/* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */ -+ -+/* Specific Function Control Register */ -+#define YTPHY_SPECIFIC_FUNCTION_CONTROL_REG 0x10 -+ -+/* 2b00 Manual MDI configuration -+ * 2b01 Manual MDIX configuration -+ * 2b10 Reserved -+ * 2b11 Enable automatic crossover for all modes *default* -+ */ -+#define YTPHY_SFCR_MDI_CROSSOVER_MODE_MASK (BIT(6) | BIT(5)) -+#define YTPHY_SFCR_CROSSOVER_EN BIT(3) -+#define YTPHY_SFCR_SQE_TEST_EN BIT(2) -+#define YTPHY_SFCR_POLARITY_REVERSAL_EN BIT(1) -+#define YTPHY_SFCR_JABBER_DIS BIT(0) -+ -+/* Specific Status Register */ -+#define YTPHY_SPECIFIC_STATUS_REG 0x11 -+#define YTPHY_SSR_SPEED_MODE_OFFSET 14 -+ -+#define YTPHY_SSR_SPEED_MODE_MASK (BIT(15) | BIT(14)) -+#define YTPHY_SSR_SPEED_10M 0x0 -+#define YTPHY_SSR_SPEED_100M 0x1 -+#define YTPHY_SSR_SPEED_1000M 0x2 -+#define YTPHY_SSR_DUPLEX_OFFSET 13 -+#define YTPHY_SSR_DUPLEX BIT(13) -+#define YTPHY_SSR_PAGE_RECEIVED BIT(12) -+#define YTPHY_SSR_SPEED_DUPLEX_RESOLVED BIT(11) -+#define YTPHY_SSR_LINK BIT(10) -+#define YTPHY_SSR_MDIX_CROSSOVER BIT(6) -+#define YTPHY_SSR_DOWNGRADE BIT(5) -+#define YTPHY_SSR_TRANSMIT_PAUSE BIT(3) -+#define YTPHY_SSR_RECEIVE_PAUSE BIT(2) -+#define YTPHY_SSR_POLARITY BIT(1) -+#define YTPHY_SSR_JABBER BIT(0) -+ -+/* Interrupt enable Register */ -+#define YTPHY_INTERRUPT_ENABLE_REG 0x12 -+#define YTPHY_IER_WOL BIT(6) -+ -+/* Interrupt Status Register */ -+#define YTPHY_INTERRUPT_STATUS_REG 0x13 -+#define YTPHY_ISR_AUTONEG_ERR BIT(15) -+#define YTPHY_ISR_SPEED_CHANGED BIT(14) -+#define YTPHY_ISR_DUPLEX_CHANGED BIT(13) -+#define YTPHY_ISR_PAGE_RECEIVED BIT(12) -+#define YTPHY_ISR_LINK_FAILED BIT(11) -+#define YTPHY_ISR_LINK_SUCCESSED BIT(10) -+#define YTPHY_ISR_WOL BIT(6) -+#define YTPHY_ISR_WIRESPEED_DOWNGRADE BIT(5) -+#define YTPHY_ISR_SERDES_LINK_FAILED BIT(3) -+#define YTPHY_ISR_SERDES_LINK_SUCCESSED BIT(2) -+#define YTPHY_ISR_POLARITY_CHANGED BIT(1) -+#define YTPHY_ISR_JABBER_HAPPENED BIT(0) -+ -+/* Speed Auto Downgrade Control Register */ -+#define YTPHY_SPEED_AUTO_DOWNGRADE_CONTROL_REG 0x14 -+#define YTPHY_SADCR_SPEED_DOWNGRADE_EN BIT(5) -+ -+/* If these bits are set to 3, the PHY attempts five times ( 3(set value) + -+ * additional 2) before downgrading, default 0x3 -+ */ -+#define YTPHY_SADCR_SPEED_RETRY_LIMIT (0x3 << 2) -+ -+/* Rx Error Counter Register */ -+#define YTPHY_RX_ERROR_COUNTER_REG 0x15 -+ -+/* Extended Register's Address Offset Register */ -+#define YTPHY_PAGE_SELECT 0x1E -+ -+/* Extended Register's Data Register */ -+#define YTPHY_PAGE_DATA 0x1F -+ -+/* FIBER Auto-Negotiation link partner ability */ -+#define YTPHY_FLPA_PAUSE (0x3 << 7) -+#define YTPHY_FLPA_ASYM_PAUSE (0x2 << 7) - - #define YT8511_PAGE_SELECT 0x1e - #define YT8511_PAGE 0x1f -@@ -38,6 +129,352 @@ - #define YT8511_DELAY_FE_TX_EN (0xf << 12) - #define YT8511_DELAY_FE_TX_DIS (0x2 << 12) - -+/* Extended register is different from MMD Register and MII Register. -+ * We can use ytphy_read_ext/ytphy_write_ext/ytphy_modify_ext function to -+ * operate extended register. -+ * Extended Register start -+ */ -+ -+/* Phy gmii clock gating Register */ -+#define YT8521_CLOCK_GATING_REG 0xC -+#define YT8521_CGR_RX_CLK_EN BIT(12) -+ -+#define YT8521_EXTREG_SLEEP_CONTROL1_REG 0x27 -+#define YT8521_ESC1R_SLEEP_SW BIT(15) -+#define YT8521_ESC1R_PLLON_SLP BIT(14) -+ -+/* Phy fiber Link timer cfg2 Register */ -+#define YT8521_LINK_TIMER_CFG2_REG 0xA5 -+#define YT8521_LTCR_EN_AUTOSEN BIT(15) -+ -+/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers -+ * of yt8521 phy. There is no need to switch reg space when operating these -+ * registers. -+ */ -+ -+#define YT8521_REG_SPACE_SELECT_REG 0xA000 -+#define YT8521_RSSR_SPACE_MASK BIT(1) -+#define YT8521_RSSR_FIBER_SPACE (0x1 << 1) -+#define YT8521_RSSR_UTP_SPACE (0x0 << 1) -+#define YT8521_RSSR_TO_BE_ARBITRATED (0xFF) -+ -+#define YT8521_CHIP_CONFIG_REG 0xA001 -+#define YT8521_CCR_SW_RST BIT(15) -+ -+#define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) -+#define YT8521_CCR_MODE_UTP_TO_RGMII 0 -+#define YT8521_CCR_MODE_FIBER_TO_RGMII 1 -+#define YT8521_CCR_MODE_UTP_FIBER_TO_RGMII 2 -+#define YT8521_CCR_MODE_UTP_TO_SGMII 3 -+#define YT8521_CCR_MODE_SGPHY_TO_RGMAC 4 -+#define YT8521_CCR_MODE_SGMAC_TO_RGPHY 5 -+#define YT8521_CCR_MODE_UTP_TO_FIBER_AUTO 6 -+#define YT8521_CCR_MODE_UTP_TO_FIBER_FORCE 7 -+ -+/* 3 phy polling modes,poll mode combines utp and fiber mode*/ -+#define YT8521_MODE_FIBER 0x1 -+#define YT8521_MODE_UTP 0x2 -+#define YT8521_MODE_POLL 0x3 -+ -+#define YT8521_RGMII_CONFIG1_REG 0xA003 -+ -+/* TX Gig-E Delay is bits 3:0, default 0x1 -+ * TX Fast-E Delay is bits 7:4, default 0xf -+ * RX Delay is bits 13:10, default 0x0 -+ * Delay = 150ps * N -+ * On = 2250ps, off = 0ps -+ */ -+#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) -+#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) -+#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) -+ -+#define YTPHY_MISC_CONFIG_REG 0xA006 -+#define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) -+#define YTPHY_MCR_FIBER_1000BX (0x1 << 0) -+#define YTPHY_MCR_FIBER_100FX (0x0 << 0) -+ -+/* WOL MAC ADDR: MACADDR2(highest), MACADDR1(middle), MACADDR0(lowest) */ -+#define YTPHY_WOL_MACADDR2_REG 0xA007 -+#define YTPHY_WOL_MACADDR1_REG 0xA008 -+#define YTPHY_WOL_MACADDR0_REG 0xA009 -+ -+#define YTPHY_WOL_CONFIG_REG 0xA00A -+#define YTPHY_WCR_INTR_SEL BIT(6) -+#define YTPHY_WCR_ENABLE BIT(3) -+ -+/* 2b00 84ms -+ * 2b01 168ms *default* -+ * 2b10 336ms -+ * 2b11 672ms -+ */ -+#define YTPHY_WCR_PULSE_WIDTH_MASK (BIT(2) | BIT(1)) -+#define YTPHY_WCR_PULSE_WIDTH_672MS (BIT(2) | BIT(1)) -+ -+/* 1b0 Interrupt and WOL events is level triggered and active LOW *default* -+ * 1b1 Interrupt and WOL events is pulse triggered and active LOW -+ */ -+#define YTPHY_WCR_TYPE_PULSE BIT(0) -+ -+/* Extended Register end */ -+ -+struct yt8521_priv { -+ /* combo_advertising is used for case of YT8521 in combo mode, -+ * this means that yt8521 may work in utp or fiber mode which depends -+ * on which media is connected (YT8521_RSSR_TO_BE_ARBITRATED). -+ */ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(combo_advertising); -+ -+ /* YT8521_MODE_FIBER / YT8521_MODE_UTP / YT8521_MODE_POLL*/ -+ u8 polling_mode; -+ u8 strap_mode; /* 8 working modes */ -+ /* current reg page of yt8521 phy: -+ * YT8521_RSSR_UTP_SPACE -+ * YT8521_RSSR_FIBER_SPACE -+ * YT8521_RSSR_TO_BE_ARBITRATED -+ */ -+ u8 reg_page; -+}; -+ -+/** -+ * ytphy_read_ext() - read a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to read -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns the value of regnum reg or negative error code -+ */ -+static int ytphy_read_ext(struct phy_device *phydev, u16 regnum) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_read(phydev, YTPHY_PAGE_DATA); -+} -+ -+/** -+ * ytphy_read_ext_with_lock() - read a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to read -+ * -+ * returns the value of regnum reg or negative error code -+ */ -+static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_read_ext(phydev, regnum); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_write_ext() - write a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_write_ext(struct phy_device *phydev, u16 regnum, u16 val) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_write(phydev, YTPHY_PAGE_DATA, val); -+} -+ -+/** -+ * ytphy_write_ext_with_lock() - write a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_write_ext_with_lock(struct phy_device *phydev, u16 regnum, -+ u16 val) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_write_ext(phydev, regnum, val); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_modify_ext() - bits modify a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's extended register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask, -+ u16 set) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_modify(phydev, YTPHY_PAGE_DATA, mask, set); -+} -+ -+/** -+ * ytphy_modify_ext_with_lock() - bits modify a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's extended register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_modify_ext_with_lock(struct phy_device *phydev, u16 regnum, -+ u16 mask, u16 set) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_modify_ext(phydev, regnum, mask, set); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_get_wol() - report whether wake-on-lan is enabled -+ * @phydev: a pointer to a &struct phy_device -+ * @wol: a pointer to a &struct ethtool_wolinfo -+ * -+ * NOTE: YTPHY_WOL_CONFIG_REG is common ext reg. -+ */ -+static void ytphy_get_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol) -+{ -+ int wol_config; -+ -+ wol->supported = WAKE_MAGIC; -+ wol->wolopts = 0; -+ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return; -+ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ wol->wolopts |= WAKE_MAGIC; -+} -+ -+/** -+ * ytphy_set_wol() - turn wake-on-lan on or off -+ * @phydev: a pointer to a &struct phy_device -+ * @wol: a pointer to a &struct ethtool_wolinfo -+ * -+ * NOTE: YTPHY_WOL_CONFIG_REG, YTPHY_WOL_MACADDR2_REG, YTPHY_WOL_MACADDR1_REG -+ * and YTPHY_WOL_MACADDR0_REG are common ext reg. The -+ * YTPHY_INTERRUPT_ENABLE_REG of UTP is special, fiber also use this register. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) -+{ -+ struct net_device *p_attached_dev; -+ const u16 mac_addr_reg[] = { -+ YTPHY_WOL_MACADDR2_REG, -+ YTPHY_WOL_MACADDR1_REG, -+ YTPHY_WOL_MACADDR0_REG, -+ }; -+ const u8 *mac_addr; -+ int old_page; -+ int ret = 0; -+ u16 mask; -+ u16 val; -+ u8 i; -+ -+ if (wol->wolopts & WAKE_MAGIC) { -+ p_attached_dev = phydev->attached_dev; -+ if (!p_attached_dev) -+ return -ENODEV; -+ -+ mac_addr = (const u8 *)p_attached_dev->dev_addr; -+ if (!is_valid_ether_addr(mac_addr)) -+ return -EINVAL; -+ -+ /* lock mdio bus then switch to utp reg space */ -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Store the device address for the magic packet */ -+ for (i = 0; i < 3; i++) { -+ ret = ytphy_write_ext(phydev, mac_addr_reg[i], -+ ((mac_addr[i * 2] << 8)) | -+ (mac_addr[i * 2 + 1])); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+ /* Enable WOL feature */ -+ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; -+ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; -+ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, val); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* Enable WOL interrupt */ -+ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, -+ YTPHY_IER_WOL); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ } else { -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Disable WOL feature */ -+ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, 0); -+ -+ /* Disable WOL interrupt */ -+ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, -+ YTPHY_IER_WOL, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ - static int yt8511_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, YT8511_PAGE_SELECT); -@@ -111,6 +548,1181 @@ err_restore_page: - return phy_restore_page(phydev, oldpage, ret); - } - -+/** -+ * yt8521_read_page() - read reg page -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns current reg space of yt8521 (YT8521_RSSR_FIBER_SPACE/ -+ * YT8521_RSSR_UTP_SPACE) or negative errno code -+ */ -+static int yt8521_read_page(struct phy_device *phydev) -+{ -+ int old_page; -+ -+ old_page = ytphy_read_ext(phydev, YT8521_REG_SPACE_SELECT_REG); -+ if (old_page < 0) -+ return old_page; -+ -+ if ((old_page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) -+ return YT8521_RSSR_FIBER_SPACE; -+ -+ return YT8521_RSSR_UTP_SPACE; -+}; -+ -+/** -+ * yt8521_write_page() - write reg page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to write. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_write_page(struct phy_device *phydev, int page) -+{ -+ int mask = YT8521_RSSR_SPACE_MASK; -+ int set; -+ -+ if ((page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) -+ set = YT8521_RSSR_FIBER_SPACE; -+ else -+ set = YT8521_RSSR_UTP_SPACE; -+ -+ return ytphy_modify_ext(phydev, YT8521_REG_SPACE_SELECT_REG, mask, set); -+}; -+ -+/** -+ * yt8521_probe() - read chip config then set suitable polling_mode -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct yt8521_priv *priv; -+ int chip_config; -+ int ret; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ phydev->priv = priv; -+ -+ chip_config = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); -+ if (chip_config < 0) -+ return chip_config; -+ -+ priv->strap_mode = chip_config & YT8521_CCR_MODE_SEL_MASK; -+ switch (priv->strap_mode) { -+ case YT8521_CCR_MODE_FIBER_TO_RGMII: -+ case YT8521_CCR_MODE_SGPHY_TO_RGMAC: -+ case YT8521_CCR_MODE_SGMAC_TO_RGPHY: -+ priv->polling_mode = YT8521_MODE_FIBER; -+ priv->reg_page = YT8521_RSSR_FIBER_SPACE; -+ phydev->port = PORT_FIBRE; -+ break; -+ case YT8521_CCR_MODE_UTP_FIBER_TO_RGMII: -+ case YT8521_CCR_MODE_UTP_TO_FIBER_AUTO: -+ case YT8521_CCR_MODE_UTP_TO_FIBER_FORCE: -+ priv->polling_mode = YT8521_MODE_POLL; -+ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; -+ phydev->port = PORT_NONE; -+ break; -+ case YT8521_CCR_MODE_UTP_TO_SGMII: -+ case YT8521_CCR_MODE_UTP_TO_RGMII: -+ priv->polling_mode = YT8521_MODE_UTP; -+ priv->reg_page = YT8521_RSSR_UTP_SPACE; -+ phydev->port = PORT_TP; -+ break; -+ } -+ /* set default reg space */ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = ytphy_write_ext_with_lock(phydev, -+ YT8521_REG_SPACE_SELECT_REG, -+ priv->reg_page); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_read_lpa(struct phy_device *phydev) -+{ -+ int lpa, lpagb; -+ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ if (!phydev->autoneg_complete) { -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, -+ 0); -+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ return 0; -+ } -+ -+ if (phydev->is_gigabit_capable) { -+ lpagb = __phy_read(phydev, MII_STAT1000); -+ if (lpagb < 0) -+ return lpagb; -+ -+ if (lpagb & LPA_1000MSFAIL) { -+ int adv = __phy_read(phydev, MII_CTRL1000); -+ -+ if (adv < 0) -+ return adv; -+ -+ if (adv & CTL1000_ENABLE_MASTER) -+ phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n"); -+ else -+ phydev_err(phydev, "Master/Slave resolution failed\n"); -+ return -ENOLINK; -+ } -+ -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, -+ lpagb); -+ } -+ -+ lpa = __phy_read(phydev, MII_LPA); -+ if (lpa < 0) -+ return lpa; -+ -+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); -+ } else { -+ linkmode_zero(phydev->lp_advertising); -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_adjust_status() - update speed and duplex to phydev. when in fiber -+ * mode, adjust speed and duplex. -+ * @phydev: a pointer to a &struct phy_device -+ * @status: yt8521 status read from YTPHY_SPECIFIC_STATUS_REG -+ * @is_utp: false(yt8521 work in fiber mode) or true(yt8521 work in utp mode) -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 -+ */ -+static int yt8521_adjust_status(struct phy_device *phydev, int status, -+ bool is_utp) -+{ -+ int speed_mode, duplex; -+ int speed; -+ int err; -+ int lpa; -+ -+ if (is_utp) -+ duplex = (status & YTPHY_SSR_DUPLEX) >> YTPHY_SSR_DUPLEX_OFFSET; -+ else -+ duplex = DUPLEX_FULL; /* for fiber, it always DUPLEX_FULL */ -+ -+ speed_mode = (status & YTPHY_SSR_SPEED_MODE_MASK) >> -+ YTPHY_SSR_SPEED_MODE_OFFSET; -+ -+ switch (speed_mode) { -+ case YTPHY_SSR_SPEED_10M: -+ if (is_utp) -+ speed = SPEED_10; -+ else -+ /* for fiber, it will never run here, default to -+ * SPEED_UNKNOWN -+ */ -+ speed = SPEED_UNKNOWN; -+ break; -+ case YTPHY_SSR_SPEED_100M: -+ speed = SPEED_100; -+ break; -+ case YTPHY_SSR_SPEED_1000M: -+ speed = SPEED_1000; -+ break; -+ default: -+ speed = SPEED_UNKNOWN; -+ break; -+ } -+ -+ phydev->speed = speed; -+ phydev->duplex = duplex; -+ -+ if (is_utp) { -+ err = ytphy_utp_read_lpa(phydev); -+ if (err < 0) -+ return err; -+ -+ phy_resolve_aneg_pause(phydev); -+ } else { -+ lpa = __phy_read(phydev, MII_LPA); -+ if (lpa < 0) -+ return lpa; -+ -+ /* only support 1000baseX Full */ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -+ phydev->lp_advertising, lpa & LPA_1000XFULL); -+ -+ if (!(lpa & YTPHY_FLPA_PAUSE)) { -+ phydev->pause = 0; -+ phydev->asym_pause = 0; -+ } else if ((lpa & YTPHY_FLPA_ASYM_PAUSE)) { -+ phydev->pause = 1; -+ phydev->asym_pause = 1; -+ } else { -+ phydev->pause = 1; -+ phydev->asym_pause = 0; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_read_status_paged() - determines the speed and duplex of one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 1 (utp or fiber link),0 (no link) or negative errno code -+ */ -+static int yt8521_read_status_paged(struct phy_device *phydev, int page) -+{ -+ int fiber_latch_val; -+ int fiber_curr_val; -+ int old_page; -+ int ret = 0; -+ int status; -+ int link; -+ -+ linkmode_zero(phydev->lp_advertising); -+ phydev->duplex = DUPLEX_UNKNOWN; -+ phydev->speed = SPEED_UNKNOWN; -+ phydev->asym_pause = 0; -+ phydev->pause = 0; -+ -+ /* YT8521 has two reg space (utp/fiber) for linkup with utp/fiber -+ * respectively. but for utp/fiber combo mode, reg space should be -+ * arbitrated based on media priority. by default, utp takes -+ * priority. reg space should be properly set before read -+ * YTPHY_SPECIFIC_STATUS_REG. -+ */ -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Read YTPHY_SPECIFIC_STATUS_REG, which indicates the speed and duplex -+ * of the PHY is actually using. -+ */ -+ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ status = ret; -+ link = !!(status & YTPHY_SSR_LINK); -+ -+ /* When PHY is in fiber mode, speed transferred from 1000Mbps to -+ * 100Mbps,there is not link down from YTPHY_SPECIFIC_STATUS_REG, so -+ * we need check MII_BMSR to identify such case. -+ */ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ fiber_latch_val = ret; -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ fiber_curr_val = ret; -+ if (link && fiber_latch_val != fiber_curr_val) { -+ link = 0; -+ phydev_info(phydev, -+ "%s, fiber link down detect, latch = %04x, curr = %04x\n", -+ __func__, fiber_latch_val, fiber_curr_val); -+ } -+ } else { -+ /* Read autonegotiation status */ -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ phydev->autoneg_complete = ret & BMSR_ANEGCOMPLETE ? 1 : 0; -+ } -+ -+ if (link) { -+ if (page == YT8521_RSSR_UTP_SPACE) -+ yt8521_adjust_status(phydev, status, true); -+ else -+ yt8521_adjust_status(phydev, status, false); -+ } -+ return phy_restore_page(phydev, old_page, link); -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_read_status() - determines the negotiated speed and duplex -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_read_status(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int link_fiber = 0; -+ int link_utp; -+ int link; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ link = yt8521_read_status_paged(phydev, priv->reg_page); -+ if (link < 0) -+ return link; -+ } else { -+ /* when page is YT8521_RSSR_TO_BE_ARBITRATED, arbitration is -+ * needed. by default, utp is higher priority. -+ */ -+ -+ link_utp = yt8521_read_status_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (link_utp < 0) -+ return link_utp; -+ -+ if (!link_utp) { -+ link_fiber = yt8521_read_status_paged(phydev, -+ YT8521_RSSR_FIBER_SPACE); -+ if (link_fiber < 0) -+ return link_fiber; -+ } -+ -+ link = link_utp || link_fiber; -+ } -+ -+ if (link) { -+ if (phydev->link == 0) { -+ /* arbitrate reg space based on linkup media type. */ -+ if (priv->polling_mode == YT8521_MODE_POLL && -+ priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { -+ if (link_fiber) -+ priv->reg_page = -+ YT8521_RSSR_FIBER_SPACE; -+ else -+ priv->reg_page = YT8521_RSSR_UTP_SPACE; -+ -+ ret = ytphy_write_ext_with_lock(phydev, -+ YT8521_REG_SPACE_SELECT_REG, -+ priv->reg_page); -+ if (ret < 0) -+ return ret; -+ -+ phydev->port = link_fiber ? PORT_FIBRE : PORT_TP; -+ -+ phydev_info(phydev, "%s, link up, media: %s\n", -+ __func__, -+ (phydev->port == PORT_TP) ? -+ "UTP" : "Fiber"); -+ } -+ } -+ phydev->link = 1; -+ } else { -+ if (phydev->link == 1) { -+ phydev_info(phydev, "%s, link down, media: %s\n", -+ __func__, (phydev->port == PORT_TP) ? -+ "UTP" : "Fiber"); -+ -+ /* When in YT8521_MODE_POLL mode, need prepare for next -+ * arbitration. -+ */ -+ if (priv->polling_mode == YT8521_MODE_POLL) { -+ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; -+ phydev->port = PORT_NONE; -+ } -+ } -+ -+ phydev->link = 0; -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_modify_bmcr_paged - bits modify a PHY's BMCR register of one page -+ * @phydev: the phy_device struct -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to operate -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's BMCR register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space -+ * has MII_BMCR. poll mode combines utp and faber,so need do both. -+ * If it is reset, it will wait for completion. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_modify_bmcr_paged(struct phy_device *phydev, int page, -+ u16 mask, u16 set) -+{ -+ int max_cnt = 500; /* the max wait time of reset ~ 500 ms */ -+ int old_page; -+ int ret = 0; -+ -+ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ ret = __phy_modify(phydev, MII_BMCR, mask, set); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* If it is reset, need to wait for the reset to complete */ -+ if (set == BMCR_RESET) { -+ while (max_cnt--) { -+ usleep_range(1000, 1100); -+ ret = __phy_read(phydev, MII_BMCR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ if (!(ret & BMCR_RESET)) -+ return phy_restore_page(phydev, old_page, 0); -+ } -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_modify_utp_fiber_bmcr - bits modify a PHY's BMCR register -+ * @phydev: the phy_device struct -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's BMCR register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space -+ * has MII_BMCR. poll mode combines utp and faber,so need do both. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_modify_utp_fiber_bmcr(struct phy_device *phydev, u16 mask, -+ u16 set) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_modify_bmcr_paged(phydev, priv->reg_page, mask, -+ set); -+ if (ret < 0) -+ return ret; -+ } else { -+ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_UTP_SPACE, -+ mask, set); -+ if (ret < 0) -+ return ret; -+ -+ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_FIBER_SPACE, -+ mask, set); -+ if (ret < 0) -+ return ret; -+ } -+ return 0; -+} -+ -+/** -+ * yt8521_soft_reset() - called to issue a PHY software reset -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_soft_reset(struct phy_device *phydev) -+{ -+ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_RESET); -+} -+ -+/** -+ * yt8521_suspend() - suspend the hardware -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_suspend(struct phy_device *phydev) -+{ -+ int wol_config; -+ -+ /* YTPHY_WOL_CONFIG_REG is common ext reg */ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return wol_config; -+ -+ /* if wol enable, do nothing */ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ return 0; -+ -+ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_PDOWN); -+} -+ -+/** -+ * yt8521_resume() - resume the hardware -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_resume(struct phy_device *phydev) -+{ -+ int ret; -+ int wol_config; -+ -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ return ret; -+ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return wol_config; -+ -+ /* if wol enable, do nothing */ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ return 0; -+ -+ return yt8521_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0); -+} -+ -+/** -+ * yt8521_config_init() - called to initialize the PHY -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_init(struct phy_device *phydev) -+{ -+ int old_page; -+ int ret = 0; -+ u16 val; -+ -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val |= YT8521_RC1R_RX_DELAY_DIS; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val |= YT8521_RC1R_RX_DELAY_EN; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val |= YT8521_RC1R_RX_DELAY_DIS; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val |= YT8521_RC1R_RX_DELAY_EN; -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ break; -+ default: /* do not support other modes */ -+ ret = -EOPNOTSUPP; -+ goto err_restore_page; -+ } -+ -+ /* set rgmii delay mode */ -+ if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { -+ ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, -+ (YT8521_RC1R_RX_DELAY_MASK | -+ YT8521_RC1R_FE_TX_DELAY_MASK | -+ YT8521_RC1R_GE_TX_DELAY_MASK), -+ val); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_prepare_fiber_features() - A small helper function that setup -+ * fiber's features. -+ * @phydev: a pointer to a &struct phy_device -+ * @dst: a pointer to store fiber's features -+ */ -+static void yt8521_prepare_fiber_features(struct phy_device *phydev, -+ unsigned long *dst) -+{ -+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, dst); -+} -+ -+/** -+ * yt8521_fiber_setup_forced - configures/forces speed from @phydev -+ * @phydev: target phy_device struct -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_fiber_setup_forced(struct phy_device *phydev) -+{ -+ u16 val; -+ int ret; -+ -+ if (phydev->speed == SPEED_1000) -+ val = YTPHY_MCR_FIBER_1000BX; -+ else if (phydev->speed == SPEED_100) -+ val = YTPHY_MCR_FIBER_100FX; -+ else -+ return -EINVAL; -+ -+ ret = __phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); -+ if (ret < 0) -+ return ret; -+ -+ /* disable Fiber auto sensing */ -+ ret = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, -+ YT8521_LTCR_EN_AUTOSEN, 0); -+ if (ret < 0) -+ return ret; -+ -+ ret = ytphy_modify_ext(phydev, YTPHY_MISC_CONFIG_REG, -+ YTPHY_MCR_FIBER_SPEED_MASK, val); -+ if (ret < 0) -+ return ret; -+ -+ return ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_SW_RST, 0); -+} -+ -+/** -+ * ytphy_check_and_restart_aneg - Enable and restart auto-negotiation -+ * @phydev: target phy_device struct -+ * @restart: whether aneg restart is requested -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_check_and_restart_aneg(struct phy_device *phydev, bool restart) -+{ -+ int ret; -+ -+ if (!restart) { -+ /* Advertisement hasn't changed, but maybe aneg was never on to -+ * begin with? Or maybe phy was isolated? -+ */ -+ ret = __phy_read(phydev, MII_BMCR); -+ if (ret < 0) -+ return ret; -+ -+ if (!(ret & BMCR_ANENABLE) || (ret & BMCR_ISOLATE)) -+ restart = true; -+ } -+ /* Enable and Restart Autonegotiation -+ * Don't isolate the PHY if we're negotiating -+ */ -+ if (restart) -+ return __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, -+ BMCR_ANENABLE | BMCR_ANRESTART); -+ -+ return 0; -+} -+ -+/** -+ * yt8521_fiber_config_aneg - restart auto-negotiation or write -+ * YTPHY_MISC_CONFIG_REG. -+ * @phydev: target phy_device struct -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_fiber_config_aneg(struct phy_device *phydev) -+{ -+ int err, changed = 0; -+ int bmcr; -+ u16 adv; -+ -+ if (phydev->autoneg != AUTONEG_ENABLE) -+ return yt8521_fiber_setup_forced(phydev); -+ -+ /* enable Fiber auto sensing */ -+ err = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, -+ 0, YT8521_LTCR_EN_AUTOSEN); -+ if (err < 0) -+ return err; -+ -+ err = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_SW_RST, 0); -+ if (err < 0) -+ return err; -+ -+ bmcr = __phy_read(phydev, MII_BMCR); -+ if (bmcr < 0) -+ return bmcr; -+ -+ /* When it is coming from fiber forced mode, add bmcr power down -+ * and power up to let aneg work fine. -+ */ -+ if (!(bmcr & BMCR_ANENABLE)) { -+ __phy_modify(phydev, MII_BMCR, 0, BMCR_PDOWN); -+ usleep_range(1000, 1100); -+ __phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0); -+ } -+ -+ adv = linkmode_adv_to_mii_adv_x(phydev->advertising, -+ ETHTOOL_LINK_MODE_1000baseX_Full_BIT); -+ -+ /* Setup fiber advertisement */ -+ err = __phy_modify_changed(phydev, MII_ADVERTISE, -+ ADVERTISE_1000XHALF | ADVERTISE_1000XFULL | -+ ADVERTISE_1000XPAUSE | -+ ADVERTISE_1000XPSE_ASYM, -+ adv); -+ if (err < 0) -+ return err; -+ -+ if (err > 0) -+ changed = 1; -+ -+ return ytphy_check_and_restart_aneg(phydev, changed); -+} -+ -+/** -+ * ytphy_setup_master_slave -+ * @phydev: target phy_device struct -+ * -+ * NOTE: The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_setup_master_slave(struct phy_device *phydev) -+{ -+ u16 ctl = 0; -+ -+ if (!phydev->is_gigabit_capable) -+ return 0; -+ -+ switch (phydev->master_slave_set) { -+ case MASTER_SLAVE_CFG_MASTER_PREFERRED: -+ ctl |= CTL1000_PREFER_MASTER; -+ break; -+ case MASTER_SLAVE_CFG_SLAVE_PREFERRED: -+ break; -+ case MASTER_SLAVE_CFG_MASTER_FORCE: -+ ctl |= CTL1000_AS_MASTER; -+ fallthrough; -+ case MASTER_SLAVE_CFG_SLAVE_FORCE: -+ ctl |= CTL1000_ENABLE_MASTER; -+ break; -+ case MASTER_SLAVE_CFG_UNKNOWN: -+ case MASTER_SLAVE_CFG_UNSUPPORTED: -+ return 0; -+ default: -+ phydev_warn(phydev, "Unsupported Master/Slave mode\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ return __phy_modify_changed(phydev, MII_CTRL1000, -+ (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER | -+ CTL1000_PREFER_MASTER), ctl); -+} -+ -+/** -+ * ytphy_utp_config_advert - sanitize and advertise auto-negotiation parameters -+ * @phydev: target phy_device struct -+ * -+ * NOTE: Writes MII_ADVERTISE with the appropriate values, -+ * after sanitizing the values to make sure we only advertise -+ * what is supported. Returns < 0 on error, 0 if the PHY's advertisement -+ * hasn't changed, and > 0 if it has changed. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_config_advert(struct phy_device *phydev) -+{ -+ int err, bmsr, changed = 0; -+ u32 adv; -+ -+ /* Only allow advertising what this PHY supports */ -+ linkmode_and(phydev->advertising, phydev->advertising, -+ phydev->supported); -+ -+ adv = linkmode_adv_to_mii_adv_t(phydev->advertising); -+ -+ /* Setup standard advertisement */ -+ err = __phy_modify_changed(phydev, MII_ADVERTISE, -+ ADVERTISE_ALL | ADVERTISE_100BASE4 | -+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, -+ adv); -+ if (err < 0) -+ return err; -+ if (err > 0) -+ changed = 1; -+ -+ bmsr = __phy_read(phydev, MII_BMSR); -+ if (bmsr < 0) -+ return bmsr; -+ -+ /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all -+ * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a -+ * logical 1. -+ */ -+ if (!(bmsr & BMSR_ESTATEN)) -+ return changed; -+ -+ adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); -+ -+ err = __phy_modify_changed(phydev, MII_CTRL1000, -+ ADVERTISE_1000FULL | ADVERTISE_1000HALF, -+ adv); -+ if (err < 0) -+ return err; -+ if (err > 0) -+ changed = 1; -+ -+ return changed; -+} -+ -+/** -+ * ytphy_utp_config_aneg - restart auto-negotiation or write BMCR -+ * @phydev: target phy_device struct -+ * @changed: whether autoneg is requested -+ * -+ * NOTE: If auto-negotiation is enabled, we configure the -+ * advertising, and then restart auto-negotiation. If it is not -+ * enabled, then we write the BMCR. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_config_aneg(struct phy_device *phydev, bool changed) -+{ -+ int err; -+ u16 ctl; -+ -+ err = ytphy_setup_master_slave(phydev); -+ if (err < 0) -+ return err; -+ else if (err) -+ changed = true; -+ -+ if (phydev->autoneg != AUTONEG_ENABLE) { -+ /* configures/forces speed/duplex from @phydev */ -+ -+ ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex); -+ -+ return __phy_modify(phydev, MII_BMCR, ~(BMCR_LOOPBACK | -+ BMCR_ISOLATE | BMCR_PDOWN), ctl); -+ } -+ -+ err = ytphy_utp_config_advert(phydev); -+ if (err < 0) /* error */ -+ return err; -+ else if (err) -+ changed = true; -+ -+ return ytphy_check_and_restart_aneg(phydev, changed); -+} -+ -+/** -+ * yt8521_config_aneg_paged() - switch reg space then call genphy_config_aneg -+ * of one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_aneg_paged(struct phy_device *phydev, int page) -+{ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(fiber_supported); -+ struct yt8521_priv *priv = phydev->priv; -+ int old_page; -+ int ret = 0; -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, -+ * phydev->advertising should be updated. -+ */ -+ if (priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { -+ linkmode_zero(fiber_supported); -+ yt8521_prepare_fiber_features(phydev, fiber_supported); -+ -+ /* prepare fiber_supported, then setup advertising. */ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, -+ fiber_supported); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, -+ fiber_supported); -+ linkmode_and(phydev->advertising, -+ priv->combo_advertising, fiber_supported); -+ } else { -+ /* ETHTOOL_LINK_MODE_Autoneg_BIT is also used in utp */ -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ fiber_supported); -+ linkmode_andnot(phydev->advertising, -+ priv->combo_advertising, -+ fiber_supported); -+ } -+ } -+ -+ if (page == YT8521_RSSR_FIBER_SPACE) -+ ret = yt8521_fiber_config_aneg(phydev); -+ else -+ ret = ytphy_utp_config_aneg(phydev, false); -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_config_aneg() - change reg space then call yt8521_config_aneg_paged -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_aneg(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_config_aneg_paged(phydev, priv->reg_page); -+ if (ret < 0) -+ return ret; -+ } else { -+ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, -+ * phydev->advertising need to be saved at first run. -+ * Because it contains the advertising which supported by both -+ * mac and yt8521(utp and fiber). -+ */ -+ if (linkmode_empty(priv->combo_advertising)) { -+ linkmode_copy(priv->combo_advertising, -+ phydev->advertising); -+ } -+ -+ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_UTP_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_FIBER_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ /* we don't known which will be link, so restore -+ * phydev->advertising as default value. -+ */ -+ linkmode_copy(phydev->advertising, priv->combo_advertising); -+ } -+ return 0; -+} -+ -+/** -+ * yt8521_aneg_done_paged() - determines the auto negotiation result of one -+ * page. -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0(no link)or 1(fiber or utp link) or negative errno code -+ */ -+static int yt8521_aneg_done_paged(struct phy_device *phydev, int page) -+{ -+ int old_page; -+ int ret = 0; -+ int link; -+ -+ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ link = !!(ret & YTPHY_SSR_LINK); -+ ret = link; -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_aneg_done() - determines the auto negotiation result -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0(no link)or 1(fiber or utp link) or negative errno code -+ */ -+static int yt8521_aneg_done(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int link_fiber = 0; -+ int link_utp; -+ int link; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ link = yt8521_aneg_done_paged(phydev, priv->reg_page); -+ } else { -+ link_utp = yt8521_aneg_done_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (link_utp < 0) -+ return link_utp; -+ -+ if (!link_utp) { -+ link_fiber = yt8521_aneg_done_paged(phydev, -+ YT8521_RSSR_FIBER_SPACE); -+ if (link_fiber < 0) -+ return link_fiber; -+ } -+ link = link_fiber || link_utp; -+ phydev_info(phydev, "%s, link_fiber: %d, link_utp: %d\n", -+ __func__, link_fiber, link_utp); -+ } -+ -+ return link; -+} -+ -+/** -+ * ytphy_utp_read_abilities - read PHY abilities from Clause 22 registers -+ * @phydev: target phy_device struct -+ * -+ * NOTE: Reads the PHY's abilities and populates -+ * phydev->supported accordingly. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_read_abilities(struct phy_device *phydev) -+{ -+ int val; -+ -+ linkmode_set_bit_array(phy_basic_ports_array, -+ ARRAY_SIZE(phy_basic_ports_array), -+ phydev->supported); -+ -+ val = __phy_read(phydev, MII_BMSR); -+ if (val < 0) -+ return val; -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported, -+ val & BMSR_ANEGCAPABLE); -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported, -+ val & BMSR_100FULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported, -+ val & BMSR_100HALF); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, phydev->supported, -+ val & BMSR_10FULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported, -+ val & BMSR_10HALF); -+ -+ if (val & BMSR_ESTATEN) { -+ val = __phy_read(phydev, MII_ESTATUS); -+ if (val < 0) -+ return val; -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, -+ phydev->supported, val & ESTATUS_1000_TFULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, -+ phydev->supported, val & ESTATUS_1000_THALF); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -+ phydev->supported, val & ESTATUS_1000_XFULL); -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_get_features_paged() - read supported link modes for one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_get_features_paged(struct phy_device *phydev, int page) -+{ -+ int old_page; -+ int ret = 0; -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ linkmode_zero(phydev->supported); -+ yt8521_prepare_fiber_features(phydev, phydev->supported); -+ } else { -+ ret = ytphy_utp_read_abilities(phydev); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_get_features - switch reg space then call yt8521_get_features_paged -+ * @phydev: target phy_device struct -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_get_features(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_get_features_paged(phydev, priv->reg_page); -+ } else { -+ ret = yt8521_get_features_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ /* add fiber's features to phydev->supported */ -+ yt8521_prepare_fiber_features(phydev, phydev->supported); -+ } -+ return ret; -+} -+ - static struct phy_driver motorcomm_phy_drvs[] = { - { - PHY_ID_MATCH_EXACT(PHY_ID_YT8511), -@@ -121,16 +1733,35 @@ static struct phy_driver motorcomm_phy_d - .read_page = yt8511_read_page, - .write_page = yt8511_write_page, - }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8521), -+ .name = "YT8521 Gigabit Ethernet", -+ .get_features = yt8521_get_features, -+ .probe = yt8521_probe, -+ .read_page = yt8521_read_page, -+ .write_page = yt8521_write_page, -+ .get_wol = ytphy_get_wol, -+ .set_wol = ytphy_set_wol, -+ .config_aneg = yt8521_config_aneg, -+ .aneg_done = yt8521_aneg_done, -+ .config_init = yt8521_config_init, -+ .read_status = yt8521_read_status, -+ .soft_reset = yt8521_soft_reset, -+ .suspend = yt8521_suspend, -+ .resume = yt8521_resume, -+ }, - }; - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); - MODULE_AUTHOR("Peter Geis"); -+MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); - - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, - { /* sentinal */ } - }; - diff --git a/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch b/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch deleted file mode 100644 index cce71c8d84..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 4e0243e7128c9b25ea2739136076a95d6adaba5e Mon Sep 17 00:00:00 2001 -From: Frank -Date: Fri, 4 Nov 2022 16:44:41 +0800 -Subject: [PATCH] net: phy: fix yt8521 duplicated argument to & or | - -cocci warnings: (new ones prefixed by >>) ->> drivers/net/phy/motorcomm.c:1122:8-35: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1126:8-35: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1130:8-34: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1134:8-34: duplicated argument to & or | - - The second YT8521_RC1R_GE_TX_DELAY_xx should be YT8521_RC1R_FE_TX_DELAY_xx. - -Fixes: 70479a40954c ("net: phy: Add driver for Motorcomm yt8521 gigabit ethernet phy") -Reported-by: kernel test robot -Reported-by: Julia Lawall -Signed-off-by: Frank -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1119,19 +1119,19 @@ static int yt8521_config_init(struct phy - - switch (phydev->interface) { - case PHY_INTERFACE_MODE_RGMII: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; - val |= YT8521_RC1R_RX_DELAY_DIS; - break; - case PHY_INTERFACE_MODE_RGMII_RXID: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; - val |= YT8521_RC1R_RX_DELAY_EN; - break; - case PHY_INTERFACE_MODE_RGMII_TXID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; - val |= YT8521_RC1R_RX_DELAY_DIS; - break; - case PHY_INTERFACE_MODE_RGMII_ID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; - val |= YT8521_RC1R_RX_DELAY_EN; - break; - case PHY_INTERFACE_MODE_SGMII: diff --git a/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch b/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch deleted file mode 100644 index d22cc69425..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 813abcd98fb1b2cccf850cdfa092a4bfc50b2363 Mon Sep 17 00:00:00 2001 -From: Frank -Date: Tue, 22 Nov 2022 16:42:32 +0800 -Subject: [PATCH] net: phy: add Motorcomm YT8531S phy id. - -We added patch for motorcomm.c to support YT8531S. This patch has -been tested on AM335x platform which has one YT8531S interface -card and passed all test cases. -The tested cases indluding: YT8531S UTP function with support of -10M/100M/1000M; YT8531S Fiber function with support of 100M/1000M; -and YT8531S Combo function that supports auto detection of media type. - -Since most functions of YT8531S are similar to YT8521 and we reuse some -codes for YT8521 in the patch file. - -Signed-off-by: Frank -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 52 +++++++++++++++++++++++++++++++++---- - 2 files changed, 48 insertions(+), 6 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -257,7 +257,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. -+ Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Motorcomm 8511/8521 PHY driver. -+ * Motorcomm 8511/8521/8531S PHY driver. - * - * Author: Peter Geis - * Author: Frank -@@ -12,9 +12,10 @@ - #include - - #define PHY_ID_YT8511 0x0000010a --#define PHY_ID_YT8521 0x0000011A -+#define PHY_ID_YT8521 0x0000011A -+#define PHY_ID_YT8531S 0x4F51E91A - --/* YT8521 Register Overview -+/* YT8521/YT8531S Register Overview - * UTP Register space | FIBER Register space - * ------------------------------------------------------------ - * | UTP MII | FIBER MII | -@@ -147,7 +148,7 @@ - #define YT8521_LINK_TIMER_CFG2_REG 0xA5 - #define YT8521_LTCR_EN_AUTOSEN BIT(15) - --/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers -+/* 0xA000, 0xA001, 0xA003, 0xA006 ~ 0xA00A and 0xA012 are common ext registers - * of yt8521 phy. There is no need to switch reg space when operating these - * registers. - */ -@@ -221,6 +222,9 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YT8531S_SYNCE_CFG_REG 0xA012 -+#define YT8531S_SCR_SYNCE_ENABLE BIT(6) -+ - /* Extended Register end */ - - struct yt8521_priv { -@@ -648,6 +652,26 @@ static int yt8521_probe(struct phy_devic - } - - /** -+ * yt8531s_probe() - read chip config then set suitable polling_mode -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8531s_probe(struct phy_device *phydev) -+{ -+ int ret; -+ -+ /* Disable SyncE clock output by default */ -+ ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, -+ YT8531S_SCR_SYNCE_ENABLE, 0); -+ if (ret < 0) -+ return ret; -+ -+ /* same as yt8521_probe */ -+ return yt8521_probe(phydev); -+} -+ -+/** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device - * -@@ -1750,11 +1774,28 @@ static struct phy_driver motorcomm_phy_d - .suspend = yt8521_suspend, - .resume = yt8521_resume, - }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), -+ .name = "YT8531S Gigabit Ethernet", -+ .get_features = yt8521_get_features, -+ .probe = yt8531s_probe, -+ .read_page = yt8521_read_page, -+ .write_page = yt8521_write_page, -+ .get_wol = ytphy_get_wol, -+ .set_wol = ytphy_set_wol, -+ .config_aneg = yt8521_config_aneg, -+ .aneg_done = yt8521_aneg_done, -+ .config_init = yt8521_config_init, -+ .read_status = yt8521_read_status, -+ .soft_reset = yt8521_soft_reset, -+ .suspend = yt8521_suspend, -+ .resume = yt8521_resume, -+ }, - }; - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); - MODULE_AUTHOR("Peter Geis"); - MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); -@@ -1762,6 +1803,7 @@ MODULE_LICENSE("GPL"); - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, - { /* sentinal */ } - }; - diff --git a/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch b/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch deleted file mode 100644 index 94fc32aadb..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 4104a713204d62aca482eebb0c6226d82a0721eb Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Sat, 28 Jan 2023 14:35:57 +0800 -Subject: [PATCH] net: phy: fix the spelling problem of Sentinel - -CHECK: 'sentinal' may be misspelled - perhaps 'sentinel'? - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230128063558.5850-1-Frank.Sae@motor-comm.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1804,7 +1804,7 @@ static const struct mdio_device_id __may - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, -- { /* sentinal */ } -+ { /* sentinel */ } - }; - - MODULE_DEVICE_TABLE(mdio, motorcomm_tbl); diff --git a/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch b/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch deleted file mode 100644 index 076fa82d26..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 3c1dc22162d673d595855d24f95200ed2643f88f Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Sat, 28 Jan 2023 14:35:58 +0800 -Subject: [PATCH] net: phy: motorcomm: change the phy id of yt8521 and yt8531s - to lowercase - -The phy id is usually defined in lower case. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230128063558.5850-2-Frank.Sae@motor-comm.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -12,8 +12,8 @@ - #include - - #define PHY_ID_YT8511 0x0000010a --#define PHY_ID_YT8521 0x0000011A --#define PHY_ID_YT8531S 0x4F51E91A -+#define PHY_ID_YT8521 0x0000011a -+#define PHY_ID_YT8531S 0x4f51e91a - - /* YT8521/YT8531S Register Overview - * UTP Register space | FIBER Register space diff --git a/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch deleted file mode 100644 index ba9a6ab4cc..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 4869a146cd60fc8115230f0a45e15e534c531922 Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:34 +0800 -Subject: [PATCH] net: phy: Add BIT macro for Motorcomm yt8521/yt8531 gigabit - ethernet phy - -Add BIT macro for Motorcomm yt8521/yt8531 gigabit ethernet phy. - This is a preparatory patch. Add BIT macro for 0xA012 reg, and - supplement for 0xA001 and 0xA003 reg. These will be used to support dts. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 55 ++++++++++++++++++++++++++++++++++--- - 1 file changed, 51 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -161,6 +161,11 @@ - - #define YT8521_CHIP_CONFIG_REG 0xA001 - #define YT8521_CCR_SW_RST BIT(15) -+/* 1b0 disable 1.9ns rxc clock delay *default* -+ * 1b1 enable 1.9ns rxc clock delay -+ */ -+#define YT8521_CCR_RXC_DLY_EN BIT(8) -+#define YT8521_CCR_RXC_DLY_1_900_NS 1900 - - #define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) - #define YT8521_CCR_MODE_UTP_TO_RGMII 0 -@@ -178,22 +183,41 @@ - #define YT8521_MODE_POLL 0x3 - - #define YT8521_RGMII_CONFIG1_REG 0xA003 -- -+/* 1b0 use original tx_clk_rgmii *default* -+ * 1b1 use inverted tx_clk_rgmii. -+ */ -+#define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) - /* TX Gig-E Delay is bits 3:0, default 0x1 - * TX Fast-E Delay is bits 7:4, default 0xf - * RX Delay is bits 13:10, default 0x0 - * Delay = 150ps * N - * On = 2250ps, off = 0ps - */ --#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) - #define YT8521_RC1R_RX_DELAY_EN (0xF << 10) - #define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) --#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) - #define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) - #define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) --#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) - #define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) - #define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) -+#define YT8521_RC1R_RGMII_0_000_NS 0 -+#define YT8521_RC1R_RGMII_0_150_NS 1 -+#define YT8521_RC1R_RGMII_0_300_NS 2 -+#define YT8521_RC1R_RGMII_0_450_NS 3 -+#define YT8521_RC1R_RGMII_0_600_NS 4 -+#define YT8521_RC1R_RGMII_0_750_NS 5 -+#define YT8521_RC1R_RGMII_0_900_NS 6 -+#define YT8521_RC1R_RGMII_1_050_NS 7 -+#define YT8521_RC1R_RGMII_1_200_NS 8 -+#define YT8521_RC1R_RGMII_1_350_NS 9 -+#define YT8521_RC1R_RGMII_1_500_NS 10 -+#define YT8521_RC1R_RGMII_1_650_NS 11 -+#define YT8521_RC1R_RGMII_1_800_NS 12 -+#define YT8521_RC1R_RGMII_1_950_NS 13 -+#define YT8521_RC1R_RGMII_2_100_NS 14 -+#define YT8521_RC1R_RGMII_2_250_NS 15 - - #define YTPHY_MISC_CONFIG_REG 0xA006 - #define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) -@@ -222,6 +246,29 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YTPHY_SYNCE_CFG_REG 0xA012 -+#define YT8521_SCR_SYNCE_ENABLE BIT(5) -+/* 1b0 output 25m clock -+ * 1b1 output 125m clock *default* -+ */ -+#define YT8521_SCR_CLK_FRE_SEL_125M BIT(3) -+#define YT8521_SCR_CLK_SRC_MASK GENMASK(2, 1) -+#define YT8521_SCR_CLK_SRC_PLL_125M 0 -+#define YT8521_SCR_CLK_SRC_UTP_RX 1 -+#define YT8521_SCR_CLK_SRC_SDS_RX 2 -+#define YT8521_SCR_CLK_SRC_REF_25M 3 -+#define YT8531_SCR_SYNCE_ENABLE BIT(6) -+/* 1b0 output 25m clock *default* -+ * 1b1 output 125m clock -+ */ -+#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4) -+#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1) -+#define YT8531_SCR_CLK_SRC_PLL_125M 0 -+#define YT8531_SCR_CLK_SRC_UTP_RX 1 -+#define YT8531_SCR_CLK_SRC_SDS_RX 2 -+#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 -+#define YT8531_SCR_CLK_SRC_REF_25M 4 -+#define YT8531_SCR_CLK_SRC_SSC_25M 5 - #define YT8531S_SYNCE_CFG_REG 0xA012 - #define YT8531S_SCR_SYNCE_ENABLE BIT(6) - diff --git a/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch deleted file mode 100644 index 6d89fae84c..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch +++ /dev/null @@ -1,343 +0,0 @@ -From a6e68f0f8769f79c67cdcfb6302feecd36197dec Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:35 +0800 -Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8521 gigabit - ethernet phy - -Add dts support for Motorcomm yt8521 gigabit ethernet phy. - Add ytphy_rgmii_clk_delay_config function to support dst config for - the delay of rgmii clk. This funciont is common for yt8521, yt8531s - and yt8531. - This patch has been verified on AM335x platform. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 253 ++++++++++++++++++++++++++++-------- - 1 file changed, 199 insertions(+), 54 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #define PHY_ID_YT8511 0x0000010a - #define PHY_ID_YT8521 0x0000011a -@@ -187,21 +188,9 @@ - * 1b1 use inverted tx_clk_rgmii. - */ - #define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) --/* TX Gig-E Delay is bits 3:0, default 0x1 -- * TX Fast-E Delay is bits 7:4, default 0xf -- * RX Delay is bits 13:10, default 0x0 -- * Delay = 150ps * N -- * On = 2250ps, off = 0ps -- */ - #define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) --#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) --#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) - #define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) --#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) --#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) - #define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) --#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) --#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) - #define YT8521_RC1R_RGMII_0_000_NS 0 - #define YT8521_RC1R_RGMII_0_150_NS 1 - #define YT8521_RC1R_RGMII_0_300_NS 2 -@@ -274,6 +263,10 @@ - - /* Extended Register end */ - -+#define YTPHY_DTS_OUTPUT_CLK_DIS 0 -+#define YTPHY_DTS_OUTPUT_CLK_25M 25000000 -+#define YTPHY_DTS_OUTPUT_CLK_125M 125000000 -+ - struct yt8521_priv { - /* combo_advertising is used for case of YT8521 in combo mode, - * this means that yt8521 may work in utp or fiber mode which depends -@@ -641,6 +634,142 @@ static int yt8521_write_page(struct phy_ - }; - - /** -+ * struct ytphy_cfg_reg_map - map a config value to a register value -+ * @cfg: value in device configuration -+ * @reg: value in the register -+ */ -+struct ytphy_cfg_reg_map { -+ u32 cfg; -+ u32 reg; -+}; -+ -+static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = { -+ /* for tx delay / rx delay with YT8521_CCR_RXC_DLY_EN is not set. */ -+ { 0, YT8521_RC1R_RGMII_0_000_NS }, -+ { 150, YT8521_RC1R_RGMII_0_150_NS }, -+ { 300, YT8521_RC1R_RGMII_0_300_NS }, -+ { 450, YT8521_RC1R_RGMII_0_450_NS }, -+ { 600, YT8521_RC1R_RGMII_0_600_NS }, -+ { 750, YT8521_RC1R_RGMII_0_750_NS }, -+ { 900, YT8521_RC1R_RGMII_0_900_NS }, -+ { 1050, YT8521_RC1R_RGMII_1_050_NS }, -+ { 1200, YT8521_RC1R_RGMII_1_200_NS }, -+ { 1350, YT8521_RC1R_RGMII_1_350_NS }, -+ { 1500, YT8521_RC1R_RGMII_1_500_NS }, -+ { 1650, YT8521_RC1R_RGMII_1_650_NS }, -+ { 1800, YT8521_RC1R_RGMII_1_800_NS }, -+ { 1950, YT8521_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */ -+ { 2100, YT8521_RC1R_RGMII_2_100_NS }, -+ { 2250, YT8521_RC1R_RGMII_2_250_NS }, -+ -+ /* only for rx delay with YT8521_CCR_RXC_DLY_EN is set. */ -+ { 0 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_000_NS }, -+ { 150 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_150_NS }, -+ { 300 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_300_NS }, -+ { 450 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_450_NS }, -+ { 600 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_600_NS }, -+ { 750 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_750_NS }, -+ { 900 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_900_NS }, -+ { 1050 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_050_NS }, -+ { 1200 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_200_NS }, -+ { 1350 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_350_NS }, -+ { 1500 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_500_NS }, -+ { 1650 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_650_NS }, -+ { 1800 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_800_NS }, -+ { 1950 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_950_NS }, -+ { 2100 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_100_NS }, -+ { 2250 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_250_NS } -+}; -+ -+static u32 ytphy_get_delay_reg_value(struct phy_device *phydev, -+ const char *prop_name, -+ const struct ytphy_cfg_reg_map *tbl, -+ int tb_size, -+ u16 *rxc_dly_en, -+ u32 dflt) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ int tb_size_half = tb_size / 2; -+ u32 val; -+ int i; -+ -+ if (of_property_read_u32(node, prop_name, &val)) -+ goto err_dts_val; -+ -+ /* when rxc_dly_en is NULL, it is get the delay for tx, only half of -+ * tb_size is valid. -+ */ -+ if (!rxc_dly_en) -+ tb_size = tb_size_half; -+ -+ for (i = 0; i < tb_size; i++) { -+ if (tbl[i].cfg == val) { -+ if (rxc_dly_en && i < tb_size_half) -+ *rxc_dly_en = 0; -+ return tbl[i].reg; -+ } -+ } -+ -+ phydev_warn(phydev, "Unsupported value %d for %s using default (%u)\n", -+ val, prop_name, dflt); -+ -+err_dts_val: -+ /* when rxc_dly_en is not NULL, it is get the delay for rx. -+ * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps, -+ * so YT8521_CCR_RXC_DLY_EN should not be set. -+ */ -+ if (rxc_dly_en) -+ *rxc_dly_en = 0; -+ -+ return dflt; -+} -+ -+static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev) -+{ -+ int tb_size = ARRAY_SIZE(ytphy_rgmii_delays); -+ u16 rxc_dly_en = YT8521_CCR_RXC_DLY_EN; -+ u32 rx_reg, tx_reg; -+ u16 mask, val = 0; -+ int ret; -+ -+ rx_reg = ytphy_get_delay_reg_value(phydev, "rx-internal-delay-ps", -+ ytphy_rgmii_delays, tb_size, -+ &rxc_dly_en, -+ YT8521_RC1R_RGMII_1_950_NS); -+ tx_reg = ytphy_get_delay_reg_value(phydev, "tx-internal-delay-ps", -+ ytphy_rgmii_delays, tb_size, NULL, -+ YT8521_RC1R_RGMII_1_950_NS); -+ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ rxc_dly_en = 0; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ rxc_dly_en = 0; -+ val |= FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg) | -+ FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); -+ break; -+ default: /* do not support other modes */ -+ return -EOPNOTSUPP; -+ } -+ -+ ret = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_RXC_DLY_EN, rxc_dly_en); -+ if (ret < 0) -+ return ret; -+ -+ /* Generally, it is not necessary to adjust YT8521_RC1R_FE_TX_DELAY */ -+ mask = YT8521_RC1R_RX_DELAY_MASK | YT8521_RC1R_GE_TX_DELAY_MASK; -+ return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); -+} -+ -+/** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device - * -@@ -648,9 +777,12 @@ static int yt8521_write_page(struct phy_ - */ - static int yt8521_probe(struct phy_device *phydev) - { -+ struct device_node *node = phydev->mdio.dev.of_node; - struct device *dev = &phydev->mdio.dev; - struct yt8521_priv *priv; - int chip_config; -+ u16 mask, val; -+ u32 freq; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -@@ -695,7 +827,45 @@ static int yt8521_probe(struct phy_devic - return ret; - } - -- return 0; -+ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq)) -+ freq = YTPHY_DTS_OUTPUT_CLK_DIS; -+ -+ if (phydev->drv->phy_id == PHY_ID_YT8521) { -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8521_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_SRC_MASK | -+ YT8521_SCR_CLK_FRE_SEL_125M; -+ val = YT8521_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, -+ YT8521_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_SRC_MASK | -+ YT8521_SCR_CLK_FRE_SEL_125M; -+ val = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, -+ YT8521_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } -+ } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { -+ return 0; -+ } else { -+ phydev_warn(phydev, "PHY id err\n"); -+ return -EINVAL; -+ } -+ -+ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, -+ val); - } - - /** -@@ -1180,61 +1350,36 @@ static int yt8521_resume(struct phy_devi - */ - static int yt8521_config_init(struct phy_device *phydev) - { -+ struct device_node *node = phydev->mdio.dev.of_node; - int old_page; - int ret = 0; -- u16 val; - - old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); - if (old_page < 0) - goto err_restore_page; - -- switch (phydev->interface) { -- case PHY_INTERFACE_MODE_RGMII: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; -- val |= YT8521_RC1R_RX_DELAY_DIS; -- break; -- case PHY_INTERFACE_MODE_RGMII_RXID: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; -- val |= YT8521_RC1R_RX_DELAY_EN; -- break; -- case PHY_INTERFACE_MODE_RGMII_TXID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; -- val |= YT8521_RC1R_RX_DELAY_DIS; -- break; -- case PHY_INTERFACE_MODE_RGMII_ID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; -- val |= YT8521_RC1R_RX_DELAY_EN; -- break; -- case PHY_INTERFACE_MODE_SGMII: -- break; -- default: /* do not support other modes */ -- ret = -EOPNOTSUPP; -- goto err_restore_page; -- } -- - /* set rgmii delay mode */ - if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { -- ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, -- (YT8521_RC1R_RX_DELAY_MASK | -- YT8521_RC1R_FE_TX_DELAY_MASK | -- YT8521_RC1R_GE_TX_DELAY_MASK), -- val); -+ ret = ytphy_rgmii_clk_delay_config(phydev); - if (ret < 0) - goto err_restore_page; - } - -- /* disable auto sleep */ -- ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -- YT8521_ESC1R_SLEEP_SW, 0); -- if (ret < 0) -- goto err_restore_page; -- -- /* enable RXC clock when no wire plug */ -- ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -- YT8521_CGR_RX_CLK_EN, 0); -- if (ret < 0) -- goto err_restore_page; -+ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } - -+ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } - err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } diff --git a/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch deleted file mode 100644 index 86fc04695c..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 36152f87dda4af221b16258751451d9cd3d0fb0b Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:36 +0800 -Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8531s gigabit - ethernet phy - -Add dts support for Motorcomm yt8531s gigabit ethernet phy. - Change yt8521_probe to support clk config of yt8531s. Becase - yt8521_probe does the things which yt8531s is needed, so - removed yt8531s function. - This patch has been verified on AM335x platform with yt8531s board. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 51 ++++++++++++++++++++----------------- - 1 file changed, 27 insertions(+), 24 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -258,8 +258,6 @@ - #define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 - #define YT8531_SCR_CLK_SRC_REF_25M 4 - #define YT8531_SCR_CLK_SRC_SSC_25M 5 --#define YT8531S_SYNCE_CFG_REG 0xA012 --#define YT8531S_SCR_SYNCE_ENABLE BIT(6) - - /* Extended Register end */ - -@@ -858,7 +856,32 @@ static int yt8521_probe(struct phy_devic - return -EINVAL; - } - } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { -- return 0; -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8531_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } - } else { - phydev_warn(phydev, "PHY id err\n"); - return -EINVAL; -@@ -869,26 +892,6 @@ static int yt8521_probe(struct phy_devic - } - - /** -- * yt8531s_probe() - read chip config then set suitable polling_mode -- * @phydev: a pointer to a &struct phy_device -- * -- * returns 0 or negative errno code -- */ --static int yt8531s_probe(struct phy_device *phydev) --{ -- int ret; -- -- /* Disable SyncE clock output by default */ -- ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, -- YT8531S_SCR_SYNCE_ENABLE, 0); -- if (ret < 0) -- return ret; -- -- /* same as yt8521_probe */ -- return yt8521_probe(phydev); --} -- --/** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device - * -@@ -1970,7 +1973,7 @@ static struct phy_driver motorcomm_phy_d - PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), - .name = "YT8531S Gigabit Ethernet", - .get_features = yt8521_get_features, -- .probe = yt8531s_probe, -+ .probe = yt8521_probe, - .read_page = yt8521_read_page, - .write_page = yt8521_write_page, - .get_wol = ytphy_get_wol, diff --git a/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch b/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch deleted file mode 100644 index 60eea4fa47..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 4ac94f728a588e7096dd5010cd7141a309ea7805 Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:37 +0800 -Subject: [PATCH] net: phy: Add driver for Motorcomm yt8531 gigabit ethernet - phy - -Add a driver for the motorcomm yt8531 gigabit ethernet phy. We have - verified the driver on AM335x platform with yt8531 board. On the - board, yt8531 gigabit ethernet phy works in utp mode, RGMII - interface, supports 1000M/100M/10M speeds, and wol(magic package). - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 208 +++++++++++++++++++++++++++++++++++- - 2 files changed, 207 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -257,7 +257,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. -+ Currently supports YT85xx Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Motorcomm 8511/8521/8531S PHY driver. -+ * Motorcomm 8511/8521/8531/8531S PHY driver. - * - * Author: Peter Geis - * Author: Frank -@@ -14,6 +14,7 @@ - - #define PHY_ID_YT8511 0x0000010a - #define PHY_ID_YT8521 0x0000011a -+#define PHY_ID_YT8531 0x4f51e91b - #define PHY_ID_YT8531S 0x4f51e91a - - /* YT8521/YT8531S Register Overview -@@ -517,6 +518,61 @@ err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } - -+static int yt8531_set_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol) -+{ -+ const u16 mac_addr_reg[] = { -+ YTPHY_WOL_MACADDR2_REG, -+ YTPHY_WOL_MACADDR1_REG, -+ YTPHY_WOL_MACADDR0_REG, -+ }; -+ const u8 *mac_addr; -+ u16 mask, val; -+ int ret; -+ u8 i; -+ -+ if (wol->wolopts & WAKE_MAGIC) { -+ mac_addr = phydev->attached_dev->dev_addr; -+ -+ /* Store the device address for the magic packet */ -+ for (i = 0; i < 3; i++) { -+ ret = ytphy_write_ext_with_lock(phydev, mac_addr_reg[i], -+ ((mac_addr[i * 2] << 8)) | -+ (mac_addr[i * 2 + 1])); -+ if (ret < 0) -+ return ret; -+ } -+ -+ /* Enable WOL feature */ -+ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; -+ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; -+ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, -+ mask, val); -+ if (ret < 0) -+ return ret; -+ -+ /* Enable WOL interrupt */ -+ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, -+ YTPHY_IER_WOL); -+ if (ret < 0) -+ return ret; -+ } else { -+ /* Disable WOL feature */ -+ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, -+ mask, 0); -+ -+ /* Disable WOL interrupt */ -+ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, -+ YTPHY_IER_WOL, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int yt8511_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, YT8511_PAGE_SELECT); -@@ -767,6 +823,17 @@ static int ytphy_rgmii_clk_delay_config( - return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); - } - -+static int ytphy_rgmii_clk_delay_config_with_lock(struct phy_device *phydev) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_rgmii_clk_delay_config(phydev); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ - /** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device -@@ -891,6 +958,43 @@ static int yt8521_probe(struct phy_devic - val); - } - -+static int yt8531_probe(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ u16 mask, val; -+ u32 freq; -+ -+ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq)) -+ freq = YTPHY_DTS_OUTPUT_CLK_DIS; -+ -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8531_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } -+ -+ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, -+ val); -+} -+ - /** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device -@@ -1387,6 +1491,94 @@ err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } - -+static int yt8531_config_init(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ int ret; -+ -+ ret = ytphy_rgmii_clk_delay_config_with_lock(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8531_link_change_notify() - Adjust the tx clock direction according to -+ * the current speed and dts config. -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * NOTE: This function is only used to adapt to VF2 with JH7110 SoC. Please -+ * keep "motorcomm,tx-clk-adj-enabled" not exist in dts when the soc is not -+ * JH7110. -+ */ -+static void yt8531_link_change_notify(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ bool tx_clk_adj_enabled = false; -+ bool tx_clk_1000_inverted; -+ bool tx_clk_100_inverted; -+ bool tx_clk_10_inverted; -+ u16 val = 0; -+ int ret; -+ -+ if (of_property_read_bool(node, "motorcomm,tx-clk-adj-enabled")) -+ tx_clk_adj_enabled = true; -+ -+ if (!tx_clk_adj_enabled) -+ return; -+ -+ if (of_property_read_bool(node, "motorcomm,tx-clk-10-inverted")) -+ tx_clk_10_inverted = true; -+ if (of_property_read_bool(node, "motorcomm,tx-clk-100-inverted")) -+ tx_clk_100_inverted = true; -+ if (of_property_read_bool(node, "motorcomm,tx-clk-1000-inverted")) -+ tx_clk_1000_inverted = true; -+ -+ if (phydev->speed < 0) -+ return; -+ -+ switch (phydev->speed) { -+ case SPEED_1000: -+ if (tx_clk_1000_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ case SPEED_100: -+ if (tx_clk_100_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ case SPEED_10: -+ if (tx_clk_10_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ default: -+ return; -+ } -+ -+ ret = ytphy_modify_ext_with_lock(phydev, YT8521_RGMII_CONFIG1_REG, -+ YT8521_RC1R_TX_CLK_SEL_INVERTED, val); -+ if (ret < 0) -+ phydev_warn(phydev, "Modify TX_CLK_SEL err:%d\n", ret); -+} -+ - /** - * yt8521_prepare_fiber_features() - A small helper function that setup - * fiber's features. -@@ -1970,6 +2162,17 @@ static struct phy_driver motorcomm_phy_d - .resume = yt8521_resume, - }, - { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8531), -+ .name = "YT8531 Gigabit Ethernet", -+ .probe = yt8531_probe, -+ .config_init = yt8531_config_init, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .get_wol = ytphy_get_wol, -+ .set_wol = yt8531_set_wol, -+ .link_change_notify = yt8531_link_change_notify, -+ }, -+ { - PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), - .name = "YT8531S Gigabit Ethernet", - .get_features = yt8521_get_features, -@@ -1990,7 +2193,7 @@ static struct phy_driver motorcomm_phy_d - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S PHY driver"); - MODULE_AUTHOR("Peter Geis"); - MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); -@@ -1998,6 +2201,7 @@ MODULE_LICENSE("GPL"); - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, - { /* sentinel */ } - }; diff --git a/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch b/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch deleted file mode 100644 index 29ae86dbbc..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 9753613f7399601f9bae6ee81e9d4274246c98ab Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Wed, 15 Feb 2023 07:21:47 +0300 -Subject: [PATCH] net: phy: motorcomm: uninitialized variables in - yt8531_link_change_notify() - -These booleans are never set to false, but are just used without being -initialized. - -Fixes: 4ac94f728a58 ("net: phy: Add driver for Motorcomm yt8531 gigabit ethernet phy") -Signed-off-by: Dan Carpenter -Reviewed-by: Frank Sae -Link: https://lore.kernel.org/r/Y+xd2yJet2ImHLoQ@kili -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1533,10 +1533,10 @@ static int yt8531_config_init(struct phy - static void yt8531_link_change_notify(struct phy_device *phydev) - { - struct device_node *node = phydev->mdio.dev.of_node; -+ bool tx_clk_1000_inverted = false; -+ bool tx_clk_100_inverted = false; -+ bool tx_clk_10_inverted = false; - bool tx_clk_adj_enabled = false; -- bool tx_clk_1000_inverted; -- bool tx_clk_100_inverted; -- bool tx_clk_10_inverted; - u16 val = 0; - int ret; - diff --git a/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch b/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch deleted file mode 100644 index 010ca9b68a..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 -From: Samin Guo -Date: Thu, 20 Jul 2023 19:15:09 +0800 -Subject: [PATCH] net: phy: motorcomm: Add pad drive strength cfg support - -The motorcomm phy (YT8531) supports the ability to adjust the drive -strength of the rx_clk/rx_data, and the default strength may not be -suitable for all boards. So add configurable options to better match -the boards.(e.g. StarFive VisionFive 2) - -When we configure the drive strength, we need to read the current -LDO voltage value to ensure that it is a legal value at that LDO -voltage. - -Reviewed-by: Hal Feng -Signed-off-by: Samin Guo -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 118 insertions(+) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -163,6 +163,10 @@ - - #define YT8521_CHIP_CONFIG_REG 0xA001 - #define YT8521_CCR_SW_RST BIT(15) -+#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) -+#define YT8531_LDO_VOL_3V3 0x0 -+#define YT8531_LDO_VOL_1V8 0x2 -+ - /* 1b0 disable 1.9ns rxc clock delay *default* - * 1b1 enable 1.9ns rxc clock delay - */ -@@ -236,6 +240,12 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 -+#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) -+#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ -+#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ -+#define YT8531_RGMII_RX_DS_DEFAULT 0x3 -+ - #define YTPHY_SYNCE_CFG_REG 0xA012 - #define YT8521_SCR_SYNCE_ENABLE BIT(5) - /* 1b0 output 25m clock -@@ -835,6 +845,110 @@ static int ytphy_rgmii_clk_delay_config_ - } - - /** -+ * struct ytphy_ldo_vol_map - map a current value to a register value -+ * @vol: ldo voltage -+ * @ds: value in the register -+ * @cur: value in device configuration -+ */ -+struct ytphy_ldo_vol_map { -+ u32 vol; -+ u32 ds; -+ u32 cur; -+}; -+ -+static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, -+}; -+ -+static u32 yt8531_get_ldo_vol(struct phy_device *phydev) -+{ -+ u32 val; -+ -+ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); -+ val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); -+ -+ return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; -+} -+ -+static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) -+{ -+ u32 vol; -+ int i; -+ -+ vol = yt8531_get_ldo_vol(phydev); -+ for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { -+ if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) -+ return yt8531_ldo_vol[i].ds; -+ } -+ -+ return -EINVAL; -+} -+ -+static int yt8531_set_ds(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ u32 ds_field_low, ds_field_hi, val; -+ int ret, ds; -+ -+ /* set rgmii rx clk driver strength */ -+ if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { -+ ds = yt8531_get_ds_map(phydev, val); -+ if (ds < 0) -+ return dev_err_probe(&phydev->mdio.dev, ds, -+ "No matching current value was found.\n"); -+ } else { -+ ds = YT8531_RGMII_RX_DS_DEFAULT; -+ } -+ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YTPHY_PAD_DRIVE_STRENGTH_REG, -+ YT8531_RGMII_RXC_DS_MASK, -+ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); -+ if (ret < 0) -+ return ret; -+ -+ /* set rgmii rx data driver strength */ -+ if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { -+ ds = yt8531_get_ds_map(phydev, val); -+ if (ds < 0) -+ return dev_err_probe(&phydev->mdio.dev, ds, -+ "No matching current value was found.\n"); -+ } else { -+ ds = YT8531_RGMII_RX_DS_DEFAULT; -+ } -+ -+ ds_field_hi = FIELD_GET(BIT(2), ds); -+ ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); -+ -+ ds_field_low = FIELD_GET(GENMASK(1, 0), ds); -+ ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); -+ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YTPHY_PAD_DRIVE_STRENGTH_REG, -+ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, -+ ds_field_low | ds_field_hi); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+/** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device - * -@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy - return ret; - } - -+ ret = yt8531_set_ds(phydev); -+ if (ret < 0) -+ return ret; -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch deleted file mode 100644 index f82c8fc622..0000000000 --- a/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 90ef0a7b0622c62758b2638604927867775479ea Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 13 Jul 2023 09:42:07 +0100 -Subject: [PATCH] net: phylink: add pcs_enable()/pcs_disable() methods - -Add phylink PCS enable/disable callbacks that will allow us to place -IEEE 802.3 register compliant PCS in power-down mode while not being -used. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 48 +++++++++++++++++++++++++++++++-------- - include/linux/phylink.h | 16 +++++++++++++ - 2 files changed, 55 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -34,6 +34,10 @@ enum { - PHYLINK_DISABLE_STOPPED, - PHYLINK_DISABLE_LINK, - PHYLINK_DISABLE_MAC_WOL, -+ -+ PCS_STATE_DOWN = 0, -+ PCS_STATE_STARTING, -+ PCS_STATE_STARTED, - }; - - /** -@@ -72,6 +76,7 @@ struct phylink { - struct phylink_link_state phy_state; - struct work_struct resolve; - unsigned int pcs_neg_mode; -+ unsigned int pcs_state; - - bool mac_link_dropped; - bool using_mac_select_pcs; -@@ -992,6 +997,22 @@ static void phylink_resolve_an_pause(str - } - } - -+static void phylink_pcs_disable(struct phylink_pcs *pcs) -+{ -+ if (pcs && pcs->ops->pcs_disable) -+ pcs->ops->pcs_disable(pcs); -+} -+ -+static int phylink_pcs_enable(struct phylink_pcs *pcs) -+{ -+ int err = 0; -+ -+ if (pcs && pcs->ops->pcs_enable) -+ err = pcs->ops->pcs_enable(pcs); -+ -+ return err; -+} -+ - static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - const struct phylink_link_state *state, - bool permit_pause_to_mac) -@@ -1094,11 +1115,17 @@ static void phylink_major_config(struct - /* If we have a new PCS, switch to the new PCS after preparing the MAC - * for the change. - */ -- if (pcs_changed) -+ if (pcs_changed) { -+ phylink_pcs_disable(pl->pcs); -+ - pl->pcs = pcs; -+ } - - phylink_mac_config(pl, state); - -+ if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) -+ phylink_pcs_enable(pl->pcs); -+ - neg_mode = pl->cur_link_an_mode; - if (pl->pcs && pl->pcs->neg_mode) - neg_mode = pl->pcs_neg_mode; -@@ -1586,6 +1613,7 @@ struct phylink *phylink_create(struct ph - pl->link_config.pause = MLO_PAUSE_AN; - pl->link_config.speed = SPEED_UNKNOWN; - pl->link_config.duplex = DUPLEX_UNKNOWN; -+ pl->pcs_state = PCS_STATE_DOWN; - pl->mac_ops = mac_ops; - __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); - timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -1987,6 +2015,8 @@ void phylink_start(struct phylink *pl) - if (pl->netdev) - netif_carrier_off(pl->netdev); - -+ pl->pcs_state = PCS_STATE_STARTING; -+ - /* Apply the link configuration to the MAC when starting. This allows - * a fixed-link to start with the correct parameters, and also - * ensures that we set the appropriate advertisement for Serdes links. -@@ -1997,6 +2027,8 @@ void phylink_start(struct phylink *pl) - */ - phylink_mac_initial_config(pl, true); - -+ pl->pcs_state = PCS_STATE_STARTED; -+ - phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); - - if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { -@@ -2015,15 +2047,9 @@ void phylink_start(struct phylink *pl) - poll = true; - } - -- switch (pl->cfg_link_an_mode) { -- case MLO_AN_FIXED: -+ if (pl->cfg_link_an_mode == MLO_AN_FIXED) - poll |= pl->config->poll_fixed_state; -- break; -- case MLO_AN_INBAND: -- if (pl->pcs) -- poll |= pl->pcs->poll; -- break; -- } -+ - if (poll) - mod_timer(&pl->link_poll, jiffies + HZ); - if (pl->phydev) -@@ -2060,6 +2086,10 @@ void phylink_stop(struct phylink *pl) - } - - phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); -+ -+ pl->pcs_state = PCS_STATE_DOWN; -+ -+ phylink_pcs_disable(pl->pcs); - } - EXPORT_SYMBOL_GPL(phylink_stop); - ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -533,6 +533,8 @@ struct phylink_pcs { - /** - * struct phylink_pcs_ops - MAC PCS operations structure. - * @pcs_validate: validate the link configuration. -+ * @pcs_enable: enable the PCS. -+ * @pcs_disable: disable the PCS. - * @pcs_get_state: read the current MAC PCS link state from the hardware. - * @pcs_config: configure the MAC PCS for the selected mode and state. - * @pcs_an_restart: restart 802.3z BaseX autonegotiation. -@@ -542,6 +544,8 @@ struct phylink_pcs { - struct phylink_pcs_ops { - int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, - const struct phylink_link_state *state); -+ int (*pcs_enable)(struct phylink_pcs *pcs); -+ void (*pcs_disable)(struct phylink_pcs *pcs); - void (*pcs_get_state)(struct phylink_pcs *pcs, - struct phylink_link_state *state); - int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, -@@ -572,6 +576,18 @@ int pcs_validate(struct phylink_pcs *pcs - const struct phylink_link_state *state); - - /** -+ * pcs_enable() - enable the PCS. -+ * @pcs: a pointer to a &struct phylink_pcs. -+ */ -+int pcs_enable(struct phylink_pcs *pcs); -+ -+/** -+ * pcs_disable() - disable the PCS. -+ * @pcs: a pointer to a &struct phylink_pcs. -+ */ -+void pcs_disable(struct phylink_pcs *pcs); -+ -+/** - * pcs_get_state() - Read the current inband link state from the hardware - * @pcs: a pointer to a &struct phylink_pcs. - * @state: a pointer to a &struct phylink_link_state. diff --git a/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch b/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch deleted file mode 100644 index 6b6369761a..0000000000 --- a/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch +++ /dev/null @@ -1,44 +0,0 @@ -From e4ccdfb78a47132f2d215658aab8902fc457c4b4 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 18 Aug 2023 04:07:46 +0100 -Subject: [PATCH 082/125] net: pcs: lynxi: implement pcs_disable op - -When switching from 10GBase-R/5GBase-R/USXGMII to one of the interface -modes provided by mtk-pcs-lynxi we need to make sure to always perform -a full configuration of the PHYA. - -Implement pcs_disable op which resets the stored interface mode to -PHY_INTERFACE_MODE_NA to trigger a full reconfiguration once the LynxI -PCS driver had previously been deselected in favor of another PCS -driver such as the to-be-added driver for the USXGMII PCS found in -MT7988. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/f23d1a60d2c9d2fb72e32dcb0eaa5f7e867a3d68.1692327891.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-mtk-lynxi.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/net/pcs/pcs-mtk-lynxi.c -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -234,11 +234,19 @@ static void mtk_pcs_lynxi_link_up(struct - } - } - -+static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ -+ mpcs->interface = PHY_INTERFACE_MODE_NA; -+} -+ - static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { - .pcs_get_state = mtk_pcs_lynxi_get_state, - .pcs_config = mtk_pcs_lynxi_config, - .pcs_an_restart = mtk_pcs_lynxi_restart_an, - .pcs_link_up = mtk_pcs_lynxi_link_up, -+ .pcs_disable = mtk_pcs_lynxi_disable, - }; - - struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, diff --git a/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch b/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch deleted file mode 100644 index c4141eee93..0000000000 --- a/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch +++ /dev/null @@ -1,136 +0,0 @@ -From: Andy Ren -Date: Mon, 7 Nov 2022 09:42:42 -0800 -Subject: [PATCH] net/core: Allow live renaming when an interface is up - -Allow a network interface to be renamed when the interface -is up. - -As described in the netconsole documentation [1], when netconsole is -used as a built-in, it will bring up the specified interface as soon as -possible. As a result, user space will not be able to rename the -interface since the kernel disallows renaming of interfaces that are -administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set -by the kernel. - -The original solution [2] to this problem was to add a new parameter to -the netconsole configuration parameters that allows renaming of -the interface used by netconsole while it is administratively up. -However, during the discussion that followed, it became apparent that we -have no reason to keep the current restriction and instead we should -allow user space to rename interfaces regardless of their administrative -state: - -1. The restriction was put in place over 20 years ago when renaming was -only possible via IOCTL and before rtnetlink started notifying user -space about such changes like it does today. - -2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version -5.2 and no regressions were reported. - -3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about -the administrative state of interface. - -Therefore, allow user space to rename running interfaces by removing the -restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in -possible triage by emitting a message to the kernel log that an -interface was renamed while UP. - -[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst -[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/ - -Signed-off-by: Andy Ren -Reviewed-by: Ido Schimmel -Reviewed-by: David Ahern -Signed-off-by: David S. Miller ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -1691,7 +1691,6 @@ struct net_device_ops { - * @IFF_FAILOVER: device is a failover master device - * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device - * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device -- * @IFF_LIVE_RENAME_OK: rename is allowed while device is up and running - * @IFF_TX_SKB_NO_LINEAR: device/driver is capable of xmitting frames with - * skb_headlen(skb) == 0 (data starts from frag0) - * @IFF_CHANGE_PROTO_DOWN: device supports setting carrier via IFLA_PROTO_DOWN -@@ -1727,7 +1726,7 @@ enum netdev_priv_flags { - IFF_FAILOVER = 1<<27, - IFF_FAILOVER_SLAVE = 1<<28, - IFF_L3MDEV_RX_HANDLER = 1<<29, -- IFF_LIVE_RENAME_OK = 1<<30, -+ /* was IFF_LIVE_RENAME_OK */ - IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), - IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), - }; -@@ -1762,7 +1761,6 @@ enum netdev_priv_flags { - #define IFF_FAILOVER IFF_FAILOVER - #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE - #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER --#define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK - #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR - - /* Specifies the type of the struct net_device::ml_priv pointer */ ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -1188,22 +1188,6 @@ int dev_change_name(struct net_device *d - - net = dev_net(dev); - -- /* Some auto-enslaved devices e.g. failover slaves are -- * special, as userspace might rename the device after -- * the interface had been brought up and running since -- * the point kernel initiated auto-enslavement. Allow -- * live name change even when these slave devices are -- * up and running. -- * -- * Typically, users of these auto-enslaving devices -- * don't actually care about slave name change, as -- * they are supposed to operate on master interface -- * directly. -- */ -- if (dev->flags & IFF_UP && -- likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK))) -- return -EBUSY; -- - down_write(&devnet_rename_sem); - - if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { -@@ -1220,7 +1204,8 @@ int dev_change_name(struct net_device *d - } - - if (oldname[0] && !strchr(oldname, '%')) -- netdev_info(dev, "renamed from %s\n", oldname); -+ netdev_info(dev, "renamed from %s%s\n", oldname, -+ dev->flags & IFF_UP ? " (while UP)" : ""); - - old_assign_type = dev->name_assign_type; - dev->name_assign_type = NET_NAME_RENAMED; ---- a/net/core/failover.c -+++ b/net/core/failover.c -@@ -80,14 +80,14 @@ static int failover_slave_register(struc - goto err_upper_link; - } - -- slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); -+ slave_dev->priv_flags |= IFF_FAILOVER_SLAVE; - - if (fops && fops->slave_register && - !fops->slave_register(slave_dev, failover_dev)) - return NOTIFY_OK; - - netdev_upper_dev_unlink(slave_dev, failover_dev); -- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); -+ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; - err_upper_link: - netdev_rx_handler_unregister(slave_dev); - done: -@@ -121,7 +121,7 @@ int failover_slave_unregister(struct net - - netdev_rx_handler_unregister(slave_dev); - netdev_upper_dev_unlink(slave_dev, failover_dev); -- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); -+ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; - - if (fops && fops->slave_unregister && - !fops->slave_unregister(slave_dev, failover_dev)) diff --git a/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch b/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch deleted file mode 100644 index 17131c16d3..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 69649ef8405320f81497f4757faac8234f61b167 Mon Sep 17 00:00:00 2001 -From: Bjørn Mork -Date: Fri, 6 Jan 2023 17:07:39 +0100 -Subject: [PATCH] cdc_ether: no need to blacklist any r8152 devices -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The r8152 driver does not need this anymore. - -Dropping blacklist entries adds optional support for these -devices in ECM mode. - -The 8153 devices are handled by the r8153_ecm driver when -in ECM mode, and must still be blacklisted here. - -Signed-off-by: Bjørn Mork -Signed-off-by: David S. Miller ---- - drivers/net/usb/cdc_ether.c | 114 ------------------------------------ - 1 file changed, 114 deletions(-) - ---- a/drivers/net/usb/cdc_ether.c -+++ b/drivers/net/usb/cdc_ether.c -@@ -768,13 +768,6 @@ static const struct usb_device_id produc - .driver_info = 0, - }, - --/* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- - /* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */ - { - USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, -@@ -782,119 +775,12 @@ static const struct usb_device_id produc - .driver_info = 0, - }, - --/* Samsung USB Ethernet Adapters */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --#if IS_ENABLED(CONFIG_USB_RTL8152) --/* Linksys USB3GIGV1 Ethernet Adapter */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, --#endif -- --/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* ThinkPad USB-C Dock (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* ThinkPad Thunderbolt 3 Dock Gen 2 (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3082, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- - /* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */ - { - USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), - .driver_info = 0, - }, -- --/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Microsoft Surface 2 dock (based on Realtek RTL8152) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07ab, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, - - /* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */ - { diff --git a/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch b/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch deleted file mode 100644 index 565fbb3074..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 02767440e1dda9861a11ca1dbe0f19a760b1d5c2 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Thu, 19 Jan 2023 15:40:43 +0800 -Subject: [PATCH] r8152: reduce the control transfer of rtl8152_get_version() - -Reduce the control transfer by moving calling rtl8152_get_version() in -rtl8152_probe(). This could prevent from calling rtl8152_get_version() -for unnecessary situations. For example, after setting config #2 for the -device, there are two interfaces and rtl8152_probe() may be called -twice. However, we don't need to call rtl8152_get_version() for this -situation. - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -9638,20 +9638,21 @@ static int rtl8152_probe(struct usb_inte - const struct usb_device_id *id) - { - struct usb_device *udev = interface_to_usbdev(intf); -- u8 version = rtl8152_get_version(intf); - struct r8152 *tp; - struct net_device *netdev; -+ u8 version; - int ret; - -- if (version == RTL_VER_UNKNOWN) -- return -ENODEV; -- - if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) - return -ENODEV; - - if (!rtl_check_vendor_ok(intf)) - return -ENODEV; - -+ version = rtl8152_get_version(intf); -+ if (version == RTL_VER_UNKNOWN) -+ return -ENODEV; -+ - usb_reset_device(udev); - netdev = alloc_etherdev(sizeof(struct r8152)); - if (!netdev) { diff --git a/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch b/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch deleted file mode 100644 index cdabca36d2..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 5cc33f139e11b893ff6dc60d8a0ae865a65521ac Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Thu, 6 Apr 2023 17:14:26 -0700 -Subject: [PATCH] r8152: Add __GFP_NOWARN to big allocations - -When memory is a little tight on my system, it's pretty easy to see -warnings that look like this. - - ksoftirqd/0: page allocation failure: order:3, mode:0x40a20(GFP_ATOMIC|__GFP_COMP), nodemask=(null),cpuset=/,mems_allowed=0 - ... - Call trace: - dump_backtrace+0x0/0x1e8 - show_stack+0x20/0x2c - dump_stack_lvl+0x60/0x78 - dump_stack+0x18/0x38 - warn_alloc+0x104/0x174 - __alloc_pages+0x588/0x67c - alloc_rx_agg+0xa0/0x190 [r8152 ...] - r8152_poll+0x270/0x760 [r8152 ...] - __napi_poll+0x44/0x1ec - net_rx_action+0x100/0x300 - __do_softirq+0xec/0x38c - run_ksoftirqd+0x38/0xec - smpboot_thread_fn+0xb8/0x248 - kthread+0x134/0x154 - ret_from_fork+0x10/0x20 - -On a fragmented system it's normal that order 3 allocations will -sometimes fail, especially atomic ones. The driver handles these -failures fine and the WARN just creates spam in the logs for this -case. The __GFP_NOWARN flag is exactly for this situation, so add it -to the allocation. - -NOTE: my testing is on a 5.15 system, but there should be no reason -that this would be fundamentally different on a mainline kernel. - -Signed-off-by: Douglas Anderson -Acked-by: Hayes Wang -Link: https://lore.kernel.org/r/20230406171411.1.I84dbef45786af440fd269b71e9436a96a8e7a152@changeid -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -1947,7 +1947,7 @@ static struct rx_agg *alloc_rx_agg(struc - if (!rx_agg) - return NULL; - -- rx_agg->page = alloc_pages(mflags | __GFP_COMP, order); -+ rx_agg->page = alloc_pages(mflags | __GFP_COMP | __GFP_NOWARN, order); - if (!rx_agg->page) - goto free_rx; - diff --git a/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch b/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch deleted file mode 100644 index 3ba79d6cc6..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 57df0fb9d511f91202114813e90128d65c0589f0 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Wed, 26 Jul 2023 11:08:07 +0800 -Subject: [PATCH] r8152: adjust generic_ocp_write function - -Reduce the control transfer if all bytes of first or the last DWORD are -written. - -The original method is to split the control transfer into three parts -(the first DWORD, middle continuous data, and the last DWORD). However, -they could be combined if whole bytes of the first DWORD or last DWORD -are written. That is, the first DWORD or the last DWORD could be combined -with the middle continuous data, if the byte_en is 0xff. - -Signed-off-by: Hayes Wang -Link: https://lore.kernel.org/r/20230726030808.9093-418-nic_swsd@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 29 ++++++++++++++++++----------- - 1 file changed, 18 insertions(+), 11 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -1313,16 +1313,24 @@ static int generic_ocp_write(struct r815 - byteen_end = byteen & BYTE_EN_END_MASK; - - byen = byteen_start | (byteen_start << 4); -- ret = set_registers(tp, index, type | byen, 4, data); -- if (ret < 0) -- goto error1; -- -- index += 4; -- data += 4; -- size -= 4; - -- if (size) { -+ /* Split the first DWORD if the byte_en is not 0xff */ -+ if (byen != BYTE_EN_DWORD) { -+ ret = set_registers(tp, index, type | byen, 4, data); -+ if (ret < 0) -+ goto error1; -+ -+ index += 4; -+ data += 4; - size -= 4; -+ } -+ -+ if (size) { -+ byen = byteen_end | (byteen_end >> 4); -+ -+ /* Split the last DWORD if the byte_en is not 0xff */ -+ if (byen != BYTE_EN_DWORD) -+ size -= 4; - - while (size) { - if (size > limit) { -@@ -1349,10 +1357,9 @@ static int generic_ocp_write(struct r815 - } - } - -- byen = byteen_end | (byteen_end >> 4); -- ret = set_registers(tp, index, type | byen, 4, data); -- if (ret < 0) -- goto error1; -+ /* Set the last DWORD */ -+ if (byen != BYTE_EN_DWORD) -+ ret = set_registers(tp, index, type | byen, 4, data); - } - - error1: diff --git a/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch b/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch deleted file mode 100644 index bc70c5af02..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch +++ /dev/null @@ -1,129 +0,0 @@ -From e5c266a61186b462c388c53a3564c375e72f2244 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Wed, 26 Jul 2023 11:08:08 +0800 -Subject: [PATCH] r8152: set bp in bulk - -PLA_BP_0 ~ PLA_BP_15 (0xfc28 ~ 0xfc46) are continuous registers, so we -could combine the control transfers into one control transfer. - -Signed-off-by: Hayes Wang -Link: https://lore.kernel.org/r/20230726030808.9093-419-nic_swsd@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 75 ++++++++++++++--------------------------- - 1 file changed, 25 insertions(+), 50 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -3990,29 +3990,10 @@ static void rtl_reset_bmu(struct r8152 * - /* Clear the bp to stop the firmware before loading a new one */ - static void rtl_clear_bp(struct r8152 *tp, u16 type) - { -- switch (tp->version) { -- case RTL_VER_01: -- case RTL_VER_02: -- case RTL_VER_07: -- break; -- case RTL_VER_03: -- case RTL_VER_04: -- case RTL_VER_05: -- case RTL_VER_06: -- ocp_write_byte(tp, type, PLA_BP_EN, 0); -- break; -- case RTL_VER_14: -- ocp_write_word(tp, type, USB_BP2_EN, 0); -+ u16 bp[16] = {0}; -+ u16 bp_num; - -- ocp_write_word(tp, type, USB_BP_8, 0); -- ocp_write_word(tp, type, USB_BP_9, 0); -- ocp_write_word(tp, type, USB_BP_10, 0); -- ocp_write_word(tp, type, USB_BP_11, 0); -- ocp_write_word(tp, type, USB_BP_12, 0); -- ocp_write_word(tp, type, USB_BP_13, 0); -- ocp_write_word(tp, type, USB_BP_14, 0); -- ocp_write_word(tp, type, USB_BP_15, 0); -- break; -+ switch (tp->version) { - case RTL_VER_08: - case RTL_VER_09: - case RTL_VER_10: -@@ -4020,32 +4001,31 @@ static void rtl_clear_bp(struct r8152 *t - case RTL_VER_12: - case RTL_VER_13: - case RTL_VER_15: -- default: - if (type == MCU_TYPE_USB) { - ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); -- -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_10, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_11, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_12, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_13, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_14, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_15, 0); -- } else { -- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0); -+ bp_num = 16; -+ break; - } -+ fallthrough; -+ case RTL_VER_03: -+ case RTL_VER_04: -+ case RTL_VER_05: -+ case RTL_VER_06: -+ ocp_write_byte(tp, type, PLA_BP_EN, 0); -+ fallthrough; -+ case RTL_VER_01: -+ case RTL_VER_02: -+ case RTL_VER_07: -+ bp_num = 8; -+ break; -+ case RTL_VER_14: -+ default: -+ ocp_write_word(tp, type, USB_BP2_EN, 0); -+ bp_num = 16; - break; - } - -- ocp_write_word(tp, type, PLA_BP_0, 0); -- ocp_write_word(tp, type, PLA_BP_1, 0); -- ocp_write_word(tp, type, PLA_BP_2, 0); -- ocp_write_word(tp, type, PLA_BP_3, 0); -- ocp_write_word(tp, type, PLA_BP_4, 0); -- ocp_write_word(tp, type, PLA_BP_5, 0); -- ocp_write_word(tp, type, PLA_BP_6, 0); -- ocp_write_word(tp, type, PLA_BP_7, 0); -+ generic_ocp_write(tp, PLA_BP_0, BYTE_EN_DWORD, bp_num << 1, bp, type); - - /* wait 3 ms to make sure the firmware is stopped */ - usleep_range(3000, 6000); -@@ -5022,10 +5002,9 @@ static void rtl8152_fw_phy_nc_apply(stru - - static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) - { -- u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg; -+ u16 bp_en_addr, type, fw_ver_reg; - u32 length; - u8 *data; -- int i; - - switch (__le32_to_cpu(mac->blk_hdr.type)) { - case RTL_FW_PLA: -@@ -5067,12 +5046,8 @@ static void rtl8152_fw_mac_apply(struct - ocp_write_word(tp, type, __le16_to_cpu(mac->bp_ba_addr), - __le16_to_cpu(mac->bp_ba_value)); - -- bp_index = __le16_to_cpu(mac->bp_start); -- bp_num = __le16_to_cpu(mac->bp_num); -- for (i = 0; i < bp_num; i++) { -- ocp_write_word(tp, type, bp_index, __le16_to_cpu(mac->bp[i])); -- bp_index += 2; -- } -+ generic_ocp_write(tp, __le16_to_cpu(mac->bp_start), BYTE_EN_DWORD, -+ __le16_to_cpu(mac->bp_num) << 1, mac->bp, type); - - bp_en_addr = __le16_to_cpu(mac->bp_en_addr); - if (bp_en_addr) diff --git a/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch b/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch deleted file mode 100644 index d7fdcdb2c6..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch +++ /dev/null @@ -1,39 +0,0 @@ -From cf74eb5a5bc867258e7d0b0d1c3c4a60e1e3de2f Mon Sep 17 00:00:00 2001 -From: Jakub Kicinski -Date: Mon, 14 Aug 2023 08:35:21 -0700 -Subject: [PATCH] eth: r8152: try to use a normal budget - -Mario reports that loading r8152 on his system leads to a: - - netif_napi_add_weight() called with weight 256 - -warning getting printed. We don't have any solid data -on why such high budget was chosen, and it may cause -stalls in processing other softirqs and rt threads. -So try to switch back to the default (64) weight. - -If this slows down someone's system we should investigate -which part of stopping starting the NAPI poll in this -driver are expensive. - -Reported-by: Mario Limonciello -Link: https://lore.kernel.org/all/0bfd445a-81f7-f702-08b0-bd5a72095e49@amd.com/ -Acked-by: Hayes Wang -Link: https://lore.kernel.org/r/20230814153521.2697982-1-kuba@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -9784,8 +9784,7 @@ static int rtl8152_probe(struct usb_inte - - usb_set_intfdata(intf, tp); - -- netif_napi_add_weight(netdev, &tp->napi, r8152_poll, -- tp->support_2500full ? 256 : 64); -+ netif_napi_add(netdev, &tp->napi, r8152_poll); - - ret = register_netdev(netdev); - if (ret != 0) { diff --git a/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch b/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch deleted file mode 100644 index 8901767be5..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch +++ /dev/null @@ -1,398 +0,0 @@ -From d9962b0d42029bcb40fe3c38bce06d1870fa4df4 Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Fri, 20 Oct 2023 14:06:59 -0700 -Subject: [PATCH] r8152: Block future register access if register access fails - -Even though the functions to read/write registers can fail, most of -the places in the r8152 driver that read/write register values don't -check error codes. The lack of error code checking is problematic in -at least two ways. - -The first problem is that the r8152 driver often uses code patterns -similar to this: - x = read_register() - x = x | SOME_BIT; - write_register(x); - -...with the above pattern, if the read_register() fails and returns -garbage then we'll end up trying to write modified garbage back to the -Realtek adapter. If the write_register() succeeds that's bad. Note -that as of commit f53a7ad18959 ("r8152: Set memory to all 0xFFs on -failed reg reads") the "garbage" returned by read_register() will at -least be consistent garbage, but it is still garbage. - -It turns out that this problem is very serious. Writing garbage to -some of the hardware registers on the Ethernet adapter can put the -adapter in such a bad state that it needs to be power cycled (fully -unplugged and plugged in again) before it can enumerate again. - -The second problem is that the r8152 driver generally has functions -that are long sequences of register writes. Assuming everything will -be OK if a random register write fails in the middle isn't a great -assumption. - -One might wonder if the above two problems are real. You could ask if -we would really have a successful write after a failed read. It turns -out that the answer appears to be "yes, this can happen". In fact, -we've seen at least two distinct failure modes where this happens. - -On a sc7180-trogdor Chromebook if you drop into kdb for a while and -then resume, you can see: -1. We get a "Tx timeout" -2. The "Tx timeout" queues up a USB reset. -3. In rtl8152_pre_reset() we try to reinit the hardware. -4. The first several (2-9) register accesses fail with a timeout, then - things recover. - -The above test case was actually fixed by the patch ("r8152: Increase -USB control msg timeout to 5000ms as per spec") but at least shows -that we really can see successful calls after failed ones. - -On a different (AMD) based Chromebook with a particular adapter, we -found that during reboot tests we'd also sometimes get a transitory -failure. In this case we saw -EPIPE being returned sometimes. Retrying -worked, but retrying is not always safe for all register accesses -since reading/writing some registers might have side effects (like -registers that clear on read). - -Let's fully lock out all register access if a register access fails. -When we do this, we'll try to queue up a USB reset and try to unlock -register access after the reset. This is slightly tricker than it -sounds since the r8152 driver has an optimized reset sequence that -only works reliably after probe happens. In order to handle this, we -avoid the optimized reset if probe didn't finish. Instead, we simply -retry the probe routine in this case. - -When locking out access, we'll use the existing infrastructure that -the driver was using when it detected we were unplugged. This keeps us -from getting stuck in delay loops in some parts of the driver. - -Signed-off-by: Douglas Anderson -Reviewed-by: Grant Grundler -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 207 ++++++++++++++++++++++++++++++++++------ - 1 file changed, 176 insertions(+), 31 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -772,6 +772,9 @@ enum rtl8152_flags { - SCHEDULE_TASKLET, - GREEN_ETHERNET, - RX_EPROTO, -+ IN_PRE_RESET, -+ PROBED_WITH_NO_ERRORS, -+ PROBE_SHOULD_RETRY, - }; - - #define DEVICE_ID_LENOVO_USB_C_TRAVEL_HUB 0x721e -@@ -952,6 +955,8 @@ struct r8152 { - u8 version; - u8 duplex; - u8 autoneg; -+ -+ unsigned int reg_access_reset_count; - }; - - /** -@@ -1199,6 +1204,96 @@ static unsigned int agg_buf_sz = 16384; - - #define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc)) - -+/* If register access fails then we block access and issue a reset. If this -+ * happens too many times in a row without a successful access then we stop -+ * trying to reset and just leave access blocked. -+ */ -+#define REGISTER_ACCESS_MAX_RESETS 3 -+ -+static void rtl_set_inaccessible(struct r8152 *tp) -+{ -+ set_bit(RTL8152_INACCESSIBLE, &tp->flags); -+ smp_mb__after_atomic(); -+} -+ -+static void rtl_set_accessible(struct r8152 *tp) -+{ -+ clear_bit(RTL8152_INACCESSIBLE, &tp->flags); -+ smp_mb__after_atomic(); -+} -+ -+static -+int r8152_control_msg(struct r8152 *tp, unsigned int pipe, __u8 request, -+ __u8 requesttype, __u16 value, __u16 index, void *data, -+ __u16 size, const char *msg_tag) -+{ -+ struct usb_device *udev = tp->udev; -+ int ret; -+ -+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) -+ return -ENODEV; -+ -+ ret = usb_control_msg(udev, pipe, request, requesttype, -+ value, index, data, size, -+ USB_CTRL_GET_TIMEOUT); -+ -+ /* No need to issue a reset to report an error if the USB device got -+ * unplugged; just return immediately. -+ */ -+ if (ret == -ENODEV) -+ return ret; -+ -+ /* If the write was successful then we're done */ -+ if (ret >= 0) { -+ tp->reg_access_reset_count = 0; -+ return ret; -+ } -+ -+ dev_err(&udev->dev, -+ "Failed to %s %d bytes at %#06x/%#06x (%d)\n", -+ msg_tag, size, value, index, ret); -+ -+ /* Block all future register access until we reset. Much of the code -+ * in the driver doesn't check for errors. Notably, many parts of the -+ * driver do a read/modify/write of a register value without -+ * confirming that the read succeeded. Writing back modified garbage -+ * like this can fully wedge the adapter, requiring a power cycle. -+ */ -+ rtl_set_inaccessible(tp); -+ -+ /* If probe hasn't yet finished, then we'll request a retry of the -+ * whole probe routine if we get any control transfer errors. We -+ * never have to clear this bit since we free/reallocate the whole "tp" -+ * structure if we retry probe. -+ */ -+ if (!test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) { -+ set_bit(PROBE_SHOULD_RETRY, &tp->flags); -+ return ret; -+ } -+ -+ /* Failing to access registers in pre-reset is not surprising since we -+ * wouldn't be resetting if things were behaving normally. The register -+ * access we do in pre-reset isn't truly mandatory--we're just reusing -+ * the disable() function and trying to be nice by powering the -+ * adapter down before resetting it. Thus, if we're in pre-reset, -+ * we'll return right away and not try to queue up yet another reset. -+ * We know the post-reset is already coming. -+ */ -+ if (test_bit(IN_PRE_RESET, &tp->flags)) -+ return ret; -+ -+ if (tp->reg_access_reset_count < REGISTER_ACCESS_MAX_RESETS) { -+ usb_queue_reset_device(tp->intf); -+ tp->reg_access_reset_count++; -+ } else if (tp->reg_access_reset_count == REGISTER_ACCESS_MAX_RESETS) { -+ dev_err(&udev->dev, -+ "Tried to reset %d times; giving up.\n", -+ REGISTER_ACCESS_MAX_RESETS); -+ } -+ -+ return ret; -+} -+ - static - int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) - { -@@ -1209,9 +1304,10 @@ int get_registers(struct r8152 *tp, u16 - if (!tmp) - return -ENOMEM; - -- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_in, -- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -- value, index, tmp, size, USB_CTRL_GET_TIMEOUT); -+ ret = r8152_control_msg(tp, tp->pipe_ctrl_in, -+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -+ value, index, tmp, size, "read"); -+ - if (ret < 0) - memset(data, 0xff, size); - else -@@ -1232,9 +1328,9 @@ int set_registers(struct r8152 *tp, u16 - if (!tmp) - return -ENOMEM; - -- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_out, -- RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, -- value, index, tmp, size, USB_CTRL_SET_TIMEOUT); -+ ret = r8152_control_msg(tp, tp->pipe_ctrl_out, -+ RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, -+ value, index, tmp, size, "write"); - - kfree(tmp); - -@@ -1243,10 +1339,8 @@ int set_registers(struct r8152 *tp, u16 - - static void rtl_set_unplug(struct r8152 *tp) - { -- if (tp->udev->state == USB_STATE_NOTATTACHED) { -- set_bit(RTL8152_INACCESSIBLE, &tp->flags); -- smp_mb__after_atomic(); -- } -+ if (tp->udev->state == USB_STATE_NOTATTACHED) -+ rtl_set_inaccessible(tp); - } - - static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size, -@@ -8275,7 +8369,7 @@ static int rtl8152_pre_reset(struct usb_ - struct r8152 *tp = usb_get_intfdata(intf); - struct net_device *netdev; - -- if (!tp) -+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) - return 0; - - netdev = tp->netdev; -@@ -8290,7 +8384,9 @@ static int rtl8152_pre_reset(struct usb_ - napi_disable(&tp->napi); - if (netif_carrier_ok(netdev)) { - mutex_lock(&tp->control); -+ set_bit(IN_PRE_RESET, &tp->flags); - tp->rtl_ops.disable(tp); -+ clear_bit(IN_PRE_RESET, &tp->flags); - mutex_unlock(&tp->control); - } - -@@ -8303,9 +8399,11 @@ static int rtl8152_post_reset(struct usb - struct net_device *netdev; - struct sockaddr sa; - -- if (!tp) -+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) - return 0; - -+ rtl_set_accessible(tp); -+ - /* reset the MAC address in case of policy change */ - if (determine_ethernet_addr(tp, &sa) >= 0) { - rtnl_lock(); -@@ -9507,17 +9605,29 @@ static u8 __rtl_get_hw_ver(struct usb_de - __le32 *tmp; - u8 version; - int ret; -+ int i; - - tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) - return 0; - -- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), -- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -- PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), -- USB_CTRL_GET_TIMEOUT); -- if (ret > 0) -- ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK; -+ /* Retry up to 3 times in case there is a transitory error. We do this -+ * since retrying a read of the version is always safe and this -+ * function doesn't take advantage of r8152_control_msg(). -+ */ -+ for (i = 0; i < 3; i++) { -+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), -+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -+ PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), -+ USB_CTRL_GET_TIMEOUT); -+ if (ret > 0) { -+ ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK; -+ break; -+ } -+ } -+ -+ if (i != 0 && ret > 0) -+ dev_warn(&udev->dev, "Needed %d retries to read version\n", i); - - kfree(tmp); - -@@ -9616,25 +9726,14 @@ static bool rtl8152_supports_lenovo_macp - return 0; - } - --static int rtl8152_probe(struct usb_interface *intf, -- const struct usb_device_id *id) -+static int rtl8152_probe_once(struct usb_interface *intf, -+ const struct usb_device_id *id, u8 version) - { - struct usb_device *udev = interface_to_usbdev(intf); - struct r8152 *tp; - struct net_device *netdev; -- u8 version; - int ret; - -- if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) -- return -ENODEV; -- -- if (!rtl_check_vendor_ok(intf)) -- return -ENODEV; -- -- version = rtl8152_get_version(intf); -- if (version == RTL_VER_UNKNOWN) -- return -ENODEV; -- - usb_reset_device(udev); - netdev = alloc_etherdev(sizeof(struct r8152)); - if (!netdev) { -@@ -9797,10 +9896,20 @@ static int rtl8152_probe(struct usb_inte - else - device_set_wakeup_enable(&udev->dev, false); - -+ /* If we saw a control transfer error while probing then we may -+ * want to try probe() again. Consider this an error. -+ */ -+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags)) -+ goto out2; -+ -+ set_bit(PROBED_WITH_NO_ERRORS, &tp->flags); - netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION); - - return 0; - -+out2: -+ unregister_netdev(netdev); -+ - out1: - tasklet_kill(&tp->tx_tl); - cancel_delayed_work_sync(&tp->hw_phy_work); -@@ -9809,10 +9918,46 @@ out1: - rtl8152_release_firmware(tp); - usb_set_intfdata(intf, NULL); - out: -+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags)) -+ ret = -EAGAIN; -+ - free_netdev(netdev); - return ret; - } - -+#define RTL8152_PROBE_TRIES 3 -+ -+static int rtl8152_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ u8 version; -+ int ret; -+ int i; -+ -+ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) -+ return -ENODEV; -+ -+ if (!rtl_check_vendor_ok(intf)) -+ return -ENODEV; -+ -+ version = rtl8152_get_version(intf); -+ if (version == RTL_VER_UNKNOWN) -+ return -ENODEV; -+ -+ for (i = 0; i < RTL8152_PROBE_TRIES; i++) { -+ ret = rtl8152_probe_once(intf, id, version); -+ if (ret != -EAGAIN) -+ break; -+ } -+ if (ret == -EAGAIN) { -+ dev_err(&intf->dev, -+ "r8152 failed probe after %d tries; giving up\n", i); -+ return -ENODEV; -+ } -+ -+ return ret; -+} -+ - static void rtl8152_disconnect(struct usb_interface *intf) - { - struct r8152 *tp = usb_get_intfdata(intf); diff --git a/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch b/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch deleted file mode 100644 index 7bbd1be820..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 66eee612a1ba39f9a76a9ace4a34d012044767fb Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Tue, 26 Sep 2023 19:17:13 +0800 -Subject: [PATCH] r8152: break the loop when the budget is exhausted - -[ Upstream commit 2cf51f931797d9a47e75d999d0993a68cbd2a560 ] - -A bulk transfer of the USB may contain many packets. And, the total -number of the packets in the bulk transfer may be more than budget. - -Originally, only budget packets would be handled by napi_gro_receive(), -and the other packets would be queued in the driver for next schedule. - -This patch would break the loop about getting next bulk transfer, when -the budget is exhausted. That is, only the current bulk transfer would -be handled, and the other bulk transfers would be queued for next -schedule. Besides, the packets which are more than the budget in the -current bulk trasnfer would be still queued in the driver, as the -original method. - -In addition, a bulk transfer wouldn't contain more than 400 packets, so -the check of queue length is unnecessary. Therefore, I replace it with -WARN_ON_ONCE(). - -Fixes: cf74eb5a5bc8 ("eth: r8152: try to use a normal budget") -Signed-off-by: Hayes Wang -Link: https://lore.kernel.org/r/20230926111714.9448-433-nic_swsd@realtek.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Sasha Levin ---- - drivers/net/usb/r8152.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -2542,7 +2542,7 @@ static int rx_bottom(struct r8152 *tp, i - } - } - -- if (list_empty(&tp->rx_done)) -+ if (list_empty(&tp->rx_done) || work_done >= budget) - goto out1; - - clear_bit(RX_EPROTO, &tp->flags); -@@ -2558,6 +2558,15 @@ static int rx_bottom(struct r8152 *tp, i - struct urb *urb; - u8 *rx_data; - -+ /* A bulk transfer of USB may contain may packets, so the -+ * total packets may more than the budget. Deal with all -+ * packets in current bulk transfer, and stop to handle the -+ * next bulk transfer until next schedule, if budget is -+ * exhausted. -+ */ -+ if (work_done >= budget) -+ break; -+ - list_del_init(cursor); - - agg = list_entry(cursor, struct rx_agg, list); -@@ -2577,9 +2586,7 @@ static int rx_bottom(struct r8152 *tp, i - unsigned int pkt_len, rx_frag_head_sz; - struct sk_buff *skb; - -- /* limit the skb numbers for rx_queue */ -- if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000)) -- break; -+ WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000); - - pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; - if (pkt_len < ETH_ZLEN) -@@ -2657,9 +2664,10 @@ submit: - } - } - -+ /* Splice the remained list back to rx_done for next schedule */ - if (!list_empty(&rx_queue)) { - spin_lock_irqsave(&tp->rx_lock, flags); -- list_splice_tail(&rx_queue, &tp->rx_done); -+ list_splice(&rx_queue, &tp->rx_done); - spin_unlock_irqrestore(&tp->rx_lock, flags); - } - diff --git a/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch b/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch deleted file mode 100644 index c858152067..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 1b0fce8c8e69485e49a7d34aac3d4c2a2aa15d62 Mon Sep 17 00:00:00 2001 -From: Davide Tronchin -Date: Thu, 29 Jun 2023 12:37:36 +0200 -Subject: [PATCH] net: usb: cdc_ether: add u-blox 0x1313 composition. - -Add CDC-ECM support for LARA-R6 01B. - -The new LARA-R6 product variant identified by the "01B" string can be -configured (by AT interface) in three different USB modes: -* Default mode (Vendor ID: 0x1546 Product ID: 0x1311) with 4 serial -interfaces -* RmNet mode (Vendor ID: 0x1546 Product ID: 0x1312) with 4 serial -interfaces and 1 RmNet virtual network interface -* CDC-ECM mode (Vendor ID: 0x1546 Product ID: 0x1313) with 4 serial -interface and 1 CDC-ECM virtual network interface -The first 4 interfaces of all the 3 configurations (default, RmNet, ECM) -are the same. - -In CDC-ECM mode LARA-R6 01B exposes the following interfaces: -If 0: Diagnostic -If 1: AT parser -If 2: AT parser -If 3: AT parset/alternative functions -If 4: CDC-ECM interface - -Signed-off-by: Davide Tronchin -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/usb/cdc_ether.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/net/usb/cdc_ether.c -+++ b/drivers/net/usb/cdc_ether.c -@@ -879,6 +879,12 @@ static const struct usb_device_id produc - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&wwan_info, - }, { -+ /* U-blox LARA-R6 01B */ -+ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM, -+ USB_CDC_SUBCLASS_ETHERNET, -+ USB_CDC_PROTO_NONE), -+ .driver_info = (unsigned long)&wwan_info, -+}, { - /* ZTE modules */ - USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, diff --git a/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch b/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch deleted file mode 100644 index 592111fb95..0000000000 --- a/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 156a5bb89ca6f3edd2be0bfd0de15e575442927e Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Tue, 3 Jan 2023 15:12:47 +0200 -Subject: [PATCH] leds: Move led_init_default_state_get() to the global header - -There are users inside and outside LED framework that have implemented -a local copy of led_init_default_state_get(). In order to deduplicate -that, as the first step move the declaration from LED header to the -global one. - -Signed-off-by: Andy Shevchenko -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230103131256.33894-3-andriy.shevchenko@linux.intel.com ---- - drivers/leds/leds.h | 1 - - include/linux/leds.h | 2 ++ - 2 files changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/leds/leds.h -+++ b/drivers/leds/leds.h -@@ -27,7 +27,6 @@ ssize_t led_trigger_read(struct file *fi - ssize_t led_trigger_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t pos, size_t count); --enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); - - extern struct rw_semaphore leds_list_lock; - extern struct list_head leds_list; ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -63,6 +63,8 @@ struct led_init_data { - bool devname_mandatory; - }; - -+enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); -+ - struct led_hw_trigger_type { - int dummy; - }; diff --git a/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch b/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch deleted file mode 100644 index f6a025fa12..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 3e8b4d6277fd19d98c817576954dd6a4ff3caa2b Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 17 Apr 2023 17:17:23 +0200 -Subject: [PATCH 1/9] net: dsa: qca8k: move qca8k_port_to_phy() to header - -Move qca8k_port_to_phy() to qca8k header as it's useful for future -reference in Switch LEDs module since the same logic is applied to get -the right index of the switch port. -Make it inline as it's simple function that just decrease the port. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Reviewed-by: Michal Kubiak -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 15 --------------- - drivers/net/dsa/qca/qca8k.h | 14 ++++++++++++++ - 2 files changed, 14 insertions(+), 15 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -789,21 +789,6 @@ err_clear_skb: - return ret; - } - --static u32 --qca8k_port_to_phy(int port) --{ -- /* From Andrew Lunn: -- * Port 0 has no internal phy. -- * Port 1 has an internal PHY at MDIO address 0. -- * Port 2 has an internal PHY at MDIO address 1. -- * ... -- * Port 5 has an internal PHY at MDIO address 4. -- * Port 6 has no internal PHY. -- */ -- -- return port - 1; --} -- - static int - qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) - { ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -421,6 +421,20 @@ struct qca8k_fdb { - u8 mac[6]; - }; - -+static inline u32 qca8k_port_to_phy(int port) -+{ -+ /* From Andrew Lunn: -+ * Port 0 has no internal phy. -+ * Port 1 has an internal PHY at MDIO address 0. -+ * Port 2 has an internal PHY at MDIO address 1. -+ * ... -+ * Port 5 has an internal PHY at MDIO address 4. -+ * Port 6 has no internal PHY. -+ */ -+ -+ return port - 1; -+} -+ - /* Common setup function */ - extern const struct qca8k_mib_desc ar8327_mib[]; - extern const struct regmap_access_table qca8k_readable_table; diff --git a/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch b/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch deleted file mode 100644 index 409fe9c7a1..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch +++ /dev/null @@ -1,435 +0,0 @@ -From 1e264f9d2918b5737023c44a23ae04def1095210 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 17 Apr 2023 17:17:24 +0200 -Subject: [PATCH 2/9] net: dsa: qca8k: add LEDs basic support - -Add LEDs basic support for qca8k Switch Family by adding basic -brightness_set() support. - -Since these LEDs refelect port status, the default label is set to -":port". DT binding should describe the color and function of the -LEDs using standard LEDs api. -Each LED always have the device name as prefix. The device name is -composed from the mii bus id and the PHY addr resulting in example -names like: -- qca8k-0.0:00:amber:lan -- qca8k-0.0:00:white:lan -- qca8k-0.0:01:amber:lan -- qca8k-0.0:01:white:lan - -These LEDs supports only blocking variant of the brightness_set() -function since they can sleep during access of the switch leds to set -the brightness. - -While at it add to the qca8k header file each mode defined by the Switch -Documentation for future use. - -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/Kconfig | 8 ++ - drivers/net/dsa/qca/Makefile | 3 + - drivers/net/dsa/qca/qca8k-8xxx.c | 5 + - drivers/net/dsa/qca/qca8k-leds.c | 239 +++++++++++++++++++++++++++++++ - drivers/net/dsa/qca/qca8k.h | 60 ++++++++ - drivers/net/dsa/qca/qca8k_leds.h | 16 +++ - 6 files changed, 331 insertions(+) - create mode 100644 drivers/net/dsa/qca/qca8k-leds.c - create mode 100644 drivers/net/dsa/qca/qca8k_leds.h - ---- a/drivers/net/dsa/qca/Kconfig -+++ b/drivers/net/dsa/qca/Kconfig -@@ -15,3 +15,11 @@ config NET_DSA_QCA8K - help - This enables support for the Qualcomm Atheros QCA8K Ethernet - switch chips. -+ -+config NET_DSA_QCA8K_LEDS_SUPPORT -+ bool "Qualcomm Atheros QCA8K Ethernet switch family LEDs support" -+ depends on NET_DSA_QCA8K -+ depends on LEDS_CLASS -+ help -+ This enabled support for LEDs present on the Qualcomm Atheros -+ QCA8K Ethernet switch chips. ---- a/drivers/net/dsa/qca/Makefile -+++ b/drivers/net/dsa/qca/Makefile -@@ -2,3 +2,6 @@ - obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o - obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o - qca8k-y += qca8k-common.o qca8k-8xxx.o -+ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT -+qca8k-y += qca8k-leds.o -+endif ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -22,6 +22,7 @@ - #include - - #include "qca8k.h" -+#include "qca8k_leds.h" - - static void - qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) -@@ -1851,6 +1852,10 @@ qca8k_setup(struct dsa_switch *ds) - if (ret) - return ret; - -+ ret = qca8k_setup_led_ctrl(priv); -+ if (ret) -+ return ret; -+ - qca8k_setup_pcs(priv, &priv->pcs_port_0, 0); - qca8k_setup_pcs(priv, &priv->pcs_port_6, 6); - ---- /dev/null -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -0,0 +1,239 @@ -+// SPDX-License-Identifier: GPL-2.0 -+#include -+#include -+ -+#include "qca8k.h" -+#include "qca8k_leds.h" -+ -+static int -+qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) -+{ -+ switch (port_num) { -+ case 0: -+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); -+ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; -+ break; -+ case 1: -+ case 2: -+ case 3: -+ /* Port 123 are controlled on a different reg */ -+ reg_info->reg = QCA8K_LED_CTRL3_REG; -+ reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num); -+ break; -+ case 4: -+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); -+ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int -+qca8k_led_brightness_set(struct qca8k_led *led, -+ enum led_brightness brightness) -+{ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 mask, val; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ val = QCA8K_LED_ALWAYS_OFF; -+ if (brightness) -+ val = QCA8K_LED_ALWAYS_ON; -+ -+ /* HW regs to control brightness is special and port 1-2-3 -+ * are placed in a different reg. -+ * -+ * To control port 0 brightness: -+ * - the 2 bit (15, 14) of: -+ * - QCA8K_LED_CTRL0_REG for led1 -+ * - QCA8K_LED_CTRL1_REG for led2 -+ * - QCA8K_LED_CTRL2_REG for led3 -+ * -+ * To control port 4: -+ * - the 2 bit (31, 30) of: -+ * - QCA8K_LED_CTRL0_REG for led1 -+ * - QCA8K_LED_CTRL1_REG for led2 -+ * - QCA8K_LED_CTRL2_REG for led3 -+ * -+ * To control port 1: -+ * - the 2 bit at (9, 8) of QCA8K_LED_CTRL3_REG are used for led1 -+ * - the 2 bit at (11, 10) of QCA8K_LED_CTRL3_REG are used for led2 -+ * - the 2 bit at (13, 12) of QCA8K_LED_CTRL3_REG are used for led3 -+ * -+ * To control port 2: -+ * - the 2 bit at (15, 14) of QCA8K_LED_CTRL3_REG are used for led1 -+ * - the 2 bit at (17, 16) of QCA8K_LED_CTRL3_REG are used for led2 -+ * - the 2 bit at (19, 18) of QCA8K_LED_CTRL3_REG are used for led3 -+ * -+ * To control port 3: -+ * - the 2 bit at (21, 20) of QCA8K_LED_CTRL3_REG are used for led1 -+ * - the 2 bit at (23, 22) of QCA8K_LED_CTRL3_REG are used for led2 -+ * - the 2 bit at (25, 24) of QCA8K_LED_CTRL3_REG are used for led3 -+ * -+ * To abstract this and have less code, we use the port and led numm -+ * to calculate the shift and the correct reg due to this problem of -+ * not having a 1:1 map of LED with the regs. -+ */ -+ if (led->port_num == 0 || led->port_num == 4) { -+ mask = QCA8K_LED_PATTERN_EN_MASK; -+ val <<= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ return regmap_update_bits(priv->regmap, reg_info.reg, -+ mask << reg_info.shift, -+ val << reg_info.shift); -+} -+ -+static int -+qca8k_cled_brightness_set_blocking(struct led_classdev *ldev, -+ enum led_brightness brightness) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ -+ return qca8k_led_brightness_set(led, brightness); -+} -+ -+static enum led_brightness -+qca8k_led_brightness_get(struct qca8k_led *led) -+{ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 val; -+ int ret; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ ret = regmap_read(priv->regmap, reg_info.reg, &val); -+ if (ret) -+ return 0; -+ -+ val >>= reg_info.shift; -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ val &= QCA8K_LED_PATTERN_EN_MASK; -+ val >>= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ /* Assume brightness ON only when the LED is set to always ON */ -+ return val == QCA8K_LED_ALWAYS_ON; -+} -+ -+static int -+qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) -+{ -+ struct fwnode_handle *led = NULL, *leds = NULL; -+ struct led_init_data init_data = { }; -+ struct dsa_switch *ds = priv->ds; -+ enum led_default_state state; -+ struct qca8k_led *port_led; -+ int led_num, led_index; -+ int ret; -+ -+ leds = fwnode_get_named_child_node(port, "leds"); -+ if (!leds) { -+ dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n", -+ port_num); -+ return 0; -+ } -+ -+ fwnode_for_each_child_node(leds, led) { -+ /* Reg represent the led number of the port. -+ * Each port can have at most 3 leds attached -+ * Commonly: -+ * 1. is gigabit led -+ * 2. is mbit led -+ * 3. additional status led -+ */ -+ if (fwnode_property_read_u32(led, "reg", &led_num)) -+ continue; -+ -+ if (led_num >= QCA8K_LED_PORT_COUNT) { -+ dev_warn(priv->dev, "Invalid LED reg %d defined for port %d", -+ led_num, port_num); -+ continue; -+ } -+ -+ led_index = QCA8K_LED_PORT_INDEX(port_num, led_num); -+ -+ port_led = &priv->ports_led[led_index]; -+ port_led->port_num = port_num; -+ port_led->led_num = led_num; -+ port_led->priv = priv; -+ -+ state = led_init_default_state_get(led); -+ switch (state) { -+ case LEDS_DEFSTATE_ON: -+ port_led->cdev.brightness = 1; -+ qca8k_led_brightness_set(port_led, 1); -+ break; -+ case LEDS_DEFSTATE_KEEP: -+ port_led->cdev.brightness = -+ qca8k_led_brightness_get(port_led); -+ break; -+ default: -+ port_led->cdev.brightness = 0; -+ qca8k_led_brightness_set(port_led, 0); -+ } -+ -+ port_led->cdev.max_brightness = 1; -+ port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; -+ init_data.default_label = ":port"; -+ init_data.fwnode = led; -+ init_data.devname_mandatory = true; -+ init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d", ds->slave_mii_bus->id, -+ port_num); -+ if (!init_data.devicename) -+ return -ENOMEM; -+ -+ ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data); -+ if (ret) -+ dev_warn(priv->dev, "Failed to init LED %d for port %d", led_num, port_num); -+ -+ kfree(init_data.devicename); -+ } -+ -+ return 0; -+} -+ -+int -+qca8k_setup_led_ctrl(struct qca8k_priv *priv) -+{ -+ struct fwnode_handle *ports, *port; -+ int port_num; -+ int ret; -+ -+ ports = device_get_named_child_node(priv->dev, "ports"); -+ if (!ports) { -+ dev_info(priv->dev, "No ports node specified in device tree!"); -+ return 0; -+ } -+ -+ fwnode_for_each_child_node(ports, port) { -+ if (fwnode_property_read_u32(port, "reg", &port_num)) -+ continue; -+ -+ /* Skip checking for CPU port 0 and CPU port 6 as not supported */ -+ if (port_num == 0 || port_num == 6) -+ continue; -+ -+ /* Each port can have at most 3 different leds attached. -+ * Switch port starts from 0 to 6, but port 0 and 6 are CPU -+ * port. The port index needs to be decreased by one to identify -+ * the correct port for LED setup. -+ */ -+ ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num)); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - - #define QCA8K_ETHERNET_MDIO_PRIORITY 7 -@@ -85,6 +86,51 @@ - #define QCA8K_MDIO_MASTER_DATA(x) FIELD_PREP(QCA8K_MDIO_MASTER_DATA_MASK, x) - #define QCA8K_MDIO_MASTER_MAX_PORTS 5 - #define QCA8K_MDIO_MASTER_MAX_REG 32 -+ -+/* LED control register */ -+#define QCA8K_LED_PORT_COUNT 3 -+#define QCA8K_LED_COUNT ((QCA8K_NUM_PORTS - QCA8K_NUM_CPU_PORTS) * QCA8K_LED_PORT_COUNT) -+#define QCA8K_LED_RULE_COUNT 6 -+#define QCA8K_LED_RULE_MAX 11 -+#define QCA8K_LED_PORT_INDEX(_phy, _led) (((_phy) * QCA8K_LED_PORT_COUNT) + (_led)) -+ -+#define QCA8K_LED_PHY123_PATTERN_EN_SHIFT(_phy, _led) ((((_phy) - 1) * 6) + 8 + (2 * (_led))) -+#define QCA8K_LED_PHY123_PATTERN_EN_MASK GENMASK(1, 0) -+ -+#define QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT 0 -+#define QCA8K_LED_PHY4_CONTROL_RULE_SHIFT 16 -+ -+#define QCA8K_LED_CTRL_REG(_i) (0x050 + (_i) * 4) -+#define QCA8K_LED_CTRL0_REG 0x50 -+#define QCA8K_LED_CTRL1_REG 0x54 -+#define QCA8K_LED_CTRL2_REG 0x58 -+#define QCA8K_LED_CTRL3_REG 0x5C -+#define QCA8K_LED_CTRL_SHIFT(_i) (((_i) % 2) * 16) -+#define QCA8K_LED_CTRL_MASK GENMASK(15, 0) -+#define QCA8K_LED_RULE_MASK GENMASK(13, 0) -+#define QCA8K_LED_BLINK_FREQ_MASK GENMASK(1, 0) -+#define QCA8K_LED_BLINK_FREQ_SHITF 0 -+#define QCA8K_LED_BLINK_2HZ 0 -+#define QCA8K_LED_BLINK_4HZ 1 -+#define QCA8K_LED_BLINK_8HZ 2 -+#define QCA8K_LED_BLINK_AUTO 3 -+#define QCA8K_LED_LINKUP_OVER_MASK BIT(2) -+#define QCA8K_LED_TX_BLINK_MASK BIT(4) -+#define QCA8K_LED_RX_BLINK_MASK BIT(5) -+#define QCA8K_LED_COL_BLINK_MASK BIT(7) -+#define QCA8K_LED_LINK_10M_EN_MASK BIT(8) -+#define QCA8K_LED_LINK_100M_EN_MASK BIT(9) -+#define QCA8K_LED_LINK_1000M_EN_MASK BIT(10) -+#define QCA8K_LED_POWER_ON_LIGHT_MASK BIT(11) -+#define QCA8K_LED_HALF_DUPLEX_MASK BIT(12) -+#define QCA8K_LED_FULL_DUPLEX_MASK BIT(13) -+#define QCA8K_LED_PATTERN_EN_MASK GENMASK(15, 14) -+#define QCA8K_LED_PATTERN_EN_SHIFT 14 -+#define QCA8K_LED_ALWAYS_OFF 0 -+#define QCA8K_LED_ALWAYS_BLINK_4HZ 1 -+#define QCA8K_LED_ALWAYS_ON 2 -+#define QCA8K_LED_RULE_CONTROLLED 3 -+ - #define QCA8K_GOL_MAC_ADDR0 0x60 - #define QCA8K_GOL_MAC_ADDR1 0x64 - #define QCA8K_MAX_FRAME_SIZE 0x78 -@@ -382,6 +428,19 @@ struct qca8k_pcs { - int port; - }; - -+struct qca8k_led_pattern_en { -+ u32 reg; -+ u8 shift; -+}; -+ -+struct qca8k_led { -+ u8 port_num; -+ u8 led_num; -+ u16 old_rule; -+ struct qca8k_priv *priv; -+ struct led_classdev cdev; -+}; -+ - struct qca8k_priv { - u8 switch_id; - u8 switch_revision; -@@ -406,6 +465,7 @@ struct qca8k_priv { - struct qca8k_pcs pcs_port_0; - struct qca8k_pcs pcs_port_6; - const struct qca8k_match_data *info; -+ struct qca8k_led ports_led[QCA8K_LED_COUNT]; - }; - - struct qca8k_mib_desc { ---- /dev/null -+++ b/drivers/net/dsa/qca/qca8k_leds.h -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#ifndef __QCA8K_LEDS_H -+#define __QCA8K_LEDS_H -+ -+/* Leds Support function */ -+#ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT -+int qca8k_setup_led_ctrl(struct qca8k_priv *priv); -+#else -+static inline int qca8k_setup_led_ctrl(struct qca8k_priv *priv) -+{ -+ return 0; -+} -+#endif -+ -+#endif /* __QCA8K_LEDS_H */ diff --git a/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch b/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch deleted file mode 100644 index 231c4156df..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 91acadcc6e599dfc62717abcdad58a459cfb1684 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 17 Apr 2023 17:17:25 +0200 -Subject: [PATCH 3/9] net: dsa: qca8k: add LEDs blink_set() support - -Add LEDs blink_set() support to qca8k Switch Family. -These LEDs support hw accellerated blinking at a fixed rate -of 4Hz. - -Reject any other value since not supported by the LEDs switch. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Acked-by: Pavel Machek -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-leds.c | 38 ++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -128,6 +128,43 @@ qca8k_led_brightness_get(struct qca8k_le - } - - static int -+qca8k_cled_blink_set(struct led_classdev *ldev, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ; -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ -+ if (*delay_on == 0 && *delay_off == 0) { -+ *delay_on = 125; -+ *delay_off = 125; -+ } -+ -+ if (*delay_on != 125 || *delay_off != 125) { -+ /* The hardware only supports blinking at 4Hz. Fall back -+ * to software implementation in other cases. -+ */ -+ return -EINVAL; -+ } -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ mask = QCA8K_LED_PATTERN_EN_MASK; -+ val <<= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, -+ val << reg_info.shift); -+ -+ return 0; -+} -+ -+static int - qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) - { - struct fwnode_handle *led = NULL, *leds = NULL; -@@ -186,6 +223,7 @@ qca8k_parse_port_leds(struct qca8k_priv - - port_led->cdev.max_brightness = 1; - port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; -+ port_led->cdev.blink_set = qca8k_cled_blink_set; - init_data.default_label = ":port"; - init_data.fwnode = led; - init_data.devname_mandatory = true; diff --git a/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch b/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch deleted file mode 100644 index bc905b4468..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch +++ /dev/null @@ -1,59 +0,0 @@ -From e5029edd53937a29801ef507cee12e657ff31ea9 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:26 +0200 -Subject: [PATCH 4/9] leds: Provide stubs for when CLASS_LED & NEW_LEDS are - disabled - -Provide stubs for devm_led_classdev_register_ext() and -led_init_default_state_get() so that LED drivers embedded within other -drivers such as PHYs and Ethernet switches still build when LEDS_CLASS -or NEW_LEDS are disabled. This also helps with Kconfig dependencies, -which are somewhat hairy for phylib and mdio and only get worse when -adding a dependency on LED_CLASS. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - include/linux/leds.h | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -63,7 +63,15 @@ struct led_init_data { - bool devname_mandatory; - }; - -+#if IS_ENABLED(CONFIG_NEW_LEDS) - enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); -+#else -+static inline enum led_default_state -+led_init_default_state_get(struct fwnode_handle *fwnode) -+{ -+ return LEDS_DEFSTATE_OFF; -+} -+#endif - - struct led_hw_trigger_type { - int dummy; -@@ -198,9 +206,19 @@ static inline int led_classdev_register( - return led_classdev_register_ext(parent, led_cdev, NULL); - } - -+#if IS_ENABLED(CONFIG_LEDS_CLASS) - int devm_led_classdev_register_ext(struct device *parent, - struct led_classdev *led_cdev, - struct led_init_data *init_data); -+#else -+static inline int -+devm_led_classdev_register_ext(struct device *parent, -+ struct led_classdev *led_cdev, -+ struct led_init_data *init_data) -+{ -+ return 0; -+} -+#endif - - static inline int devm_led_classdev_register(struct device *parent, - struct led_classdev *led_cdev) diff --git a/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch deleted file mode 100644 index 0d2c0bcd83..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 01e5b728e9e43ae444e0369695a5f72209906464 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:27 +0200 -Subject: [PATCH 5/9] net: phy: Add a binding for PHY LEDs - -Define common binding parsing for all PHY drivers with LEDs using -phylib. Parse the DT as part of the phy_probe and add LEDs to the -linux LED class infrastructure. For the moment, provide a dummy -brightness function, which will later be replaced with a call into the -PHY driver. This allows testing since the LED core might otherwise -reject an LED whose brightness cannot be set. - -Add a dependency on LED_CLASS. It either needs to be built in, or not -enabled, since a modular build can result in linker errors. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 1 + - drivers/net/phy/phy_device.c | 76 ++++++++++++++++++++++++++++++++++++ - include/linux/phy.h | 16 ++++++++ - 3 files changed, 93 insertions(+) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -18,6 +18,7 @@ menuconfig PHYLIB - depends on NETDEVICES - select MDIO_DEVICE - select MDIO_DEVRES -+ depends on LEDS_CLASS || LEDS_CLASS=n - help - Ethernet controllers are usually attached to PHY - devices. This option provides infrastructure for ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -19,10 +19,12 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -642,6 +644,7 @@ struct phy_device *phy_device_create(str - device_initialize(&mdiodev->dev); - - dev->state = PHY_DOWN; -+ INIT_LIST_HEAD(&dev->leds); - - mutex_init(&dev->lock); - INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); -@@ -3035,6 +3038,74 @@ static bool phy_drv_supports_irq(struct - return phydrv->config_intr && phydrv->handle_interrupt; - } - -+/* Dummy implementation until calls into PHY driver are added */ -+static int phy_led_set_brightness(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ return 0; -+} -+ -+static int of_phy_led(struct phy_device *phydev, -+ struct device_node *led) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct led_init_data init_data = {}; -+ struct led_classdev *cdev; -+ struct phy_led *phyled; -+ int err; -+ -+ phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL); -+ if (!phyled) -+ return -ENOMEM; -+ -+ cdev = &phyled->led_cdev; -+ -+ err = of_property_read_u8(led, "reg", &phyled->index); -+ if (err) -+ return err; -+ -+ cdev->brightness_set_blocking = phy_led_set_brightness; -+ cdev->max_brightness = 1; -+ init_data.devicename = dev_name(&phydev->mdio.dev); -+ init_data.fwnode = of_fwnode_handle(led); -+ init_data.devname_mandatory = true; -+ -+ err = devm_led_classdev_register_ext(dev, cdev, &init_data); -+ if (err) -+ return err; -+ -+ list_add(&phyled->list, &phydev->leds); -+ -+ return 0; -+} -+ -+static int of_phy_leds(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ struct device_node *leds, *led; -+ int err; -+ -+ if (!IS_ENABLED(CONFIG_OF_MDIO)) -+ return 0; -+ -+ if (!node) -+ return 0; -+ -+ leds = of_get_child_by_name(node, "leds"); -+ if (!leds) -+ return 0; -+ -+ for_each_available_child_of_node(leds, led) { -+ err = of_phy_led(phydev, led); -+ if (err) { -+ of_node_put(led); -+ return err; -+ } -+ } -+ -+ return 0; -+} -+ - /** - * fwnode_mdio_find_device - Given a fwnode, find the mdio_device - * @fwnode: pointer to the mdio_device's fwnode -@@ -3213,6 +3284,11 @@ static int phy_probe(struct device *dev) - /* Set the state to READY by default */ - phydev->state = PHY_READY; - -+ /* Get the LEDs from the device tree, and instantiate standard -+ * LEDs for them. -+ */ -+ err = of_phy_leds(phydev); -+ - out: - /* Re-assert the reset signal on error */ - if (err) ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -606,6 +607,7 @@ struct macsec_ops; - * @phy_num_led_triggers: Number of triggers in @phy_led_triggers - * @led_link_trigger: LED trigger for link up/down - * @last_triggered: last LED trigger for link speed -+ * @leds: list of PHY LED structures - * @master_slave_set: User requested master/slave configuration - * @master_slave_get: Current master/slave advertisement - * @master_slave_state: Current master/slave configuration -@@ -698,6 +700,7 @@ struct phy_device { - - struct phy_led_trigger *led_link_trigger; - #endif -+ struct list_head leds; - - /* - * Interrupt number for this PHY -@@ -772,6 +775,19 @@ struct phy_tdr_config { - #define PHY_PAIR_ALL -1 - - /** -+ * struct phy_led: An LED driven by the PHY -+ * -+ * @list: List of LEDs -+ * @led_cdev: Standard LED class structure -+ * @index: Number of the LED -+ */ -+struct phy_led { -+ struct list_head list; -+ struct led_classdev led_cdev; -+ u8 index; -+}; -+ -+/** - * struct phy_driver - Driver structure for a particular PHY type - * - * @mdiodrv: Data common to all MDIO devices diff --git a/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch deleted file mode 100644 index 4873c40a77..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 684818189b04b095b34964ed4a3ea5249a840eab Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:28 +0200 -Subject: [PATCH 6/9] net: phy: phy_device: Call into the PHY driver to set LED - brightness - -Linux LEDs can be software controlled via the brightness file in /sys. -LED drivers need to implement a brightness_set function which the core -will call. Implement an intermediary in phy_device, which will call -into the phy driver if it implements the necessary function. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 15 ++++++++++++--- - include/linux/phy.h | 13 +++++++++++++ - 2 files changed, 25 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3038,11 +3038,18 @@ static bool phy_drv_supports_irq(struct - return phydrv->config_intr && phydrv->handle_interrupt; - } - --/* Dummy implementation until calls into PHY driver are added */ - static int phy_led_set_brightness(struct led_classdev *led_cdev, - enum led_brightness value) - { -- return 0; -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_brightness_set(phydev, phyled->index, value); -+ mutex_unlock(&phydev->lock); -+ -+ return err; - } - - static int of_phy_led(struct phy_device *phydev, -@@ -3059,12 +3066,14 @@ static int of_phy_led(struct phy_device - return -ENOMEM; - - cdev = &phyled->led_cdev; -+ phyled->phydev = phydev; - - err = of_property_read_u8(led, "reg", &phyled->index); - if (err) - return err; - -- cdev->brightness_set_blocking = phy_led_set_brightness; -+ if (phydev->drv->led_brightness_set) -+ cdev->brightness_set_blocking = phy_led_set_brightness; - cdev->max_brightness = 1; - init_data.devicename = dev_name(&phydev->mdio.dev); - init_data.fwnode = of_fwnode_handle(led); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -778,15 +778,19 @@ struct phy_tdr_config { - * struct phy_led: An LED driven by the PHY - * - * @list: List of LEDs -+ * @phydev: PHY this LED is attached to - * @led_cdev: Standard LED class structure - * @index: Number of the LED - */ - struct phy_led { - struct list_head list; -+ struct phy_device *phydev; - struct led_classdev led_cdev; - u8 index; - }; - -+#define to_phy_led(d) container_of(d, struct phy_led, led_cdev) -+ - /** - * struct phy_driver - Driver structure for a particular PHY type - * -@@ -1001,6 +1005,15 @@ struct phy_driver { - int (*get_sqi)(struct phy_device *dev); - /** @get_sqi_max: Get the maximum signal quality indication */ - int (*get_sqi_max)(struct phy_device *dev); -+ -+ /** -+ * @led_brightness_set: Set a PHY LED brightness. Index -+ * indicates which of the PHYs led should be set. Value -+ * follows the standard LED class meaning, e.g. LED_OFF, -+ * LED_HALF, LED_FULL. -+ */ -+ int (*led_brightness_set)(struct phy_device *dev, -+ u8 index, enum led_brightness value); - }; - #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ - struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch b/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch deleted file mode 100644 index 5114c0e6da..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 2d3960e58ef7c83fe1dbf952f056b9e906cb6df8 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:29 +0200 -Subject: [PATCH 7/9] net: phy: marvell: Add software control of the LEDs - -Add a brightness function, so the LEDs can be controlled from -software using the standard Linux LED infrastructure. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/marvell.c | 45 ++++++++++++++++++++++++++++++++++----- - 1 file changed, 40 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -144,11 +144,13 @@ - /* WOL Event Interrupt Enable */ - #define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7) - --/* LED Timer Control Register */ --#define MII_88E1318S_PHY_LED_TCR 0x12 --#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) --#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) --#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) -+#define MII_88E1318S_PHY_LED_FUNC 0x10 -+#define MII_88E1318S_PHY_LED_FUNC_OFF (0x8) -+#define MII_88E1318S_PHY_LED_FUNC_ON (0x9) -+#define MII_88E1318S_PHY_LED_TCR 0x12 -+#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) -+#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) -+#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) - - /* Magic Packet MAC address registers */ - #define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17 -@@ -2832,6 +2834,34 @@ static int marvell_hwmon_probe(struct ph - } - #endif - -+static int m88e1318_led_brightness_set(struct phy_device *phydev, -+ u8 index, enum led_brightness value) -+{ -+ int reg; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ reg &= ~(0xf << (4 * index)); -+ if (value == LED_OFF) -+ reg |= MII_88E1318S_PHY_LED_FUNC_OFF << (4 * index); -+ else -+ reg |= MII_88E1318S_PHY_LED_FUNC_ON << (4 * index); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC, reg); -+} -+ - static int marvell_probe(struct phy_device *phydev) - { - struct marvell_priv *priv; -@@ -3081,6 +3111,7 @@ static struct phy_driver marvell_drivers - .get_sset_count = marvell_get_sset_count, - .get_strings = marvell_get_strings, - .get_stats = marvell_get_stats, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1145, -@@ -3187,6 +3218,7 @@ static struct phy_driver marvell_drivers - .cable_test_start = marvell_vct7_cable_test_start, - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1540, -@@ -3213,6 +3245,7 @@ static struct phy_driver marvell_drivers - .cable_test_start = marvell_vct7_cable_test_start, - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1545, -@@ -3239,6 +3272,7 @@ static struct phy_driver marvell_drivers - .cable_test_start = marvell_vct7_cable_test_start, - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E3016, -@@ -3380,6 +3414,7 @@ static struct phy_driver marvell_drivers - .get_stats = marvell_get_stats, - .get_tunable = m88e1540_get_tunable, - .set_tunable = m88e1540_set_tunable, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - }; - diff --git a/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch deleted file mode 100644 index 00bdcc5468..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 4e901018432e38eab35d2a352661ce4727795be1 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:30 +0200 -Subject: [PATCH 8/9] net: phy: phy_device: Call into the PHY driver to set LED - blinking - -Linux LEDs can be requested to perform hardware accelerated -blinking. Pass this to the PHY driver, if it implements the op. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 18 ++++++++++++++++++ - include/linux/phy.h | 12 ++++++++++++ - 2 files changed, 30 insertions(+) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3052,6 +3052,22 @@ static int phy_led_set_brightness(struct - return err; - } - -+static int phy_led_blink_set(struct led_classdev *led_cdev, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_blink_set(phydev, phyled->index, -+ delay_on, delay_off); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ - static int of_phy_led(struct phy_device *phydev, - struct device_node *led) - { -@@ -3074,6 +3090,8 @@ static int of_phy_led(struct phy_device - - if (phydev->drv->led_brightness_set) - cdev->brightness_set_blocking = phy_led_set_brightness; -+ if (phydev->drv->led_blink_set) -+ cdev->blink_set = phy_led_blink_set; - cdev->max_brightness = 1; - init_data.devicename = dev_name(&phydev->mdio.dev); - init_data.fwnode = of_fwnode_handle(led); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1014,6 +1014,18 @@ struct phy_driver { - */ - int (*led_brightness_set)(struct phy_device *dev, - u8 index, enum led_brightness value); -+ -+ /** -+ * @led_blink_set: Set a PHY LED brightness. Index indicates -+ * which of the PHYs led should be configured to blink. Delays -+ * are in milliseconds and if both are zero then a sensible -+ * default should be chosen. The call should adjust the -+ * timings in that case and if it can't match the values -+ * specified exactly. -+ */ -+ int (*led_blink_set)(struct phy_device *dev, u8 index, -+ unsigned long *delay_on, -+ unsigned long *delay_off); - }; - #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ - struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch b/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch deleted file mode 100644 index 8d5081a43c..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch +++ /dev/null @@ -1,104 +0,0 @@ -From ea9e86485decb2ac1750005bd96c166c9b780406 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:31 +0200 -Subject: [PATCH 9/9] net: phy: marvell: Implement led_blink_set() - -The Marvell PHY can blink the LEDs, simple on/off. All LEDs blink at -the same rate, and the reset default is 84ms per blink, which is -around 12Hz. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/marvell.c | 36 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 36 insertions(+) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -147,6 +147,8 @@ - #define MII_88E1318S_PHY_LED_FUNC 0x10 - #define MII_88E1318S_PHY_LED_FUNC_OFF (0x8) - #define MII_88E1318S_PHY_LED_FUNC_ON (0x9) -+#define MII_88E1318S_PHY_LED_FUNC_HI_Z (0xa) -+#define MII_88E1318S_PHY_LED_FUNC_BLINK (0xb) - #define MII_88E1318S_PHY_LED_TCR 0x12 - #define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) - #define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) -@@ -2862,6 +2864,35 @@ static int m88e1318_led_brightness_set(s - MII_88E1318S_PHY_LED_FUNC, reg); - } - -+static int m88e1318_led_blink_set(struct phy_device *phydev, u8 index, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ int reg; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ reg &= ~(0xf << (4 * index)); -+ reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); -+ /* Reset default is 84ms */ -+ *delay_on = 84 / 2; -+ *delay_off = 84 / 2; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC, reg); -+} -+ - static int marvell_probe(struct phy_device *phydev) - { - struct marvell_priv *priv; -@@ -3112,6 +3143,7 @@ static struct phy_driver marvell_drivers - .get_strings = marvell_get_strings, - .get_stats = marvell_get_stats, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1145, -@@ -3219,6 +3251,7 @@ static struct phy_driver marvell_drivers - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1540, -@@ -3246,6 +3279,7 @@ static struct phy_driver marvell_drivers - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1545, -@@ -3273,6 +3307,7 @@ static struct phy_driver marvell_drivers - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E3016, -@@ -3415,6 +3450,7 @@ static struct phy_driver marvell_drivers - .get_tunable = m88e1540_get_tunable, - .set_tunable = m88e1540_set_tunable, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - }; - diff --git a/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch b/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch deleted file mode 100644 index 56df3f095e..0000000000 --- a/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 4774ad841bef97cc51df90195338c5b2573dd4cb Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 23 Apr 2023 19:28:00 +0200 -Subject: [PATCH] net: phy: marvell: Fix inconsistent indenting in - led_blink_set - -Fix inconsistent indeinting in m88e1318_led_blink_set reported by kernel -test robot, probably done by the presence of an if condition dropped in -later revision of the same code. - -Reported-by: kernel test robot -Link: https://lore.kernel.org/oe-kbuild-all/202304240007.0VEX8QYG-lkp@intel.com/ -Fixes: ea9e86485dec ("net: phy: marvell: Implement led_blink_set()") -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230423172800.3470-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/marvell.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -2880,10 +2880,10 @@ static int m88e1318_led_blink_set(struct - case 1: - case 2: - reg &= ~(0xf << (4 * index)); -- reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); -- /* Reset default is 84ms */ -- *delay_on = 84 / 2; -- *delay_off = 84 / 2; -+ reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); -+ /* Reset default is 84ms */ -+ *delay_on = 84 / 2; -+ *delay_off = 84 / 2; - break; - default: - return -EINVAL; diff --git a/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch b/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch deleted file mode 100644 index 3170c26058..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch +++ /dev/null @@ -1,87 +0,0 @@ -From e2f24cb1b5daf9a4f6f3ba574c1fa74aab9807a4 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:40 +0200 -Subject: [PATCH 2/5] leds: trigger: netdev: Drop NETDEV_LED_MODE_LINKUP from - mode - -Putting NETDEV_LED_MODE_LINKUP in the same list of the netdev trigger -modes is wrong as it's used to set the link state of the device and not -to set a blink mode as it's done by NETDEV_LED_LINK, NETDEV_LED_TX and -NETDEV_LED_RX. It's also wrong to put this state in the same bitmap of the -netdev trigger mode and should be external to it. - -Drop NETDEV_LED_MODE_LINKUP from mode list and convert to a simple bool -that will be true or false based on the carrier link. No functional -change intended. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-3-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 19 ++++++++----------- - 1 file changed, 8 insertions(+), 11 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -50,10 +50,10 @@ struct led_netdev_data { - unsigned int last_activity; - - unsigned long mode; -+ bool carrier_link_up; - #define NETDEV_LED_LINK 0 - #define NETDEV_LED_TX 1 - #define NETDEV_LED_RX 2 --#define NETDEV_LED_MODE_LINKUP 3 - }; - - enum netdev_led_attr { -@@ -73,9 +73,9 @@ static void set_baseline_state(struct le - if (!led_cdev->blink_brightness) - led_cdev->blink_brightness = led_cdev->max_brightness; - -- if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode)) -+ if (!trigger_data->carrier_link_up) { - led_set_brightness(led_cdev, LED_OFF); -- else { -+ } else { - if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); -@@ -131,10 +131,9 @@ static ssize_t device_name_store(struct - trigger_data->net_dev = - dev_get_by_name(&init_net, trigger_data->device_name); - -- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = false; - if (trigger_data->net_dev != NULL) -- if (netif_carrier_ok(trigger_data->net_dev)) -- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); - - trigger_data->last_activity = 0; - -@@ -315,11 +314,10 @@ static int netdev_trig_notify(struct not - - spin_lock_bh(&trigger_data->lock); - -- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = false; - switch (evt) { - case NETDEV_CHANGENAME: -- if (netif_carrier_ok(dev)) -- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = netif_carrier_ok(dev); - fallthrough; - case NETDEV_REGISTER: - if (trigger_data->net_dev) -@@ -333,8 +331,7 @@ static int netdev_trig_notify(struct not - break; - case NETDEV_UP: - case NETDEV_CHANGE: -- if (netif_carrier_ok(dev)) -- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = netif_carrier_ok(dev); - break; - } - diff --git a/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch b/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch deleted file mode 100644 index 19cc1d7c9e..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch +++ /dev/null @@ -1,149 +0,0 @@ -From bdec9cb83936e0ac4cb87fed5b49fad0175f7dec Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:41 +0200 -Subject: [PATCH 3/5] leds: trigger: netdev: Rename add namespace to netdev - trigger enum modes - -Rename NETDEV trigger enum modes to a more symbolic name and add a -namespace to them. - -Also add __TRIGGER_NETDEV_MAX to identify the max modes of the netdev -trigger. - -This is a cleanup to drop the define and no behaviour change are -intended. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-4-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 58 ++++++++++++--------------- - 1 file changed, 25 insertions(+), 33 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -51,15 +51,15 @@ struct led_netdev_data { - - unsigned long mode; - bool carrier_link_up; --#define NETDEV_LED_LINK 0 --#define NETDEV_LED_TX 1 --#define NETDEV_LED_RX 2 - }; - --enum netdev_led_attr { -- NETDEV_ATTR_LINK, -- NETDEV_ATTR_TX, -- NETDEV_ATTR_RX -+enum led_trigger_netdev_modes { -+ TRIGGER_NETDEV_LINK = 0, -+ TRIGGER_NETDEV_TX, -+ TRIGGER_NETDEV_RX, -+ -+ /* Keep last */ -+ __TRIGGER_NETDEV_MAX, - }; - - static void set_baseline_state(struct led_netdev_data *trigger_data) -@@ -76,7 +76,7 @@ static void set_baseline_state(struct le - if (!trigger_data->carrier_link_up) { - led_set_brightness(led_cdev, LED_OFF); - } else { -- if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); - else -@@ -85,8 +85,8 @@ static void set_baseline_state(struct le - /* If we are looking for RX/TX start periodically - * checking stats - */ -- if (test_bit(NETDEV_LED_TX, &trigger_data->mode) || -- test_bit(NETDEV_LED_RX, &trigger_data->mode)) -+ if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) - schedule_delayed_work(&trigger_data->work, 0); - } - } -@@ -146,20 +146,16 @@ static ssize_t device_name_store(struct - static DEVICE_ATTR_RW(device_name); - - static ssize_t netdev_led_attr_show(struct device *dev, char *buf, -- enum netdev_led_attr attr) -+ enum led_trigger_netdev_modes attr) - { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - int bit; - - switch (attr) { -- case NETDEV_ATTR_LINK: -- bit = NETDEV_LED_LINK; -- break; -- case NETDEV_ATTR_TX: -- bit = NETDEV_LED_TX; -- break; -- case NETDEV_ATTR_RX: -- bit = NETDEV_LED_RX; -+ case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_TX: -+ case TRIGGER_NETDEV_RX: -+ bit = attr; - break; - default: - return -EINVAL; -@@ -169,7 +165,7 @@ static ssize_t netdev_led_attr_show(stru - } - - static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, -- size_t size, enum netdev_led_attr attr) -+ size_t size, enum led_trigger_netdev_modes attr) - { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - unsigned long state; -@@ -181,14 +177,10 @@ static ssize_t netdev_led_attr_store(str - return ret; - - switch (attr) { -- case NETDEV_ATTR_LINK: -- bit = NETDEV_LED_LINK; -- break; -- case NETDEV_ATTR_TX: -- bit = NETDEV_LED_TX; -- break; -- case NETDEV_ATTR_RX: -- bit = NETDEV_LED_RX; -+ case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_TX: -+ case TRIGGER_NETDEV_RX: -+ bit = attr; - break; - default: - return -EINVAL; -@@ -360,21 +352,21 @@ static void netdev_trig_work(struct work - } - - /* If we are not looking for RX/TX then return */ -- if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) && -- !test_bit(NETDEV_LED_RX, &trigger_data->mode)) -+ if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) && -+ !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) - return; - - dev_stats = dev_get_stats(trigger_data->net_dev, &temp); - new_activity = -- (test_bit(NETDEV_LED_TX, &trigger_data->mode) ? -+ (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ? - dev_stats->tx_packets : 0) + -- (test_bit(NETDEV_LED_RX, &trigger_data->mode) ? -+ (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ? - dev_stats->rx_packets : 0); - - if (trigger_data->last_activity != new_activity) { - led_stop_software_blink(trigger_data->led_cdev); - -- invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode); -+ invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); - interval = jiffies_to_msecs( - atomic_read(&trigger_data->interval)); - /* base state is ON (link present) */ diff --git a/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch b/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch deleted file mode 100644 index 3b45951f57..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 164b67d53476a9d114be85c885bd31f783835be4 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:42 +0200 -Subject: [PATCH 4/5] leds: trigger: netdev: Convert device attr to macro - -Convert link tx and rx device attr to a common macro to reduce common -code and in preparation for additional attr. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-5-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 57 ++++++++------------------- - 1 file changed, 16 insertions(+), 41 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -198,47 +198,22 @@ static ssize_t netdev_led_attr_store(str - return size; - } - --static ssize_t link_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK); --} -- --static ssize_t link_store(struct device *dev, -- struct device_attribute *attr, const char *buf, size_t size) --{ -- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK); --} -- --static DEVICE_ATTR_RW(link); -- --static ssize_t tx_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX); --} -- --static ssize_t tx_store(struct device *dev, -- struct device_attribute *attr, const char *buf, size_t size) --{ -- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX); --} -- --static DEVICE_ATTR_RW(tx); -- --static ssize_t rx_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX); --} -- --static ssize_t rx_store(struct device *dev, -- struct device_attribute *attr, const char *buf, size_t size) --{ -- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX); --} -- --static DEVICE_ATTR_RW(rx); -+#define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \ -+ static ssize_t trigger_name##_show(struct device *dev, \ -+ struct device_attribute *attr, char *buf) \ -+ { \ -+ return netdev_led_attr_show(dev, buf, trigger); \ -+ } \ -+ static ssize_t trigger_name##_store(struct device *dev, \ -+ struct device_attribute *attr, const char *buf, size_t size) \ -+ { \ -+ return netdev_led_attr_store(dev, buf, size, trigger); \ -+ } \ -+ static DEVICE_ATTR_RW(trigger_name) -+ -+DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); -+DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); -+DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); - - static ssize_t interval_show(struct device *dev, - struct device_attribute *attr, char *buf) diff --git a/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch b/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch deleted file mode 100644 index 180bee9612..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch +++ /dev/null @@ -1,106 +0,0 @@ -From d1b9e1391ab2dc80e9db87fe8b2de015c651e4c9 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:43 +0200 -Subject: [PATCH 5/5] leds: trigger: netdev: Use mutex instead of spinlocks - -Some LEDs may require to sleep while doing some operation like setting -brightness and other cleanup. - -For this reason, using a spinlock will cause a sleep under spinlock -warning. - -It should be safe to convert this to a sleepable lock since: -- sysfs read/write can sleep -- netdev_trig_work is a work queue and can sleep -- netdev _trig_notify can sleep - -The spinlock was used when brightness didn't support sleeping, but this -changed and now it supported with brightness_set_blocking(). - -Convert to mutex lock to permit sleeping using brightness_set_blocking(). - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-6-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -20,7 +20,7 @@ - #include - #include - #include --#include -+#include - #include - #include "../leds.h" - -@@ -37,7 +37,7 @@ - */ - - struct led_netdev_data { -- spinlock_t lock; -+ struct mutex lock; - - struct delayed_work work; - struct notifier_block notifier; -@@ -97,9 +97,9 @@ static ssize_t device_name_show(struct d - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - ssize_t len; - -- spin_lock_bh(&trigger_data->lock); -+ mutex_lock(&trigger_data->lock); - len = sprintf(buf, "%s\n", trigger_data->device_name); -- spin_unlock_bh(&trigger_data->lock); -+ mutex_unlock(&trigger_data->lock); - - return len; - } -@@ -115,7 +115,7 @@ static ssize_t device_name_store(struct - - cancel_delayed_work_sync(&trigger_data->work); - -- spin_lock_bh(&trigger_data->lock); -+ mutex_lock(&trigger_data->lock); - - if (trigger_data->net_dev) { - dev_put(trigger_data->net_dev); -@@ -138,7 +138,7 @@ static ssize_t device_name_store(struct - trigger_data->last_activity = 0; - - set_baseline_state(trigger_data); -- spin_unlock_bh(&trigger_data->lock); -+ mutex_unlock(&trigger_data->lock); - - return size; - } -@@ -279,7 +279,7 @@ static int netdev_trig_notify(struct not - - cancel_delayed_work_sync(&trigger_data->work); - -- spin_lock_bh(&trigger_data->lock); -+ mutex_lock(&trigger_data->lock); - - trigger_data->carrier_link_up = false; - switch (evt) { -@@ -304,7 +304,7 @@ static int netdev_trig_notify(struct not - - set_baseline_state(trigger_data); - -- spin_unlock_bh(&trigger_data->lock); -+ mutex_unlock(&trigger_data->lock); - - return NOTIFY_DONE; - } -@@ -365,7 +365,7 @@ static int netdev_trig_activate(struct l - if (!trigger_data) - return -ENOMEM; - -- spin_lock_init(&trigger_data->lock); -+ mutex_init(&trigger_data->lock); - - trigger_data->notifier.notifier_call = netdev_trig_notify; - trigger_data->notifier.priority = 10; diff --git a/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch b/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch deleted file mode 100644 index ac18611733..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch +++ /dev/null @@ -1,74 +0,0 @@ -From ed554d3f945179c5b159bddfad7be34b403fe11a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:31 +0200 -Subject: [PATCH 01/13] leds: add APIs for LEDs hw control - -Add an option to permit LED driver to declare support for a specific -trigger to use hw control and setup the LED to blink based on specific -provided modes. - -Add APIs for LEDs hw control. These functions will be used to activate -hardware control where a LED will use the provided flags, from an -unique defined supported trigger, to setup the LED to be driven by -hardware. - -Add hw_control_is_supported() to ask the LED driver if the requested -mode by the trigger are supported and the LED can be setup to follow -the requested modes. - -Deactivate hardware blink control by setting brightness to LED_OFF via -the brightness_set() callback. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - include/linux/leds.h | 37 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 37 insertions(+) - ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -164,6 +164,43 @@ struct led_classdev { - - /* LEDs that have private triggers have this set */ - struct led_hw_trigger_type *trigger_type; -+ -+ /* Unique trigger name supported by LED set in hw control mode */ -+ const char *hw_control_trigger; -+ /* -+ * Check if the LED driver supports the requested mode provided by the -+ * defined supported trigger to setup the LED to hw control mode. -+ * -+ * Return 0 on success. Return -EOPNOTSUPP when the passed flags are not -+ * supported and software fallback needs to be used. -+ * Return a negative error number on any other case for check fail due -+ * to various reason like device not ready or timeouts. -+ */ -+ int (*hw_control_is_supported)(struct led_classdev *led_cdev, -+ unsigned long flags); -+ /* -+ * Activate hardware control, LED driver will use the provided flags -+ * from the supported trigger and setup the LED to be driven by hardware -+ * following the requested mode from the trigger flags. -+ * Deactivate hardware blink control by setting brightness to LED_OFF via -+ * the brightness_set() callback. -+ * -+ * Return 0 on success, a negative error number on flags apply fail. -+ */ -+ int (*hw_control_set)(struct led_classdev *led_cdev, -+ unsigned long flags); -+ /* -+ * Get from the LED driver the current mode that the LED is set in hw -+ * control mode and put them in flags. -+ * Trigger can use this to get the initial state of a LED already set in -+ * hardware blink control. -+ * -+ * Return 0 on success, a negative error number on failing parsing the -+ * initial mode. Error from this function is NOT FATAL as the device -+ * may be in a not supported initial state by the attached LED trigger. -+ */ -+ int (*hw_control_get)(struct led_classdev *led_cdev, -+ unsigned long *flags); - #endif - - #ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED diff --git a/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch b/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch deleted file mode 100644 index 1a221727a0..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 052c38eb17e866c5b4cd43924e7a5e20167b55c0 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:32 +0200 -Subject: [PATCH 02/13] leds: add API to get attached device for LED hw control - -Some specific LED triggers blink the LED based on events from a device -or subsystem. -For example, an LED could be blinked to indicate a network device is -receiving packets, or a disk is reading blocks. To correctly enable and -request the hw control of the LED, the trigger has to check if the -network interface or block device configured via a /sys/class/led file -match the one the LED driver provide for hw control for. - -Provide an API call to get the device which the LED blinks for. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - include/linux/leds.h | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -201,6 +201,12 @@ struct led_classdev { - */ - int (*hw_control_get)(struct led_classdev *led_cdev, - unsigned long *flags); -+ /* -+ * Get the device this LED blinks in response to. -+ * e.g. for a PHY LED, it is the network device. If the LED is -+ * not yet associated to a device, return NULL. -+ */ -+ struct device *(*hw_control_get_device)(struct led_classdev *led_cdev); - #endif - - #ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED diff --git a/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch b/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch deleted file mode 100644 index af9fb7fdc3..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 8aa2fd7b66980ecd2e45e95af61cf7eafede1211 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:33 +0200 -Subject: [PATCH 03/13] Documentation: leds: leds-class: Document new Hardware - driven LEDs APIs - -Document new Hardware driven LEDs APIs. - -Some LEDs can be programmed to be driven by hardware. This is not -limited to blink but also to turn off or on autonomously. -To support this feature, a LED needs to implement various additional -ops and needs to declare specific support for the supported triggers. - -Add documentation for each required value and API to make hw control -possible and implementable by both LEDs and triggers. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - Documentation/leds/leds-class.rst | 81 +++++++++++++++++++++++++++++++ - 1 file changed, 81 insertions(+) - ---- a/Documentation/leds/leds-class.rst -+++ b/Documentation/leds/leds-class.rst -@@ -169,6 +169,87 @@ Setting the brightness to zero with brig - should completely turn off the LED and cancel the previously programmed - hardware blinking function, if any. - -+Hardware driven LEDs -+==================== -+ -+Some LEDs can be programmed to be driven by hardware. This is not -+limited to blink but also to turn off or on autonomously. -+To support this feature, a LED needs to implement various additional -+ops and needs to declare specific support for the supported triggers. -+ -+With hw control we refer to the LED driven by hardware. -+ -+LED driver must define the following value to support hw control: -+ -+ - hw_control_trigger: -+ unique trigger name supported by the LED in hw control -+ mode. -+ -+LED driver must implement the following API to support hw control: -+ - hw_control_is_supported: -+ check if the flags passed by the supported trigger can -+ be parsed and activate hw control on the LED. -+ -+ Return 0 if the passed flags mask is supported and -+ can be set with hw_control_set(). -+ -+ If the passed flags mask is not supported -EOPNOTSUPP -+ must be returned, the LED trigger will use software -+ fallback in this case. -+ -+ Return a negative error in case of any other error like -+ device not ready or timeouts. -+ -+ - hw_control_set: -+ activate hw control. LED driver will use the provided -+ flags passed from the supported trigger, parse them to -+ a set of mode and setup the LED to be driven by hardware -+ following the requested modes. -+ -+ Set LED_OFF via the brightness_set to deactivate hw control. -+ -+ Return 0 on success, a negative error number on failing to -+ apply flags. -+ -+ - hw_control_get: -+ get active modes from a LED already in hw control, parse -+ them and set in flags the current active flags for the -+ supported trigger. -+ -+ Return 0 on success, a negative error number on failing -+ parsing the initial mode. -+ Error from this function is NOT FATAL as the device may -+ be in a not supported initial state by the attached LED -+ trigger. -+ -+ - hw_control_get_device: -+ return the device associated with the LED driver in -+ hw control. A trigger might use this to match the -+ returned device from this function with a configured -+ device for the trigger as the source for blinking -+ events and correctly enable hw control. -+ (example a netdev trigger configured to blink for a -+ particular dev match the returned dev from get_device -+ to set hw control) -+ -+ Returns a pointer to a struct device or NULL if nothing -+ is currently attached. -+ -+LED driver can activate additional modes by default to workaround the -+impossibility of supporting each different mode on the supported trigger. -+Examples are hardcoding the blink speed to a set interval, enable special -+feature like bypassing blink if some requirements are not met. -+ -+A trigger should first check if the hw control API are supported by the LED -+driver and check if the trigger is supported to verify if hw control is possible, -+use hw_control_is_supported to check if the flags are supported and only at -+the end use hw_control_set to activate hw control. -+ -+A trigger can use hw_control_get to check if a LED is already in hw control -+and init their flags. -+ -+When the LED is in hw control, no software blink is possible and doing so -+will effectively disable hw control. - - Known Issues - ============ diff --git a/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch b/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch deleted file mode 100644 index 3c804c0b41..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 28a6a2ef18ad840a390d519840c303b03040961c Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:34 +0200 -Subject: [PATCH 04/13] leds: trigger: netdev: refactor code setting device - name - -Move the code into a helper, ready for it to be called at -other times. No intended behaviour change. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 29 ++++++++++++++++++--------- - 1 file changed, 20 insertions(+), 9 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -104,15 +104,9 @@ static ssize_t device_name_show(struct d - return len; - } - --static ssize_t device_name_store(struct device *dev, -- struct device_attribute *attr, const char *buf, -- size_t size) -+static int set_device_name(struct led_netdev_data *trigger_data, -+ const char *name, size_t size) - { -- struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -- -- if (size >= IFNAMSIZ) -- return -EINVAL; -- - cancel_delayed_work_sync(&trigger_data->work); - - mutex_lock(&trigger_data->lock); -@@ -122,7 +116,7 @@ static ssize_t device_name_store(struct - trigger_data->net_dev = NULL; - } - -- memcpy(trigger_data->device_name, buf, size); -+ memcpy(trigger_data->device_name, name, size); - trigger_data->device_name[size] = 0; - if (size > 0 && trigger_data->device_name[size - 1] == '\n') - trigger_data->device_name[size - 1] = 0; -@@ -140,6 +134,23 @@ static ssize_t device_name_store(struct - set_baseline_state(trigger_data); - mutex_unlock(&trigger_data->lock); - -+ return 0; -+} -+ -+static ssize_t device_name_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, -+ size_t size) -+{ -+ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -+ int ret; -+ -+ if (size >= IFNAMSIZ) -+ return -EINVAL; -+ -+ ret = set_device_name(trigger_data, buf, size); -+ -+ if (ret < 0) -+ return ret; - return size; - } - diff --git a/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch b/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch deleted file mode 100644 index 284b519482..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 4fd1b6d47a7a38e81fdc6f8be2ccd4216b3f93db Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:35 +0200 -Subject: [PATCH 05/13] leds: trigger: netdev: introduce check for possible hw - control - -Introduce function to check if the requested mode can use hw control in -preparation for hw control support. Currently everything is handled in -software so can_hw_control will always return false. - -Add knob with the new value hw_control in trigger_data struct to -set hw control possible. Useful for future implementation to implement -in set_baseline_state() the required function to set the requested mode -using LEDs hw control ops and in other function to reject set if hw -control is currently active. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -51,6 +51,7 @@ struct led_netdev_data { - - unsigned long mode; - bool carrier_link_up; -+ bool hw_control; - }; - - enum led_trigger_netdev_modes { -@@ -91,6 +92,11 @@ static void set_baseline_state(struct le - } - } - -+static bool can_hw_control(struct led_netdev_data *trigger_data) -+{ -+ return false; -+} -+ - static ssize_t device_name_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -204,6 +210,8 @@ static ssize_t netdev_led_attr_store(str - else - clear_bit(bit, &trigger_data->mode); - -+ trigger_data->hw_control = can_hw_control(trigger_data); -+ - set_baseline_state(trigger_data); - - return size; diff --git a/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch b/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch deleted file mode 100644 index 09759bc623..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 6352f25f9fadba59d5df2ba7139495759ccc81d5 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:36 +0200 -Subject: [PATCH 06/13] leds: trigger: netdev: add basic check for hw control - support - -Add basic check for hw control support. Check if the required API are -defined and check if the defined trigger supported in hw control for the -LED driver match netdev. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -92,8 +92,22 @@ static void set_baseline_state(struct le - } - } - -+static bool supports_hw_control(struct led_classdev *led_cdev) -+{ -+ if (!led_cdev->hw_control_get || !led_cdev->hw_control_set || -+ !led_cdev->hw_control_is_supported) -+ return false; -+ -+ return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); -+} -+ - static bool can_hw_control(struct led_netdev_data *trigger_data) - { -+ struct led_classdev *led_cdev = trigger_data->led_cdev; -+ -+ if (!supports_hw_control(led_cdev)) -+ return false; -+ - return false; - } - diff --git a/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch b/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch deleted file mode 100644 index 6634906800..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch +++ /dev/null @@ -1,28 +0,0 @@ -From c84c80c7388f887b10dafd70fc55bc6c5fe9fa5a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:37 +0200 -Subject: [PATCH 07/13] leds: trigger: netdev: reject interval store for - hw_control - -Reject interval store with hw_control enabled. It's are currently not -supported and MUST be set to the default value with hw control enabled. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -265,6 +265,9 @@ static ssize_t interval_store(struct dev - unsigned long value; - int ret; - -+ if (trigger_data->hw_control) -+ return -EINVAL; -+ - ret = kstrtoul(buf, 0, &value); - if (ret) - return ret; diff --git a/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch b/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch deleted file mode 100644 index 52faa4809b..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 7c145a34ba6e380616af93262fcab9fc7261d851 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:38 +0200 -Subject: [PATCH 08/13] leds: trigger: netdev: add support for LED hw control - -Add support for LED hw control for the netdev trigger. - -The trigger on calling set_baseline_state to configure a new mode, will -do various check to verify if hw control can be used for the requested -mode in can_hw_control() function. - -It will first check if the LED driver supports hw control for the netdev -trigger, then will use hw_control_is_supported() and finally will call -hw_control_set() to apply the requested mode. - -To use such mode, interval MUST be set to the default value and net_dev -MUST be set. If one of these 2 value are not valid, hw control will -never be used and normal software fallback is used. - -The default interval value is moved to a define to make sure they are -always synced. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 43 +++++++++++++++++++++++++-- - 1 file changed, 41 insertions(+), 2 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -24,6 +24,8 @@ - #include - #include "../leds.h" - -+#define NETDEV_LED_DEFAULT_INTERVAL 50 -+ - /* - * Configurable sysfs attributes: - * -@@ -68,6 +70,13 @@ static void set_baseline_state(struct le - int current_brightness; - struct led_classdev *led_cdev = trigger_data->led_cdev; - -+ /* Already validated, hw control is possible with the requested mode */ -+ if (trigger_data->hw_control) { -+ led_cdev->hw_control_set(led_cdev, trigger_data->mode); -+ -+ return; -+ } -+ - current_brightness = led_cdev->brightness; - if (current_brightness) - led_cdev->blink_brightness = current_brightness; -@@ -103,12 +112,42 @@ static bool supports_hw_control(struct l - - static bool can_hw_control(struct led_netdev_data *trigger_data) - { -+ unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); -+ unsigned int interval = atomic_read(&trigger_data->interval); - struct led_classdev *led_cdev = trigger_data->led_cdev; -+ int ret; - - if (!supports_hw_control(led_cdev)) - return false; - -- return false; -+ /* -+ * Interval must be set to the default -+ * value. Any different value is rejected if in hw -+ * control. -+ */ -+ if (interval != default_interval) -+ return false; -+ -+ /* -+ * net_dev must be set with hw control, otherwise no -+ * blinking can be happening and there is nothing to -+ * offloaded. -+ */ -+ if (!trigger_data->net_dev) -+ return false; -+ -+ /* Check if the requested mode is supported */ -+ ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode); -+ /* Fall back to software blinking if not supported */ -+ if (ret == -EOPNOTSUPP) -+ return false; -+ if (ret) { -+ dev_warn(led_cdev->dev, -+ "Current mode check failed with error %d\n", ret); -+ return false; -+ } -+ -+ return true; - } - - static ssize_t device_name_show(struct device *dev, -@@ -413,7 +452,7 @@ static int netdev_trig_activate(struct l - trigger_data->device_name[0] = 0; - - trigger_data->mode = 0; -- atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); -+ atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); - trigger_data->last_activity = 0; - - led_set_trigger_data(led_cdev, trigger_data); diff --git a/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch b/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch deleted file mode 100644 index c129ffa4f5..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 33ec0b53befff2c0a7f3aa19ff08556d60585d6b Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:39 +0200 -Subject: [PATCH 09/13] leds: trigger: netdev: validate configured netdev - -The netdev which the LED should blink for is configurable in -/sys/class/led/foo/device_name. Ensure when offloading that the -configured netdev is the same as the netdev the LED is associated -with. If it is not, only perform software blinking. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 24 ++++++++++++++++++++++-- - 1 file changed, 22 insertions(+), 2 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -110,6 +110,24 @@ static bool supports_hw_control(struct l - return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); - } - -+/* -+ * Validate the configured netdev is the same as the one associated with -+ * the LED driver in hw control. -+ */ -+static bool validate_net_dev(struct led_classdev *led_cdev, -+ struct net_device *net_dev) -+{ -+ struct device *dev = led_cdev->hw_control_get_device(led_cdev); -+ struct net_device *ndev; -+ -+ if (!dev) -+ return false; -+ -+ ndev = to_net_dev(dev); -+ -+ return ndev == net_dev; -+} -+ - static bool can_hw_control(struct led_netdev_data *trigger_data) - { - unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); -@@ -131,9 +149,11 @@ static bool can_hw_control(struct led_ne - /* - * net_dev must be set with hw control, otherwise no - * blinking can be happening and there is nothing to -- * offloaded. -+ * offloaded. Additionally, for hw control to be -+ * valid, the configured netdev must be the same as -+ * netdev associated to the LED. - */ -- if (!trigger_data->net_dev) -+ if (!validate_net_dev(led_cdev, trigger_data->net_dev)) - return false; - - /* Check if the requested mode is supported */ diff --git a/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch b/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch deleted file mode 100644 index e20594c99a..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0316cc5629d15880dd3f097d221c55ca648bcd61 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:40 +0200 -Subject: [PATCH 10/13] leds: trigger: netdev: init mode if hw control already - active - -On netdev trigger activation, hw control may be already active by -default. If this is the case and a device is actually provided by -hw_control_get_device(), init the already active mode and set the -bool to hw_control bool to true to reflect the already set mode in the -trigger_data. - -Co-developed-by: Andrew Lunn -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -454,6 +454,8 @@ static void netdev_trig_work(struct work - static int netdev_trig_activate(struct led_classdev *led_cdev) - { - struct led_netdev_data *trigger_data; -+ unsigned long mode; -+ struct device *dev; - int rc; - - trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); -@@ -475,6 +477,21 @@ static int netdev_trig_activate(struct l - atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); - trigger_data->last_activity = 0; - -+ /* Check if hw control is active by default on the LED. -+ * Init already enabled mode in hw control. -+ */ -+ if (supports_hw_control(led_cdev) && -+ !led_cdev->hw_control_get(led_cdev, &mode)) { -+ dev = led_cdev->hw_control_get_device(led_cdev); -+ if (dev) { -+ const char *name = dev_name(dev); -+ -+ set_device_name(trigger_data, name, strlen(name)); -+ trigger_data->hw_control = true; -+ trigger_data->mode = mode; -+ } -+ } -+ - led_set_trigger_data(led_cdev, trigger_data); - - rc = register_netdevice_notifier(&trigger_data->notifier); diff --git a/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch b/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch deleted file mode 100644 index 70aed850d1..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 947acacab5ea151291b861cdfbde16ff5cf1b08c Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:41 +0200 -Subject: [PATCH 11/13] leds: trigger: netdev: expose netdev trigger modes in - linux include - -Expose netdev trigger modes to make them accessible by LED driver that -will support netdev trigger for hw control. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 9 --------- - include/linux/leds.h | 10 ++++++++++ - 2 files changed, 10 insertions(+), 9 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -56,15 +56,6 @@ struct led_netdev_data { - bool hw_control; - }; - --enum led_trigger_netdev_modes { -- TRIGGER_NETDEV_LINK = 0, -- TRIGGER_NETDEV_TX, -- TRIGGER_NETDEV_RX, -- -- /* Keep last */ -- __TRIGGER_NETDEV_MAX, --}; -- - static void set_baseline_state(struct led_netdev_data *trigger_data) - { - int current_brightness; ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -527,6 +527,16 @@ static inline void *led_get_trigger_data - - #endif /* CONFIG_LEDS_TRIGGERS */ - -+/* Trigger specific enum */ -+enum led_trigger_netdev_modes { -+ TRIGGER_NETDEV_LINK = 0, -+ TRIGGER_NETDEV_TX, -+ TRIGGER_NETDEV_RX, -+ -+ /* Keep last */ -+ __TRIGGER_NETDEV_MAX, -+}; -+ - /* Trigger specific functions */ - #ifdef CONFIG_LEDS_TRIGGER_DISK - void ledtrig_disk_activity(bool write); diff --git a/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch b/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch deleted file mode 100644 index ad76d89b7b..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch +++ /dev/null @@ -1,200 +0,0 @@ -From e0256648c831af13cbfe4a1787327fcec01c2807 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:42 +0200 -Subject: [PATCH 12/13] net: dsa: qca8k: implement hw_control ops - -Implement hw_control ops to drive Switch LEDs based on hardware events. - -Netdev trigger is the declared supported trigger for hw control -operation and supports the following mode: -- tx -- rx - -When hw_control_set is called, LEDs are set to follow the requested -mode. -Each LEDs will blink at 4Hz by default. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-leds.c | 154 +++++++++++++++++++++++++++++++ - 1 file changed, 154 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -32,6 +32,43 @@ qca8k_get_enable_led_reg(int port_num, i - } - - static int -+qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) -+{ -+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); -+ -+ /* 6 total control rule: -+ * 3 control rules for phy0-3 that applies to all their leds -+ * 3 control rules for phy4 -+ */ -+ if (port_num == 4) -+ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; -+ else -+ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; -+ -+ return 0; -+} -+ -+static int -+qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger) -+{ -+ /* Parsing specific to netdev trigger */ -+ if (test_bit(TRIGGER_NETDEV_TX, &rules)) -+ *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; -+ if (test_bit(TRIGGER_NETDEV_RX, &rules)) -+ *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; -+ -+ if (rules && !*offload_trigger) -+ return -EOPNOTSUPP; -+ -+ /* Enable some default rule by default to the requested mode: -+ * - Blink at 4Hz by default -+ */ -+ *offload_trigger |= QCA8K_LED_BLINK_4HZ; -+ -+ return 0; -+} -+ -+static int - qca8k_led_brightness_set(struct qca8k_led *led, - enum led_brightness brightness) - { -@@ -165,6 +202,119 @@ qca8k_cled_blink_set(struct led_classdev - } - - static int -+qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 mask, val = QCA8K_LED_ALWAYS_OFF; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ if (enable) -+ val = QCA8K_LED_RULE_CONTROLLED; -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ mask = QCA8K_LED_PATTERN_EN_MASK; -+ val <<= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, -+ val << reg_info.shift); -+} -+ -+static bool -+qca8k_cled_hw_control_status(struct led_classdev *ldev) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 val; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ regmap_read(priv->regmap, reg_info.reg, &val); -+ -+ val >>= reg_info.shift; -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ val &= QCA8K_LED_PATTERN_EN_MASK; -+ val >>= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ return val == QCA8K_LED_RULE_CONTROLLED; -+} -+ -+static int -+qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules) -+{ -+ u32 offload_trigger = 0; -+ -+ return qca8k_parse_netdev(rules, &offload_trigger); -+} -+ -+static int -+qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 offload_trigger = 0; -+ int ret; -+ -+ ret = qca8k_parse_netdev(rules, &offload_trigger); -+ if (ret) -+ return ret; -+ -+ ret = qca8k_cled_trigger_offload(ldev, true); -+ if (ret) -+ return ret; -+ -+ qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); -+ -+ return regmap_update_bits(priv->regmap, reg_info.reg, -+ QCA8K_LED_RULE_MASK << reg_info.shift, -+ offload_trigger << reg_info.shift); -+} -+ -+static int -+qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 val; -+ int ret; -+ -+ /* With hw control not active return err */ -+ if (!qca8k_cled_hw_control_status(ldev)) -+ return -EINVAL; -+ -+ qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); -+ -+ ret = regmap_read(priv->regmap, reg_info.reg, &val); -+ if (ret) -+ return ret; -+ -+ val >>= reg_info.shift; -+ val &= QCA8K_LED_RULE_MASK; -+ -+ /* Parsing specific to netdev trigger */ -+ if (val & QCA8K_LED_TX_BLINK_MASK) -+ set_bit(TRIGGER_NETDEV_TX, rules); -+ if (val & QCA8K_LED_RX_BLINK_MASK) -+ set_bit(TRIGGER_NETDEV_RX, rules); -+ -+ return 0; -+} -+ -+static int - qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) - { - struct fwnode_handle *led = NULL, *leds = NULL; -@@ -224,6 +374,10 @@ qca8k_parse_port_leds(struct qca8k_priv - port_led->cdev.max_brightness = 1; - port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; - port_led->cdev.blink_set = qca8k_cled_blink_set; -+ port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; -+ port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; -+ port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; -+ port_led->cdev.hw_control_trigger = "netdev"; - init_data.default_label = ":port"; - init_data.fwnode = led; - init_data.devname_mandatory = true; diff --git a/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch b/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch deleted file mode 100644 index feb6b9e1e4..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 4f53c27f772e27e4cf4e5507d6f4d5980002cb6a Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:43 +0200 -Subject: [PATCH 13/13] net: dsa: qca8k: add op to get ports netdev - -In order that the LED trigger can blink the switch MAC ports LED, it -needs to know the netdev associated to the port. Add the callback to -return the struct device of the netdev. - -Add an helper function qca8k_phy_to_port() to convert the phy back to -dsa_port index, as we reference LED port based on the internal PHY -index and needs to be converted back. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-leds.c | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -5,6 +5,18 @@ - #include "qca8k.h" - #include "qca8k_leds.h" - -+static u32 qca8k_phy_to_port(int phy) -+{ -+ /* Internal PHY 0 has port at index 1. -+ * Internal PHY 1 has port at index 2. -+ * Internal PHY 2 has port at index 3. -+ * Internal PHY 3 has port at index 4. -+ * Internal PHY 4 has port at index 5. -+ */ -+ -+ return phy + 1; -+} -+ - static int - qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) - { -@@ -314,6 +326,20 @@ qca8k_cled_hw_control_get(struct led_cla - return 0; - } - -+static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ struct qca8k_priv *priv = led->priv; -+ struct dsa_port *dp; -+ -+ dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num)); -+ if (!dp) -+ return NULL; -+ if (dp->slave) -+ return &dp->slave->dev; -+ return NULL; -+} -+ - static int - qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) - { -@@ -377,6 +403,7 @@ qca8k_parse_port_leds(struct qca8k_priv - port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; - port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; - port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; -+ port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device; - port_led->cdev.hw_control_trigger = "netdev"; - init_data.default_label = ":port"; - init_data.fwnode = led; diff --git a/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch b/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch deleted file mode 100644 index 1c564b3897..0000000000 --- a/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch +++ /dev/null @@ -1,242 +0,0 @@ -From d5e01266e7f5fa12400d4c8aa4e86fe89dcc61e9 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 19 Jun 2023 22:46:58 +0200 -Subject: [PATCH 1/3] leds: trigger: netdev: add additional specific link speed - mode - -Add additional modes for specific link speed. Use ethtool APIs to get the -current link speed and enable the LED accordingly. Under netdev event -handler the rtnl lock is already held and is not needed to be set to -access ethtool APIs. - -This is especially useful for PHY and Switch that supports LEDs hw -control for specific link speed. (example scenario a PHY that have 2 LED -connected one green and one orange where the green is turned on with -1000mbps speed and orange is turned on with 10mpbs speed) - -On mode set from sysfs we check if we have enabled split link speed mode -and reject enabling generic link mode to prevent wrong and redundant -configuration. - -Rework logic on the set baseline state to support these new modes to -select if we need to turn on or off the LED. - -Add additional modes: -- link_10: Turn on LED when link speed is 10mbps -- link_100: Turn on LED when link speed is 100mbps -- link_1000: Turn on LED when link speed is 1000mbps - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 80 +++++++++++++++++++++++---- - include/linux/leds.h | 3 + - 2 files changed, 73 insertions(+), 10 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -21,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include "../leds.h" - -@@ -52,6 +54,8 @@ struct led_netdev_data { - unsigned int last_activity; - - unsigned long mode; -+ int link_speed; -+ - bool carrier_link_up; - bool hw_control; - }; -@@ -77,7 +81,24 @@ static void set_baseline_state(struct le - if (!trigger_data->carrier_link_up) { - led_set_brightness(led_cdev, LED_OFF); - } else { -+ bool blink_on = false; -+ - if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) && -+ trigger_data->link_speed == SPEED_10) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) && -+ trigger_data->link_speed == SPEED_100) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) && -+ trigger_data->link_speed == SPEED_1000) -+ blink_on = true; -+ -+ if (blink_on) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); - else -@@ -161,6 +182,18 @@ static bool can_hw_control(struct led_ne - return true; - } - -+static void get_device_state(struct led_netdev_data *trigger_data) -+{ -+ struct ethtool_link_ksettings cmd; -+ -+ trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); -+ if (!trigger_data->carrier_link_up) -+ return; -+ -+ if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) -+ trigger_data->link_speed = cmd.base.speed; -+} -+ - static ssize_t device_name_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -196,8 +229,12 @@ static int set_device_name(struct led_ne - dev_get_by_name(&init_net, trigger_data->device_name); - - trigger_data->carrier_link_up = false; -- if (trigger_data->net_dev != NULL) -- trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); -+ trigger_data->link_speed = SPEED_UNKNOWN; -+ if (trigger_data->net_dev != NULL) { -+ rtnl_lock(); -+ get_device_state(trigger_data); -+ rtnl_unlock(); -+ } - - trigger_data->last_activity = 0; - -@@ -234,6 +271,9 @@ static ssize_t netdev_led_attr_show(stru - - switch (attr) { - case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_LINK_10: -+ case TRIGGER_NETDEV_LINK_100: -+ case TRIGGER_NETDEV_LINK_1000: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -249,7 +289,7 @@ static ssize_t netdev_led_attr_store(str - size_t size, enum led_trigger_netdev_modes attr) - { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -- unsigned long state; -+ unsigned long state, mode = trigger_data->mode; - int ret; - int bit; - -@@ -259,6 +299,9 @@ static ssize_t netdev_led_attr_store(str - - switch (attr) { - case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_LINK_10: -+ case TRIGGER_NETDEV_LINK_100: -+ case TRIGGER_NETDEV_LINK_1000: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -267,13 +310,20 @@ static ssize_t netdev_led_attr_store(str - return -EINVAL; - } - -- cancel_delayed_work_sync(&trigger_data->work); -- - if (state) -- set_bit(bit, &trigger_data->mode); -+ set_bit(bit, &mode); - else -- clear_bit(bit, &trigger_data->mode); -+ clear_bit(bit, &mode); -+ -+ if (test_bit(TRIGGER_NETDEV_LINK, &mode) && -+ (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || -+ test_bit(TRIGGER_NETDEV_LINK_100, &mode) || -+ test_bit(TRIGGER_NETDEV_LINK_1000, &mode))) -+ return -EINVAL; -+ -+ cancel_delayed_work_sync(&trigger_data->work); - -+ trigger_data->mode = mode; - trigger_data->hw_control = can_hw_control(trigger_data); - - set_baseline_state(trigger_data); -@@ -295,6 +345,9 @@ static ssize_t netdev_led_attr_store(str - static DEVICE_ATTR_RW(trigger_name) - - DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); -+DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); -+DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); -+DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); - DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); - DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); - -@@ -338,6 +391,9 @@ static DEVICE_ATTR_RW(interval); - static struct attribute *netdev_trig_attrs[] = { - &dev_attr_device_name.attr, - &dev_attr_link.attr, -+ &dev_attr_link_10.attr, -+ &dev_attr_link_100.attr, -+ &dev_attr_link_1000.attr, - &dev_attr_rx.attr, - &dev_attr_tx.attr, - &dev_attr_interval.attr, -@@ -368,9 +424,10 @@ static int netdev_trig_notify(struct not - mutex_lock(&trigger_data->lock); - - trigger_data->carrier_link_up = false; -+ trigger_data->link_speed = SPEED_UNKNOWN; - switch (evt) { - case NETDEV_CHANGENAME: -- trigger_data->carrier_link_up = netif_carrier_ok(dev); -+ get_device_state(trigger_data); - fallthrough; - case NETDEV_REGISTER: - if (trigger_data->net_dev) -@@ -384,7 +441,7 @@ static int netdev_trig_notify(struct not - break; - case NETDEV_UP: - case NETDEV_CHANGE: -- trigger_data->carrier_link_up = netif_carrier_ok(dev); -+ get_device_state(trigger_data); - break; - } - -@@ -427,7 +484,10 @@ static void netdev_trig_work(struct work - if (trigger_data->last_activity != new_activity) { - led_stop_software_blink(trigger_data->led_cdev); - -- invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); -+ invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); - interval = jiffies_to_msecs( - atomic_read(&trigger_data->interval)); - /* base state is ON (link present) */ ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -530,6 +530,9 @@ static inline void *led_get_trigger_data - /* Trigger specific enum */ - enum led_trigger_netdev_modes { - TRIGGER_NETDEV_LINK = 0, -+ TRIGGER_NETDEV_LINK_10, -+ TRIGGER_NETDEV_LINK_100, -+ TRIGGER_NETDEV_LINK_1000, - TRIGGER_NETDEV_TX, - TRIGGER_NETDEV_RX, - diff --git a/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch b/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch deleted file mode 100644 index a5ab461828..0000000000 --- a/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch +++ /dev/null @@ -1,138 +0,0 @@ -From f22f95b9ff1551c9bab13104131929f33d51f23f Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 19 Jun 2023 22:46:59 +0200 -Subject: [PATCH 2/3] leds: trigger: netdev: add additional specific link - duplex mode - -Add additional modes for specific link duplex. Use ethtool APIs to get the -current link duplex and enable the LED accordingly. Under netdev event -handler the rtnl lock is already held and is not needed to be set to -access ethtool APIs. - -This is especially useful for PHY and Switch that supports LEDs hw -control for specific link duplex. - -Add additional modes: -- half_duplex: Turn on LED when link is half duplex -- full_duplex: Turn on LED when link is full duplex - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 27 +++++++++++++++++++++++++-- - include/linux/leds.h | 2 ++ - 2 files changed, 27 insertions(+), 2 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -55,6 +55,7 @@ struct led_netdev_data { - - unsigned long mode; - int link_speed; -+ u8 duplex; - - bool carrier_link_up; - bool hw_control; -@@ -98,6 +99,14 @@ static void set_baseline_state(struct le - trigger_data->link_speed == SPEED_1000) - blink_on = true; - -+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && -+ trigger_data->duplex == DUPLEX_HALF) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) && -+ trigger_data->duplex == DUPLEX_FULL) -+ blink_on = true; -+ - if (blink_on) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); -@@ -190,8 +199,10 @@ static void get_device_state(struct led_ - if (!trigger_data->carrier_link_up) - return; - -- if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) -+ if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) { - trigger_data->link_speed = cmd.base.speed; -+ trigger_data->duplex = cmd.base.duplex; -+ } - } - - static ssize_t device_name_show(struct device *dev, -@@ -230,6 +241,7 @@ static int set_device_name(struct led_ne - - trigger_data->carrier_link_up = false; - trigger_data->link_speed = SPEED_UNKNOWN; -+ trigger_data->duplex = DUPLEX_UNKNOWN; - if (trigger_data->net_dev != NULL) { - rtnl_lock(); - get_device_state(trigger_data); -@@ -274,6 +286,8 @@ static ssize_t netdev_led_attr_show(stru - case TRIGGER_NETDEV_LINK_10: - case TRIGGER_NETDEV_LINK_100: - case TRIGGER_NETDEV_LINK_1000: -+ case TRIGGER_NETDEV_HALF_DUPLEX: -+ case TRIGGER_NETDEV_FULL_DUPLEX: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -302,6 +316,8 @@ static ssize_t netdev_led_attr_store(str - case TRIGGER_NETDEV_LINK_10: - case TRIGGER_NETDEV_LINK_100: - case TRIGGER_NETDEV_LINK_1000: -+ case TRIGGER_NETDEV_HALF_DUPLEX: -+ case TRIGGER_NETDEV_FULL_DUPLEX: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -348,6 +364,8 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD - DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); - DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); - DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); -+DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); -+DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); - DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); - DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); - -@@ -394,6 +412,8 @@ static struct attribute *netdev_trig_att - &dev_attr_link_10.attr, - &dev_attr_link_100.attr, - &dev_attr_link_1000.attr, -+ &dev_attr_full_duplex.attr, -+ &dev_attr_half_duplex.attr, - &dev_attr_rx.attr, - &dev_attr_tx.attr, - &dev_attr_interval.attr, -@@ -425,6 +445,7 @@ static int netdev_trig_notify(struct not - - trigger_data->carrier_link_up = false; - trigger_data->link_speed = SPEED_UNKNOWN; -+ trigger_data->duplex = DUPLEX_UNKNOWN; - switch (evt) { - case NETDEV_CHANGENAME: - get_device_state(trigger_data); -@@ -487,7 +508,9 @@ static void netdev_trig_work(struct work - invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || - test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || - test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || -- test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); -+ test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); - interval = jiffies_to_msecs( - atomic_read(&trigger_data->interval)); - /* base state is ON (link present) */ ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -533,6 +533,8 @@ enum led_trigger_netdev_modes { - TRIGGER_NETDEV_LINK_10, - TRIGGER_NETDEV_LINK_100, - TRIGGER_NETDEV_LINK_1000, -+ TRIGGER_NETDEV_HALF_DUPLEX, -+ TRIGGER_NETDEV_FULL_DUPLEX, - TRIGGER_NETDEV_TX, - TRIGGER_NETDEV_RX, - diff --git a/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch b/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch deleted file mode 100644 index 67528cafe0..0000000000 --- a/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b655892ffd6d89b0c7407e099c40dbde82ee3f03 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 19 Jun 2023 22:47:00 +0200 -Subject: [PATCH 3/3] leds: trigger: netdev: expose hw_control status via sysfs - -Expose hw_control status via sysfs for the netdev trigger to give -userspace better understanding of the current state of the trigger and -the LED. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Reviewed-by: Kalesh AP -Acked-by: Lee Jones -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -406,6 +406,16 @@ static ssize_t interval_store(struct dev - - static DEVICE_ATTR_RW(interval); - -+static ssize_t hw_control_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -+ -+ return sprintf(buf, "%d\n", trigger_data->hw_control); -+} -+ -+static DEVICE_ATTR_RO(hw_control); -+ - static struct attribute *netdev_trig_attrs[] = { - &dev_attr_device_name.attr, - &dev_attr_link.attr, -@@ -417,6 +427,7 @@ static struct attribute *netdev_trig_att - &dev_attr_rx.attr, - &dev_attr_tx.attr, - &dev_attr_interval.attr, -+ &dev_attr_hw_control.attr, - NULL - }; - ATTRIBUTE_GROUPS(netdev_trig); diff --git a/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch b/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch deleted file mode 100644 index ac322e1939..0000000000 --- a/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 2555f35a4f428a9bfdf09aa0459dbfdf59a24a9a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 21 Jun 2023 11:54:09 +0200 -Subject: [PATCH] net: dsa: qca8k: add support for additional modes for netdev - trigger - -The QCA8K switch supports additional modes that can be handled in -hardware for the LED netdev trigger. - -Add these additional modes to further support the Switch LEDs and -offload more blink modes. - -Add additional modes: -- link_10 -- link_100 -- link_1000 -- half_duplex -- full_duplex - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230621095409.25859-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/qca/qca8k-leds.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -68,6 +68,16 @@ qca8k_parse_netdev(unsigned long rules, - *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; - if (test_bit(TRIGGER_NETDEV_RX, &rules)) - *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; -+ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -+ *offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK; -+ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) -+ *offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK; -+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) -+ *offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK; -+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) -+ *offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK; -+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) -+ *offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK; - - if (rules && !*offload_trigger) - return -EOPNOTSUPP; -@@ -322,6 +332,16 @@ qca8k_cled_hw_control_get(struct led_cla - set_bit(TRIGGER_NETDEV_TX, rules); - if (val & QCA8K_LED_RX_BLINK_MASK) - set_bit(TRIGGER_NETDEV_RX, rules); -+ if (val & QCA8K_LED_LINK_10M_EN_MASK) -+ set_bit(TRIGGER_NETDEV_LINK_10, rules); -+ if (val & QCA8K_LED_LINK_100M_EN_MASK) -+ set_bit(TRIGGER_NETDEV_LINK_100, rules); -+ if (val & QCA8K_LED_LINK_1000M_EN_MASK) -+ set_bit(TRIGGER_NETDEV_LINK_1000, rules); -+ if (val & QCA8K_LED_HALF_DUPLEX_MASK) -+ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); -+ if (val & QCA8K_LED_FULL_DUPLEX_MASK) -+ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch b/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch deleted file mode 100644 index 58777cd280..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 4f86eb098e18fd0f032877dfa1a7e8c1503ca409 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:41 +0200 -Subject: [PATCH 1/6] net: dsa: mv88e6xxx: pass directly chip structure to - mv88e6xxx_phy_is_internal -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since this function is a simple helper, we do not need to pass a full -dsa_switch structure, we can directly pass the mv88e6xxx_chip structure. -Doing so will allow to share this function with any other function -not manipulating dsa_switch structure but needing info about number of -internal phys - -Signed-off-by: Alexis Lothoré -Reviewed-by: Russell King (Oracle) -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -470,10 +470,8 @@ restore_link: - return err; - } - --static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) -+static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) - { -- struct mv88e6xxx_chip *chip = ds->priv; -- - return port < chip->info->num_internal_phys; - } - -@@ -591,7 +589,7 @@ static void mv88e6095_phylink_get_caps(s - - config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; - -- if (mv88e6xxx_phy_is_internal(chip->ds, port)) { -+ if (mv88e6xxx_phy_is_internal(chip, port)) { - __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); - } else { - if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) && -@@ -839,7 +837,7 @@ static void mv88e6xxx_get_caps(struct ds - chip->info->ops->phylink_get_caps(chip, port, config); - mv88e6xxx_reg_unlock(chip); - -- if (mv88e6xxx_phy_is_internal(ds, port)) { -+ if (mv88e6xxx_phy_is_internal(chip, port)) { - __set_bit(PHY_INTERFACE_MODE_INTERNAL, - config->supported_interfaces); - /* Internal ports with no phy-mode need GMII for PHYLIB */ -@@ -860,7 +858,7 @@ static void mv88e6xxx_mac_config(struct - - mv88e6xxx_reg_lock(chip); - -- if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { -+ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) { - /* In inband mode, the link may come up at any time while the - * link is not forced down. Force the link down while we - * reconfigure the interface mode. diff --git a/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch b/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch deleted file mode 100644 index 75a21a931d..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 73cbfad9296eed004992806e056db5b48583ca41 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:42 +0200 -Subject: [PATCH 2/6] net: dsa: mv88e6xxx: use mv88e6xxx_phy_is_internal in - mv88e6xxx_port_ppu_updates -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make sure to use existing helper to get internal PHYs count instead of -redoing it manually - -Signed-off-by: Alexis Lothoré -Reviewed-by: Russell King (Oracle) -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -484,7 +484,7 @@ static int mv88e6xxx_port_ppu_updates(st - * report whether the port is internal. - */ - if (chip->info->family == MV88E6XXX_FAMILY_6250) -- return port < chip->info->num_internal_phys; -+ return mv88e6xxx_phy_is_internal(chip, port); - - err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); - if (err) { diff --git a/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch b/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch deleted file mode 100644 index e24dca819b..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 1414d30660d201f515a9d877571ceea9ca190b6a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:43 +0200 -Subject: [PATCH 3/6] net: dsa: mv88e6xxx: add field to specify internal phys - layout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -mv88e6xxx currently assumes that switch equipped with internal phys have -those phys mapped contiguously starting from port 0 (see -mv88e6xxx_phy_is_internal). However, some switches have internal PHYs but -NOT starting from port 0. For example 88e6393X, 88E6193X and 88E6191X have -integrated PHYs available on ports 1 to 8 -To properly support this offset, add a new field to allow specifying an -internal PHYs layout. If field is not set, default layout is assumed (start -at port 0) - -Signed-off-by: Alexis Lothoré -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 4 +++- - drivers/net/dsa/mv88e6xxx/chip.h | 5 +++++ - drivers/net/dsa/mv88e6xxx/global2.c | 5 ++++- - 3 files changed, 12 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -472,7 +472,9 @@ restore_link: - - static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) - { -- return port < chip->info->num_internal_phys; -+ return port >= chip->info->internal_phys_offset && -+ port < chip->info->num_internal_phys + -+ chip->info->internal_phys_offset; - } - - static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -167,6 +167,11 @@ struct mv88e6xxx_info { - - /* Supports PTP */ - bool ptp_support; -+ -+ /* Internal PHY start index. 0 means that internal PHYs range starts at -+ * port 0, 1 means internal PHYs range starts at port 1, etc -+ */ -+ unsigned int internal_phys_offset; - }; - - struct mv88e6xxx_atu_entry { ---- a/drivers/net/dsa/mv88e6xxx/global2.c -+++ b/drivers/net/dsa/mv88e6xxx/global2.c -@@ -1185,8 +1185,11 @@ int mv88e6xxx_g2_irq_mdio_setup(struct m - struct mii_bus *bus) - { - int phy, irq, err, err_phy; -+ int phy_start = chip->info->internal_phys_offset; -+ int phy_end = chip->info->internal_phys_offset + -+ chip->info->num_internal_phys; - -- for (phy = 0; phy < chip->info->num_internal_phys; phy++) { -+ for (phy = phy_start; phy < phy_end; phy++) { - irq = irq_find_mapping(chip->g2_irq.domain, phy); - if (irq < 0) { - err = irq; diff --git a/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch b/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch deleted file mode 100644 index 12ea3ebda0..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch +++ /dev/null @@ -1,52 +0,0 @@ -From eb8c75f82a6711387f3b9e03e28923f3e75a761b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:44 +0200 -Subject: [PATCH 4/6] net: dsa: mv88e6xxx: fix 88E6393X family internal phys - layout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -88E6393X/88E6193X/88E6191X switches have in fact 8 internal PHYs, but those -are not present starting at port 0: supported ports go from 1 to 8 - -Signed-off-by: Alexis Lothoré -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -5944,7 +5944,8 @@ static const struct mv88e6xxx_info mv88e - .name = "Marvell 88E6191X", - .num_databases = 4096, - .num_ports = 11, /* 10 + Z80 */ -- .num_internal_phys = 9, -+ .num_internal_phys = 8, -+ .internal_phys_offset = 1, - .max_vid = 8191, - .max_sid = 63, - .port_base_addr = 0x0, -@@ -5967,7 +5968,8 @@ static const struct mv88e6xxx_info mv88e - .name = "Marvell 88E6193X", - .num_databases = 4096, - .num_ports = 11, /* 10 + Z80 */ -- .num_internal_phys = 9, -+ .num_internal_phys = 8, -+ .internal_phys_offset = 1, - .max_vid = 8191, - .max_sid = 63, - .port_base_addr = 0x0, -@@ -6286,7 +6288,8 @@ static const struct mv88e6xxx_info mv88e - .name = "Marvell 88E6393X", - .num_databases = 4096, - .num_ports = 11, /* 10 + Z80 */ -- .num_internal_phys = 9, -+ .num_internal_phys = 8, -+ .internal_phys_offset = 1, - .max_vid = 8191, - .max_sid = 63, - .port_base_addr = 0x0, diff --git a/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch b/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch deleted file mode 100644 index 72dfcee82c..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch +++ /dev/null @@ -1,110 +0,0 @@ -From cef945452c8468efce75ba0dc8420510a5b84af9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:45 +0200 -Subject: [PATCH 5/6] net: dsa: mv88e6xxx: pass mv88e6xxx_chip structure to - port_max_speed_mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some switches families have minor differences on supported link speed for -ports. Instead of redefining a new port_max_speed_mode for each different -configuration, allow to pass mv88e6xxx_chip structure to allow -differentiating those chips by known chip id - -Signed-off-by: Alexis Lothoré -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 2 +- - drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- - drivers/net/dsa/mv88e6xxx/port.c | 12 ++++++++---- - drivers/net/dsa/mv88e6xxx/port.h | 12 ++++++++---- - 4 files changed, 19 insertions(+), 10 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3328,7 +3328,7 @@ static int mv88e6xxx_setup_port(struct m - caps = pl_config.mac_capabilities; - - if (chip->info->ops->port_max_speed_mode) -- mode = chip->info->ops->port_max_speed_mode(port); -+ mode = chip->info->ops->port_max_speed_mode(chip, port); - else - mode = PHY_INTERFACE_MODE_NA; - ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -508,7 +508,8 @@ struct mv88e6xxx_ops { - int speed, int duplex); - - /* What interface mode should be used for maximum speed? */ -- phy_interface_t (*port_max_speed_mode)(int port); -+ phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip, -+ int port); - - int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); - ---- a/drivers/net/dsa/mv88e6xxx/port.c -+++ b/drivers/net/dsa/mv88e6xxx/port.c -@@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(stru - duplex); - } - --phy_interface_t mv88e6341_port_max_speed_mode(int port) -+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 5) - return PHY_INTERFACE_MODE_2500BASEX; -@@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(stru - duplex); - } - --phy_interface_t mv88e6390_port_max_speed_mode(int port) -+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 9 || port == 10) - return PHY_INTERFACE_MODE_2500BASEX; -@@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(str - duplex); - } - --phy_interface_t mv88e6390x_port_max_speed_mode(int port) -+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 9 || port == 10) - return PHY_INTERFACE_MODE_XAUI; -@@ -500,7 +503,8 @@ int mv88e6393x_port_set_speed_duplex(str - return 0; - } - --phy_interface_t mv88e6393x_port_max_speed_mode(int port) -+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 0 || port == 9 || port == 10) - return PHY_INTERFACE_MODE_10GBASER; ---- a/drivers/net/dsa/mv88e6xxx/port.h -+++ b/drivers/net/dsa/mv88e6xxx/port.h -@@ -359,10 +359,14 @@ int mv88e6390x_port_set_speed_duplex(str - int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, - int speed, int duplex); - --phy_interface_t mv88e6341_port_max_speed_mode(int port); --phy_interface_t mv88e6390_port_max_speed_mode(int port); --phy_interface_t mv88e6390x_port_max_speed_mode(int port); --phy_interface_t mv88e6393x_port_max_speed_mode(int port); -+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); -+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); -+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); -+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); - - int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); - diff --git a/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch b/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch deleted file mode 100644 index dc6d5497f2..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 23680321789863bab2d60af507858ce50ff9f56a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:46 +0200 -Subject: [PATCH 6/6] net: dsa: mv88e6xxx: enable support for 88E6361 switch -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Marvell 88E6361 is an 8-port switch derived from the -88E6393X/88E9193X/88E6191X switches family. It can benefit from the -existing mv88e6xxx driver by simply adding the proper switch description in -the driver. Main differences with other switches from this -family are: -- 8 ports exposed (instead of 11): ports 1, 2 and 8 not available -- No 5GBase-x nor SFI/USXGMII support - -Signed-off-by: Alexis Lothoré -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 42 ++++++++++++++++++++++++++++---- - drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- - drivers/net/dsa/mv88e6xxx/port.c | 14 ++++++++--- - drivers/net/dsa/mv88e6xxx/port.h | 1 + - 4 files changed, 51 insertions(+), 9 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -797,6 +797,8 @@ static void mv88e6393x_phylink_get_caps( - unsigned long *supported = config->supported_interfaces; - bool is_6191x = - chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; -+ bool is_6361 = -+ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361; - - mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); - -@@ -811,13 +813,17 @@ static void mv88e6393x_phylink_get_caps( - /* 6191X supports >1G modes only on port 10 */ - if (!is_6191x || port == 10) { - __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); -- __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); -- __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); -+ config->mac_capabilities |= MAC_2500FD; -+ -+ /* 6361 only supports up to 2500BaseX */ -+ if (!is_6361) { -+ __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); -+ config->mac_capabilities |= MAC_5000FD | -+ MAC_10000FD; -+ } - /* FIXME: USXGMII is not supported yet */ - /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */ -- -- config->mac_capabilities |= MAC_2500FD | MAC_5000FD | -- MAC_10000FD; - } - } - -@@ -6231,6 +6237,32 @@ static const struct mv88e6xxx_info mv88e - .ptp_support = true, - .ops = &mv88e6352_ops, - }, -+ [MV88E6361] = { -+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361, -+ .family = MV88E6XXX_FAMILY_6393, -+ .name = "Marvell 88E6361", -+ .num_databases = 4096, -+ .num_macs = 16384, -+ .num_ports = 11, -+ /* Ports 1, 2 and 8 are not routed */ -+ .invalid_port_mask = BIT(1) | BIT(2) | BIT(8), -+ .num_internal_phys = 5, -+ .internal_phys_offset = 3, -+ .max_vid = 4095, -+ .max_sid = 63, -+ .port_base_addr = 0x0, -+ .phy_base_addr = 0x0, -+ .global1_addr = 0x1b, -+ .global2_addr = 0x1c, -+ .age_time_coeff = 3750, -+ .g1_irqs = 10, -+ .g2_irqs = 14, -+ .atu_move_port_mask = 0x1f, -+ .pvt = true, -+ .multi_chip = true, -+ .ptp_support = true, -+ .ops = &mv88e6393x_ops, -+ }, - [MV88E6390] = { - .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, - .family = MV88E6XXX_FAMILY_6390, ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -82,6 +82,7 @@ enum mv88e6xxx_model { - MV88E6350, - MV88E6351, - MV88E6352, -+ MV88E6361, - MV88E6390, - MV88E6390X, - MV88E6393X, -@@ -100,7 +101,7 @@ enum mv88e6xxx_family { - MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ - MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ - MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ -- MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */ -+ MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */ - }; - - /** ---- a/drivers/net/dsa/mv88e6xxx/port.c -+++ b/drivers/net/dsa/mv88e6xxx/port.c -@@ -424,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(str - u16 reg, ctrl; - int err; - -+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 && -+ speed > 2500) -+ return -EOPNOTSUPP; -+ - if (speed == 200 && port != 0) - return -EOPNOTSUPP; - -@@ -506,10 +510,14 @@ int mv88e6393x_port_set_speed_duplex(str - phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, - int port) - { -- if (port == 0 || port == 9 || port == 10) -- return PHY_INTERFACE_MODE_10GBASER; - -- return PHY_INTERFACE_MODE_NA; -+ if (port != 0 && port != 9 && port != 10) -+ return PHY_INTERFACE_MODE_NA; -+ -+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361) -+ return PHY_INTERFACE_MODE_2500BASEX; -+ -+ return PHY_INTERFACE_MODE_10GBASER; - } - - static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, ---- a/drivers/net/dsa/mv88e6xxx/port.h -+++ b/drivers/net/dsa/mv88e6xxx/port.h -@@ -133,6 +133,7 @@ - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 -+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 diff --git a/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch b/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch deleted file mode 100644 index 33759632eb..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch +++ /dev/null @@ -1,82 +0,0 @@ -From fbfc4ca465a1f8d81bf2d67d95bf7fc67c3cf0c2 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Fri, 18 Nov 2022 06:39:20 +0000 -Subject: [PATCH] nvmem: stm32: move STM32MP15_BSEC_NUM_LOWER in config - -Support STM32MP15_BSEC_NUM_LOWER in stm32 romem config to prepare -the next SoC in STM32MP family. - -Signed-off-by: Patrick Delaunay -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-2-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 21 ++++++++++++++++----- - 1 file changed, 16 insertions(+), 5 deletions(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -22,16 +22,15 @@ - /* shadow registers offest */ - #define STM32MP15_BSEC_DATA0 0x200 - --/* 32 (x 32-bits) lower shadow registers */ --#define STM32MP15_BSEC_NUM_LOWER 32 -- - struct stm32_romem_cfg { - int size; -+ u8 lower; - }; - - struct stm32_romem_priv { - void __iomem *base; - struct nvmem_config cfg; -+ u8 lower; - }; - - static int stm32_romem_read(void *context, unsigned int offset, void *buf, -@@ -85,7 +84,7 @@ static int stm32_bsec_read(void *context - for (i = roffset; (i < roffset + rbytes); i += 4) { - u32 otp = i >> 2; - -- if (otp < STM32MP15_BSEC_NUM_LOWER) { -+ if (otp < priv->lower) { - /* read lower data from shadow registers */ - val = readl_relaxed( - priv->base + STM32MP15_BSEC_DATA0 + i); -@@ -159,6 +158,8 @@ static int stm32_romem_probe(struct plat - priv->cfg.priv = priv; - priv->cfg.owner = THIS_MODULE; - -+ priv->lower = 0; -+ - cfg = (const struct stm32_romem_cfg *) - of_match_device(dev->driver->of_match_table, dev)->data; - if (!cfg) { -@@ -167,6 +168,7 @@ static int stm32_romem_probe(struct plat - priv->cfg.reg_read = stm32_romem_read; - } else { - priv->cfg.size = cfg->size; -+ priv->lower = cfg->lower; - priv->cfg.reg_read = stm32_bsec_read; - priv->cfg.reg_write = stm32_bsec_write; - } -@@ -174,8 +176,17 @@ static int stm32_romem_probe(struct plat - return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); - } - -+/* -+ * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) -+ * => 96 x 32-bits data words -+ * - Lower: 1K bits, 2:1 redundancy, incremental bit programming -+ * => 32 (x 32-bits) lower shadow registers = words 0 to 31 -+ * - Upper: 2K bits, ECC protection, word programming only -+ * => 64 (x 32-bits) = words 32 to 95 -+ */ - static const struct stm32_romem_cfg stm32mp15_bsec_cfg = { -- .size = 384, /* 96 x 32-bits data words */ -+ .size = 384, -+ .lower = 32, - }; - - static const struct of_device_id stm32_romem_of_match[] = { diff --git a/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch b/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch deleted file mode 100644 index 5791df2606..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch +++ /dev/null @@ -1,34 +0,0 @@ -From d61784e6410f3df2028e6eb91b06ffed37a660e0 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Fri, 18 Nov 2022 06:39:21 +0000 -Subject: [PATCH] nvmem: stm32: add warning when upper OTPs are updated - -As the upper OTPs are ECC protected, they support only one 32 bits word -programming. -For a second modification of this word, these ECC become invalid and -this OTP will be no more accessible, the shadowed value is invalid. - -This patch adds a warning to indicate an upper OTP update, because this -operation is dangerous as OTP is not locked by the driver after the first -update to avoid a second update. - -Signed-off-by: Patrick Delaunay -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-3-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -132,6 +132,9 @@ static int stm32_bsec_write(void *contex - } - } - -+ if (offset + bytes >= priv->lower * 4) -+ dev_warn(dev, "Update of upper OTPs with ECC protection (word programming, only once)\n"); -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch b/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch deleted file mode 100644 index b83ad69c6b..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a3816a7d7c097c1da46aad5f5d1e229b607dce04 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Fri, 18 Nov 2022 06:39:22 +0000 -Subject: [PATCH] nvmem: stm32: add nvmem type attribute - -Inform NVMEM framework of type attribute for stm32-romem as NVMEM_TYPE_OTP -so userspace is able to know how the data is stored in BSEC. - -Signed-off-by: Patrick Delaunay -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-4-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -160,6 +160,7 @@ static int stm32_romem_probe(struct plat - priv->cfg.dev = dev; - priv->cfg.priv = priv; - priv->cfg.owner = THIS_MODULE; -+ priv->cfg.type = NVMEM_TYPE_OTP; - - priv->lower = 0; - diff --git a/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch b/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch deleted file mode 100644 index 52ba1e65b5..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 06aac0e11960a7ddccc1888326b5906d017e0f24 Mon Sep 17 00:00:00 2001 -From: Jiangshan Yi -Date: Fri, 18 Nov 2022 06:39:24 +0000 -Subject: [PATCH] nvmem: stm32: fix spelling typo in comment - -Fix spelling typo in comment. - -Reported-by: k2ci -Signed-off-by: Jiangshan Yi -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-6-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -19,7 +19,7 @@ - #define STM32_SMC_WRITE_SHADOW 0x03 - #define STM32_SMC_READ_OTP 0x04 - --/* shadow registers offest */ -+/* shadow registers offset */ - #define STM32MP15_BSEC_DATA0 0x200 - - struct stm32_romem_cfg { diff --git a/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch b/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch deleted file mode 100644 index 8f024f4c1a..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch +++ /dev/null @@ -1,27 +0,0 @@ -From fb817c4ef63e8cfb6e77ae4a2875ae854c80708f Mon Sep 17 00:00:00 2001 -From: Colin Ian King -Date: Fri, 18 Nov 2022 06:39:26 +0000 -Subject: [PATCH] nvmem: Kconfig: Fix spelling mistake "controlls" -> - "controls" - -There is a spelling mistake in a Kconfig description. Fix it. - -Signed-off-by: Colin Ian King -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -164,7 +164,7 @@ config NVMEM_MICROCHIP_OTPC - depends on ARCH_AT91 || COMPILE_TEST - help - This driver enable the OTP controller available on Microchip SAMA7G5 -- SoCs. It controlls the access to the OTP memory connected to it. -+ SoCs. It controls the access to the OTP memory connected to it. - - config NVMEM_MTK_EFUSE - tristate "Mediatek SoCs EFUSE support" diff --git a/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch b/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch deleted file mode 100644 index 861386ad31..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch +++ /dev/null @@ -1,67 +0,0 @@ -From ada84d07af6097b2addd18262668ce6cb9e15206 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 18 Nov 2022 06:39:27 +0000 -Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They -decided to store U-Boot environment data inside U-Boot partition and to -use a custom header (with "uEnv" magic and env data length). - -Add support for Broadcom's specific binding and their custom format. - -Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding") -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/u-boot-env.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -16,6 +16,7 @@ - enum u_boot_env_format { - U_BOOT_FORMAT_SINGLE, - U_BOOT_FORMAT_REDUNDANT, -+ U_BOOT_FORMAT_BROADCOM, - }; - - struct u_boot_env { -@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant { - uint8_t data[]; - } __packed; - -+struct u_boot_env_image_broadcom { -+ __le32 magic; -+ __le32 len; -+ __le32 crc32; -+ uint8_t data[0]; -+} __packed; -+ - static int u_boot_env_read(void *context, unsigned int offset, void *val, - size_t bytes) - { -@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo - crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); - data_offset = offsetof(struct u_boot_env_image_redundant, data); - break; -+ case U_BOOT_FORMAT_BROADCOM: -+ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); -+ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); -+ data_offset = offsetof(struct u_boot_env_image_broadcom, data); -+ break; - } - crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); - crc32_data_len = priv->mtd->size - crc32_data_offset; -@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_ - { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, - { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, - { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, -+ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, - {}, - }; - diff --git a/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch b/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch deleted file mode 100644 index 01400fd490..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2e8dc541ae207349b51c65391be625ffe1f86e0c Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Mon, 6 Feb 2023 13:43:41 +0000 -Subject: [PATCH] nvmem: core: remove spurious white space - -Remove a spurious white space in for the ida_alloc() call. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -764,7 +764,7 @@ struct nvmem_device *nvmem_register(cons - if (!nvmem) - return ERR_PTR(-ENOMEM); - -- rval = ida_alloc(&nvmem_ida, GFP_KERNEL); -+ rval = ida_alloc(&nvmem_ida, GFP_KERNEL); - if (rval < 0) { - kfree(nvmem); - return ERR_PTR(rval); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch b/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch deleted file mode 100644 index 454d3bf0ed..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 5d8e6e6c10a3d37486d263b16ddc15991a7e4a88 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:46 +0000 -Subject: [PATCH] nvmem: core: add an index parameter to the cell - -Sometimes a cell can represend multiple values. For example, a base -ethernet address stored in the NVMEM can be expanded into multiple -discreet ones by adding an offset. - -For this use case, introduce an index parameter which is then used to -distiguish between values. This parameter will then be passed to the -post process hook which can then use it to create different values -during reading. - -At the moment, there is only support for the device tree path. You can -add the index to the phandle, e.g. - - &net { - nvmem-cells = <&base_mac_address 2>; - nvmem-cell-names = "mac-address"; - }; - - &nvmem_provider { - base_mac_address: base-mac-address@0 { - #nvmem-cell-cells = <1>; - reg = <0 6>; - }; - }; - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-13-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 37 ++++++++++++++++++++++++---------- - drivers/nvmem/imx-ocotp.c | 4 ++-- - include/linux/nvmem-provider.h | 4 ++-- - 3 files changed, 30 insertions(+), 15 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -60,6 +60,7 @@ struct nvmem_cell_entry { - struct nvmem_cell { - struct nvmem_cell_entry *entry; - const char *id; -+ int index; - }; - - static DEFINE_MUTEX(nvmem_mutex); -@@ -1122,7 +1123,8 @@ struct nvmem_device *devm_nvmem_device_g - } - EXPORT_SYMBOL_GPL(devm_nvmem_device_get); - --static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id) -+static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, -+ const char *id, int index) - { - struct nvmem_cell *cell; - const char *name = NULL; -@@ -1141,6 +1143,7 @@ static struct nvmem_cell *nvmem_create_c - - cell->id = name; - cell->entry = entry; -+ cell->index = index; - - return cell; - } -@@ -1179,7 +1182,7 @@ nvmem_cell_get_from_lookup(struct device - __nvmem_device_put(nvmem); - cell = ERR_PTR(-ENOENT); - } else { -- cell = nvmem_create_cell(cell_entry, con_id); -+ cell = nvmem_create_cell(cell_entry, con_id, 0); - if (IS_ERR(cell)) - __nvmem_device_put(nvmem); - } -@@ -1227,15 +1230,27 @@ struct nvmem_cell *of_nvmem_cell_get(str - struct nvmem_device *nvmem; - struct nvmem_cell_entry *cell_entry; - struct nvmem_cell *cell; -+ struct of_phandle_args cell_spec; - int index = 0; -+ int cell_index = 0; -+ int ret; - - /* if cell name exists, find index to the name */ - if (id) - index = of_property_match_string(np, "nvmem-cell-names", id); - -- cell_np = of_parse_phandle(np, "nvmem-cells", index); -- if (!cell_np) -- return ERR_PTR(-ENOENT); -+ ret = of_parse_phandle_with_optional_args(np, "nvmem-cells", -+ "#nvmem-cell-cells", -+ index, &cell_spec); -+ if (ret) -+ return ERR_PTR(ret); -+ -+ if (cell_spec.args_count > 1) -+ return ERR_PTR(-EINVAL); -+ -+ cell_np = cell_spec.np; -+ if (cell_spec.args_count) -+ cell_index = cell_spec.args[0]; - - nvmem_np = of_get_parent(cell_np); - if (!nvmem_np) { -@@ -1257,7 +1272,7 @@ struct nvmem_cell *of_nvmem_cell_get(str - return ERR_PTR(-ENOENT); - } - -- cell = nvmem_create_cell(cell_entry, id); -+ cell = nvmem_create_cell(cell_entry, id, cell_index); - if (IS_ERR(cell)) - __nvmem_device_put(nvmem); - -@@ -1410,8 +1425,8 @@ static void nvmem_shift_read_buffer_in_p - } - - static int __nvmem_cell_read(struct nvmem_device *nvmem, -- struct nvmem_cell_entry *cell, -- void *buf, size_t *len, const char *id) -+ struct nvmem_cell_entry *cell, -+ void *buf, size_t *len, const char *id, int index) - { - int rc; - -@@ -1425,7 +1440,7 @@ static int __nvmem_cell_read(struct nvme - nvmem_shift_read_buffer_in_place(cell, buf); - - if (nvmem->cell_post_process) { -- rc = nvmem->cell_post_process(nvmem->priv, id, -+ rc = nvmem->cell_post_process(nvmem->priv, id, index, - cell->offset, buf, cell->bytes); - if (rc) - return rc; -@@ -1460,7 +1475,7 @@ void *nvmem_cell_read(struct nvmem_cell - if (!buf) - return ERR_PTR(-ENOMEM); - -- rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id); -+ rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id, cell->index); - if (rc) { - kfree(buf); - return ERR_PTR(rc); -@@ -1773,7 +1788,7 @@ ssize_t nvmem_device_cell_read(struct nv - if (rc) - return rc; - -- rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL); -+ rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL, 0); - if (rc) - return rc; - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -222,8 +222,8 @@ read_end: - return ret; - } - --static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset, -- void *data, size_t bytes) -+static int imx_ocotp_cell_pp(void *context, const char *id, int index, -+ unsigned int offset, void *data, size_t bytes) - { - struct ocotp_priv *priv = context; - ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -20,8 +20,8 @@ typedef int (*nvmem_reg_read_t)(void *pr - typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, - void *val, size_t bytes); - /* used for vendor specific post processing of cell data */ --typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset, -- void *buf, size_t bytes); -+typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index, -+ unsigned int offset, void *buf, size_t bytes); - - enum nvmem_type { - NVMEM_TYPE_UNKNOWN = 0, diff --git a/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch b/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch deleted file mode 100644 index f3829b3e17..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch +++ /dev/null @@ -1,78 +0,0 @@ -From fbd03d27776c6121a483921601418e3c8f0ff37e Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:47 +0000 -Subject: [PATCH] nvmem: core: move struct nvmem_cell_info to nvmem-provider.h - -struct nvmem_cell_info is used to describe a cell. Thus this should -really be in the nvmem-provider's header. There are two (unused) nvmem -access methods which use the nvmem_cell_info to describe the cell to be -accesses. One can argue, that they will create a cell before accessing, -thus they are both a provider and a consumer. - -struct nvmem_cell_info will get used more and more by nvmem-providers, -don't force them to also include the consumer header, although they are -not. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-14-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/nvmem-consumer.h | 10 +--------- - include/linux/nvmem-provider.h | 19 ++++++++++++++++++- - 2 files changed, 19 insertions(+), 10 deletions(-) - ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -18,15 +18,7 @@ struct device_node; - /* consumer cookie */ - struct nvmem_cell; - struct nvmem_device; -- --struct nvmem_cell_info { -- const char *name; -- unsigned int offset; -- unsigned int bytes; -- unsigned int bit_offset; -- unsigned int nbits; -- struct device_node *np; --}; -+struct nvmem_cell_info; - - /** - * struct nvmem_cell_lookup - cell lookup entry ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -14,7 +14,6 @@ - #include - - struct nvmem_device; --struct nvmem_cell_info; - typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset, - void *val, size_t bytes); - typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, -@@ -48,6 +47,24 @@ struct nvmem_keepout { - }; - - /** -+ * struct nvmem_cell_info - NVMEM cell description -+ * @name: Name. -+ * @offset: Offset within the NVMEM device. -+ * @bytes: Length of the cell. -+ * @bit_offset: Bit offset if cell is smaller than a byte. -+ * @nbits: Number of bits. -+ * @np: Optional device_node pointer. -+ */ -+struct nvmem_cell_info { -+ const char *name; -+ unsigned int offset; -+ unsigned int bytes; -+ unsigned int bit_offset; -+ unsigned int nbits; -+ struct device_node *np; -+}; -+ -+/** - * struct nvmem_config - NVMEM device configuration - * - * @dev: Parent device. diff --git a/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch b/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch deleted file mode 100644 index 8f996eab34..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch +++ /dev/null @@ -1,65 +0,0 @@ -From cc5bdd323dde6494623f3ffe3a5b887fa21cd375 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:48 +0000 -Subject: [PATCH] nvmem: core: drop the removal of the cells in - nvmem_add_cells() - -If nvmem_add_cells() fails, the whole nvmem_register() will fail -and the cells will then be removed anyway. This is a preparation -to introduce a nvmem_add_one_cell() which can then be used by -nvmem_add_cells(). - -This is then the same to what nvmem_add_cells_from_table() and -nvmem_add_cells_from_of() do. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-15-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 14 ++++---------- - 1 file changed, 4 insertions(+), 10 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -515,7 +515,7 @@ static int nvmem_add_cells(struct nvmem_ - int ncells) - { - struct nvmem_cell_entry **cells; -- int i, rval; -+ int i, rval = 0; - - cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL); - if (!cells) -@@ -525,28 +525,22 @@ static int nvmem_add_cells(struct nvmem_ - cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL); - if (!cells[i]) { - rval = -ENOMEM; -- goto err; -+ goto out; - } - - rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]); - if (rval) { - kfree(cells[i]); -- goto err; -+ goto out; - } - - nvmem_cell_entry_add(cells[i]); - } - -+out: - /* remove tmp array */ - kfree(cells); - -- return 0; --err: -- while (i--) -- nvmem_cell_entry_drop(cells[i]); -- -- kfree(cells); -- - return rval; - } - diff --git a/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch b/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch deleted file mode 100644 index 711ce229b2..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 2ded6830d376d5e7bf43d59f7f7fdf1a59abc676 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:49 +0000 -Subject: [PATCH] nvmem: core: add nvmem_add_one_cell() - -Add a new function to add exactly one cell. This will be used by the -nvmem layout drivers to add custom cells. In contrast to the -nvmem_add_cells(), this has the advantage that we don't have to assemble -a list of cells on runtime. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-16-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 59 ++++++++++++++++++++-------------- - include/linux/nvmem-provider.h | 8 +++++ - 2 files changed, 43 insertions(+), 24 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -502,6 +502,36 @@ static int nvmem_cell_info_to_nvmem_cell - } - - /** -+ * nvmem_add_one_cell() - Add one cell information to an nvmem device -+ * -+ * @nvmem: nvmem device to add cells to. -+ * @info: nvmem cell info to add to the device -+ * -+ * Return: 0 or negative error code on failure. -+ */ -+int nvmem_add_one_cell(struct nvmem_device *nvmem, -+ const struct nvmem_cell_info *info) -+{ -+ struct nvmem_cell_entry *cell; -+ int rval; -+ -+ cell = kzalloc(sizeof(*cell), GFP_KERNEL); -+ if (!cell) -+ return -ENOMEM; -+ -+ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell); -+ if (rval) { -+ kfree(cell); -+ return rval; -+ } -+ -+ nvmem_cell_entry_add(cell); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(nvmem_add_one_cell); -+ -+/** - * nvmem_add_cells() - Add cell information to an nvmem device - * - * @nvmem: nvmem device to add cells to. -@@ -514,34 +544,15 @@ static int nvmem_add_cells(struct nvmem_ - const struct nvmem_cell_info *info, - int ncells) - { -- struct nvmem_cell_entry **cells; -- int i, rval = 0; -- -- cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL); -- if (!cells) -- return -ENOMEM; -+ int i, rval; - - for (i = 0; i < ncells; i++) { -- cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL); -- if (!cells[i]) { -- rval = -ENOMEM; -- goto out; -- } -- -- rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]); -- if (rval) { -- kfree(cells[i]); -- goto out; -- } -- -- nvmem_cell_entry_add(cells[i]); -+ rval = nvmem_add_one_cell(nvmem, &info[i]); -+ if (rval) -+ return rval; - } - --out: -- /* remove tmp array */ -- kfree(cells); -- -- return rval; -+ return 0; - } - - /** ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -153,6 +153,9 @@ struct nvmem_device *devm_nvmem_register - void nvmem_add_cell_table(struct nvmem_cell_table *table); - void nvmem_del_cell_table(struct nvmem_cell_table *table); - -+int nvmem_add_one_cell(struct nvmem_device *nvmem, -+ const struct nvmem_cell_info *info); -+ - #else - - static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) -@@ -170,6 +173,11 @@ devm_nvmem_register(struct device *dev, - - static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {} - static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {} -+static inline int nvmem_add_one_cell(struct nvmem_device *nvmem, -+ const struct nvmem_cell_info *info) -+{ -+ return -EOPNOTSUPP; -+} - - #endif /* CONFIG_NVMEM */ - #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch b/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch deleted file mode 100644 index e1791e5c83..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 50014d659617dc58780a5d31ceb76c82779a9d8b Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:50 +0000 -Subject: [PATCH] nvmem: core: use nvmem_add_one_cell() in - nvmem_add_cells_from_of() - -Convert nvmem_add_cells_from_of() to use the new nvmem_add_one_cell(). -This will remove duplicate code and it will make it possible to add a -hook to a nvmem layout in between, which can change fields before the -cell is finally added. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-17-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 45 ++++++++++++++------------------------------ - 1 file changed, 14 insertions(+), 31 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -688,15 +688,14 @@ static int nvmem_validate_keepouts(struc - - static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) - { -- struct device_node *parent, *child; - struct device *dev = &nvmem->dev; -- struct nvmem_cell_entry *cell; -+ struct device_node *child; - const __be32 *addr; -- int len; -+ int len, ret; - -- parent = dev->of_node; -+ for_each_child_of_node(dev->of_node, child) { -+ struct nvmem_cell_info info = {0}; - -- for_each_child_of_node(parent, child) { - addr = of_get_property(child, "reg", &len); - if (!addr) - continue; -@@ -706,40 +705,24 @@ static int nvmem_add_cells_from_of(struc - return -EINVAL; - } - -- cell = kzalloc(sizeof(*cell), GFP_KERNEL); -- if (!cell) { -- of_node_put(child); -- return -ENOMEM; -- } -- -- cell->nvmem = nvmem; -- cell->offset = be32_to_cpup(addr++); -- cell->bytes = be32_to_cpup(addr); -- cell->name = kasprintf(GFP_KERNEL, "%pOFn", child); -+ info.offset = be32_to_cpup(addr++); -+ info.bytes = be32_to_cpup(addr); -+ info.name = kasprintf(GFP_KERNEL, "%pOFn", child); - - addr = of_get_property(child, "bits", &len); - if (addr && len == (2 * sizeof(u32))) { -- cell->bit_offset = be32_to_cpup(addr++); -- cell->nbits = be32_to_cpup(addr); -+ info.bit_offset = be32_to_cpup(addr++); -+ info.nbits = be32_to_cpup(addr); - } - -- if (cell->nbits) -- cell->bytes = DIV_ROUND_UP( -- cell->nbits + cell->bit_offset, -- BITS_PER_BYTE); -- -- if (!IS_ALIGNED(cell->offset, nvmem->stride)) { -- dev_err(dev, "cell %s unaligned to nvmem stride %d\n", -- cell->name, nvmem->stride); -- /* Cells already added will be freed later. */ -- kfree_const(cell->name); -- kfree(cell); -+ info.np = of_node_get(child); -+ -+ ret = nvmem_add_one_cell(nvmem, &info); -+ kfree(info.name); -+ if (ret) { - of_node_put(child); -- return -EINVAL; -+ return ret; - } -- -- cell->np = of_node_get(child); -- nvmem_cell_entry_add(cell); - } - - return 0; diff --git a/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch b/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch deleted file mode 100644 index 172a78b76a..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch +++ /dev/null @@ -1,562 +0,0 @@ -From 6a0bc3522e746025e2d9a63ab2cb5d7062c2d39c Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Mon, 6 Feb 2023 13:43:51 +0000 -Subject: [PATCH] nvmem: stm32: add OP-TEE support for STM32MP13x - -For boot with OP-TEE on STM32MP13, the communication with the secure -world no more use STMicroelectronics SMC but communication with the -STM32MP BSEC TA, for data access (read/write) or lock operation: -- all the request are sent to OP-TEE trusted application, -- for upper OTP with ECC protection and with word programming only - each OTP are permanently locked when programmed to avoid ECC error - on the second write operation - -Signed-off-by: Patrick Delaunay -Reviewed-by: Etienne Carriere -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-18-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 11 + - drivers/nvmem/Makefile | 1 + - drivers/nvmem/stm32-bsec-optee-ta.c | 298 ++++++++++++++++++++++++++++ - drivers/nvmem/stm32-bsec-optee-ta.h | 80 ++++++++ - drivers/nvmem/stm32-romem.c | 54 ++++- - 5 files changed, 441 insertions(+), 3 deletions(-) - create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.c - create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.h - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -290,9 +290,20 @@ config NVMEM_SPRD_EFUSE - This driver can also be built as a module. If so, the module - will be called nvmem-sprd-efuse. - -+config NVMEM_STM32_BSEC_OPTEE_TA -+ bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver" -+ depends on OPTEE -+ help -+ Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE -+ trusted application STM32MP BSEC. -+ -+ This library is a used by stm32-romem driver or included in the module -+ called nvmem-stm32-romem. -+ - config NVMEM_STM32_ROMEM - tristate "STMicroelectronics STM32 factory-programmed memory support" - depends on ARCH_STM32 || COMPILE_TEST -+ imply NVMEM_STM32_BSEC_OPTEE_TA - help - Say y here to enable read-only access for STMicroelectronics STM32 - factory-programmed memory area. ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -61,6 +61,7 @@ obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem - nvmem_sprd_efuse-y := sprd-efuse.o - obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o - nvmem_stm32_romem-y := stm32-romem.o -+nvmem_stm32_romem-$(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) += stm32-bsec-optee-ta.o - obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o - nvmem_sunplus_ocotp-y := sunplus-ocotp.o - obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o ---- /dev/null -+++ b/drivers/nvmem/stm32-bsec-optee-ta.c -@@ -0,0 +1,298 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver -+ * -+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+ -+#include "stm32-bsec-optee-ta.h" -+ -+/* -+ * Read OTP memory -+ * -+ * [in] value[0].a OTP start offset in byte -+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) -+ * [out] memref[1].buffer Output buffer to store read values -+ * [out] memref[1].size Size of OTP to be read -+ * -+ * Return codes: -+ * TEE_SUCCESS - Invoke command success -+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param -+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller -+ */ -+#define PTA_BSEC_READ_MEM 0x0 -+ -+/* -+ * Write OTP memory -+ * -+ * [in] value[0].a OTP start offset in byte -+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) -+ * [in] memref[1].buffer Input buffer to read values -+ * [in] memref[1].size Size of OTP to be written -+ * -+ * Return codes: -+ * TEE_SUCCESS - Invoke command success -+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param -+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller -+ */ -+#define PTA_BSEC_WRITE_MEM 0x1 -+ -+/* value of PTA_BSEC access type = value[in] b */ -+#define SHADOW_ACCESS 0 -+#define FUSE_ACCESS 1 -+#define LOCK_ACCESS 2 -+ -+/* Bitfield definition for LOCK status */ -+#define LOCK_PERM BIT(30) -+ -+/* OP-TEE STM32MP BSEC TA UUID */ -+static const uuid_t stm32mp_bsec_ta_uuid = -+ UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5, -+ 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03); -+ -+/* -+ * Check whether this driver supports the BSEC TA in the TEE instance -+ * represented by the params (ver/data) to this function. -+ */ -+static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver, -+ const void *data) -+{ -+ /* Currently this driver only supports GP compliant, OP-TEE based TA */ -+ if ((ver->impl_id == TEE_IMPL_ID_OPTEE) && -+ (ver->gen_caps & TEE_GEN_CAP_GP)) -+ return 1; -+ else -+ return 0; -+} -+ -+/* Open a session to OP-TEE for STM32MP BSEC TA */ -+static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id) -+{ -+ struct tee_ioctl_open_session_arg sess_arg; -+ int rc; -+ -+ memset(&sess_arg, 0, sizeof(sess_arg)); -+ export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid); -+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; -+ sess_arg.num_params = 0; -+ -+ rc = tee_client_open_session(ctx, &sess_arg, NULL); -+ if ((rc < 0) || (sess_arg.ret != 0)) { -+ pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n", -+ __func__, sess_arg.ret, rc); -+ if (!rc) -+ rc = -EINVAL; -+ } else { -+ *id = sess_arg.session; -+ } -+ -+ return rc; -+} -+ -+/* close a session to OP-TEE for STM32MP BSEC TA */ -+static void stm32_bsec_ta_close_session(void *ctx, u32 id) -+{ -+ tee_client_close_session(ctx, id); -+} -+ -+/* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */ -+int stm32_bsec_optee_ta_open(struct tee_context **ctx) -+{ -+ struct tee_context *tee_ctx; -+ u32 session_id; -+ int rc; -+ -+ /* Open context with TEE driver */ -+ tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL); -+ if (IS_ERR(tee_ctx)) { -+ rc = PTR_ERR(tee_ctx); -+ if (rc == -ENOENT) -+ return -EPROBE_DEFER; -+ pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc); -+ -+ return rc; -+ } -+ -+ /* Check STM32MP BSEC TA presence */ -+ rc = stm32_bsec_ta_open_session(tee_ctx, &session_id); -+ if (rc) { -+ tee_client_close_context(tee_ctx); -+ return rc; -+ } -+ -+ stm32_bsec_ta_close_session(tee_ctx, session_id); -+ -+ *ctx = tee_ctx; -+ -+ return 0; -+} -+ -+/* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */ -+void stm32_bsec_optee_ta_close(void *ctx) -+{ -+ tee_client_close_context(ctx); -+} -+ -+/* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */ -+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset, -+ void *buf, size_t bytes) -+{ -+ struct tee_shm *shm; -+ struct tee_ioctl_invoke_arg arg; -+ struct tee_param param[2]; -+ u8 *shm_buf; -+ u32 start, num_bytes; -+ int ret; -+ u32 session_id; -+ -+ ret = stm32_bsec_ta_open_session(ctx, &session_id); -+ if (ret) -+ return ret; -+ -+ memset(&arg, 0, sizeof(arg)); -+ memset(¶m, 0, sizeof(param)); -+ -+ arg.func = PTA_BSEC_READ_MEM; -+ arg.session = session_id; -+ arg.num_params = 2; -+ -+ /* align access on 32bits */ -+ start = ALIGN_DOWN(offset, 4); -+ num_bytes = round_up(offset + bytes - start, 4); -+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; -+ param[0].u.value.a = start; -+ param[0].u.value.b = SHADOW_ACCESS; -+ -+ shm = tee_shm_alloc_kernel_buf(ctx, num_bytes); -+ if (IS_ERR(shm)) { -+ ret = PTR_ERR(shm); -+ goto out_tee_session; -+ } -+ -+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; -+ param[1].u.memref.shm = shm; -+ param[1].u.memref.size = num_bytes; -+ -+ ret = tee_client_invoke_func(ctx, &arg, param); -+ if (ret < 0 || arg.ret != 0) { -+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", -+ arg.ret, ret); -+ if (!ret) -+ ret = -EIO; -+ } -+ if (!ret) { -+ shm_buf = tee_shm_get_va(shm, 0); -+ if (IS_ERR(shm_buf)) { -+ ret = PTR_ERR(shm_buf); -+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); -+ } else { -+ /* read data from 32 bits aligned buffer */ -+ memcpy(buf, &shm_buf[offset % 4], bytes); -+ } -+ } -+ -+ tee_shm_free(shm); -+ -+out_tee_session: -+ stm32_bsec_ta_close_session(ctx, session_id); -+ -+ return ret; -+} -+ -+/* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */ -+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower, -+ unsigned int offset, void *buf, size_t bytes) -+{ struct tee_shm *shm; -+ struct tee_ioctl_invoke_arg arg; -+ struct tee_param param[2]; -+ u8 *shm_buf; -+ int ret; -+ u32 session_id; -+ -+ ret = stm32_bsec_ta_open_session(ctx, &session_id); -+ if (ret) -+ return ret; -+ -+ /* Allow only writing complete 32-bits aligned words */ -+ if ((bytes % 4) || (offset % 4)) -+ return -EINVAL; -+ -+ memset(&arg, 0, sizeof(arg)); -+ memset(¶m, 0, sizeof(param)); -+ -+ arg.func = PTA_BSEC_WRITE_MEM; -+ arg.session = session_id; -+ arg.num_params = 2; -+ -+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; -+ param[0].u.value.a = offset; -+ param[0].u.value.b = FUSE_ACCESS; -+ -+ shm = tee_shm_alloc_kernel_buf(ctx, bytes); -+ if (IS_ERR(shm)) { -+ ret = PTR_ERR(shm); -+ goto out_tee_session; -+ } -+ -+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; -+ param[1].u.memref.shm = shm; -+ param[1].u.memref.size = bytes; -+ -+ shm_buf = tee_shm_get_va(shm, 0); -+ if (IS_ERR(shm_buf)) { -+ ret = PTR_ERR(shm_buf); -+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); -+ tee_shm_free(shm); -+ -+ goto out_tee_session; -+ } -+ -+ memcpy(shm_buf, buf, bytes); -+ -+ ret = tee_client_invoke_func(ctx, &arg, param); -+ if (ret < 0 || arg.ret != 0) { -+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); -+ if (!ret) -+ ret = -EIO; -+ } -+ pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret); -+ -+ /* Lock the upper OTPs with ECC protection, word programming only */ -+ if (!ret && ((offset + bytes) >= (lower * 4))) { -+ u32 start, nb_lock; -+ u32 *lock = (u32 *)shm_buf; -+ int i; -+ -+ /* -+ * don't lock the lower OTPs, no ECC protection and incremental -+ * bit programming, a second write is allowed -+ */ -+ start = max_t(u32, offset, lower * 4); -+ nb_lock = (offset + bytes - start) / 4; -+ -+ param[0].u.value.a = start; -+ param[0].u.value.b = LOCK_ACCESS; -+ param[1].u.memref.size = nb_lock * 4; -+ -+ for (i = 0; i < nb_lock; i++) -+ lock[i] = LOCK_PERM; -+ -+ ret = tee_client_invoke_func(ctx, &arg, param); -+ if (ret < 0 || arg.ret != 0) { -+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); -+ if (!ret) -+ ret = -EIO; -+ } -+ pr_debug("Lock upper OTPs %d to %d, ret=%d\n", -+ start / 4, start / 4 + nb_lock, ret); -+ } -+ -+ tee_shm_free(shm); -+ -+out_tee_session: -+ stm32_bsec_ta_close_session(ctx, session_id); -+ -+ return ret; -+} ---- /dev/null -+++ b/drivers/nvmem/stm32-bsec-optee-ta.h -@@ -0,0 +1,80 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+/* -+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver -+ * -+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved -+ */ -+ -+#if IS_ENABLED(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) -+/** -+ * stm32_bsec_optee_ta_open() - initialize the STM32 BSEC TA -+ * @ctx: the OP-TEE context on success -+ * -+ * Return: -+ * On success, 0. On failure, -errno. -+ */ -+int stm32_bsec_optee_ta_open(struct tee_context **ctx); -+ -+/** -+ * stm32_bsec_optee_ta_close() - release the STM32 BSEC TA -+ * @ctx: the OP-TEE context -+ * -+ * This function used to clean the OP-TEE resources initialized in -+ * stm32_bsec_optee_ta_open(); it can be used as callback to -+ * devm_add_action_or_reset() -+ */ -+void stm32_bsec_optee_ta_close(void *ctx); -+ -+/** -+ * stm32_bsec_optee_ta_read() - nvmem read access using TA client driver -+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open -+ * @offset: nvmem offset -+ * @buf: buffer to fill with nvem values -+ * @bytes: number of bytes to read -+ * -+ * Return: -+ * On success, 0. On failure, -errno. -+ */ -+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset, -+ void *buf, size_t bytes); -+ -+/** -+ * stm32_bsec_optee_ta_write() - nvmem write access using TA client driver -+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open -+ * @lower: number of lower OTP, not protected by ECC -+ * @offset: nvmem offset -+ * @buf: buffer with nvem values -+ * @bytes: number of bytes to write -+ * -+ * Return: -+ * On success, 0. On failure, -errno. -+ */ -+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower, -+ unsigned int offset, void *buf, size_t bytes); -+ -+#else -+ -+static inline int stm32_bsec_optee_ta_open(struct tee_context **ctx) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline void stm32_bsec_optee_ta_close(void *ctx) -+{ -+} -+ -+static inline int stm32_bsec_optee_ta_read(struct tee_context *ctx, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int stm32_bsec_optee_ta_write(struct tee_context *ctx, -+ unsigned int lower, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ return -EOPNOTSUPP; -+} -+#endif /* CONFIG_NVMEM_STM32_BSEC_OPTEE_TA */ ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -11,6 +11,9 @@ - #include - #include - #include -+#include -+ -+#include "stm32-bsec-optee-ta.h" - - /* BSEC secure service access from non-secure */ - #define STM32_SMC_BSEC 0x82001003 -@@ -25,12 +28,14 @@ - struct stm32_romem_cfg { - int size; - u8 lower; -+ bool ta; - }; - - struct stm32_romem_priv { - void __iomem *base; - struct nvmem_config cfg; - u8 lower; -+ struct tee_context *ctx; - }; - - static int stm32_romem_read(void *context, unsigned int offset, void *buf, -@@ -138,12 +143,29 @@ static int stm32_bsec_write(void *contex - return 0; - } - -+static int stm32_bsec_pta_read(void *context, unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ struct stm32_romem_priv *priv = context; -+ -+ return stm32_bsec_optee_ta_read(priv->ctx, offset, buf, bytes); -+} -+ -+static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ struct stm32_romem_priv *priv = context; -+ -+ return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes); -+} -+ - static int stm32_romem_probe(struct platform_device *pdev) - { - const struct stm32_romem_cfg *cfg; - struct device *dev = &pdev->dev; - struct stm32_romem_priv *priv; - struct resource *res; -+ int rc; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -173,15 +195,31 @@ static int stm32_romem_probe(struct plat - } else { - priv->cfg.size = cfg->size; - priv->lower = cfg->lower; -- priv->cfg.reg_read = stm32_bsec_read; -- priv->cfg.reg_write = stm32_bsec_write; -+ if (cfg->ta) { -+ rc = stm32_bsec_optee_ta_open(&priv->ctx); -+ /* wait for OP-TEE client driver to be up and ready */ -+ if (rc) -+ return rc; -+ } -+ if (priv->ctx) { -+ rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx); -+ if (rc) { -+ dev_err(dev, "devm_add_action_or_reset() failed (%d)\n", rc); -+ return rc; -+ } -+ priv->cfg.reg_read = stm32_bsec_pta_read; -+ priv->cfg.reg_write = stm32_bsec_pta_write; -+ } else { -+ priv->cfg.reg_read = stm32_bsec_read; -+ priv->cfg.reg_write = stm32_bsec_write; -+ } - } - - return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); - } - - /* -- * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) -+ * STM32MP15/13 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) - * => 96 x 32-bits data words - * - Lower: 1K bits, 2:1 redundancy, incremental bit programming - * => 32 (x 32-bits) lower shadow registers = words 0 to 31 -@@ -191,6 +229,13 @@ static int stm32_romem_probe(struct plat - static const struct stm32_romem_cfg stm32mp15_bsec_cfg = { - .size = 384, - .lower = 32, -+ .ta = false, -+}; -+ -+static const struct stm32_romem_cfg stm32mp13_bsec_cfg = { -+ .size = 384, -+ .lower = 32, -+ .ta = true, - }; - - static const struct of_device_id stm32_romem_of_match[] = { -@@ -198,7 +243,10 @@ static const struct of_device_id stm32_r - .compatible = "st,stm32mp15-bsec", - .data = (void *)&stm32mp15_bsec_cfg, - }, { -+ .compatible = "st,stm32mp13-bsec", -+ .data = (void *)&stm32mp13_bsec_cfg, - }, -+ { /* sentinel */ }, - }; - MODULE_DEVICE_TABLE(of, stm32_romem_of_match); - diff --git a/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch b/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch deleted file mode 100644 index cea8e93858..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch +++ /dev/null @@ -1,85 +0,0 @@ -From df2f34ef1d924125ffaf29dfdaf7cdbd3183c321 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Mon, 6 Feb 2023 13:43:52 +0000 -Subject: [PATCH] nvmem: stm32: detect bsec pta presence for STM32MP15x - -On STM32MP15x SoC, the SMC backend is optional when OP-TEE is used; -the PTA BSEC should be used as it is done on STM32MP13x platform, -but the BSEC SMC can be also used: it is a legacy mode in OP-TEE, -not recommended but used in previous OP-TEE firmware. - -The presence of OP-TEE is dynamically detected in STM32MP15x device tree -and the supported NVMEM backend is dynamically detected: -- PTA with stm32_bsec_pta_find -- SMC with stm32_bsec_check - -With OP-TEE but without PTA and SMC detection, the probe is deferred for -STM32MP15x devices. - -On STM32MP13x platform, only the PTA is supported with cfg->ta = true -and this detection is skipped. - -Signed-off-by: Patrick Delaunay -Reviewed-by: Etienne Carriere -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-19-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 38 +++++++++++++++++++++++++++++++++---- - 1 file changed, 34 insertions(+), 4 deletions(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -159,6 +159,31 @@ static int stm32_bsec_pta_write(void *co - return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes); - } - -+static bool stm32_bsec_smc_check(void) -+{ -+ u32 val; -+ int ret; -+ -+ /* check that the OP-TEE support the BSEC SMC (legacy mode) */ -+ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, 0, 0, &val); -+ -+ return !ret; -+} -+ -+static bool optee_presence_check(void) -+{ -+ struct device_node *np; -+ bool tee_detected = false; -+ -+ /* check that the OP-TEE node is present and available. */ -+ np = of_find_compatible_node(NULL, NULL, "linaro,optee-tz"); -+ if (np && of_device_is_available(np)) -+ tee_detected = true; -+ of_node_put(np); -+ -+ return tee_detected; -+} -+ - static int stm32_romem_probe(struct platform_device *pdev) - { - const struct stm32_romem_cfg *cfg; -@@ -195,11 +220,16 @@ static int stm32_romem_probe(struct plat - } else { - priv->cfg.size = cfg->size; - priv->lower = cfg->lower; -- if (cfg->ta) { -+ if (cfg->ta || optee_presence_check()) { - rc = stm32_bsec_optee_ta_open(&priv->ctx); -- /* wait for OP-TEE client driver to be up and ready */ -- if (rc) -- return rc; -+ if (rc) { -+ /* wait for OP-TEE client driver to be up and ready */ -+ if (rc == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ /* BSEC PTA is required or SMC not supported */ -+ if (cfg->ta || !stm32_bsec_smc_check()) -+ return rc; -+ } - } - if (priv->ctx) { - rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch b/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch deleted file mode 100644 index 9d6275a737..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 3e5ac22aa564026e99defc3a8e02082521a5b231 Mon Sep 17 00:00:00 2001 -From: Randy Dunlap -Date: Mon, 6 Feb 2023 13:43:53 +0000 -Subject: [PATCH] nvmem: rave-sp-eeprm: fix kernel-doc bad line warning - -Convert an empty line to " *" to avoid a kernel-doc warning: - -drivers/nvmem/rave-sp-eeprom.c:48: warning: bad line: - -Signed-off-by: Randy Dunlap -Cc: Srinivas Kandagatla -Cc: Andrey Vostrikov -Cc: Nikita Yushchenko -Cc: Andrey Smirnov -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-20-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rave-sp-eeprom.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/rave-sp-eeprom.c -+++ b/drivers/nvmem/rave-sp-eeprom.c -@@ -45,7 +45,7 @@ enum rave_sp_eeprom_header_size { - * @type: Access type (see enum rave_sp_eeprom_access_type) - * @success: Success flag (Success = 1, Failure = 0) - * @data: Read data -- -+ * - * Note this structure corresponds to RSP_*_EEPROM payload from RAVE - * SP ICD - */ diff --git a/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch b/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch deleted file mode 100644 index 1ab9e609d3..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch +++ /dev/null @@ -1,43 +0,0 @@ -From eb7dda20f42a9137e9ee53d5ed3b743d49338cb5 Mon Sep 17 00:00:00 2001 -From: Johan Hovold -Date: Mon, 6 Feb 2023 13:43:54 +0000 -Subject: [PATCH] nvmem: qcom-spmi-sdam: register at device init time - -There are currently no in-tree users of the Qualcomm SDAM nvmem driver -and there is generally no point in registering a driver that can be -built as a module at subsys init time. - -Register the driver at the normal device init time instead and let -driver core sort out the probe order. - -Signed-off-by: Johan Hovold -Reviewed-by: Bjorn Andersson -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-21-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/qcom-spmi-sdam.c | 13 +------------ - 1 file changed, 1 insertion(+), 12 deletions(-) - ---- a/drivers/nvmem/qcom-spmi-sdam.c -+++ b/drivers/nvmem/qcom-spmi-sdam.c -@@ -175,18 +175,7 @@ static struct platform_driver sdam_drive - }, - .probe = sdam_probe, - }; -- --static int __init sdam_init(void) --{ -- return platform_driver_register(&sdam_driver); --} --subsys_initcall(sdam_init); -- --static void __exit sdam_exit(void) --{ -- return platform_driver_unregister(&sdam_driver); --} --module_exit(sdam_exit); -+module_platform_driver(sdam_driver); - - MODULE_DESCRIPTION("QCOM SPMI SDAM driver"); - MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch b/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch deleted file mode 100644 index dcf704c6ff..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 1dc7e37bb0ec1c997fac82031332a38c7610352f Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Mon, 6 Feb 2023 13:43:56 +0000 -Subject: [PATCH] nvmem: stm32: fix OPTEE dependency - -The stm32 nvmem driver fails to link as built-in when OPTEE -is a loadable module: - -aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec: -stm32-bsec-optee-ta.c:(.text+0xc8): undefined reference to `tee_client_open_session' -aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec: -stm32-bsec-optee-ta.c:(.text+0x1fc): undefined reference to `tee_client_open_context' - -Change the CONFIG_NVMEM_STM32_ROMEM definition so it can only -be built-in if OPTEE is either built-in or disabled, and -make NVMEM_STM32_BSEC_OPTEE_TA a hidden symbol instead. - -Signed-off-by: Arnd Bergmann -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-23-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -291,8 +291,7 @@ config NVMEM_SPRD_EFUSE - will be called nvmem-sprd-efuse. - - config NVMEM_STM32_BSEC_OPTEE_TA -- bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver" -- depends on OPTEE -+ def_bool NVMEM_STM32_ROMEM && OPTEE - help - Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE - trusted application STM32MP BSEC. -@@ -303,7 +302,7 @@ config NVMEM_STM32_BSEC_OPTEE_TA - config NVMEM_STM32_ROMEM - tristate "STMicroelectronics STM32 factory-programmed memory support" - depends on ARCH_STM32 || COMPILE_TEST -- imply NVMEM_STM32_BSEC_OPTEE_TA -+ depends on OPTEE || !OPTEE - help - Say y here to enable read-only access for STMicroelectronics STM32 - factory-programmed memory area. diff --git a/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch b/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch deleted file mode 100644 index 60a90136c9..0000000000 --- a/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 4d70c74659d9746502b23d055dba03d1d28ec388 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Wed, 30 Nov 2022 15:48:35 +0200 -Subject: [PATCH] i915: Move list_count() to list.h as list_count_nodes() for - broader use - -Some of the existing users, and definitely will be new ones, want to -count existing nodes in the list. Provide a generic API for that by -moving code from i915 to list.h. - -Reviewed-by: Lucas De Marchi -Acked-by: Jani Nikula -Signed-off-by: Andy Shevchenko -Link: https://lore.kernel.org/r/20221130134838.23805-1-andriy.shevchenko@linux.intel.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/gpu/drm/i915/gt/intel_engine_cs.c | 15 ++------------- - include/linux/list.h | 15 +++++++++++++++ - 2 files changed, 17 insertions(+), 13 deletions(-) - ---- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -@@ -4154,17 +4154,6 @@ void intel_execlists_show_requests(struc - spin_unlock_irqrestore(&sched_engine->lock, flags); - } - --static unsigned long list_count(struct list_head *list) --{ -- struct list_head *pos; -- unsigned long count = 0; -- -- list_for_each(pos, list) -- count++; -- -- return count; --} -- - void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, - struct i915_request *hung_rq, - struct drm_printer *m) -@@ -4175,8 +4164,8 @@ void intel_execlists_dump_active_request - - intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m); - -- drm_printf(m, "\tOn hold?: %lu\n", -- list_count(&engine->sched_engine->hold)); -+ drm_printf(m, "\tOn hold?: %zu\n", -+ list_count_nodes(&engine->sched_engine->hold)); - - spin_unlock_irqrestore(&engine->sched_engine->lock, flags); - } ---- a/include/linux/list.h -+++ b/include/linux/list.h -@@ -656,6 +656,21 @@ static inline void list_splice_tail_init - pos = n, n = pos->prev) - - /** -+ * list_count_nodes - count nodes in the list -+ * @head: the head for your list. -+ */ -+static inline size_t list_count_nodes(struct list_head *head) -+{ -+ struct list_head *pos; -+ size_t count = 0; -+ -+ list_for_each(pos, head) -+ count++; -+ -+ return count; -+} -+ -+/** - * list_entry_is_head - test if the entry points to the head of the list - * @pos: the type * to cursor - * @head: the head for your list. diff --git a/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch b/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch deleted file mode 100644 index 8328e87c0a..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch +++ /dev/null @@ -1,35 +0,0 @@ -From bcd1fe07def0f070eb5f31594620aaee6f81d31a Mon Sep 17 00:00:00 2001 -From: Nick Alcock -Date: Tue, 4 Apr 2023 18:21:11 +0100 -Subject: [PATCH] nvmem: xilinx: zynqmp: make modular - -This driver has a MODULE_LICENSE but is not tristate so cannot be -built as a module, unlike all its peers: make it modular to match. - -Signed-off-by: Nick Alcock -Suggested-by: Michal Simek -Cc: Luis Chamberlain -Cc: linux-modules@vger.kernel.org -Cc: linux-kernel@vger.kernel.org -Cc: Hitomi Hasegawa -Cc: Srinivas Kandagatla -Cc: Michal Simek -Cc: linux-arm-kernel@lists.infradead.org -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-4-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP - be called nvmem-vf610-ocotp. - - config NVMEM_ZYNQMP -- bool "Xilinx ZYNQMP SoC nvmem firmware support" -+ tristate "Xilinx ZYNQMP SoC nvmem firmware support" - depends on ARCH_ZYNQMP - help - This is a driver to access hardware related data like diff --git a/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch b/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch deleted file mode 100644 index 94cd23c18a..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch +++ /dev/null @@ -1,387 +0,0 @@ -From 266570f496b90dea8fda893c2cf7c28d63ae2bd9 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:21 +0100 -Subject: [PATCH] nvmem: core: introduce NVMEM layouts - -NVMEM layouts are used to generate NVMEM cells during runtime. Think of -an EEPROM with a well-defined conent. For now, the content can be -described by a device tree or a board file. But this only works if the -offsets and lengths are static and don't change. One could also argue -that putting the layout of the EEPROM in the device tree is the wrong -place. Instead, the device tree should just have a specific compatible -string. - -Right now there are two use cases: - (1) The NVMEM cell needs special processing. E.g. if it only specifies - a base MAC address offset and you need to add an offset, or it - needs to parse a MAC from ASCII format or some proprietary format. - (Post processing of cells is added in a later commit). - (2) u-boot environment parsing. The cells don't have a particular - offset but it needs parsing the content to determine the offsets - and length. - -Co-developed-by: Miquel Raynal -Signed-off-by: Miquel Raynal -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-14-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/driver-api/nvmem.rst | 15 ++++ - drivers/nvmem/Kconfig | 4 + - drivers/nvmem/Makefile | 1 + - drivers/nvmem/core.c | 120 +++++++++++++++++++++++++++++ - drivers/nvmem/layouts/Kconfig | 5 ++ - drivers/nvmem/layouts/Makefile | 4 + - include/linux/nvmem-consumer.h | 7 ++ - include/linux/nvmem-provider.h | 51 ++++++++++++ - 8 files changed, 207 insertions(+) - create mode 100644 drivers/nvmem/layouts/Kconfig - create mode 100644 drivers/nvmem/layouts/Makefile - ---- a/Documentation/driver-api/nvmem.rst -+++ b/Documentation/driver-api/nvmem.rst -@@ -185,3 +185,18 @@ ex:: - ===================== - - See Documentation/devicetree/bindings/nvmem/nvmem.txt -+ -+8. NVMEM layouts -+================ -+ -+NVMEM layouts are yet another mechanism to create cells. With the device -+tree binding it is possible to specify simple cells by using an offset -+and a length. Sometimes, the cells doesn't have a static offset, but -+the content is still well defined, e.g. tag-length-values. In this case, -+the NVMEM device content has to be first parsed and the cells need to -+be added accordingly. Layouts let you read the content of the NVMEM device -+and let you add cells dynamically. -+ -+Another use case for layouts is the post processing of cells. With layouts, -+it is possible to associate a custom post processing hook to a cell. It -+even possible to add this hook to cells not created by the layout itself. ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -21,6 +21,10 @@ config NVMEM_SYSFS - This interface is mostly used by userspace applications to - read/write directly into nvmem. - -+# Layouts -+ -+source "drivers/nvmem/layouts/Kconfig" -+ - # Devices - - config NVMEM_APPLE_EFUSES ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -5,6 +5,7 @@ - - obj-$(CONFIG_NVMEM) += nvmem_core.o - nvmem_core-y := core.o -+obj-y += layouts/ - - # Devices - obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -40,6 +40,7 @@ struct nvmem_device { - nvmem_reg_write_t reg_write; - nvmem_cell_post_process_t cell_post_process; - struct gpio_desc *wp_gpio; -+ struct nvmem_layout *layout; - void *priv; - }; - -@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list); - - static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); - -+static DEFINE_SPINLOCK(nvmem_layout_lock); -+static LIST_HEAD(nvmem_layouts); -+ - static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, - void *val, size_t bytes) - { -@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struc - return 0; - } - -+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) -+{ -+ layout->owner = owner; -+ -+ spin_lock(&nvmem_layout_lock); -+ list_add(&layout->node, &nvmem_layouts); -+ spin_unlock(&nvmem_layout_lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(__nvmem_layout_register); -+ -+void nvmem_layout_unregister(struct nvmem_layout *layout) -+{ -+ spin_lock(&nvmem_layout_lock); -+ list_del(&layout->node); -+ spin_unlock(&nvmem_layout_lock); -+} -+EXPORT_SYMBOL_GPL(nvmem_layout_unregister); -+ -+static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) -+{ -+ struct device_node *layout_np, *np = nvmem->dev.of_node; -+ struct nvmem_layout *l, *layout = NULL; -+ -+ layout_np = of_get_child_by_name(np, "nvmem-layout"); -+ if (!layout_np) -+ return NULL; -+ -+ spin_lock(&nvmem_layout_lock); -+ -+ list_for_each_entry(l, &nvmem_layouts, node) { -+ if (of_match_node(l->of_match_table, layout_np)) { -+ if (try_module_get(l->owner)) -+ layout = l; -+ -+ break; -+ } -+ } -+ -+ spin_unlock(&nvmem_layout_lock); -+ of_node_put(layout_np); -+ -+ return layout; -+} -+ -+static void nvmem_layout_put(struct nvmem_layout *layout) -+{ -+ if (layout) -+ module_put(layout->owner); -+} -+ -+static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem) -+{ -+ struct nvmem_layout *layout = nvmem->layout; -+ int ret; -+ -+ if (layout && layout->add_cells) { -+ ret = layout->add_cells(&nvmem->dev, nvmem, layout); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+#if IS_ENABLED(CONFIG_OF) -+/** -+ * of_nvmem_layout_get_container() - Get OF node to layout container. -+ * -+ * @nvmem: nvmem device. -+ * -+ * Return: a node pointer with refcount incremented or NULL if no -+ * container exists. Use of_node_put() on it when done. -+ */ -+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) -+{ -+ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); -+} -+EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container); -+#endif -+ -+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ struct device_node __maybe_unused *layout_np; -+ const struct of_device_id *match; -+ -+ layout_np = of_nvmem_layout_get_container(nvmem); -+ match = of_match_node(layout->of_match_table, layout_np); -+ -+ return match ? match->data : NULL; -+} -+EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); -+ - /** - * nvmem_register() - Register a nvmem device for given nvmem_config. - * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem -@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(cons - goto err_put_device; - } - -+ /* -+ * If the driver supplied a layout by config->layout, the module -+ * pointer will be NULL and nvmem_layout_put() will be a noop. -+ */ -+ nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); -+ - if (config->cells) { - rval = nvmem_add_cells(nvmem, config->cells, config->ncells); - if (rval) -@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -+ rval = nvmem_add_cells_from_layout(nvmem); -+ if (rval) -+ goto err_remove_cells; -+ - blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); - - return nvmem; - - err_remove_cells: - nvmem_device_remove_all_cells(nvmem); -+ nvmem_layout_put(nvmem->layout); - if (config->compat) - nvmem_sysfs_remove_compat(nvmem, config); - err_put_device: -@@ -881,6 +991,7 @@ static void nvmem_device_release(struct - device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); - - nvmem_device_remove_all_cells(nvmem); -+ nvmem_layout_put(nvmem->layout); - device_unregister(&nvmem->dev); - } - -@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(str - return ERR_PTR(-EINVAL); - } - -+ /* nvmem layouts produce cells within the nvmem-layout container */ -+ if (of_node_name_eq(nvmem_np, "nvmem-layout")) { -+ nvmem_np = of_get_next_parent(nvmem_np); -+ if (!nvmem_np) { -+ of_node_put(cell_np); -+ return ERR_PTR(-EINVAL); -+ } -+ } -+ - nvmem = __nvmem_device_get(nvmem_np, device_match_of_node); - of_node_put(nvmem_np); - if (IS_ERR(nvmem)) { ---- /dev/null -+++ b/drivers/nvmem/layouts/Kconfig -@@ -0,0 +1,5 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+menu "Layout Types" -+ -+endmenu ---- /dev/null -+++ b/drivers/nvmem/layouts/Makefile -@@ -0,0 +1,4 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# Makefile for nvmem layouts. -+# ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -239,6 +239,7 @@ struct nvmem_cell *of_nvmem_cell_get(str - const char *id); - struct nvmem_device *of_nvmem_device_get(struct device_node *np, - const char *name); -+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); - #else - static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, - const char *id) -@@ -251,6 +252,12 @@ static inline struct nvmem_device *of_nv - { - return ERR_PTR(-EOPNOTSUPP); - } -+ -+static inline struct device_node * -+of_nvmem_layout_get_container(struct nvmem_device *nvmem) -+{ -+ return ERR_PTR(-EOPNOTSUPP); -+} - #endif /* CONFIG_NVMEM && CONFIG_OF */ - - #endif /* ifndef _LINUX_NVMEM_CONSUMER_H */ ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -88,6 +88,7 @@ struct nvmem_cell_info { - * @stride: Minimum read/write access stride. - * @priv: User context passed to read/write callbacks. - * @ignore_wp: Write Protect pin is managed by the provider. -+ * @layout: Fixed layout associated with this nvmem device. - * - * Note: A default "nvmem" name will be assigned to the device if - * no name is specified in its configuration. In such case "" is -@@ -109,6 +110,7 @@ struct nvmem_config { - bool read_only; - bool root_only; - bool ignore_wp; -+ struct nvmem_layout *layout; - struct device_node *of_node; - bool no_of_node; - nvmem_reg_read_t reg_read; -@@ -142,6 +144,33 @@ struct nvmem_cell_table { - struct list_head node; - }; - -+/** -+ * struct nvmem_layout - NVMEM layout definitions -+ * -+ * @name: Layout name. -+ * @of_match_table: Open firmware match table. -+ * @add_cells: Will be called if a nvmem device is found which -+ * has this layout. The function will add layout -+ * specific cells with nvmem_add_one_cell(). -+ * @owner: Pointer to struct module. -+ * @node: List node. -+ * -+ * A nvmem device can hold a well defined structure which can just be -+ * evaluated during runtime. For example a TLV list, or a list of "name=val" -+ * pairs. A nvmem layout can parse the nvmem device and add appropriate -+ * cells. -+ */ -+struct nvmem_layout { -+ const char *name; -+ const struct of_device_id *of_match_table; -+ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, -+ struct nvmem_layout *layout); -+ -+ /* private */ -+ struct module *owner; -+ struct list_head node; -+}; -+ - #if IS_ENABLED(CONFIG_NVMEM) - - struct nvmem_device *nvmem_register(const struct nvmem_config *cfg); -@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_c - int nvmem_add_one_cell(struct nvmem_device *nvmem, - const struct nvmem_cell_info *info); - -+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner); -+#define nvmem_layout_register(layout) \ -+ __nvmem_layout_register(layout, THIS_MODULE) -+void nvmem_layout_unregister(struct nvmem_layout *layout); -+ -+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout); -+ - #else - - static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) -@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(str - return -EOPNOTSUPP; - } - -+static inline int nvmem_layout_register(struct nvmem_layout *layout) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} -+ -+static inline const void * -+nvmem_layout_get_match_data(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ return NULL; -+} -+ - #endif /* CONFIG_NVMEM */ - #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch b/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch deleted file mode 100644 index 6fa7b6382d..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 6468a6f45148fb5e95c86b4efebf63f9abcd2137 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:22 +0100 -Subject: [PATCH] nvmem: core: handle the absence of expected layouts - -Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout -is not available. This condition cannot be triggered today as nvmem -layout drivers are initialed as part of an early init call, but soon -these drivers will be converted into modules and be initialized with a -standard priority, so the unavailability of the drivers might become a -reality that must be taken care of. - -Let's anticipate this by telling the caller the layout might not yet be -available. A probe deferral is requested in this case. - -Please note this does not affect any nvmem device not using layouts, -because an early check against the "nvmem-layout" container presence -will return NULL in this case. - -Signed-off-by: Miquel Raynal -Tested-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-15-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste - static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) - { - struct device_node *layout_np, *np = nvmem->dev.of_node; -- struct nvmem_layout *l, *layout = NULL; -+ struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); - - layout_np = of_get_child_by_name(np, "nvmem-layout"); - if (!layout_np) -@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(cons - * pointer will be NULL and nvmem_layout_put() will be a noop. - */ - nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); -+ if (IS_ERR(nvmem->layout)) { -+ rval = PTR_ERR(nvmem->layout); -+ nvmem->layout = NULL; -+ -+ if (rval == -EPROBE_DEFER) -+ goto err_teardown_compat; -+ } - - if (config->cells) { - rval = nvmem_add_cells(nvmem, config->cells, config->ncells); -@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(cons - err_remove_cells: - nvmem_device_remove_all_cells(nvmem); - nvmem_layout_put(nvmem->layout); -+err_teardown_compat: - if (config->compat) - nvmem_sysfs_remove_compat(nvmem, config); - err_put_device: diff --git a/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch b/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch deleted file mode 100644 index b9341666f9..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch +++ /dev/null @@ -1,52 +0,0 @@ -From b1c37bec1ccfe5ccab72bc0ddc0dfa45c43e2de2 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:23 +0100 -Subject: [PATCH] nvmem: core: request layout modules loading - -When a storage device like an eeprom or an mtd device probes, it -registers an nvmem device if the nvmem subsystem has been enabled (bool -symbol). During nvmem registration, if the device is using layouts to -expose dynamic nvmem cells, the core will first try to get a reference -over the layout driver callbacks. In practice there is not relationship -that can be described between the storage driver and the nvmem -layout. So there is no way we can enforce both drivers will be built-in -or both will be modules. If the storage device driver is built-in but -the layout is built as a module, instead of badly failing with an -endless probe deferral loop, lets just make a modprobe call in case the -driver was made available in an initramfs with -of_device_node_request_module(), and offer a fully functional system to -the user. - -Signed-off-by: Miquel Raynal -Tested-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-16-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - - struct nvmem_device { -@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout - if (!layout_np) - return NULL; - -+ /* -+ * In case the nvmem device was built-in while the layout was built as a -+ * module, we shall manually request the layout driver loading otherwise -+ * we'll never have any match. -+ */ -+ of_request_module(layout_np); -+ - spin_lock(&nvmem_layout_lock); - - list_for_each_entry(l, &nvmem_layouts, node) { diff --git a/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch b/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch deleted file mode 100644 index 53628cd4e4..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 345ec382cd4b736c36e01f155d08c913b225b736 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:24 +0100 -Subject: [PATCH] nvmem: core: add per-cell post processing - -Instead of relying on the name the consumer is using for the cell, like -it is done for the nvmem .cell_post_process configuration parameter, -provide a per-cell post processing hook. This can then be populated by -the NVMEM provider (or the NVMEM layout) when adding the cell. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-17-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 17 +++++++++++++++++ - include/linux/nvmem-provider.h | 3 +++ - 2 files changed, 20 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -54,6 +54,7 @@ struct nvmem_cell_entry { - int bytes; - int bit_offset; - int nbits; -+ nvmem_cell_post_process_t read_post_process; - struct device_node *np; - struct nvmem_device *nvmem; - struct list_head node; -@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell - cell->offset = info->offset; - cell->bytes = info->bytes; - cell->name = info->name; -+ cell->read_post_process = info->read_post_process; - - cell->bit_offset = info->bit_offset; - cell->nbits = info->nbits; -@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvme - if (cell->bit_offset || cell->nbits) - nvmem_shift_read_buffer_in_place(cell, buf); - -+ if (cell->read_post_process) { -+ rc = cell->read_post_process(nvmem->priv, id, index, -+ cell->offset, buf, cell->bytes); -+ if (rc) -+ return rc; -+ } -+ - if (nvmem->cell_post_process) { - rc = nvmem->cell_post_process(nvmem->priv, id, index, - cell->offset, buf, cell->bytes); -@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(stru - (cell->bit_offset == 0 && len != cell->bytes)) - return -EINVAL; - -+ /* -+ * Any cells which have a read_post_process hook are read-only because -+ * we cannot reverse the operation and it might affect other cells, -+ * too. -+ */ -+ if (cell->read_post_process) -+ return -EINVAL; -+ - if (cell->bit_offset || cell->nbits) { - buf = nvmem_cell_prepare_write_buffer(cell, buf, len); - if (IS_ERR(buf)) ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -54,6 +54,8 @@ struct nvmem_keepout { - * @bit_offset: Bit offset if cell is smaller than a byte. - * @nbits: Number of bits. - * @np: Optional device_node pointer. -+ * @read_post_process: Callback for optional post processing of cell data -+ * on reads. - */ - struct nvmem_cell_info { - const char *name; -@@ -62,6 +64,7 @@ struct nvmem_cell_info { - unsigned int bit_offset; - unsigned int nbits; - struct device_node *np; -+ nvmem_cell_post_process_t read_post_process; - }; - - /** diff --git a/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch b/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch deleted file mode 100644 index 32990148c8..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch +++ /dev/null @@ -1,59 +0,0 @@ -From de12c9691501ccba41a154c223869f82be4c12fd Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:25 +0100 -Subject: [PATCH] nvmem: core: allow to modify a cell before adding it - -Provide a way to modify a cell before it will get added. This is useful -to attach a custom post processing hook via a layout. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-18-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 4 ++++ - include/linux/nvmem-provider.h | 5 +++++ - 2 files changed, 9 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struc - - static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) - { -+ struct nvmem_layout *layout = nvmem->layout; - struct device *dev = &nvmem->dev; - struct device_node *child; - const __be32 *addr; -@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struc - - info.np = of_node_get(child); - -+ if (layout && layout->fixup_cell_info) -+ layout->fixup_cell_info(nvmem, layout, &info); -+ - ret = nvmem_add_one_cell(nvmem, &info); - kfree(info.name); - if (ret) { ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -155,6 +155,8 @@ struct nvmem_cell_table { - * @add_cells: Will be called if a nvmem device is found which - * has this layout. The function will add layout - * specific cells with nvmem_add_one_cell(). -+ * @fixup_cell_info: Will be called before a cell is added. Can be -+ * used to modify the nvmem_cell_info. - * @owner: Pointer to struct module. - * @node: List node. - * -@@ -168,6 +170,9 @@ struct nvmem_layout { - const struct of_device_id *of_match_table; - int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, - struct nvmem_layout *layout); -+ void (*fixup_cell_info)(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout, -+ struct nvmem_cell_info *cell); - - /* private */ - struct module *owner; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch b/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch deleted file mode 100644 index 2a5fa618ea..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 6c56a82d7895a213a43182a5d01a21a906a79847 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:26 +0100 -Subject: [PATCH] nvmem: imx-ocotp: replace global post processing with layouts - -In preparation of retiring the global post processing hook change this -driver to use layouts. The layout will be supplied during registration -and will be used to add the post processing hook to all added cells. - -Signed-off-by: Michael Walle -Tested-by: Michael Walle # on kontron-pitx-imx8m -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-19-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++----------- - 1 file changed, 19 insertions(+), 11 deletions(-) - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -225,18 +225,13 @@ read_end: - static int imx_ocotp_cell_pp(void *context, const char *id, int index, - unsigned int offset, void *data, size_t bytes) - { -- struct ocotp_priv *priv = context; -+ u8 *buf = data; -+ int i; - - /* Deal with some post processing of nvmem cell data */ -- if (id && !strcmp(id, "mac-address")) { -- if (priv->params->reverse_mac_address) { -- u8 *buf = data; -- int i; -- -- for (i = 0; i < bytes/2; i++) -- swap(buf[i], buf[bytes - i - 1]); -- } -- } -+ if (id && !strcmp(id, "mac-address")) -+ for (i = 0; i < bytes / 2; i++) -+ swap(buf[i], buf[bytes - i - 1]); - - return 0; - } -@@ -488,7 +483,6 @@ static struct nvmem_config imx_ocotp_nvm - .stride = 1, - .reg_read = imx_ocotp_read, - .reg_write = imx_ocotp_write, -- .cell_post_process = imx_ocotp_cell_pp, - }; - - static const struct ocotp_params imx6q_params = { -@@ -595,6 +589,17 @@ static const struct of_device_id imx_oco - }; - MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); - -+static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout, -+ struct nvmem_cell_info *cell) -+{ -+ cell->read_post_process = imx_ocotp_cell_pp; -+} -+ -+struct nvmem_layout imx_ocotp_layout = { -+ .fixup_cell_info = imx_ocotp_fixup_cell_info, -+}; -+ - static int imx_ocotp_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platfo - imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; - imx_ocotp_nvmem_config.dev = dev; - imx_ocotp_nvmem_config.priv = priv; -+ if (priv->params->reverse_mac_address) -+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; -+ - priv->config = &imx_ocotp_nvmem_config; - - clk_prepare_enable(priv->clk); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch b/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch deleted file mode 100644 index eac202b882..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 011e40a166fdaa65fb9946b7cd91efec85b70dbb Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:27 +0100 -Subject: [PATCH] nvmem: cell: drop global cell_post_process - -There are no users anymore for the global cell_post_process callback -anymore. New users should use proper nvmem layouts. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-20-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 9 --------- - include/linux/nvmem-provider.h | 2 -- - 2 files changed, 11 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -39,7 +39,6 @@ struct nvmem_device { - unsigned int nkeepout; - nvmem_reg_read_t reg_read; - nvmem_reg_write_t reg_write; -- nvmem_cell_post_process_t cell_post_process; - struct gpio_desc *wp_gpio; - struct nvmem_layout *layout; - void *priv; -@@ -903,7 +902,6 @@ struct nvmem_device *nvmem_register(cons - nvmem->type = config->type; - nvmem->reg_read = config->reg_read; - nvmem->reg_write = config->reg_write; -- nvmem->cell_post_process = config->cell_post_process; - nvmem->keepout = config->keepout; - nvmem->nkeepout = config->nkeepout; - if (config->of_node) -@@ -1575,13 +1573,6 @@ static int __nvmem_cell_read(struct nvme - if (rc) - return rc; - } -- -- if (nvmem->cell_post_process) { -- rc = nvmem->cell_post_process(nvmem->priv, id, index, -- cell->offset, buf, cell->bytes); -- if (rc) -- return rc; -- } - - if (len) - *len = cell->bytes; ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -85,7 +85,6 @@ struct nvmem_cell_info { - * @no_of_node: Device should not use the parent's of_node even if it's !NULL. - * @reg_read: Callback to read data. - * @reg_write: Callback to write data. -- * @cell_post_process: Callback for vendor specific post processing of cell data - * @size: Device size. - * @word_size: Minimum read/write access granularity. - * @stride: Minimum read/write access stride. -@@ -118,7 +117,6 @@ struct nvmem_config { - bool no_of_node; - nvmem_reg_read_t reg_read; - nvmem_reg_write_t reg_write; -- nvmem_cell_post_process_t cell_post_process; - int size; - int word_size; - int stride; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch b/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch deleted file mode 100644 index 46b30a2ed9..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 8a134fd9f9323f4c39ec27055b3d3723cfb5c1e9 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:28 +0100 -Subject: [PATCH] nvmem: core: provide own priv pointer in post process - callback - -It doesn't make any more sense to have a opaque pointer set up by the -nvmem device. Usually, the layout isn't associated with a particular -nvmem device. Instead, let the caller who set the post process callback -provide the priv pointer. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-21-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 4 +++- - include/linux/nvmem-provider.h | 5 ++++- - 2 files changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -54,6 +54,7 @@ struct nvmem_cell_entry { - int bit_offset; - int nbits; - nvmem_cell_post_process_t read_post_process; -+ void *priv; - struct device_node *np; - struct nvmem_device *nvmem; - struct list_head node; -@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell - cell->bytes = info->bytes; - cell->name = info->name; - cell->read_post_process = info->read_post_process; -+ cell->priv = info->priv; - - cell->bit_offset = info->bit_offset; - cell->nbits = info->nbits; -@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvme - nvmem_shift_read_buffer_in_place(cell, buf); - - if (cell->read_post_process) { -- rc = cell->read_post_process(nvmem->priv, id, index, -+ rc = cell->read_post_process(cell->priv, id, index, - cell->offset, buf, cell->bytes); - if (rc) - return rc; ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *p - void *val, size_t bytes); - /* used for vendor specific post processing of cell data */ - typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index, -- unsigned int offset, void *buf, size_t bytes); -+ unsigned int offset, void *buf, -+ size_t bytes); - - enum nvmem_type { - NVMEM_TYPE_UNKNOWN = 0, -@@ -56,6 +57,7 @@ struct nvmem_keepout { - * @np: Optional device_node pointer. - * @read_post_process: Callback for optional post processing of cell data - * on reads. -+ * @priv: Opaque data passed to the read_post_process hook. - */ - struct nvmem_cell_info { - const char *name; -@@ -65,6 +67,7 @@ struct nvmem_cell_info { - unsigned int nbits; - struct device_node *np; - nvmem_cell_post_process_t read_post_process; -+ void *priv; - }; - - /** diff --git a/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch deleted file mode 100644 index 7d97658b60..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch +++ /dev/null @@ -1,215 +0,0 @@ -From d9fae023fe86069750092fc1c2f3a73e2fb18512 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:29 +0100 -Subject: [PATCH] nvmem: layouts: sl28vpd: Add new layout driver - -This layout applies to the VPD of the Kontron sl28 boards. The VPD only -contains a base MAC address. Therefore, we have to add an individual -offset to it. This is done by taking the second argument of the nvmem -phandle into account. Also this let us checking the VPD version and the -checksum. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-22-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/Kconfig | 9 ++ - drivers/nvmem/layouts/Makefile | 2 + - drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++ - 3 files changed, 176 insertions(+) - create mode 100644 drivers/nvmem/layouts/sl28vpd.c - ---- a/drivers/nvmem/layouts/Kconfig -+++ b/drivers/nvmem/layouts/Kconfig -@@ -2,4 +2,13 @@ - - menu "Layout Types" - -+config NVMEM_LAYOUT_SL28_VPD -+ tristate "Kontron sl28 VPD layout support" -+ select CRC8 -+ help -+ Say Y here if you want to support the VPD layout of the Kontron -+ SMARC-sAL28 boards. -+ -+ If unsure, say N. -+ - endmenu ---- a/drivers/nvmem/layouts/Makefile -+++ b/drivers/nvmem/layouts/Makefile -@@ -2,3 +2,5 @@ - # - # Makefile for nvmem layouts. - # -+ -+obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o ---- /dev/null -+++ b/drivers/nvmem/layouts/sl28vpd.c -@@ -0,0 +1,165 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define SL28VPD_MAGIC 'V' -+ -+struct sl28vpd_header { -+ u8 magic; -+ u8 version; -+} __packed; -+ -+struct sl28vpd_v1 { -+ struct sl28vpd_header header; -+ char serial_number[15]; -+ u8 base_mac_address[ETH_ALEN]; -+ u8 crc8; -+} __packed; -+ -+static int sl28vpd_mac_address_pp(void *priv, const char *id, int index, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ if (bytes != ETH_ALEN) -+ return -EINVAL; -+ -+ if (index < 0) -+ return -EINVAL; -+ -+ if (!is_valid_ether_addr(buf)) -+ return -EINVAL; -+ -+ eth_addr_add(buf, index); -+ -+ return 0; -+} -+ -+static const struct nvmem_cell_info sl28vpd_v1_entries[] = { -+ { -+ .name = "serial-number", -+ .offset = offsetof(struct sl28vpd_v1, serial_number), -+ .bytes = sizeof_field(struct sl28vpd_v1, serial_number), -+ }, -+ { -+ .name = "base-mac-address", -+ .offset = offsetof(struct sl28vpd_v1, base_mac_address), -+ .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address), -+ .read_post_process = sl28vpd_mac_address_pp, -+ }, -+}; -+ -+static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem) -+{ -+ struct sl28vpd_v1 data_v1; -+ u8 table[CRC8_TABLE_SIZE]; -+ int ret; -+ u8 crc; -+ -+ crc8_populate_msb(table, 0x07); -+ -+ ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1); -+ if (ret < 0) -+ return ret; -+ else if (ret != sizeof(data_v1)) -+ return -EIO; -+ -+ crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0); -+ -+ if (crc != data_v1.crc8) { -+ dev_err(dev, -+ "Checksum is invalid (got %02x, expected %02x).\n", -+ crc, data_v1.crc8); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ const struct nvmem_cell_info *pinfo; -+ struct nvmem_cell_info info = {0}; -+ struct device_node *layout_np; -+ struct sl28vpd_header hdr; -+ int ret, i; -+ -+ /* check header */ -+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); -+ if (ret < 0) -+ return ret; -+ else if (ret != sizeof(hdr)) -+ return -EIO; -+ -+ if (hdr.magic != SL28VPD_MAGIC) { -+ dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic); -+ return -EINVAL; -+ } -+ -+ if (hdr.version != 1) { -+ dev_err(dev, "Version %d is unsupported.\n", hdr.version); -+ return -EINVAL; -+ } -+ -+ ret = sl28vpd_v1_check_crc(dev, nvmem); -+ if (ret) -+ return ret; -+ -+ layout_np = of_nvmem_layout_get_container(nvmem); -+ if (!layout_np) -+ return -ENOENT; -+ -+ for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) { -+ pinfo = &sl28vpd_v1_entries[i]; -+ -+ info.name = pinfo->name; -+ info.offset = pinfo->offset; -+ info.bytes = pinfo->bytes; -+ info.read_post_process = pinfo->read_post_process; -+ info.np = of_get_child_by_name(layout_np, pinfo->name); -+ -+ ret = nvmem_add_one_cell(nvmem, &info); -+ if (ret) { -+ of_node_put(layout_np); -+ return ret; -+ } -+ } -+ -+ of_node_put(layout_np); -+ -+ return 0; -+} -+ -+static const struct of_device_id sl28vpd_of_match_table[] = { -+ { .compatible = "kontron,sl28-vpd" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); -+ -+struct nvmem_layout sl28vpd_layout = { -+ .name = "sl28-vpd", -+ .of_match_table = sl28vpd_of_match_table, -+ .add_cells = sl28vpd_add_cells, -+}; -+ -+static int __init sl28vpd_init(void) -+{ -+ return nvmem_layout_register(&sl28vpd_layout); -+} -+ -+static void __exit sl28vpd_exit(void) -+{ -+ nvmem_layout_unregister(&sl28vpd_layout); -+} -+ -+module_init(sl28vpd_init); -+module_exit(sl28vpd_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Michael Walle "); -+MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch deleted file mode 100644 index ca8b4bc069..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch +++ /dev/null @@ -1,306 +0,0 @@ -From d3c0d12f6474216bf386101e2449cc73e5c5b61d Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:31 +0100 -Subject: [PATCH] nvmem: layouts: onie-tlv: Add new layout driver - -This layout applies on top of any non volatile storage device containing -an ONIE table factory flashed. This table follows the tlv -(type-length-value) organization described in the link below. We cannot -afford using regular parsers because the content of these tables is -manufacturer specific and must be dynamically discovered. - -Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-24-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/Kconfig | 9 ++ - drivers/nvmem/layouts/Makefile | 1 + - drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++ - 3 files changed, 267 insertions(+) - create mode 100644 drivers/nvmem/layouts/onie-tlv.c - ---- a/drivers/nvmem/layouts/Kconfig -+++ b/drivers/nvmem/layouts/Kconfig -@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD - - If unsure, say N. - -+config NVMEM_LAYOUT_ONIE_TLV -+ tristate "ONIE tlv support" -+ select CRC32 -+ help -+ Say Y here if you want to support the Open Compute Project ONIE -+ Type-Length-Value standard table. -+ -+ If unsure, say N. -+ - endmenu ---- a/drivers/nvmem/layouts/Makefile -+++ b/drivers/nvmem/layouts/Makefile -@@ -4,3 +4,4 @@ - # - - obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o -+obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o ---- /dev/null -+++ b/drivers/nvmem/layouts/onie-tlv.c -@@ -0,0 +1,257 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * ONIE tlv NVMEM cells provider -+ * -+ * Copyright (C) 2022 Open Compute Group ONIE -+ * Author: Miquel Raynal -+ * Based on the nvmem driver written by: Vadym Kochan -+ * Inspired by the first layout written by: Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define ONIE_TLV_MAX_LEN 2048 -+#define ONIE_TLV_CRC_FIELD_SZ 6 -+#define ONIE_TLV_CRC_SZ 4 -+#define ONIE_TLV_HDR_ID "TlvInfo" -+ -+struct onie_tlv_hdr { -+ u8 id[8]; -+ u8 version; -+ __be16 data_len; -+} __packed; -+ -+struct onie_tlv { -+ u8 type; -+ u8 len; -+} __packed; -+ -+static const char *onie_tlv_cell_name(u8 type) -+{ -+ switch (type) { -+ case 0x21: -+ return "product-name"; -+ case 0x22: -+ return "part-number"; -+ case 0x23: -+ return "serial-number"; -+ case 0x24: -+ return "mac-address"; -+ case 0x25: -+ return "manufacture-date"; -+ case 0x26: -+ return "device-version"; -+ case 0x27: -+ return "label-revision"; -+ case 0x28: -+ return "platform-name"; -+ case 0x29: -+ return "onie-version"; -+ case 0x2A: -+ return "num-macs"; -+ case 0x2B: -+ return "manufacturer"; -+ case 0x2C: -+ return "country-code"; -+ case 0x2D: -+ return "vendor"; -+ case 0x2E: -+ return "diag-version"; -+ case 0x2F: -+ return "service-tag"; -+ case 0xFD: -+ return "vendor-extension"; -+ case 0xFE: -+ return "crc32"; -+ default: -+ break; -+ } -+ -+ return NULL; -+} -+ -+static int onie_tlv_mac_read_cb(void *priv, const char *id, int index, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ eth_addr_add(buf, index); -+ -+ return 0; -+} -+ -+static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf) -+{ -+ switch (type) { -+ case 0x24: -+ return &onie_tlv_mac_read_cb; -+ default: -+ break; -+ } -+ -+ return NULL; -+} -+ -+static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem, -+ size_t data_len, u8 *data) -+{ -+ struct nvmem_cell_info cell = {}; -+ struct device_node *layout; -+ struct onie_tlv tlv; -+ unsigned int hdr_len = sizeof(struct onie_tlv_hdr); -+ unsigned int offset = 0; -+ int ret; -+ -+ layout = of_nvmem_layout_get_container(nvmem); -+ if (!layout) -+ return -ENOENT; -+ -+ while (offset < data_len) { -+ memcpy(&tlv, data + offset, sizeof(tlv)); -+ if (offset + tlv.len >= data_len) { -+ dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n", -+ tlv.len, hdr_len + offset); -+ break; -+ } -+ -+ cell.name = onie_tlv_cell_name(tlv.type); -+ if (!cell.name) -+ continue; -+ -+ cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len); -+ cell.bytes = tlv.len; -+ cell.np = of_get_child_by_name(layout, cell.name); -+ cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv)); -+ -+ ret = nvmem_add_one_cell(nvmem, &cell); -+ if (ret) { -+ of_node_put(layout); -+ return ret; -+ } -+ -+ offset += sizeof(tlv) + tlv.len; -+ } -+ -+ of_node_put(layout); -+ -+ return 0; -+} -+ -+static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr) -+{ -+ if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) { -+ dev_err(dev, "Invalid header\n"); -+ return false; -+ } -+ -+ if (hdr->version != 0x1) { -+ dev_err(dev, "Invalid version number\n"); -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table) -+{ -+ struct onie_tlv crc_hdr; -+ u32 read_crc, calc_crc; -+ __be32 crc_be; -+ -+ memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr)); -+ if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) { -+ dev_err(dev, "Invalid CRC field\n"); -+ return false; -+ } -+ -+ /* The table contains a JAMCRC, which is XOR'ed compared to the original -+ * CRC32 implementation as known in the Ethernet world. -+ */ -+ memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ); -+ read_crc = be32_to_cpu(crc_be); -+ calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF; -+ if (read_crc != calc_crc) { -+ dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n", -+ read_crc, calc_crc); -+ return false; -+ } -+ -+ return true; -+} -+ -+static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ struct onie_tlv_hdr hdr; -+ size_t table_len, data_len, hdr_len; -+ u8 *table, *data; -+ int ret; -+ -+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); -+ if (ret < 0) -+ return ret; -+ -+ if (!onie_tlv_hdr_is_valid(dev, &hdr)) { -+ dev_err(dev, "Invalid ONIE TLV header\n"); -+ return -EINVAL; -+ } -+ -+ hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len); -+ data_len = be16_to_cpu(hdr.data_len); -+ table_len = hdr_len + data_len; -+ if (table_len > ONIE_TLV_MAX_LEN) { -+ dev_err(dev, "Invalid ONIE TLV data length\n"); -+ return -EINVAL; -+ } -+ -+ table = devm_kmalloc(dev, table_len, GFP_KERNEL); -+ if (!table) -+ return -ENOMEM; -+ -+ ret = nvmem_device_read(nvmem, 0, table_len, table); -+ if (ret != table_len) -+ return ret; -+ -+ if (!onie_tlv_crc_is_valid(dev, table_len, table)) -+ return -EINVAL; -+ -+ data = table + hdr_len; -+ ret = onie_tlv_add_cells(dev, nvmem, data_len, data); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static const struct of_device_id onie_tlv_of_match_table[] = { -+ { .compatible = "onie,tlv-layout", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table); -+ -+static struct nvmem_layout onie_tlv_layout = { -+ .name = "ONIE tlv layout", -+ .of_match_table = onie_tlv_of_match_table, -+ .add_cells = onie_tlv_parse_table, -+}; -+ -+static int __init onie_tlv_init(void) -+{ -+ return nvmem_layout_register(&onie_tlv_layout); -+} -+ -+static void __exit onie_tlv_exit(void) -+{ -+ nvmem_layout_unregister(&onie_tlv_layout); -+} -+ -+module_init(onie_tlv_init); -+module_exit(onie_tlv_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Miquel Raynal "); -+MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing"); -+MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch b/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch deleted file mode 100644 index 94a0911d73..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a4fb434ef96ace5af758ca2c52c3a3f8f3abc87c Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 4 Apr 2023 18:21:34 +0100 -Subject: [PATCH] nvmem: stm32-romem: mark OF related data as maybe unused -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The driver can be compile tested with !CONFIG_OF making certain data -unused: - - drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=] - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-27-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm3 - .ta = true, - }; - --static const struct of_device_id stm32_romem_of_match[] = { -+static const struct of_device_id stm32_romem_of_match[] __maybe_unused = { - { .compatible = "st,stm32f4-otp", }, { - .compatible = "st,stm32mp15-bsec", - .data = (void *)&stm32mp15_bsec_cfg, diff --git a/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch b/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch deleted file mode 100644 index abda402bdd..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch +++ /dev/null @@ -1,120 +0,0 @@ -From de6e05097f7db066afb0ad4c88b730949f7b7749 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Tue, 4 Apr 2023 18:21:35 +0100 -Subject: [PATCH] nvmem: mtk-efuse: Support postprocessing for GPU speed - binning data - -On some MediaTek SoCs GPU speed binning data is available for read -in the SoC's eFuse array but it has a format that is incompatible -with what the OPP API expects, as we read a number from 0 to 7 but -opp-supported-hw is expecting a bitmask to enable an OPP entry: -being what we read limited to 0-7, it's straightforward to simply -convert the value to BIT(value) as a post-processing action. - -So, introduce post-processing support and enable it by evaluating -the newly introduced platform data's `uses_post_processing` member, -currently enabled only for MT8186. - -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-28-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++-- - 1 file changed, 51 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/mtk-efuse.c -+++ b/drivers/nvmem/mtk-efuse.c -@@ -10,6 +10,11 @@ - #include - #include - #include -+#include -+ -+struct mtk_efuse_pdata { -+ bool uses_post_processing; -+}; - - struct mtk_efuse_priv { - void __iomem *base; -@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context, - return 0; - } - -+static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index, -+ unsigned int offset, void *data, size_t bytes) -+{ -+ u8 *val = data; -+ -+ if (val[0] < 8) -+ val[0] = BIT(val[0]); -+ -+ return 0; -+} -+ -+static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout, -+ struct nvmem_cell_info *cell) -+{ -+ size_t sz = strlen(cell->name); -+ -+ /* -+ * On some SoCs, the GPU speedbin is not read as bitmask but as -+ * a number with range [0-7] (max 3 bits): post process to use -+ * it in OPP tables to describe supported-hw. -+ */ -+ if (cell->nbits <= 3 && -+ strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0) -+ cell->read_post_process = mtk_efuse_gpu_speedbin_pp; -+} -+ -+static struct nvmem_layout mtk_efuse_layout = { -+ .fixup_cell_info = mtk_efuse_fixup_cell_info, -+}; -+ - static int mtk_efuse_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platfo - struct nvmem_device *nvmem; - struct nvmem_config econfig = {}; - struct mtk_efuse_priv *priv; -+ const struct mtk_efuse_pdata *pdata; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platfo - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - -+ pdata = device_get_match_data(dev); - econfig.stride = 1; - econfig.word_size = 1; - econfig.reg_read = mtk_reg_read; - econfig.size = resource_size(res); - econfig.priv = priv; - econfig.dev = dev; -+ if (pdata->uses_post_processing) -+ econfig.layout = &mtk_efuse_layout; - nvmem = devm_nvmem_register(dev, &econfig); - - return PTR_ERR_OR_ZERO(nvmem); - } - -+static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = { -+ .uses_post_processing = true, -+}; -+ -+static const struct mtk_efuse_pdata mtk_efuse_pdata = { -+ .uses_post_processing = false, -+}; -+ - static const struct of_device_id mtk_efuse_of_match[] = { -- { .compatible = "mediatek,mt8173-efuse",}, -- { .compatible = "mediatek,efuse",}, -+ { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata }, -+ { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata }, -+ { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata }, - {/* sentinel */}, - }; - MODULE_DEVICE_TABLE(of, mtk_efuse_of_match); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch b/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch deleted file mode 100644 index 200eb1928f..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 1dc552fa33cf98af3e784dbc0500da93cae3b24a Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Tue, 4 Apr 2023 18:21:38 +0100 -Subject: [PATCH] nvmem: bcm-ocotp: Use devm_platform_ioremap_resource() - -According to commit 7945f929f1a7 ("drivers: provide -devm_platform_ioremap_resource()"), convert platform_get_resource(), -devm_ioremap_resource() to a single call to use -devm_platform_ioremap_resource(), as this is exactly what this function -does. - -Signed-off-by: Yang Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-31-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/bcm-ocotp.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/bcm-ocotp.c -+++ b/drivers/nvmem/bcm-ocotp.c -@@ -244,7 +244,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_ - static int bcm_otpc_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -- struct resource *res; - struct otpc_priv *priv; - struct nvmem_device *nvmem; - int err; -@@ -259,8 +258,7 @@ static int bcm_otpc_probe(struct platfor - return -ENODEV; - - /* Get OTP base address register. */ -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->base)) { - dev_err(dev, "unable to map I/O memory\n"); - return PTR_ERR(priv->base); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch b/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch deleted file mode 100644 index 890dacd08d..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 649409990d2e93fac657be7c6960c28a2c601d65 Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Tue, 4 Apr 2023 18:21:39 +0100 -Subject: [PATCH] nvmem: nintendo-otp: Use devm_platform_ioremap_resource() - -According to commit 7945f929f1a7 ("drivers: provide -devm_platform_ioremap_resource()"), convert platform_get_resource(), -devm_ioremap_resource() to a single call to use -devm_platform_ioremap_resource(), as this is exactly what this function -does. - -Signed-off-by: Yang Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-32-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/nintendo-otp.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/nintendo-otp.c -+++ b/drivers/nvmem/nintendo-otp.c -@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct pla - struct device *dev = &pdev->dev; - const struct of_device_id *of_id = - of_match_device(nintendo_otp_of_table, dev); -- struct resource *res; - struct nvmem_device *nvmem; - struct nintendo_otp_priv *priv; - -@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct pla - if (!priv) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->regs = devm_ioremap_resource(dev, res); -+ priv->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->regs)) - return PTR_ERR(priv->regs); - diff --git a/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch deleted file mode 100644 index 3f5d3c1ad4..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c2367aa60d5e34d48582362c6de34b4131d92be7 Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Tue, 4 Apr 2023 18:21:40 +0100 -Subject: [PATCH] nvmem: vf610-ocotp: Use - devm_platform_get_and_ioremap_resource() - -According to commit 890cc39a8799 ("drivers: provide -devm_platform_get_and_ioremap_resource()"), convert -platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yang Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-33-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/vf610-ocotp.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/vf610-ocotp.c -+++ b/drivers/nvmem/vf610-ocotp.c -@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct plat - if (!ocotp_dev) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- ocotp_dev->base = devm_ioremap_resource(dev, res); -+ ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(ocotp_dev->base)) - return PTR_ERR(ocotp_dev->base); - diff --git a/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch b/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch deleted file mode 100644 index eeb407e9bb..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Apr 2023 18:21:42 +0100 -Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post - read lengths -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Callback .read_post_process() is designed to modify raw cell content -before providing it to the consumer. So far we were dealing with -modifications that didn't affect cell size (length). In some cases -however cell content needs to be reformatted and resized. - -It's required e.g. to provide properly formatted MAC address in case -it's stored in a non-binary format (e.g. using ASCII). - -There were few discussions how to optimally handle that. Following -possible solutions were considered: -1. Allow .read_post_process() to realloc (resize) content buffer -2. Allow .read_post_process() to adjust (decrease) just buffer length -3. Register NVMEM cells using post-read sizes - -The preferred solution was the last one. The problem is that simply -adjusting "bytes" in NVMEM providers would result in core code NOT -passing whole raw data to .read_post_process() callbacks. It means -callback functions couldn't do their job without somehow manually -reading original cell content on their own. - -This patch deals with that by registering NVMEM cells with both lengths: -raw content one and post read one. It allows: -1. Core code to read whole raw cell content -2. Callbacks to return content they want - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 11 +++++++---- - include/linux/nvmem-provider.h | 2 ++ - 2 files changed, 9 insertions(+), 4 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -50,6 +50,7 @@ struct nvmem_device { - struct nvmem_cell_entry { - const char *name; - int offset; -+ size_t raw_len; - int bytes; - int bit_offset; - int nbits; -@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell - { - cell->nvmem = nvmem; - cell->offset = info->offset; -+ cell->raw_len = info->raw_len ?: info->bytes; - cell->bytes = info->bytes; - cell->name = info->name; - cell->read_post_process = info->read_post_process; -@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme - { - int rc; - -- rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes); -+ rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len); - - if (rc) - return rc; -@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme - - if (cell->read_post_process) { - rc = cell->read_post_process(cell->priv, id, index, -- cell->offset, buf, cell->bytes); -+ cell->offset, buf, cell->raw_len); - if (rc) - return rc; - } -@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme - */ - void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len) - { -- struct nvmem_device *nvmem = cell->entry->nvmem; -+ struct nvmem_cell_entry *entry = cell->entry; -+ struct nvmem_device *nvmem = entry->nvmem; - u8 *buf; - int rc; - - if (!nvmem) - return ERR_PTR(-EINVAL); - -- buf = kzalloc(cell->entry->bytes, GFP_KERNEL); -+ buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL); - if (!buf) - return ERR_PTR(-ENOMEM); - ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -51,6 +51,7 @@ struct nvmem_keepout { - * struct nvmem_cell_info - NVMEM cell description - * @name: Name. - * @offset: Offset within the NVMEM device. -+ * @raw_len: Length of raw data (without post processing). - * @bytes: Length of the cell. - * @bit_offset: Bit offset if cell is smaller than a byte. - * @nbits: Number of bits. -@@ -62,6 +63,7 @@ struct nvmem_keepout { - struct nvmem_cell_info { - const char *name; - unsigned int offset; -+ size_t raw_len; - unsigned int bytes; - unsigned int bit_offset; - unsigned int nbits; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch b/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch deleted file mode 100644 index adde0ffc4b..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch +++ /dev/null @@ -1,81 +0,0 @@ -From c49f1a8af6bcf6d18576bca898f8083ca4b129e1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Apr 2023 18:21:43 +0100 -Subject: [PATCH] nvmem: u-boot-env: post-process "ethaddr" env variable -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -U-Boot environment variables are stored in ASCII format so "ethaddr" -requires parsing into binary to make it work with Ethernet interfaces. - -This includes support for indexes to support #nvmem-cell-cells = <1>. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-36-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 1 + - drivers/nvmem/u-boot-env.c | 26 ++++++++++++++++++++++++++ - 2 files changed, 27 insertions(+) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -340,6 +340,7 @@ config NVMEM_U_BOOT_ENV - tristate "U-Boot environment variables support" - depends on OF && MTD - select CRC32 -+ select GENERIC_NET_UTILS - help - U-Boot stores its setup as environment variables. This driver adds - support for verifying & exporting such data. It also exposes variables ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -4,6 +4,8 @@ - */ - - #include -+#include -+#include - #include - #include - #include -@@ -70,6 +72,25 @@ static int u_boot_env_read(void *context - return 0; - } - -+static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, -+ unsigned int offset, void *buf, size_t bytes) -+{ -+ u8 mac[ETH_ALEN]; -+ -+ if (bytes != 3 * ETH_ALEN - 1) -+ return -EINVAL; -+ -+ if (!mac_pton(buf, mac)) -+ return -EINVAL; -+ -+ if (index) -+ eth_addr_add(mac, index); -+ -+ ether_addr_copy(buf, mac); -+ -+ return 0; -+} -+ - static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, - size_t data_offset, size_t data_len) - { -@@ -101,6 +122,11 @@ static int u_boot_env_add_cells(struct u - priv->cells[idx].offset = data_offset + value - data; - priv->cells[idx].bytes = strlen(value); - priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); -+ if (!strcmp(var, "ethaddr")) { -+ priv->cells[idx].raw_len = strlen(value); -+ priv->cells[idx].bytes = ETH_ALEN; -+ priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; -+ } - } - - if (WARN_ON(idx != priv->ncells)) diff --git a/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch b/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch deleted file mode 100644 index 7c6fe22b5f..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 814c978f02db17f16e6aa2efa2a929372f06da09 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:44 +0100 -Subject: [PATCH] nvmem: Add macro to register nvmem layout drivers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Provide a module_nvmem_layout_driver() macro at the end of the -nvmem-provider.h header to reduce the boilerplate when registering nvmem -layout drivers. - -Suggested-by: Srinivas Kandagatla -Signed-off-by: Miquel Raynal -Acked-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-37-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/nvmem-provider.h | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -9,6 +9,7 @@ - #ifndef _LINUX_NVMEM_PROVIDER_H - #define _LINUX_NVMEM_PROVIDER_H - -+#include - #include - #include - #include -@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem - } - - #endif /* CONFIG_NVMEM */ -+ -+#define module_nvmem_layout_driver(__layout_driver) \ -+ module_driver(__layout_driver, nvmem_layout_register, \ -+ nvmem_layout_unregister) -+ - #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch deleted file mode 100644 index 06646dd68b..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0abdf99fe0c86252ba274703425f8d543d7e7f0d Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:45 +0100 -Subject: [PATCH] nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver() - -Stop open-coding the module init/exit functions. Use the -module_nvmem_layout_driver() instead. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-38-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/sl28vpd.c | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - ---- a/drivers/nvmem/layouts/sl28vpd.c -+++ b/drivers/nvmem/layouts/sl28vpd.c -@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = { - .of_match_table = sl28vpd_of_match_table, - .add_cells = sl28vpd_add_cells, - }; -- --static int __init sl28vpd_init(void) --{ -- return nvmem_layout_register(&sl28vpd_layout); --} -- --static void __exit sl28vpd_exit(void) --{ -- nvmem_layout_unregister(&sl28vpd_layout); --} -- --module_init(sl28vpd_init); --module_exit(sl28vpd_exit); -+module_nvmem_layout_driver(sl28vpd_layout); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Michael Walle "); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch b/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch deleted file mode 100644 index 826f4378c2..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch +++ /dev/null @@ -1,39 +0,0 @@ -From d119eb38faab61125aaa4f63c74eef61585cf34c Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:46 +0100 -Subject: [PATCH] nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver() - -Stop open-coding the module init/exit functions. Use the -module_nvmem_layout_driver() instead. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-39-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/onie-tlv.c | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - ---- a/drivers/nvmem/layouts/onie-tlv.c -+++ b/drivers/nvmem/layouts/onie-tlv.c -@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layo - .of_match_table = onie_tlv_of_match_table, - .add_cells = onie_tlv_parse_table, - }; -- --static int __init onie_tlv_init(void) --{ -- return nvmem_layout_register(&onie_tlv_layout); --} -- --static void __exit onie_tlv_exit(void) --{ -- nvmem_layout_unregister(&onie_tlv_layout); --} -- --module_init(onie_tlv_init); --module_exit(onie_tlv_exit); -+module_nvmem_layout_driver(onie_tlv_layout); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Miquel Raynal "); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch b/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch deleted file mode 100644 index f20db85ceb..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 6b13e4b6a9a45028ac730e550380077df1845912 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:47 +0100 -Subject: [PATCH] nvmem: layouts: onie-tlv: Drop wrong module alias - -The MODULE_ALIAS macro is misused here as it carries the -description. There is currently no relevant alias to provide so let's -just drop it. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-40-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/onie-tlv.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/nvmem/layouts/onie-tlv.c -+++ b/drivers/nvmem/layouts/onie-tlv.c -@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layo - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Miquel Raynal "); - MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing"); --MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch b/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch deleted file mode 100644 index 5cf847b57a..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch +++ /dev/null @@ -1,31 +0,0 @@ -From a8642cd11635a35a5f1dc31857887900d6610778 Mon Sep 17 00:00:00 2001 -From: Tom Rix -Date: Tue, 4 Apr 2023 18:21:48 +0100 -Subject: [PATCH] nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout - storage-class-specifier to static - -smatch reports -drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol - 'sl28vpd_layout' was not declared. Should it be static? - -This variable is only used in one file so it should be static. - -Signed-off-by: Tom Rix -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-41-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/sl28vpd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/layouts/sl28vpd.c -+++ b/drivers/nvmem/layouts/sl28vpd.c -@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd - }; - MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); - --struct nvmem_layout sl28vpd_layout = { -+static struct nvmem_layout sl28vpd_layout = { - .name = "sl28-vpd", - .of_match_table = sl28vpd_of_match_table, - .add_cells = sl28vpd_add_cells, diff --git a/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch b/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch deleted file mode 100644 index 13ee2d4229..0000000000 --- a/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch +++ /dev/null @@ -1,100 +0,0 @@ -From a5be5ce0e25439fae3cd42e3d775979547926812 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 3 Nov 2022 09:25:29 +0100 -Subject: [PATCH] firmware/nvram: bcm47xx: support init from IO memory -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Provide NVMEM content to the NVRAM driver from a simple -memory resource. This is necessary to use NVRAM in a memory- -mapped flash device. Patch taken from OpenWrts development -tree. - -This patch makes it possible to use memory-mapped NVRAM -on the D-Link DWL-8610AP and the D-Link DIR-890L. - -Cc: Hauke Mehrtens -Cc: linux-mips@vger.kernel.org -Cc: Florian Fainelli -Cc: bcm-kernel-feedback-list@broadcom.com -Cc: Thomas Bogendoerfer -Signed-off-by: Rafał Miłecki -[Added an export for modules potentially using the init symbol] -Signed-off-by: Linus Walleij -Link: https://lore.kernel.org/r/20221103082529.359084-1-linus.walleij@linaro.org -Signed-off-by: Florian Fainelli ---- - drivers/firmware/broadcom/bcm47xx_nvram.c | 18 ++++++++++++++++++ - drivers/nvmem/brcm_nvram.c | 3 +++ - include/linux/bcm47xx_nvram.h | 6 ++++++ - 3 files changed, 27 insertions(+) - ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -110,6 +110,24 @@ found: - return 0; - } - -+int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size) -+{ -+ if (nvram_len) { -+ pr_warn("nvram already initialized\n"); -+ return -EEXIST; -+ } -+ -+ if (!bcm47xx_nvram_is_valid(nvram_start)) { -+ pr_err("No valid NVRAM found\n"); -+ return -ENOENT; -+ } -+ -+ bcm47xx_nvram_copy(nvram_start, res_size); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(bcm47xx_nvram_init_from_iomem); -+ - /* - * On bcm47xx we need access to the NVRAM very early, so we can't use mtd - * subsystem to access flash. We can't even use platform device / driver to ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -3,6 +3,7 @@ - * Copyright (C) 2021 Rafał Miłecki - */ - -+#include - #include - #include - #include -@@ -139,6 +140,8 @@ static int brcm_nvram_probe(struct platf - if (err) - return err; - -+ bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res)); -+ - config.dev = dev; - config.cells = priv->cells; - config.ncells = priv->ncells; ---- a/include/linux/bcm47xx_nvram.h -+++ b/include/linux/bcm47xx_nvram.h -@@ -11,6 +11,7 @@ - #include - - #ifdef CONFIG_BCM47XX_NVRAM -+int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size); - int bcm47xx_nvram_init_from_mem(u32 base, u32 lim); - int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); - int bcm47xx_nvram_gpio_pin(const char *name); -@@ -20,6 +21,11 @@ static inline void bcm47xx_nvram_release - vfree(nvram); - }; - #else -+static inline int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, -+ size_t res_size) -+{ -+ return -ENOTSUPP; -+} - static inline int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) - { - return -ENOTSUPP; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch b/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch deleted file mode 100644 index 38cfccd5ef..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch +++ /dev/null @@ -1,31 +0,0 @@ -From eebc6573ad940b62a87776db3917e912b4f52d78 Mon Sep 17 00:00:00 2001 -From: Tom Rix -Date: Sun, 11 Jun 2023 15:03:05 +0100 -Subject: [PATCH] nvmem: imx-ocotp: set varaiable imx_ocotp_layout - storage-class-specifier to static - -smatch reports -drivers/nvmem/imx-ocotp.c:599:21: warning: symbol - 'imx_ocotp_layout' was not declared. Should it be static? - -This variable is only used in one file so should be static. - -Signed-off-by: Tom Rix -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-2-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/imx-ocotp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -596,7 +596,7 @@ static void imx_ocotp_fixup_cell_info(st - cell->read_post_process = imx_ocotp_cell_pp; - } - --struct nvmem_layout imx_ocotp_layout = { -+static struct nvmem_layout imx_ocotp_layout = { - .fixup_cell_info = imx_ocotp_fixup_cell_info, - }; - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch b/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch deleted file mode 100644 index 7523e5ebf6..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 8a00fc606312c68b98add8fe8e6f7a013ce29e78 Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Sun, 11 Jun 2023 15:03:06 +0100 -Subject: [PATCH] nvmem: imx-ocotp: Reverse MAC addresses on all i.MX derivates - -Not just i.MX8M, but all i.MX6/7 (and subtypes) need to reverse the -MAC address read from fuses. Exceptions are i.MX6SLL and i.MX7ULP which -do not support ethernet at all. - -Fixes: d0221a780cbc ("nvmem: imx-ocotp: add support for post processing") -Signed-off-by: Alexander Stein -Tested-by: Richard Leitner # imx6q -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-3-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/imx-ocotp.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -97,7 +97,6 @@ struct ocotp_params { - unsigned int bank_address_words; - void (*set_timing)(struct ocotp_priv *priv); - struct ocotp_ctrl_reg ctrl; -- bool reverse_mac_address; - }; - - static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags) -@@ -545,7 +544,6 @@ static const struct ocotp_params imx8mq_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, -- .reverse_mac_address = true, - }; - - static const struct ocotp_params imx8mm_params = { -@@ -553,7 +551,6 @@ static const struct ocotp_params imx8mm_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, -- .reverse_mac_address = true, - }; - - static const struct ocotp_params imx8mn_params = { -@@ -561,7 +558,6 @@ static const struct ocotp_params imx8mn_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, -- .reverse_mac_address = true, - }; - - static const struct ocotp_params imx8mp_params = { -@@ -569,7 +565,6 @@ static const struct ocotp_params imx8mp_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_8MP, -- .reverse_mac_address = true, - }; - - static const struct of_device_id imx_ocotp_dt_ids[] = { -@@ -624,8 +619,7 @@ static int imx_ocotp_probe(struct platfo - imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; - imx_ocotp_nvmem_config.dev = dev; - imx_ocotp_nvmem_config.priv = priv; -- if (priv->params->reverse_mac_address) -- imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; -+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; - - priv->config = &imx_ocotp_nvmem_config; - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch b/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch deleted file mode 100644 index fb4d346a95..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 73bcd133c910bff3b6d3b3834d0d14be9444e90a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sun, 11 Jun 2023 15:03:08 +0100 -Subject: [PATCH] nvmem: brcm_nvram: add .read_post_process() for MACs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -1. Parse ASCII MAC format into byte based -2. Calculate relative addresses based on index argument - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-5-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 1 + - drivers/nvmem/brcm_nvram.c | 28 ++++++++++++++++++++++++++++ - 2 files changed, 29 insertions(+) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM - tristate "Broadcom's NVRAM support" - depends on ARCH_BCM_5301X || COMPILE_TEST - depends on HAS_IOMEM -+ select GENERIC_NET_UTILS - help - This driver provides support for Broadcom's NVRAM that can be accessed - using I/O mapping. ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -4,6 +4,8 @@ - */ - - #include -+#include -+#include - #include - #include - #include -@@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context - return 0; - } - -+static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index, -+ unsigned int offset, void *buf, size_t bytes) -+{ -+ u8 mac[ETH_ALEN]; -+ -+ if (bytes != 3 * ETH_ALEN - 1) -+ return -EINVAL; -+ -+ if (!mac_pton(buf, mac)) -+ return -EINVAL; -+ -+ if (index) -+ eth_addr_add(mac, index); -+ -+ ether_addr_copy(buf, mac); -+ -+ return 0; -+} -+ - static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data, - size_t len) - { -@@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct b - priv->cells[idx].offset = value - (char *)data; - priv->cells[idx].bytes = strlen(value); - priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); -+ if (!strcmp(var, "et0macaddr") || -+ !strcmp(var, "et1macaddr") || -+ !strcmp(var, "et2macaddr")) { -+ priv->cells[idx].raw_len = strlen(value); -+ priv->cells[idx].bytes = ETH_ALEN; -+ priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; -+ } - } - - return 0; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch b/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch deleted file mode 100644 index 3b6e6e57f5..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 8dc61364164e79e44c07fa2ac0a7b6939f00d5db Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:13 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data - -In preparation to support new Rockchip OTP memory devices with different -clock configurations and register layout, extend rockchip_data struct -with the related members: clks, num_clks, reg_read. - -Additionally, to avoid managing redundant driver data, drop num_clks -member from rockchip_otp struct and update all references to point to -the equivalent member in rockchip_data. - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-10-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 79 ++++++++++++++++++++++-------------- - 1 file changed, 49 insertions(+), 30 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -54,21 +54,19 @@ - - #define OTPC_TIMEOUT 10000 - -+struct rockchip_data { -+ int size; -+ const char * const *clks; -+ int num_clks; -+ nvmem_reg_read_t reg_read; -+}; -+ - struct rockchip_otp { - struct device *dev; - void __iomem *base; -- struct clk_bulk_data *clks; -- int num_clks; -+ struct clk_bulk_data *clks; - struct reset_control *rst; --}; -- --/* list of required clocks */ --static const char * const rockchip_otp_clocks[] = { -- "otp", "apb_pclk", "phy", --}; -- --struct rockchip_data { -- int size; -+ const struct rockchip_data *data; - }; - - static int rockchip_otp_reset(struct rockchip_otp *otp) -@@ -132,29 +130,23 @@ static int rockchip_otp_ecc_enable(struc - return ret; - } - --static int rockchip_otp_read(void *context, unsigned int offset, -- void *val, size_t bytes) -+static int px30_otp_read(void *context, unsigned int offset, -+ void *val, size_t bytes) - { - struct rockchip_otp *otp = context; - u8 *buf = val; -- int ret = 0; -- -- ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks); -- if (ret < 0) { -- dev_err(otp->dev, "failed to prepare/enable clks\n"); -- return ret; -- } -+ int ret; - - ret = rockchip_otp_reset(otp); - if (ret) { - dev_err(otp->dev, "failed to reset otp phy\n"); -- goto disable_clks; -+ return ret; - } - - ret = rockchip_otp_ecc_enable(otp, false); - if (ret < 0) { - dev_err(otp->dev, "rockchip_otp_ecc_enable err\n"); -- goto disable_clks; -+ return ret; - } - - writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); -@@ -174,8 +166,28 @@ static int rockchip_otp_read(void *conte - - read_end: - writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); --disable_clks: -- clk_bulk_disable_unprepare(otp->num_clks, otp->clks); -+ -+ return ret; -+} -+ -+static int rockchip_otp_read(void *context, unsigned int offset, -+ void *val, size_t bytes) -+{ -+ struct rockchip_otp *otp = context; -+ int ret; -+ -+ if (!otp->data || !otp->data->reg_read) -+ return -EINVAL; -+ -+ ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks); -+ if (ret < 0) { -+ dev_err(otp->dev, "failed to prepare/enable clks\n"); -+ return ret; -+ } -+ -+ ret = otp->data->reg_read(context, offset, val, bytes); -+ -+ clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks); - - return ret; - } -@@ -189,8 +201,15 @@ static struct nvmem_config otp_config = - .reg_read = rockchip_otp_read, - }; - -+static const char * const px30_otp_clocks[] = { -+ "otp", "apb_pclk", "phy", -+}; -+ - static const struct rockchip_data px30_data = { - .size = 0x40, -+ .clks = px30_otp_clocks, -+ .num_clks = ARRAY_SIZE(px30_otp_clocks), -+ .reg_read = px30_otp_read, - }; - - static const struct of_device_id rockchip_otp_match[] = { -@@ -225,21 +244,21 @@ static int rockchip_otp_probe(struct pla - if (!otp) - return -ENOMEM; - -+ otp->data = data; - otp->dev = dev; - otp->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(otp->base)) - return PTR_ERR(otp->base); - -- otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks); -- otp->clks = devm_kcalloc(dev, otp->num_clks, -- sizeof(*otp->clks), GFP_KERNEL); -+ otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks), -+ GFP_KERNEL); - if (!otp->clks) - return -ENOMEM; - -- for (i = 0; i < otp->num_clks; ++i) -- otp->clks[i].id = rockchip_otp_clocks[i]; -+ for (i = 0; i < data->num_clks; ++i) -+ otp->clks[i].id = data->clks[i]; - -- ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks); -+ ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks); - if (ret) - return ret; - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch b/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch deleted file mode 100644 index b5b66cfc5a..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 30fd21cfb1e64ef20035559a8246f5fbf682c40e Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:14 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Generalize rockchip_otp_wait_status() - -In preparation to support additional Rockchip OTP memory devices with -different register layout, generalize rockchip_otp_wait_status() to -accept a new parameter for specifying the offset of the status register. - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-11-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -90,18 +90,19 @@ static int rockchip_otp_reset(struct roc - return 0; - } - --static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag) -+static int rockchip_otp_wait_status(struct rockchip_otp *otp, -+ unsigned int reg, u32 flag) - { - u32 status = 0; - int ret; - -- ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status, -+ ret = readl_poll_timeout_atomic(otp->base + reg, status, - (status & flag), 1, OTPC_TIMEOUT); - if (ret) - return ret; - - /* clean int status */ -- writel(flag, otp->base + OTPC_INT_STATUS); -+ writel(flag, otp->base + reg); - - return 0; - } -@@ -123,7 +124,7 @@ static int rockchip_otp_ecc_enable(struc - - writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL); - -- ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); -+ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_SBPI_DONE); - if (ret < 0) - dev_err(otp->dev, "timeout during ecc_enable\n"); - -@@ -156,7 +157,7 @@ static int px30_otp_read(void *context, - otp->base + OTPC_USER_ADDR); - writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, - otp->base + OTPC_USER_ENABLE); -- ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); -+ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE); - if (ret < 0) { - dev_err(otp->dev, "timeout during read setup\n"); - goto read_end; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch b/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch deleted file mode 100644 index 3a17479d95..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch +++ /dev/null @@ -1,31 +0,0 @@ -From d325c9dd2b6e94040ca722ddcadcd6af358dd2be Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:15 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Use - devm_reset_control_array_get_exclusive() - -In preparation to support new Rockchip OTP memory devices having -specific reset configurations, switch devm_reset_control_get() to -devm_reset_control_array_get_exclusive(). - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-12-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -263,7 +263,7 @@ static int rockchip_otp_probe(struct pla - if (ret) - return ret; - -- otp->rst = devm_reset_control_get(dev, "phy"); -+ otp->rst = devm_reset_control_array_get_exclusive(dev); - if (IS_ERR(otp->rst)) - return PTR_ERR(otp->rst); - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch b/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch deleted file mode 100644 index 37cb927b10..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 912517345b867a69542dc9f5c2cc3e9d8beaccf5 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:16 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Improve probe error handling - -Enhance error handling in the probe function by making use of -dev_err_probe(), which ensures the error code is always printed, in -addition to the specified error message. - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-13-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -235,10 +235,8 @@ static int rockchip_otp_probe(struct pla - int ret, i; - - data = of_device_get_match_data(dev); -- if (!data) { -- dev_err(dev, "failed to get match data\n"); -- return -EINVAL; -- } -+ if (!data) -+ return dev_err_probe(dev, -EINVAL, "failed to get match data\n"); - - otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp), - GFP_KERNEL); -@@ -249,7 +247,8 @@ static int rockchip_otp_probe(struct pla - otp->dev = dev; - otp->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(otp->base)) -- return PTR_ERR(otp->base); -+ return dev_err_probe(dev, PTR_ERR(otp->base), -+ "failed to ioremap resource\n"); - - otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks), - GFP_KERNEL); -@@ -261,18 +260,22 @@ static int rockchip_otp_probe(struct pla - - ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks); - if (ret) -- return ret; -+ return dev_err_probe(dev, ret, "failed to get clocks\n"); - - otp->rst = devm_reset_control_array_get_exclusive(dev); - if (IS_ERR(otp->rst)) -- return PTR_ERR(otp->rst); -+ return dev_err_probe(dev, PTR_ERR(otp->rst), -+ "failed to get resets\n"); - - otp_config.size = data->size; - otp_config.priv = otp; - otp_config.dev = dev; -- nvmem = devm_nvmem_register(dev, &otp_config); - -- return PTR_ERR_OR_ZERO(nvmem); -+ nvmem = devm_nvmem_register(dev, &otp_config); -+ if (IS_ERR(nvmem)) -+ return dev_err_probe(dev, PTR_ERR(nvmem), -+ "failed to register nvmem device\n"); -+ return 0; - } - - static struct platform_driver rockchip_otp_driver = { diff --git a/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch b/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch deleted file mode 100644 index c1e2231c9e..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 8ab099fafbbc8c9607c399d21a774784a6cb8b45 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:17 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3588 - -Add support for the OTP memory device found on the Rockchip RK3588 SoC. - -While here, remove the unnecessary 'void *' casts in the OF device ID -table. - -Co-developed-by: Finley Xiao -Signed-off-by: Finley Xiao -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-14-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 78 +++++++++++++++++++++++++++++++++++- - 1 file changed, 76 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -54,6 +54,19 @@ - - #define OTPC_TIMEOUT 10000 - -+/* RK3588 Register */ -+#define RK3588_OTPC_AUTO_CTRL 0x04 -+#define RK3588_OTPC_AUTO_EN 0x08 -+#define RK3588_OTPC_INT_ST 0x84 -+#define RK3588_OTPC_DOUT0 0x20 -+#define RK3588_NO_SECURE_OFFSET 0x300 -+#define RK3588_NBYTES 4 -+#define RK3588_BURST_NUM 1 -+#define RK3588_BURST_SHIFT 8 -+#define RK3588_ADDR_SHIFT 16 -+#define RK3588_AUTO_EN BIT(0) -+#define RK3588_RD_DONE BIT(1) -+ - struct rockchip_data { - int size; - const char * const *clks; -@@ -171,6 +184,52 @@ read_end: - return ret; - } - -+static int rk3588_otp_read(void *context, unsigned int offset, -+ void *val, size_t bytes) -+{ -+ struct rockchip_otp *otp = context; -+ unsigned int addr_start, addr_end, addr_len; -+ int ret, i = 0; -+ u32 data; -+ u8 *buf; -+ -+ addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES; -+ addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES; -+ addr_len = addr_end - addr_start; -+ addr_start += RK3588_NO_SECURE_OFFSET; -+ -+ buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ while (addr_len--) { -+ writel((addr_start << RK3588_ADDR_SHIFT) | -+ (RK3588_BURST_NUM << RK3588_BURST_SHIFT), -+ otp->base + RK3588_OTPC_AUTO_CTRL); -+ writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN); -+ -+ ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST, -+ RK3588_RD_DONE); -+ if (ret < 0) { -+ dev_err(otp->dev, "timeout during read setup\n"); -+ goto read_end; -+ } -+ -+ data = readl(otp->base + RK3588_OTPC_DOUT0); -+ memcpy(&buf[i], &data, RK3588_NBYTES); -+ -+ i += RK3588_NBYTES; -+ addr_start++; -+ } -+ -+ memcpy(val, buf + offset % RK3588_NBYTES, bytes); -+ -+read_end: -+ kfree(buf); -+ -+ return ret; -+} -+ - static int rockchip_otp_read(void *context, unsigned int offset, - void *val, size_t bytes) - { -@@ -213,14 +272,29 @@ static const struct rockchip_data px30_d - .reg_read = px30_otp_read, - }; - -+static const char * const rk3588_otp_clocks[] = { -+ "otp", "apb_pclk", "phy", "arb", -+}; -+ -+static const struct rockchip_data rk3588_data = { -+ .size = 0x400, -+ .clks = rk3588_otp_clocks, -+ .num_clks = ARRAY_SIZE(rk3588_otp_clocks), -+ .reg_read = rk3588_otp_read, -+}; -+ - static const struct of_device_id rockchip_otp_match[] = { - { - .compatible = "rockchip,px30-otp", -- .data = (void *)&px30_data, -+ .data = &px30_data, - }, - { - .compatible = "rockchip,rk3308-otp", -- .data = (void *)&px30_data, -+ .data = &px30_data, -+ }, -+ { -+ .compatible = "rockchip,rk3588-otp", -+ .data = &rk3588_data, - }, - { /* sentinel */ }, - }; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch b/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch deleted file mode 100644 index 220e3e9a05..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 9734408969e978a1c0d5d752be63dd638288e374 Mon Sep 17 00:00:00 2001 -From: Michal Simek -Date: Sun, 11 Jun 2023 15:03:23 +0100 -Subject: [PATCH] nvmem: zynqmp: Switch @xilinx.com emails to @amd.com - -@xilinx.com is still working but better to switch to new amd.com after -AMD/Xilinx acquisition. - -Signed-off-by: Michal Simek -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-20-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/zynqmp_nvmem.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/zynqmp_nvmem.c -+++ b/drivers/nvmem/zynqmp_nvmem.c -@@ -76,6 +76,6 @@ static struct platform_driver zynqmp_nvm - - module_platform_driver(zynqmp_nvmem_driver); - --MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); -+MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); - MODULE_DESCRIPTION("ZynqMP NVMEM driver"); - MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch b/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch deleted file mode 100644 index f8e6be4241..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch +++ /dev/null @@ -1,230 +0,0 @@ -From 22e9e6fcfb5042cb6d6c7874c459b034800092f1 Mon Sep 17 00:00:00 2001 -From: Peng Fan -Date: Sun, 11 Jun 2023 15:03:25 +0100 -Subject: [PATCH] nvmem: imx: support i.MX93 OCOTP - -Add i.MX93 OCOTP support. i.MX93 OCOTP has two parts: Fuse shadow -block(fsb) and fuse managed by ELE. The FSB part could be directly -accessed with MMIO, the ELE could only be accessed with ELE API. - -Currently the ELE API is not ready, so NULL function callback is used, -but it was tested with downstream ELE API. - -Signed-off-by: Peng Fan -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-22-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 9 ++ - drivers/nvmem/Makefile | 2 + - drivers/nvmem/imx-ocotp-ele.c | 175 ++++++++++++++++++++++++++++++++++ - 3 files changed, 186 insertions(+) - create mode 100644 drivers/nvmem/imx-ocotp-ele.c - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -83,6 +83,15 @@ config NVMEM_IMX_OCOTP - This driver can also be built as a module. If so, the module - will be called nvmem-imx-ocotp. - -+config NVMEM_IMX_OCOTP_ELE -+ tristate "i.MX On-Chip OTP Controller support" -+ depends on ARCH_MXC || COMPILE_TEST -+ depends on HAS_IOMEM -+ depends on OF -+ help -+ This is a driver for the On-Chip OTP Controller (OCOTP) -+ available on i.MX SoCs which has ELE. -+ - config NVMEM_IMX_OCOTP_SCU - tristate "i.MX8 SCU On-Chip OTP Controller support" - depends on IMX_SCU ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -18,6 +18,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-im - nvmem-imx-iim-y := imx-iim.o - obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o - nvmem-imx-ocotp-y := imx-ocotp.o -+obj-$(CONFIG_NVMEM_IMX_OCOTP_ELE) += nvmem-imx-ocotp-ele.o -+nvmem-imx-ocotp-ele-y := imx-ocotp-ele.o - obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o - nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o - obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o ---- /dev/null -+++ b/drivers/nvmem/imx-ocotp-ele.c -@@ -0,0 +1,175 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * i.MX9 OCOTP fusebox driver -+ * -+ * Copyright 2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+enum fuse_type { -+ FUSE_FSB = 1, -+ FUSE_ELE = 2, -+ FUSE_INVALID = -1 -+}; -+ -+struct ocotp_map_entry { -+ u32 start; /* start word */ -+ u32 num; /* num words */ -+ enum fuse_type type; -+}; -+ -+struct ocotp_devtype_data { -+ u32 reg_off; -+ char *name; -+ u32 size; -+ u32 num_entry; -+ u32 flag; -+ nvmem_reg_read_t reg_read; -+ struct ocotp_map_entry entry[]; -+}; -+ -+struct imx_ocotp_priv { -+ struct device *dev; -+ void __iomem *base; -+ struct nvmem_config config; -+ struct mutex lock; -+ const struct ocotp_devtype_data *data; -+}; -+ -+static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index) -+{ -+ struct imx_ocotp_priv *priv = context; -+ const struct ocotp_devtype_data *data = priv->data; -+ u32 start, end; -+ int i; -+ -+ for (i = 0; i < data->num_entry; i++) { -+ start = data->entry[i].start; -+ end = data->entry[i].start + data->entry[i].num; -+ -+ if (index >= start && index < end) -+ return data->entry[i].type; -+ } -+ -+ return FUSE_INVALID; -+} -+ -+static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, size_t bytes) -+{ -+ struct imx_ocotp_priv *priv = context; -+ void __iomem *reg = priv->base + priv->data->reg_off; -+ u32 count, index, num_bytes; -+ enum fuse_type type; -+ u32 *buf; -+ void *p; -+ int i; -+ -+ index = offset; -+ num_bytes = round_up(bytes, 4); -+ count = num_bytes >> 2; -+ -+ if (count > ((priv->data->size >> 2) - index)) -+ count = (priv->data->size >> 2) - index; -+ -+ p = kzalloc(num_bytes, GFP_KERNEL); -+ if (!p) -+ return -ENOMEM; -+ -+ mutex_lock(&priv->lock); -+ -+ buf = p; -+ -+ for (i = index; i < (index + count); i++) { -+ type = imx_ocotp_fuse_type(context, i); -+ if (type == FUSE_INVALID || type == FUSE_ELE) { -+ *buf++ = 0; -+ continue; -+ } -+ -+ *buf++ = readl_relaxed(reg + (i << 2)); -+ } -+ -+ memcpy(val, (u8 *)p, bytes); -+ -+ mutex_unlock(&priv->lock); -+ -+ kfree(p); -+ -+ return 0; -+}; -+ -+static int imx_ele_ocotp_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct imx_ocotp_priv *priv; -+ struct nvmem_device *nvmem; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->data = of_device_get_match_data(dev); -+ -+ priv->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(priv->base)) -+ return PTR_ERR(priv->base); -+ -+ priv->config.dev = dev; -+ priv->config.name = "ELE-OCOTP"; -+ priv->config.id = NVMEM_DEVID_AUTO; -+ priv->config.owner = THIS_MODULE; -+ priv->config.size = priv->data->size; -+ priv->config.reg_read = priv->data->reg_read; -+ priv->config.word_size = 4; -+ priv->config.stride = 1; -+ priv->config.priv = priv; -+ priv->config.read_only = true; -+ mutex_init(&priv->lock); -+ -+ nvmem = devm_nvmem_register(dev, &priv->config); -+ if (IS_ERR(nvmem)) -+ return PTR_ERR(nvmem); -+ -+ return 0; -+} -+ -+static const struct ocotp_devtype_data imx93_ocotp_data = { -+ .reg_off = 0x8000, -+ .reg_read = imx_ocotp_reg_read, -+ .size = 2048, -+ .num_entry = 6, -+ .entry = { -+ { 0, 52, FUSE_FSB }, -+ { 63, 1, FUSE_ELE}, -+ { 128, 16, FUSE_ELE }, -+ { 182, 1, FUSE_ELE }, -+ { 188, 1, FUSE_ELE }, -+ { 312, 200, FUSE_FSB } -+ }, -+}; -+ -+static const struct of_device_id imx_ele_ocotp_dt_ids[] = { -+ { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids); -+ -+static struct platform_driver imx_ele_ocotp_driver = { -+ .driver = { -+ .name = "imx_ele_ocotp", -+ .of_match_table = imx_ele_ocotp_dt_ids, -+ }, -+ .probe = imx_ele_ocotp_probe, -+}; -+module_platform_driver(imx_ele_ocotp_driver); -+ -+MODULE_DESCRIPTION("i.MX OCOTP/ELE driver"); -+MODULE_AUTHOR("Peng Fan "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch b/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch deleted file mode 100644 index 59b2f9fa2c..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 27f699e578b1a72df89dfa3bc42e093a01dc8d10 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sun, 11 Jun 2023 15:03:29 +0100 -Subject: [PATCH] nvmem: core: add support for fixed cells *layout* -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds support for the "fixed-layout" NVMEM layout binding. It allows -defining NVMEM cells in a layout DT node named "nvmem-layout". - -While NVMEM subsystem supports layout drivers it has been discussed that -"fixed-layout" may actually be supperted internally. It's because: -1. It's a very basic layout -2. It allows sharing code with legacy syntax parsing -3. It's safer for soc_device_match() due to -EPROBE_DEFER -4. This will make the syntax transition easier - -Signed-off-by: Rafał Miłecki -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-26-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 32 +++++++++++++++++++++++++++++--- - 1 file changed, 29 insertions(+), 3 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -696,7 +696,7 @@ static int nvmem_validate_keepouts(struc - return 0; - } - --static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) -+static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) - { - struct nvmem_layout *layout = nvmem->layout; - struct device *dev = &nvmem->dev; -@@ -704,7 +704,7 @@ static int nvmem_add_cells_from_of(struc - const __be32 *addr; - int len, ret; - -- for_each_child_of_node(dev->of_node, child) { -+ for_each_child_of_node(np, child) { - struct nvmem_cell_info info = {0}; - - addr = of_get_property(child, "reg", &len); -@@ -742,6 +742,28 @@ static int nvmem_add_cells_from_of(struc - return 0; - } - -+static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem) -+{ -+ return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node); -+} -+ -+static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem) -+{ -+ struct device_node *layout_np; -+ int err = 0; -+ -+ layout_np = of_nvmem_layout_get_container(nvmem); -+ if (!layout_np) -+ return 0; -+ -+ if (of_device_is_compatible(layout_np, "fixed-layout")) -+ err = nvmem_add_cells_from_dt(nvmem, layout_np); -+ -+ of_node_put(layout_np); -+ -+ return err; -+} -+ - int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) - { - layout->owner = owner; -@@ -972,7 +994,7 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -- rval = nvmem_add_cells_from_of(nvmem); -+ rval = nvmem_add_cells_from_legacy_of(nvmem); - if (rval) - goto err_remove_cells; - -@@ -982,6 +1004,10 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -+ rval = nvmem_add_cells_from_fixed_layout(nvmem); -+ if (rval) -+ goto err_remove_cells; -+ - rval = nvmem_add_cells_from_layout(nvmem); - if (rval) - goto err_remove_cells; diff --git a/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch b/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch deleted file mode 100644 index bf7a816bb2..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 9ccfcbeb8f32ff89e99b36cb9cdebaa0d1b44ed1 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:24 +0100 -Subject: [PATCH] nvmem: sunxi_sid: Convert to devm_platform_ioremap_resource() - -Use devm_platform_ioremap_resource() to simplify code. - -Signed-off-by: Yangtao Li -Acked-by: Jernej Skrabec -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-3-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/sunxi_sid.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/sunxi_sid.c -+++ b/drivers/nvmem/sunxi_sid.c -@@ -125,7 +125,6 @@ static int sun8i_sid_read_by_reg(void *c - static int sunxi_sid_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -- struct resource *res; - struct nvmem_config *nvmem_cfg; - struct nvmem_device *nvmem; - struct sunxi_sid *sid; -@@ -142,8 +141,7 @@ static int sunxi_sid_probe(struct platfo - return -EINVAL; - sid->value_offset = cfg->value_offset; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- sid->base = devm_ioremap_resource(dev, res); -+ sid->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(sid->base)) - return PTR_ERR(sid->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch b/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch deleted file mode 100644 index f142d735de..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch +++ /dev/null @@ -1,30 +0,0 @@ -From cfadd0e7d9225566f320bc4dc716682be910be6c Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:25 +0100 -Subject: [PATCH] nvmem: brcm_nvram: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-4-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/brcm_nvram.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -159,8 +159,7 @@ static int brcm_nvram_probe(struct platf - return -ENOMEM; - priv->dev = dev; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch b/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch deleted file mode 100644 index 0395bbf8bc..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0b49178e2b6b4aac3c7fa3ce8d8c02208a13b988 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:26 +0100 -Subject: [PATCH] nvmem: lpc18xx_otp: Convert to - devm_platform_ioremap_resource() - -Use devm_platform_ioremap_resource() to simplify code. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-5-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/lpc18xx_otp.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/lpc18xx_otp.c -+++ b/drivers/nvmem/lpc18xx_otp.c -@@ -68,14 +68,12 @@ static int lpc18xx_otp_probe(struct plat - { - struct nvmem_device *nvmem; - struct lpc18xx_otp *otp; -- struct resource *res; - - otp = devm_kzalloc(&pdev->dev, sizeof(*otp), GFP_KERNEL); - if (!otp) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- otp->base = devm_ioremap_resource(&pdev->dev, res); -+ otp->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(otp->base)) - return PTR_ERR(otp->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch b/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch deleted file mode 100644 index da077eb4b7..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0a223a097709b99a0ba738d6be5b4f52c04ffb64 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:27 +0100 -Subject: [PATCH] nvmem: meson-mx-efuse: Convert to - devm_platform_ioremap_resource() - -Use devm_platform_ioremap_resource() to simplify code. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-6-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/meson-mx-efuse.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/meson-mx-efuse.c -+++ b/drivers/nvmem/meson-mx-efuse.c -@@ -194,7 +194,6 @@ static int meson_mx_efuse_probe(struct p - { - const struct meson_mx_efuse_platform_data *drvdata; - struct meson_mx_efuse *efuse; -- struct resource *res; - - drvdata = of_device_get_match_data(&pdev->dev); - if (!drvdata) -@@ -204,8 +203,7 @@ static int meson_mx_efuse_probe(struct p - if (!efuse) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- efuse->base = devm_ioremap_resource(&pdev->dev, res); -+ efuse->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(efuse->base)) - return PTR_ERR(efuse->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch b/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch deleted file mode 100644 index dc144ddfbd..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 94904db28db49ac8fbb2a273d25156db26a3a985 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:28 +0100 -Subject: [PATCH] nvmem: rockchip-efuse: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-7-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-efuse.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/rockchip-efuse.c -+++ b/drivers/nvmem/rockchip-efuse.c -@@ -267,8 +267,7 @@ static int rockchip_efuse_probe(struct p - if (!efuse) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- efuse->base = devm_ioremap_resource(dev, res); -+ efuse->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(efuse->base)) - return PTR_ERR(efuse->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch deleted file mode 100644 index 99e20939cc..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0a4a8c0d238fec1fa4b85591524ef42ad261cb97 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:29 +0100 -Subject: [PATCH] nvmem: stm32-romem: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -196,8 +196,7 @@ static int stm32_romem_probe(struct plat - if (!priv) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch b/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch deleted file mode 100644 index 6d93752e27..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0bc0d6dc2a9a05ae6729b4622f09782d9f230815 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:30 +0100 -Subject: [PATCH] nvmem: qfprom: do some cleanup - -Use devm_platform_ioremap_resource() and -devm_platform_get_and_ioremap_resource() to simplify code. -BTW convert to use dev_err_probe() instead of open it. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/qfprom.c | 17 +++++------------ - 1 file changed, 5 insertions(+), 12 deletions(-) - ---- a/drivers/nvmem/qfprom.c -+++ b/drivers/nvmem/qfprom.c -@@ -374,8 +374,7 @@ static int qfprom_probe(struct platform_ - return -ENOMEM; - - /* The corrected section is always provided */ -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->qfpcorrected = devm_ioremap_resource(dev, res); -+ priv->qfpcorrected = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->qfpcorrected)) - return PTR_ERR(priv->qfpcorrected); - -@@ -402,12 +401,10 @@ static int qfprom_probe(struct platform_ - priv->qfpraw = devm_ioremap_resource(dev, res); - if (IS_ERR(priv->qfpraw)) - return PTR_ERR(priv->qfpraw); -- res = platform_get_resource(pdev, IORESOURCE_MEM, 2); -- priv->qfpconf = devm_ioremap_resource(dev, res); -+ priv->qfpconf = devm_platform_ioremap_resource(pdev, 2); - if (IS_ERR(priv->qfpconf)) - return PTR_ERR(priv->qfpconf); -- res = platform_get_resource(pdev, IORESOURCE_MEM, 3); -- priv->qfpsecurity = devm_ioremap_resource(dev, res); -+ priv->qfpsecurity = devm_platform_ioremap_resource(pdev, 3); - if (IS_ERR(priv->qfpsecurity)) - return PTR_ERR(priv->qfpsecurity); - -@@ -427,12 +424,8 @@ static int qfprom_probe(struct platform_ - return PTR_ERR(priv->vcc); - - priv->secclk = devm_clk_get(dev, "core"); -- if (IS_ERR(priv->secclk)) { -- ret = PTR_ERR(priv->secclk); -- if (ret != -EPROBE_DEFER) -- dev_err(dev, "Error getting clock: %d\n", ret); -- return ret; -- } -+ if (IS_ERR(priv->secclk)) -+ return dev_err_probe(dev, PTR_ERR(priv->secclk), "Error getting clock\n"); - - /* Only enable writing if we have SoC data. */ - if (priv->soc_data) diff --git a/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch b/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch deleted file mode 100644 index 3e328a4c99..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 6ac41c556e22a0d7d267c9b9d48681d73af4b368 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:31 +0100 -Subject: [PATCH] nvmem: uniphier: Use devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-10-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/uniphier-efuse.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/uniphier-efuse.c -+++ b/drivers/nvmem/uniphier-efuse.c -@@ -41,8 +41,7 @@ static int uniphier_efuse_probe(struct p - if (!priv) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch b/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch deleted file mode 100644 index acbe18e270..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch +++ /dev/null @@ -1,133 +0,0 @@ -From c8efcf7a86ebf2ff48584d270b3070a7075bc345 Mon Sep 17 00:00:00 2001 -From: Richard Alpe -Date: Mon, 10 Apr 2023 10:20:51 +0200 -Subject: [PATCH] nvmem: add new NXP QorIQ eFuse driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add SFP (Security Fuse Processor) read support for NXP (Freescale) -QorIQ series SOC's. - -This patch adds support for the T1023 SOC using the SFP offset from -the existing T1023 device tree. In theory this should also work for -T1024, T1014 and T1013 which uses the same SFP base offset. - -Signed-off-by: Richard Alpe -Reviewed-by: Niklas Söderlund -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/Kconfig | 12 ++++++ - drivers/nvmem/Makefile | 2 + - drivers/nvmem/qoriq-efuse.c | 78 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 92 insertions(+) - create mode 100644 drivers/nvmem/qoriq-efuse.c - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -392,4 +392,16 @@ config NVMEM_ZYNQMP - - If sure, say yes. If unsure, say no. - -+config NVMEM_QORIQ_EFUSE -+ tristate "NXP QorIQ eFuse support" -+ depends on PPC_85xx || COMPILE_TEST -+ depends on HAS_IOMEM -+ help -+ This driver provides read support for the eFuses (SFP) on NXP QorIQ -+ series SoC's. This includes secure boot settings, the globally unique -+ NXP ID 'FUIDR' and the OEM unique ID 'OUIDR'. -+ -+ This driver can also be built as a module. If so, the module -+ will be called nvmem_qoriq_efuse. -+ - endif ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -77,3 +77,5 @@ obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvme - nvmem-vf610-ocotp-y := vf610-ocotp.o - obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o - nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o -+obj-$(CONFIG_NVMEM_QORIQ_EFUSE) += nvmem-qoriq-efuse.o -+nvmem-qoriq-efuse-y := qoriq-efuse.o ---- /dev/null -+++ b/drivers/nvmem/qoriq-efuse.c -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2023 Westermo Network Technologies AB -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct qoriq_efuse_priv { -+ void __iomem *base; -+}; -+ -+static int qoriq_efuse_read(void *context, unsigned int offset, void *val, -+ size_t bytes) -+{ -+ struct qoriq_efuse_priv *priv = context; -+ -+ /* .stride = 4 so offset is guaranteed to be aligned */ -+ __ioread32_copy(val, priv->base + offset, bytes / 4); -+ -+ /* Ignore trailing bytes (there shouldn't be any) */ -+ -+ return 0; -+} -+ -+static int qoriq_efuse_probe(struct platform_device *pdev) -+{ -+ struct nvmem_config config = { -+ .dev = &pdev->dev, -+ .read_only = true, -+ .reg_read = qoriq_efuse_read, -+ .stride = sizeof(u32), -+ .word_size = sizeof(u32), -+ .name = "qoriq_efuse_read", -+ .id = NVMEM_DEVID_AUTO, -+ .root_only = true, -+ }; -+ struct qoriq_efuse_priv *priv; -+ struct nvmem_device *nvmem; -+ struct resource *res; -+ -+ priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ if (IS_ERR(priv->base)) -+ return PTR_ERR(priv->base); -+ -+ config.size = resource_size(res); -+ config.priv = priv; -+ nvmem = devm_nvmem_register(config.dev, &config); -+ -+ return PTR_ERR_OR_ZERO(nvmem); -+} -+ -+static const struct of_device_id qoriq_efuse_of_match[] = { -+ { .compatible = "fsl,t1023-sfp", }, -+ {/* sentinel */}, -+}; -+MODULE_DEVICE_TABLE(of, qoriq_efuse_of_match); -+ -+static struct platform_driver qoriq_efuse_driver = { -+ .probe = qoriq_efuse_probe, -+ .driver = { -+ .name = "qoriq-efuse", -+ .of_match_table = qoriq_efuse_of_match, -+ }, -+}; -+module_platform_driver(qoriq_efuse_driver); -+ -+MODULE_AUTHOR("Richard Alpe "); -+MODULE_DESCRIPTION("NXP QorIQ Security Fuse Processor (SFP) Reader"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch b/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch deleted file mode 100644 index 67f30e34a2..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 9d53d595f688c9837e88a919229cc61a165c7b9e Mon Sep 17 00:00:00 2001 -From: Diederik de Haas -Date: Mon, 24 Jul 2023 13:36:22 +0200 -Subject: [PATCH] nvmem: Kconfig: Fix typo "drive" -> "driver" - -Fix typo where "driver" was meant instead of "drive". -While at it, also capitalize "OTP". - -Signed-off-by: Diederik de Haas -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/Kconfig | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -247,7 +247,7 @@ config NVMEM_ROCKCHIP_EFUSE - depends on ARCH_ROCKCHIP || COMPILE_TEST - depends on HAS_IOMEM - help -- This is a simple drive to dump specified values of Rockchip SoC -+ This is a simple driver to dump specified values of Rockchip SoC - from eFuse, such as cpu-leakage. - - This driver can also be built as a module. If so, the module -@@ -258,8 +258,8 @@ config NVMEM_ROCKCHIP_OTP - depends on ARCH_ROCKCHIP || COMPILE_TEST - depends on HAS_IOMEM - help -- This is a simple drive to dump specified values of Rockchip SoC -- from otp, such as cpu-leakage. -+ This is a simple driver to dump specified values of Rockchip SoC -+ from OTP, such as cpu-leakage. - - This driver can also be built as a module. If so, the module - will be called nvmem_rockchip_otp. diff --git a/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch b/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch deleted file mode 100644 index af4a2926dc..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0a9ec38c47c1ca4528aa058e2b9ea61901a7e632 Mon Sep 17 00:00:00 2001 -From: Komal Bajaj -Date: Tue, 1 Aug 2023 12:10:25 +0530 -Subject: [PATCH] nvmem: sec-qfprom: Add Qualcomm secure QFPROM support - -For some of the Qualcomm SoC's, it is possible that -some of the fuse regions or entire qfprom region is -protected from non-secure access. In such situations, -the OS will have to use secure calls to read the region. -With that motivation, add secure qfprom driver. - -Signed-off-by: Komal Bajaj -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/Kconfig | 13 ++++++ - drivers/nvmem/Makefile | 2 + - drivers/nvmem/sec-qfprom.c | 96 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 111 insertions(+) - create mode 100644 drivers/nvmem/sec-qfprom.c - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -226,6 +226,19 @@ config NVMEM_QCOM_QFPROM - This driver can also be built as a module. If so, the module - will be called nvmem_qfprom. - -+config NVMEM_QCOM_SEC_QFPROM -+ tristate "QCOM SECURE QFPROM Support" -+ depends on ARCH_QCOM || COMPILE_TEST -+ depends on HAS_IOMEM -+ depends on OF -+ select QCOM_SCM -+ help -+ Say y here to enable secure QFPROM support. The secure QFPROM provides access -+ functions for QFPROM data to rest of the drivers via nvmem interface. -+ -+ This driver can also be built as a module. If so, the module will be called -+ nvmem_sec_qfprom. -+ - config NVMEM_RAVE_SP_EEPROM - tristate "Rave SP EEPROM Support" - depends on RAVE_SP_CORE ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -46,6 +46,8 @@ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvme - nvmem-nintendo-otp-y := nintendo-otp.o - obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o - nvmem_qfprom-y := qfprom.o -+obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o -+nvmem_sec_qfprom-y := sec-qfprom.o - obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o - nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o - obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o ---- /dev/null -+++ b/drivers/nvmem/sec-qfprom.c -@@ -0,0 +1,96 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * struct sec_qfprom - structure holding secure qfprom attributes -+ * -+ * @base: starting physical address for secure qfprom corrected address space. -+ * @dev: qfprom device structure. -+ */ -+struct sec_qfprom { -+ phys_addr_t base; -+ struct device *dev; -+}; -+ -+static int sec_qfprom_reg_read(void *context, unsigned int reg, void *_val, size_t bytes) -+{ -+ struct sec_qfprom *priv = context; -+ unsigned int i; -+ u8 *val = _val; -+ u32 read_val; -+ u8 *tmp; -+ -+ for (i = 0; i < bytes; i++, reg++) { -+ if (i == 0 || reg % 4 == 0) { -+ if (qcom_scm_io_readl(priv->base + (reg & ~3), &read_val)) { -+ dev_err(priv->dev, "Couldn't access fuse register\n"); -+ return -EINVAL; -+ } -+ tmp = (u8 *)&read_val; -+ } -+ -+ val[i] = tmp[reg & 3]; -+ } -+ -+ return 0; -+} -+ -+static int sec_qfprom_probe(struct platform_device *pdev) -+{ -+ struct nvmem_config econfig = { -+ .name = "sec-qfprom", -+ .stride = 1, -+ .word_size = 1, -+ .id = NVMEM_DEVID_AUTO, -+ .reg_read = sec_qfprom_reg_read, -+ }; -+ struct device *dev = &pdev->dev; -+ struct nvmem_device *nvmem; -+ struct sec_qfprom *priv; -+ struct resource *res; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -EINVAL; -+ -+ priv->base = res->start; -+ -+ econfig.size = resource_size(res); -+ econfig.dev = dev; -+ econfig.priv = priv; -+ -+ priv->dev = dev; -+ -+ nvmem = devm_nvmem_register(dev, &econfig); -+ -+ return PTR_ERR_OR_ZERO(nvmem); -+} -+ -+static const struct of_device_id sec_qfprom_of_match[] = { -+ { .compatible = "qcom,sec-qfprom" }, -+ {/* sentinel */}, -+}; -+MODULE_DEVICE_TABLE(of, sec_qfprom_of_match); -+ -+static struct platform_driver qfprom_driver = { -+ .probe = sec_qfprom_probe, -+ .driver = { -+ .name = "qcom_sec_qfprom", -+ .of_match_table = sec_qfprom_of_match, -+ }, -+}; -+module_platform_driver(qfprom_driver); -+MODULE_DESCRIPTION("Qualcomm Secure QFPROM driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch b/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch deleted file mode 100644 index dab8ec2c24..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c32f2186acc9abb4d766361255d7ddf07d15eeb2 Mon Sep 17 00:00:00 2001 -From: Atul Raut -Date: Sun, 30 Jul 2023 15:39:15 -0700 -Subject: [PATCH] nvmem: u-boot-env:: Replace zero-length array with - DECLARE_FLEX_ARRAY() helper - -We are moving toward replacing zero-length arrays with C99 flexible-array -members since they are deprecated. Therefore, the new DECLARE_FLEX_ARRAY() -helper macro should be used to replace the zero-length array declaration. - -This fixes warnings such as: -./drivers/nvmem/u-boot-env.c:50:9-13: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays) - -Signed-off-by: Atul Raut -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -47,7 +47,7 @@ struct u_boot_env_image_broadcom { - __le32 magic; - __le32 len; - __le32 crc32; -- uint8_t data[0]; -+ DECLARE_FLEX_ARRAY(uint8_t, data); - } __packed; - - static int u_boot_env_read(void *context, unsigned int offset, void *val, diff --git a/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch b/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch deleted file mode 100644 index f9532f39c3..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 104af6a5b199eb4dc7970d1304aef38ac5a6ed54 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:26 +0200 -Subject: [PATCH] nvmem: core: Create all cells before adding the nvmem device - -Let's pack all the cells creation in one place, so they are all created -before we add the nvmem device. - -Signed-off-by: Miquel Raynal -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/core.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -998,17 +998,17 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -- dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); -- -- rval = device_add(&nvmem->dev); -+ rval = nvmem_add_cells_from_fixed_layout(nvmem); - if (rval) - goto err_remove_cells; - -- rval = nvmem_add_cells_from_fixed_layout(nvmem); -+ rval = nvmem_add_cells_from_layout(nvmem); - if (rval) - goto err_remove_cells; - -- rval = nvmem_add_cells_from_layout(nvmem); -+ dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); -+ -+ rval = device_add(&nvmem->dev); - if (rval) - goto err_remove_cells; - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch b/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch deleted file mode 100644 index 8f64d0c28b..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 6c7f48ea2e663b679aa8e60d8d8e1e6306a644f9 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:27 +0200 -Subject: [PATCH] nvmem: core: Return NULL when no nvmem layout is found - -Currently, of_nvmem_layout_get_container() returns NULL on error, or an -error pointer if either CONFIG_NVMEM or CONFIG_OF is turned off. We -should likely avoid this kind of mix for two reasons: to clarify the -intend and anyway fix the !CONFIG_OF which will likely always if we use -this helper somewhere else. Let's just return NULL when no layout is -found, we don't need an error value here. - -Link: https://staticthinking.wordpress.com/2022/08/01/mixing-error-pointers-and-null/ -Fixes: 266570f496b9 ("nvmem: core: introduce NVMEM layouts") -Reported-by: kernel test robot -Reported-by: Dan Carpenter -Closes: https://lore.kernel.org/r/202308030002.DnSFOrMB-lkp@intel.com/ -Signed-off-by: Miquel Raynal -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla ---- - include/linux/nvmem-consumer.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -256,7 +256,7 @@ static inline struct nvmem_device *of_nv - static inline struct device_node * - of_nvmem_layout_get_container(struct nvmem_device *nvmem) - { -- return ERR_PTR(-EOPNOTSUPP); -+ return NULL; - } - #endif /* CONFIG_NVMEM && CONFIG_OF */ - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch b/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch deleted file mode 100644 index 28d8bba194..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch +++ /dev/null @@ -1,29 +0,0 @@ -From b8257f61b4ddac6d7d0e19a5a4e8b07afb3b4ed3 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:28 +0200 -Subject: [PATCH] nvmem: core: Do not open-code existing functions - -Use of_nvmem_layout_get_container() instead of hardcoding it. - -Signed-off-by: Miquel Raynal -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -786,10 +786,10 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste - - static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) - { -- struct device_node *layout_np, *np = nvmem->dev.of_node; -+ struct device_node *layout_np; - struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); - -- layout_np = of_get_child_by_name(np, "nvmem-layout"); -+ layout_np = of_nvmem_layout_get_container(nvmem); - if (!layout_np) - return NULL; - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch b/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch deleted file mode 100644 index b62a0e18da..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0991afbe4b1805e7f0113ef10d7c5f0698a739e4 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:29 +0200 -Subject: [PATCH] nvmem: core: Notify when a new layout is registered - -Tell listeners a new layout was introduced and is now available. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/core.c | 4 ++++ - include/linux/nvmem-consumer.h | 2 ++ - 2 files changed, 6 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -772,12 +772,16 @@ int __nvmem_layout_register(struct nvmem - list_add(&layout->node, &nvmem_layouts); - spin_unlock(&nvmem_layout_lock); - -+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_ADD, layout); -+ - return 0; - } - EXPORT_SYMBOL_GPL(__nvmem_layout_register); - - void nvmem_layout_unregister(struct nvmem_layout *layout) - { -+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_REMOVE, layout); -+ - spin_lock(&nvmem_layout_lock); - list_del(&layout->node); - spin_unlock(&nvmem_layout_lock); ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -43,6 +43,8 @@ enum { - NVMEM_REMOVE, - NVMEM_CELL_ADD, - NVMEM_CELL_REMOVE, -+ NVMEM_LAYOUT_ADD, -+ NVMEM_LAYOUT_REMOVE, - }; - - #if IS_ENABLED(CONFIG_NVMEM) diff --git a/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch b/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch deleted file mode 100644 index e17be439b2..0000000000 --- a/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch +++ /dev/null @@ -1,29 +0,0 @@ -From a75b58a46423cfd9b1f73581f4bd2ac2ae743996 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Wed, 2 Aug 2023 18:07:45 +0200 -Subject: [PATCH 1/6] leds: turris-omnia: Use sysfs_emit() instead of sprintf() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use the dedicated sysfs_emit() function instead of sprintf() in sysfs -attribute accessor brightness_show(). - -Signed-off-by: Marek Behún -Link: https://lore.kernel.org/r/20230802160748.11208-4-kabel@kernel.org -Signed-off-by: Lee Jones ---- - drivers/leds/leds-turris-omnia.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/leds/leds-turris-omnia.c -+++ b/drivers/leds/leds-turris-omnia.c -@@ -194,7 +194,7 @@ static ssize_t brightness_show(struct de - if (ret < 0) - return ret; - -- return sprintf(buf, "%d\n", ret); -+ return sysfs_emit(buf, "%d\n", ret); - } - - static ssize_t brightness_store(struct device *dev, struct device_attribute *a, diff --git a/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch b/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch deleted file mode 100644 index bd5ceaabf7..0000000000 --- a/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b7c1e53751cb3990153084f31c41f25fde3b629c Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Fri, 24 Nov 2023 20:38:14 +0100 -Subject: [PATCH] nvmem: Do not expect fixed layouts to grab a layout driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Two series lived in parallel for some time, which led to this situation: -- The nvmem-layout container is used for dynamic layouts -- We now expect fixed layouts to also use the nvmem-layout container but -this does not require any additional driver, the support is built-in the -nvmem core. - -Ensure we don't refuse to probe for wrong reasons. - -Fixes: 27f699e578b1 ("nvmem: core: add support for fixed cells *layout*") -Cc: stable@vger.kernel.org -Reported-by: Luca Ceresoli -Signed-off-by: Miquel Raynal -Tested-by: Rafał Miłecki -Tested-by: Luca Ceresoli -Reviewed-by: Luca Ceresoli - -Link: https://lore.kernel.org/r/20231124193814.360552-1-miquel.raynal@bootlin.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -797,6 +797,12 @@ static struct nvmem_layout *nvmem_layout - if (!layout_np) - return NULL; - -+ /* Fixed layouts don't have a matching driver */ -+ if (of_device_is_compatible(layout_np, "fixed-layout")) { -+ of_node_put(layout_np); -+ return NULL; -+ } -+ - /* - * In case the nvmem device was built-in while the layout was built as a - * module, we shall manually request the layout driver loading otherwise diff --git a/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch b/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch deleted file mode 100644 index d49a20599d..0000000000 --- a/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch +++ /dev/null @@ -1,261 +0,0 @@ -From 1e37bf84afacd5ba17b7a13a18ca2bc78aff05c0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 15 Dec 2023 11:13:58 +0000 -Subject: [PATCH] nvmem: brcm_nvram: store a copy of NVRAM content -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This driver uses MMIO access for reading NVRAM from a flash device. -Underneath there is a flash controller that reads data and provides -mapping window. - -Using MMIO interface affects controller configuration and may break real -controller driver. It was reported by multiple users of devices with -NVRAM stored on NAND. - -Modify driver to read & cache NVRAM content during init and use that -copy to provide NVMEM data when requested. On NAND flashes due to their -alignment NVRAM partitions can be quite big (1 MiB and more) while -actual NVRAM content stays quite small (usually 16 to 32 KiB). To avoid -allocating so much memory check for actual data length. - -Link: https://lore.kernel.org/linux-mtd/CACna6rwf3_9QVjYcM+847biTX=K0EoWXuXcSMkJO1Vy_5vmVqA@mail.gmail.com/ -Fixes: 3fef9ed0627a ("nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM") -Cc: -Cc: Arınç ÜNAL -Cc: Florian Fainelli -Cc: Scott Branden -Signed-off-by: Rafał Miłecki -Acked-by: Arınç ÜNAL -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20231215111358.316727-3-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/brcm_nvram.c | 134 ++++++++++++++++++++++++++----------- - 1 file changed, 94 insertions(+), 40 deletions(-) - ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -17,9 +17,23 @@ - - #define NVRAM_MAGIC "FLSH" - -+/** -+ * struct brcm_nvram - driver state internal struct -+ * -+ * @dev: NVMEM device pointer -+ * @nvmem_size: Size of the whole space available for NVRAM -+ * @data: NVRAM data copy stored to avoid poking underlaying flash controller -+ * @data_len: NVRAM data size -+ * @padding_byte: Padding value used to fill remaining space -+ * @cells: Array of discovered NVMEM cells -+ * @ncells: Number of elements in cells -+ */ - struct brcm_nvram { - struct device *dev; -- void __iomem *base; -+ size_t nvmem_size; -+ uint8_t *data; -+ size_t data_len; -+ uint8_t padding_byte; - struct nvmem_cell_info *cells; - int ncells; - }; -@@ -36,10 +50,47 @@ static int brcm_nvram_read(void *context - size_t bytes) - { - struct brcm_nvram *priv = context; -- u8 *dst = val; -+ size_t to_copy; -+ -+ if (offset + bytes > priv->data_len) -+ to_copy = max_t(ssize_t, (ssize_t)priv->data_len - offset, 0); -+ else -+ to_copy = bytes; -+ -+ memcpy(val, priv->data + offset, to_copy); -+ -+ memset((uint8_t *)val + to_copy, priv->padding_byte, bytes - to_copy); -+ -+ return 0; -+} -+ -+static int brcm_nvram_copy_data(struct brcm_nvram *priv, struct platform_device *pdev) -+{ -+ struct resource *res; -+ void __iomem *base; -+ -+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ priv->nvmem_size = resource_size(res); -+ -+ priv->padding_byte = readb(base + priv->nvmem_size - 1); -+ for (priv->data_len = priv->nvmem_size; -+ priv->data_len; -+ priv->data_len--) { -+ if (readb(base + priv->data_len - 1) != priv->padding_byte) -+ break; -+ } -+ WARN(priv->data_len > SZ_128K, "Unexpected (big) NVRAM size: %zu B\n", priv->data_len); - -- while (bytes--) -- *dst++ = readb(priv->base + offset++); -+ priv->data = devm_kzalloc(priv->dev, priv->data_len, GFP_KERNEL); -+ if (!priv->data) -+ return -ENOMEM; -+ -+ memcpy_fromio(priv->data, base, priv->data_len); -+ -+ bcm47xx_nvram_init_from_iomem(base, priv->data_len); - - return 0; - } -@@ -67,8 +118,13 @@ static int brcm_nvram_add_cells(struct b - size_t len) - { - struct device *dev = priv->dev; -- char *var, *value, *eq; -+ char *var, *value; -+ uint8_t tmp; - int idx; -+ int err = 0; -+ -+ tmp = priv->data[len - 1]; -+ priv->data[len - 1] = '\0'; - - priv->ncells = 0; - for (var = data + sizeof(struct brcm_nvram_header); -@@ -78,67 +134,68 @@ static int brcm_nvram_add_cells(struct b - } - - priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); -- if (!priv->cells) -- return -ENOMEM; -+ if (!priv->cells) { -+ err = -ENOMEM; -+ goto out; -+ } - - for (var = data + sizeof(struct brcm_nvram_header), idx = 0; - var < (char *)data + len && *var; - var = value + strlen(value) + 1, idx++) { -+ char *eq, *name; -+ - eq = strchr(var, '='); - if (!eq) - break; - *eq = '\0'; -+ name = devm_kstrdup(dev, var, GFP_KERNEL); -+ *eq = '='; -+ if (!name) { -+ err = -ENOMEM; -+ goto out; -+ } - value = eq + 1; - -- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); -- if (!priv->cells[idx].name) -- return -ENOMEM; -+ priv->cells[idx].name = name; - priv->cells[idx].offset = value - (char *)data; - priv->cells[idx].bytes = strlen(value); - priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); -- if (!strcmp(var, "et0macaddr") || -- !strcmp(var, "et1macaddr") || -- !strcmp(var, "et2macaddr")) { -+ if (!strcmp(name, "et0macaddr") || -+ !strcmp(name, "et1macaddr") || -+ !strcmp(name, "et2macaddr")) { - priv->cells[idx].raw_len = strlen(value); - priv->cells[idx].bytes = ETH_ALEN; - priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; - } - } - -- return 0; -+out: -+ priv->data[len - 1] = tmp; -+ return err; - } - - static int brcm_nvram_parse(struct brcm_nvram *priv) - { -+ struct brcm_nvram_header *header = (struct brcm_nvram_header *)priv->data; - struct device *dev = priv->dev; -- struct brcm_nvram_header header; -- uint8_t *data; - size_t len; - int err; - -- memcpy_fromio(&header, priv->base, sizeof(header)); -- -- if (memcmp(header.magic, NVRAM_MAGIC, 4)) { -+ if (memcmp(header->magic, NVRAM_MAGIC, 4)) { - dev_err(dev, "Invalid NVRAM magic\n"); - return -EINVAL; - } - -- len = le32_to_cpu(header.len); -- -- data = kzalloc(len, GFP_KERNEL); -- if (!data) -- return -ENOMEM; -- -- memcpy_fromio(data, priv->base, len); -- data[len - 1] = '\0'; -- -- err = brcm_nvram_add_cells(priv, data, len); -- if (err) { -- dev_err(dev, "Failed to add cells: %d\n", err); -- return err; -+ len = le32_to_cpu(header->len); -+ if (len > priv->nvmem_size) { -+ dev_err(dev, "NVRAM length (%zd) exceeds mapped size (%zd)\n", len, -+ priv->nvmem_size); -+ return -EINVAL; - } - -- kfree(data); -+ err = brcm_nvram_add_cells(priv, priv->data, len); -+ if (err) -+ dev_err(dev, "Failed to add cells: %d\n", err); - - return 0; - } -@@ -150,7 +207,6 @@ static int brcm_nvram_probe(struct platf - .reg_read = brcm_nvram_read, - }; - struct device *dev = &pdev->dev; -- struct resource *res; - struct brcm_nvram *priv; - int err; - -@@ -159,21 +215,19 @@ static int brcm_nvram_probe(struct platf - return -ENOMEM; - priv->dev = dev; - -- priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -- if (IS_ERR(priv->base)) -- return PTR_ERR(priv->base); -+ err = brcm_nvram_copy_data(priv, pdev); -+ if (err) -+ return err; - - err = brcm_nvram_parse(priv); - if (err) - return err; - -- bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res)); -- - config.dev = dev; - config.cells = priv->cells; - config.ncells = priv->ncells; - config.priv = priv; -- config.size = resource_size(res); -+ config.size = priv->nvmem_size; - - return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); - } diff --git a/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch b/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch deleted file mode 100644 index 3b68403690..0000000000 --- a/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 4bb7aac70b5d8a4bddf4ee0791b834f9f56883d2 Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Thu, 20 Apr 2023 10:45:51 +0200 -Subject: [PATCH] net: phy: fix circular LEDS_CLASS dependencies - -The CONFIG_PHYLIB symbol is selected by a number of device drivers that -need PHY support, but it now has a dependency on CONFIG_LEDS_CLASS, -which may not be enabled, causing build failures. - -Avoid the risk of missing and circular dependencies by guarding the -phylib LED support itself in another Kconfig symbol that can only be -enabled if the dependency is met. - -This could be made a hidden symbol and always enabled when both CONFIG_OF -and CONFIG_LEDS_CLASS are reachable from the phylib, but there may be an -advantage in having users see this option when they have a misconfigured -kernel without built-in LED support. - -Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") -Signed-off-by: Arnd Bergmann -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230420084624.3005701-1-arnd@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/Kconfig | 9 ++++++++- - drivers/net/phy/phy_device.c | 3 ++- - 2 files changed, 10 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -18,7 +18,6 @@ menuconfig PHYLIB - depends on NETDEVICES - select MDIO_DEVICE - select MDIO_DEVRES -- depends on LEDS_CLASS || LEDS_CLASS=n - help - Ethernet controllers are usually attached to PHY - devices. This option provides infrastructure for -@@ -45,6 +44,14 @@ config LED_TRIGGER_PHY - Mbps OR Gbps OR link - for any speed known to the PHY. - -+config PHYLIB_LEDS -+ bool "Support probing LEDs from device tree" -+ depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB -+ depends on OF -+ default y -+ help -+ When LED class support is enabled, phylib can automatically -+ probe LED setting from device tree. - - config FIXED_PHY - tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs" ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3314,7 +3314,8 @@ static int phy_probe(struct device *dev) - /* Get the LEDs from the device tree, and instantiate standard - * LEDs for them. - */ -- err = of_phy_leds(phydev); -+ if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) -+ err = of_phy_leds(phydev); - - out: - /* Re-assert the reset signal on error */ diff --git a/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch b/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch deleted file mode 100644 index 622bb9e94a..0000000000 --- a/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch +++ /dev/null @@ -1,43 +0,0 @@ -From aed8fdad2152d946add50bec00a6b07c457bdcdf Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Mon, 24 Apr 2023 16:16:48 +0200 -Subject: [PATCH] net: phy: Fix reading LED reg property - -'reg' is always encoded in 32 bits, thus it has to be read using the -function with the corresponding bit width. - -Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") -Signed-off-by: Alexander Stein -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230424141648.317944-1-alexander.stein@ew.tq-group.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy_device.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3075,6 +3075,7 @@ static int of_phy_led(struct phy_device - struct led_init_data init_data = {}; - struct led_classdev *cdev; - struct phy_led *phyled; -+ u32 index; - int err; - - phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL); -@@ -3084,10 +3085,13 @@ static int of_phy_led(struct phy_device - cdev = &phyled->led_cdev; - phyled->phydev = phydev; - -- err = of_property_read_u8(led, "reg", &phyled->index); -+ err = of_property_read_u32(led, "reg", &index); - if (err) - return err; -+ if (index > U8_MAX) -+ return -EINVAL; - -+ phyled->index = index; - if (phydev->drv->led_brightness_set) - cdev->brightness_set_blocking = phy_led_set_brightness; - if (phydev->drv->led_blink_set) diff --git a/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch b/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch deleted file mode 100644 index 80197e963b..0000000000 --- a/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch +++ /dev/null @@ -1,67 +0,0 @@ -From c938ab4da0eb1620ae3243b0b24c572ddfc318fc Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Sat, 17 Jun 2023 17:55:00 +0200 -Subject: [PATCH] net: phy: Manual remove LEDs to ensure correct ordering - -If the core is left to remove the LEDs via devm_, it is performed too -late, after the PHY driver is removed from the PHY. This results in -dereferencing a NULL pointer when the LED core tries to turn the LED -off before destroying the LED. - -Manually unregister the LEDs at a safe point in phy_remove. - -Cc: stable@vger.kernel.org -Reported-by: Florian Fainelli -Suggested-by: Florian Fainelli -Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") -Signed-off-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3068,6 +3068,15 @@ static int phy_led_blink_set(struct led_ - return err; - } - -+static void phy_leds_unregister(struct phy_device *phydev) -+{ -+ struct phy_led *phyled; -+ -+ list_for_each_entry(phyled, &phydev->leds, list) { -+ led_classdev_unregister(&phyled->led_cdev); -+ } -+} -+ - static int of_phy_led(struct phy_device *phydev, - struct device_node *led) - { -@@ -3101,7 +3110,7 @@ static int of_phy_led(struct phy_device - init_data.fwnode = of_fwnode_handle(led); - init_data.devname_mandatory = true; - -- err = devm_led_classdev_register_ext(dev, cdev, &init_data); -+ err = led_classdev_register_ext(dev, cdev, &init_data); - if (err) - return err; - -@@ -3130,6 +3139,7 @@ static int of_phy_leds(struct phy_device - err = of_phy_led(phydev, led); - if (err) { - of_node_put(led); -+ phy_leds_unregister(phydev); - return err; - } - } -@@ -3335,6 +3345,9 @@ static int phy_remove(struct device *dev - - cancel_delayed_work_sync(&phydev->state_queue); - -+ if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) -+ phy_leds_unregister(phydev); -+ - phydev->state = PHY_DOWN; - - sfp_bus_del_upstream(phydev->sfp_bus); diff --git a/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch b/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch deleted file mode 100644 index 609115b04a..0000000000 --- a/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch +++ /dev/null @@ -1,44 +0,0 @@ -From af7320ecae0ce646fd2c4a88341a3fbc243553da Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Thu, 11 May 2023 15:08:20 +0800 -Subject: [PATCH] leds: trigger: netdev: Remove NULL check before dev_{put, - hold} - -The call netdev_{put, hold} of dev_{put, hold} will check NULL, -so there is no need to check before using dev_{put, hold}, -remove it to silence the warnings: - -./drivers/leds/trigger/ledtrig-netdev.c:291:3-10: WARNING: NULL check before dev_{put, hold} functions is not needed. -./drivers/leds/trigger/ledtrig-netdev.c:401:2-9: WARNING: NULL check before dev_{put, hold} functions is not needed. - -Reported-by: Abaci Robot -Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=4929 -Signed-off-by: Yang Li -Link: https://lore.kernel.org/r/20230511070820.52731-1-yang.lee@linux.alibaba.com -Signed-off-by: Lee Jones ---- - drivers/leds/trigger/ledtrig-netdev.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -462,8 +462,7 @@ static int netdev_trig_notify(struct not - get_device_state(trigger_data); - fallthrough; - case NETDEV_REGISTER: -- if (trigger_data->net_dev) -- dev_put(trigger_data->net_dev); -+ dev_put(trigger_data->net_dev); - dev_hold(dev); - trigger_data->net_dev = dev; - break; -@@ -594,8 +593,7 @@ static void netdev_trig_deactivate(struc - - cancel_delayed_work_sync(&trigger_data->work); - -- if (trigger_data->net_dev) -- dev_put(trigger_data->net_dev); -+ dev_put(trigger_data->net_dev); - - kfree(trigger_data); - } diff --git a/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch b/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch deleted file mode 100644 index 2f7a6ced90..0000000000 --- a/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 97c5209b3d374a25ebdb4c2ea9e9c1b121768da0 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Wed, 14 Jun 2023 10:03:59 +0300 -Subject: [PATCH] leds: trigger: netdev: uninitialized variable in - netdev_trig_activate() - -The qca8k_cled_hw_control_get() function which implements ->hw_control_get -sets the appropriate bits but does not clear them. This leads to an -uninitialized variable bug. Fix this by setting mode to zero at the -start. - -Fixes: e0256648c831 ("net: dsa: qca8k: implement hw_control ops") -Signed-off-by: Dan Carpenter -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -538,7 +538,7 @@ static void netdev_trig_work(struct work - static int netdev_trig_activate(struct led_classdev *led_cdev) - { - struct led_netdev_data *trigger_data; -- unsigned long mode; -+ unsigned long mode = 0; - struct device *dev; - int rc; - diff --git a/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch b/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch deleted file mode 100644 index dedf84c64b..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 7df1f14c04cbb1950e79c19793420f87227c3e80 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:33 +0200 -Subject: [PATCH 1/4] led: trig: netdev: Fix requesting offload device - -When the netdev trigger is activates, it tries to determine what -device the LED blinks for, and what the current blink mode is. - -The documentation for hw_control_get() says: - - * Return 0 on success, a negative error number on failing parsing the - * initial mode. Error from this function is NOT FATAL as the device - * may be in a not supported initial state by the attached LED trigger. - */ - -For the Marvell PHY and the Armada 370-rd board, the initial LED blink -mode is not supported by the trigger, so it returns an error. This -resulted in not getting the device the LED is blinking for. As a -result, the device is unknown and offloaded is never performed. - -Change to condition to always get the device if offloading is -supported, and reduce the scope of testing for an error from -hw_control_get() to skip setting trigger internal state if there is an -error. - -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-2-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -564,15 +564,17 @@ static int netdev_trig_activate(struct l - /* Check if hw control is active by default on the LED. - * Init already enabled mode in hw control. - */ -- if (supports_hw_control(led_cdev) && -- !led_cdev->hw_control_get(led_cdev, &mode)) { -+ if (supports_hw_control(led_cdev)) { - dev = led_cdev->hw_control_get_device(led_cdev); - if (dev) { - const char *name = dev_name(dev); - - set_device_name(trigger_data, name, strlen(name)); - trigger_data->hw_control = true; -- trigger_data->mode = mode; -+ -+ rc = led_cdev->hw_control_get(led_cdev, &mode); -+ if (!rc) -+ trigger_data->mode = mode; - } - } - diff --git a/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch deleted file mode 100644 index 505513a53f..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 1dcc03c9a7a824a31eaaecdfaa03542fb25feb6c Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:34 +0200 -Subject: [PATCH 2/4] net: phy: phy_device: Call into the PHY driver to set LED - offload - -Linux LEDs can be requested to perform hardware accelerated blinking -to indicate link, RX, TX etc. Pass the rules for blinking to the PHY -driver, if it implements the ops needed to determine if a given -pattern can be offloaded, to offload it, and what the current offload -is. Additionally implement the op needed to get what device the LED is -for. - -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-3-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy_device.c | 68 ++++++++++++++++++++++++++++++++++++ - include/linux/phy.h | 33 +++++++++++++++++ - 2 files changed, 101 insertions(+) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3068,6 +3068,61 @@ static int phy_led_blink_set(struct led_ - return err; - } - -+static __maybe_unused struct device * -+phy_led_hw_control_get_device(struct led_classdev *led_cdev) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ -+ if (phydev->attached_dev) -+ return &phydev->attached_dev->dev; -+ return NULL; -+} -+ -+static int __maybe_unused -+phy_led_hw_control_get(struct led_classdev *led_cdev, -+ unsigned long *rules) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_hw_control_get(phydev, phyled->index, rules); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ -+static int __maybe_unused -+phy_led_hw_control_set(struct led_classdev *led_cdev, -+ unsigned long rules) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_hw_control_set(phydev, phyled->index, rules); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ -+static __maybe_unused int phy_led_hw_is_supported(struct led_classdev *led_cdev, -+ unsigned long rules) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_hw_is_supported(phydev, phyled->index, rules); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ - static void phy_leds_unregister(struct phy_device *phydev) - { - struct phy_led *phyled; -@@ -3105,6 +3160,19 @@ static int of_phy_led(struct phy_device - cdev->brightness_set_blocking = phy_led_set_brightness; - if (phydev->drv->led_blink_set) - cdev->blink_set = phy_led_blink_set; -+ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (phydev->drv->led_hw_is_supported && -+ phydev->drv->led_hw_control_set && -+ phydev->drv->led_hw_control_get) { -+ cdev->hw_control_is_supported = phy_led_hw_is_supported; -+ cdev->hw_control_set = phy_led_hw_control_set; -+ cdev->hw_control_get = phy_led_hw_control_get; -+ cdev->hw_control_trigger = "netdev"; -+ } -+ -+ cdev->hw_control_get_device = phy_led_hw_control_get_device; -+#endif - cdev->max_brightness = 1; - init_data.devicename = dev_name(&phydev->mdio.dev); - init_data.fwnode = of_fwnode_handle(led); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1026,6 +1026,39 @@ struct phy_driver { - int (*led_blink_set)(struct phy_device *dev, u8 index, - unsigned long *delay_on, - unsigned long *delay_off); -+ /** -+ * @led_hw_is_supported: Can the HW support the given rules. -+ * @dev: PHY device which has the LED -+ * @index: Which LED of the PHY device -+ * @rules The core is interested in these rules -+ * -+ * Return 0 if yes, -EOPNOTSUPP if not, or an error code. -+ */ -+ int (*led_hw_is_supported)(struct phy_device *dev, u8 index, -+ unsigned long rules); -+ /** -+ * @led_hw_control_set: Set the HW to control the LED -+ * @dev: PHY device which has the LED -+ * @index: Which LED of the PHY device -+ * @rules The rules used to control the LED -+ * -+ * Returns 0, or a an error code. -+ */ -+ int (*led_hw_control_set)(struct phy_device *dev, u8 index, -+ unsigned long rules); -+ /** -+ * @led_hw_control_get: Get how the HW is controlling the LED -+ * @dev: PHY device which has the LED -+ * @index: Which LED of the PHY device -+ * @rules Pointer to the rules used to control the LED -+ * -+ * Set *@rules to how the HW is currently blinking. Returns 0 -+ * on success, or a error code if the current blinking cannot -+ * be represented in rules, or some other error happens. -+ */ -+ int (*led_hw_control_get)(struct phy_device *dev, u8 index, -+ unsigned long *rules); -+ - }; - #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ - struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch b/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch deleted file mode 100644 index 1300583b66..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch +++ /dev/null @@ -1,344 +0,0 @@ -From 460b0b648fab24f576c481424e0de5479ffb9786 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:35 +0200 -Subject: [PATCH 3/4] net: phy: marvell: Add support for offloading LED - blinking - -Add the code needed to indicate if a given blinking pattern can be -offloaded, to offload a pattern and to try to return the current -pattern. - -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-4-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/marvell.c | 281 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 281 insertions(+) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -2893,6 +2893,272 @@ static int m88e1318_led_blink_set(struct - MII_88E1318S_PHY_LED_FUNC, reg); - } - -+struct marvell_led_rules { -+ int mode; -+ unsigned long rules; -+}; -+ -+static const struct marvell_led_rules marvell_led0[] = { -+ { -+ .mode = 0, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ }, -+ { -+ .mode = 1, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 3, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 4, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 5, -+ .rules = BIT(TRIGGER_NETDEV_TX), -+ }, -+ { -+ .mode = 6, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ }, -+ { -+ .mode = 7, -+ .rules = BIT(TRIGGER_NETDEV_LINK_1000), -+ }, -+ { -+ .mode = 8, -+ .rules = 0, -+ }, -+}; -+ -+static const struct marvell_led_rules marvell_led1[] = { -+ { -+ .mode = 1, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 2, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX)), -+ }, -+ { -+ .mode = 3, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 4, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 6, -+ .rules = (BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000)), -+ }, -+ { -+ .mode = 7, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100), -+ }, -+ { -+ .mode = 8, -+ .rules = 0, -+ }, -+}; -+ -+static const struct marvell_led_rules marvell_led2[] = { -+ { -+ .mode = 0, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ }, -+ { -+ .mode = 1, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 3, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 4, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 5, -+ .rules = BIT(TRIGGER_NETDEV_TX), -+ }, -+ { -+ .mode = 6, -+ .rules = (BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_1000)), -+ }, -+ { -+ .mode = 7, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10), -+ }, -+ { -+ .mode = 8, -+ .rules = 0, -+ }, -+}; -+ -+static int marvell_find_led_mode(unsigned long rules, -+ const struct marvell_led_rules *marvell_rules, -+ int count, -+ int *mode) -+{ -+ int i; -+ -+ for (i = 0; i < count; i++) { -+ if (marvell_rules[i].rules == rules) { -+ *mode = marvell_rules[i].mode; -+ return 0; -+ } -+ } -+ return -EOPNOTSUPP; -+} -+ -+static int marvell_get_led_mode(u8 index, unsigned long rules, int *mode) -+{ -+ int ret; -+ -+ switch (index) { -+ case 0: -+ ret = marvell_find_led_mode(rules, marvell_led0, -+ ARRAY_SIZE(marvell_led0), mode); -+ break; -+ case 1: -+ ret = marvell_find_led_mode(rules, marvell_led1, -+ ARRAY_SIZE(marvell_led1), mode); -+ break; -+ case 2: -+ ret = marvell_find_led_mode(rules, marvell_led2, -+ ARRAY_SIZE(marvell_led2), mode); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static int marvell_find_led_rules(unsigned long *rules, -+ const struct marvell_led_rules *marvell_rules, -+ int count, -+ int mode) -+{ -+ int i; -+ -+ for (i = 0; i < count; i++) { -+ if (marvell_rules[i].mode == mode) { -+ *rules = marvell_rules[i].rules; -+ return 0; -+ } -+ } -+ return -EOPNOTSUPP; -+} -+ -+static int marvell_get_led_rules(u8 index, unsigned long *rules, int mode) -+{ -+ int ret; -+ -+ switch (index) { -+ case 0: -+ ret = marvell_find_led_rules(rules, marvell_led0, -+ ARRAY_SIZE(marvell_led0), mode); -+ break; -+ case 1: -+ ret = marvell_find_led_rules(rules, marvell_led1, -+ ARRAY_SIZE(marvell_led1), mode); -+ break; -+ case 2: -+ ret = marvell_find_led_rules(rules, marvell_led2, -+ ARRAY_SIZE(marvell_led2), mode); -+ break; -+ default: -+ ret = -EOPNOTSUPP; -+ } -+ -+ return ret; -+} -+ -+static int m88e1318_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ int mode, ret; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ ret = marvell_get_led_mode(index, rules, &mode); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static int m88e1318_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ int mode, ret, reg; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ ret = marvell_get_led_mode(index, rules, &mode); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ if (ret < 0) -+ return ret; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ reg &= ~(0xf << (4 * index)); -+ reg |= mode << (4 * index); -+ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC, reg); -+} -+ -+static int m88e1318_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ int mode, reg; -+ -+ if (index > 2) -+ return -EINVAL; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ mode = (reg >> (4 * index)) & 0xf; -+ -+ return marvell_get_led_rules(index, rules, mode); -+} -+ - static int marvell_probe(struct phy_device *phydev) - { - struct marvell_priv *priv; -@@ -3144,6 +3410,9 @@ static struct phy_driver marvell_drivers - .get_stats = marvell_get_stats, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E1145, -@@ -3252,6 +3521,9 @@ static struct phy_driver marvell_drivers - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E1540, -@@ -3280,6 +3552,9 @@ static struct phy_driver marvell_drivers - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E1545, -@@ -3308,6 +3583,9 @@ static struct phy_driver marvell_drivers - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E3016, -@@ -3451,6 +3729,9 @@ static struct phy_driver marvell_drivers - .set_tunable = m88e1540_set_tunable, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - }; - diff --git a/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch b/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch deleted file mode 100644 index d6a69aa9ca..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e8fbcc47a8e935f36f044d85f21a99acecbd7bfb Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:36 +0200 -Subject: [PATCH 4/4] leds: trig-netdev: Disable offload on deactivation of - trigger - -Ensure that the offloading of blinking is stopped when the trigger is -deactivated. Calling led_set_brightness() is documented as stopping -offload and setting the LED to a constant brightness. - -Suggested-by: Daniel Golle -Signed-off-by: Andrew Lunn -Reviewed-by: Simon Horman -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-5-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -595,6 +595,8 @@ static void netdev_trig_deactivate(struc - - cancel_delayed_work_sync(&trigger_data->work); - -+ led_set_brightness(led_cdev, LED_OFF); -+ - dev_put(trigger_data->net_dev); - - kfree(trigger_data); diff --git a/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch b/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch deleted file mode 100644 index f568c3f6ce..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c5d264d4b527c96ae8903376a4b195df47b05203 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:43 +0000 -Subject: [PATCH] of: base: add of_parse_phandle_with_optional_args() - -Add a new variant of the of_parse_phandle_with_args() which treats the -cells name as optional. If it's missing, it is assumed that the phandle -has no arguments. - -Up until now, a nvmem node didn't have any arguments, so all the device -trees haven't any '#*-cells' property. But there is a need for an -additional argument for the phandle, for which we need a '#*-cells' -property. Therefore, we need to support nvmem nodes with and without -this property. - -Signed-off-by: Michael Walle -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-10-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/of.h | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -1009,6 +1009,31 @@ static inline int of_parse_phandle_with_ - } - - /** -+ * of_parse_phandle_with_optional_args() - Find a node pointed by phandle in a list -+ * @np: pointer to a device tree node containing a list -+ * @list_name: property name that contains a list -+ * @cells_name: property name that specifies phandles' arguments count -+ * @index: index of a phandle to parse out -+ * @out_args: optional pointer to output arguments structure (will be filled) -+ * -+ * Same as of_parse_phandle_with_args() except that if the cells_name property -+ * is not found, cell_count of 0 is assumed. -+ * -+ * This is used to useful, if you have a phandle which didn't have arguments -+ * before and thus doesn't have a '#*-cells' property but is now migrated to -+ * having arguments while retaining backwards compatibility. -+ */ -+static inline int of_parse_phandle_with_optional_args(const struct device_node *np, -+ const char *list_name, -+ const char *cells_name, -+ int index, -+ struct of_phandle_args *out_args) -+{ -+ return __of_parse_phandle_with_args(np, list_name, cells_name, -+ 0, index, out_args); -+} -+ -+/** - * of_property_count_u8_elems - Count the number of u8 elements in a property - * - * @np: device node from which the property value is to be read. diff --git a/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch b/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch deleted file mode 100644 index 66c29126b6..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch +++ /dev/null @@ -1,34 +0,0 @@ -From ff24fed10ba414d19579e26e60b126fad2f2bb07 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:44 +0000 -Subject: [PATCH] of: property: make #.*-cells optional for simple props - -Sometimes, future bindings for phandles will get additional arguments. -Thus the target node of the phandle will need a new #.*-cells property. -To be backwards compatible, this needs to be optional. - -Prepare the DEFINE_SIMPLE_PROPS() to handle the cells name as optional. - -Signed-off-by: Michael Walle -Tested-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-11-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/property.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/of/property.c -+++ b/drivers/of/property.c -@@ -1146,8 +1146,8 @@ static struct device_node *parse_prop_ce - if (strcmp(prop_name, list_name)) - return NULL; - -- if (of_parse_phandle_with_args(np, list_name, cells_name, index, -- &sup_args)) -+ if (__of_parse_phandle_with_args(np, list_name, cells_name, 0, index, -+ &sup_args)) - return NULL; - - return sup_args.np; diff --git a/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch b/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch deleted file mode 100644 index 07354d7da7..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch +++ /dev/null @@ -1,30 +0,0 @@ -From e2d8172043d2e50df19fcd59c11e5593de8188d7 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:45 +0000 -Subject: [PATCH] of: property: add #nvmem-cell-cells property - -Bindings describe the new '#nvmem-cell-cells' property. Now that the -arguments count property is optional, we just add this property to the -nvmem-cells. - -Signed-off-by: Michael Walle -Tested-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-12-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/property.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/of/property.c -+++ b/drivers/of/property.c -@@ -1251,7 +1251,7 @@ DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-c - DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") - DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") - DEFINE_SIMPLE_PROP(extcon, "extcon", NULL) --DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) -+DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", "#nvmem-cell-cells") - DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") - DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) - DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL) diff --git a/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch b/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch deleted file mode 100644 index 8dc370618e..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 553bd29700145e1849698985e9800f14e967da49 Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Tue, 7 Feb 2023 12:05:29 +0100 -Subject: [PATCH] of: device: Ignore modalias of reused nodes - -If of_node is reused, do not use that node's modalias. This will hide -the name of the actual device. This is rather prominent in USB glue -drivers creating a platform device for the host controller. - -Signed-off-by: Alexander Stein -Reviewed-by: Rob Herring -Link: https://lore.kernel.org/r/20230207110531.1060252-2-alexander.stein@ew.tq-group.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -256,7 +256,7 @@ static ssize_t of_device_get_modalias(st - ssize_t csize; - ssize_t tsize; - -- if ((!dev) || (!dev->of_node)) -+ if ((!dev) || (!dev->of_node) || dev->of_node_reused) - return -ENODEV; - - /* Name & Type */ -@@ -379,7 +379,7 @@ int of_device_uevent_modalias(struct dev - { - int sl; - -- if ((!dev) || (!dev->of_node)) -+ if ((!dev) || (!dev->of_node) || dev->of_node_reused) - return -ENODEV; - - /* Devicetree modalias is tricky, we add it in 2 steps */ diff --git a/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch b/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch deleted file mode 100644 index dcdc2313ba..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 2295bed9bebe8d1eef276194fed5b5fbe89c5363 Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Tue, 7 Feb 2023 12:05:30 +0100 -Subject: [PATCH] of: device: Do not ignore error code in - of_device_uevent_modalias - -of_device_get_modalias might return an error code, propagate that one. -Otherwise the negative, signed integer is propagated to unsigned integer -for the comparison resulting in a huge 'sl' size. - -Signed-off-by: Alexander Stein -Reviewed-by: Rob Herring -Link: https://lore.kernel.org/r/20230207110531.1060252-3-alexander.stein@ew.tq-group.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -388,6 +388,8 @@ int of_device_uevent_modalias(struct dev - - sl = of_device_get_modalias(dev, &env->buf[env->buflen-1], - sizeof(env->buf) - env->buflen); -+ if (sl < 0) -+ return sl; - if (sl >= (sizeof(env->buf) - env->buflen)) - return -ENOMEM; - env->buflen += sl; diff --git a/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch b/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch deleted file mode 100644 index 280ed9085c..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 5c3d15e127ebfc0754cd18def7124633b6d46672 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:15 +0100 -Subject: [PATCH] of: Update of_device_get_modalias() - -This function only needs a "struct device_node" to work, but for -convenience the author (and only user) of this helper did use a "struct -device" and put it in device.c. - -Let's convert this helper to take a "struct device node" instead. This -change asks for two additional changes: renaming it "of_modalias()" -to fit the current naming, and moving it outside of device.c which will -be done in a follow-up commit. - -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 29 +++++++++++++++++------------ - 1 file changed, 17 insertions(+), 12 deletions(-) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -248,7 +248,7 @@ const void *of_device_get_match_data(con - } - EXPORT_SYMBOL(of_device_get_match_data); - --static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) -+static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) - { - const char *compat; - char *c; -@@ -256,19 +256,16 @@ static ssize_t of_device_get_modalias(st - ssize_t csize; - ssize_t tsize; - -- if ((!dev) || (!dev->of_node) || dev->of_node_reused) -- return -ENODEV; -- - /* Name & Type */ - /* %p eats all alphanum characters, so %c must be used here */ -- csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T', -- of_node_get_device_type(dev->of_node)); -+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', -+ of_node_get_device_type(np)); - tsize = csize; - len -= csize; - if (str) - str += csize; - -- of_property_for_each_string(dev->of_node, "compatible", p, compat) { -+ of_property_for_each_string(np, "compatible", p, compat) { - csize = strlen(compat) + 1; - tsize += csize; - if (csize > len) -@@ -293,7 +290,10 @@ int of_device_request_module(struct devi - ssize_t size; - int ret; - -- size = of_device_get_modalias(dev, NULL, 0); -+ if (!dev || !dev->of_node) -+ return -ENODEV; -+ -+ size = of_modalias(dev->of_node, NULL, 0); - if (size < 0) - return size; - -@@ -304,7 +304,7 @@ int of_device_request_module(struct devi - if (!str) - return -ENOMEM; - -- of_device_get_modalias(dev, str, size); -+ of_modalias(dev->of_node, str, size); - str[size - 1] = '\0'; - ret = request_module(str); - kfree(str); -@@ -321,7 +321,12 @@ EXPORT_SYMBOL_GPL(of_device_request_modu - */ - ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) - { -- ssize_t sl = of_device_get_modalias(dev, str, len - 2); -+ ssize_t sl; -+ -+ if (!dev || !dev->of_node || dev->of_node_reused) -+ return -ENODEV; -+ -+ sl = of_modalias(dev->of_node, str, len - 2); - if (sl < 0) - return sl; - if (sl > len - 2) -@@ -386,8 +391,8 @@ int of_device_uevent_modalias(struct dev - if (add_uevent_var(env, "MODALIAS=")) - return -ENOMEM; - -- sl = of_device_get_modalias(dev, &env->buf[env->buflen-1], -- sizeof(env->buf) - env->buflen); -+ sl = of_modalias(dev->of_node, &env->buf[env->buflen-1], -+ sizeof(env->buf) - env->buflen); - if (sl < 0) - return sl; - if (sl >= (sizeof(env->buf) - env->buflen)) diff --git a/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch b/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch deleted file mode 100644 index 671556fbaa..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 673aa1ed1c9b6710bf24e3f0957d85e2f46c77db Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:16 +0100 -Subject: [PATCH] of: Rename of_modalias_node() - -This helper does not produce a real modalias, but tries to get the -"product" compatible part of the "vendor,product" compatibles only. It -is far from creating a purely useful modalias string and does not seem -to be used like that directly anyway, so let's try to give this helper a -more meaningful name before moving there a real modalias helper (already -existing under of/device.c). - -Also update the various documentations to refer to the strings as -"aliases" rather than "modaliases" which has a real meaning in the Linux -kernel. - -There is no functional change. - -Cc: Rafael J. Wysocki -Cc: Len Brown -Cc: Maarten Lankhorst -Cc: Maxime Ripard -Cc: Thomas Zimmermann -Cc: Sebastian Reichel -Cc: Wolfram Sang -Cc: Mark Brown -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Acked-by: Mark Brown -Signed-off-by: Srinivas Kandagatla -Acked-by: Sebastian Reichel -Link: https://lore.kernel.org/r/20230404172148.82422-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/acpi/bus.c | 7 ++++--- - drivers/gpu/drm/drm_mipi_dsi.c | 2 +- - drivers/hsi/hsi_core.c | 2 +- - drivers/i2c/busses/i2c-powermac.c | 2 +- - drivers/i2c/i2c-core-of.c | 2 +- - drivers/of/base.c | 18 +++++++++++------- - drivers/spi/spi.c | 4 ++-- - include/linux/of.h | 3 ++- - 8 files changed, 23 insertions(+), 17 deletions(-) - ---- a/drivers/acpi/bus.c -+++ b/drivers/acpi/bus.c -@@ -806,9 +806,10 @@ static bool acpi_of_modalias(struct acpi - * @modalias: Pointer to buffer that modalias value will be copied into - * @len: Length of modalias buffer - * -- * This is a counterpart of of_modalias_node() for struct acpi_device objects. -- * If there is a compatible string for @adev, it will be copied to @modalias -- * with the vendor prefix stripped; otherwise, @default_id will be used. -+ * This is a counterpart of of_alias_from_compatible() for struct acpi_device -+ * objects. If there is a compatible string for @adev, it will be copied to -+ * @modalias with the vendor prefix stripped; otherwise, @default_id will be -+ * used. - */ - void acpi_set_modalias(struct acpi_device *adev, const char *default_id, - char *modalias, size_t len) ---- a/drivers/gpu/drm/drm_mipi_dsi.c -+++ b/drivers/gpu/drm/drm_mipi_dsi.c -@@ -160,7 +160,7 @@ of_mipi_dsi_device_add(struct mipi_dsi_h - int ret; - u32 reg; - -- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { -+ if (of_alias_from_compatible(node, info.type, sizeof(info.type)) < 0) { - drm_err(host, "modalias failure on %pOF\n", node); - return ERR_PTR(-EINVAL); - } ---- a/drivers/hsi/hsi_core.c -+++ b/drivers/hsi/hsi_core.c -@@ -207,7 +207,7 @@ static void hsi_add_client_from_dt(struc - if (!cl) - return; - -- err = of_modalias_node(client, name, sizeof(name)); -+ err = of_alias_from_compatible(client, name, sizeof(name)); - if (err) - goto err; - ---- a/drivers/i2c/busses/i2c-powermac.c -+++ b/drivers/i2c/busses/i2c-powermac.c -@@ -284,7 +284,7 @@ static bool i2c_powermac_get_type(struct - */ - - /* First try proper modalias */ -- if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) { -+ if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) { - snprintf(type, type_size, "MAC,%s", tmp); - return true; - } ---- a/drivers/i2c/i2c-core-of.c -+++ b/drivers/i2c/i2c-core-of.c -@@ -27,7 +27,7 @@ int of_i2c_get_board_info(struct device - - memset(info, 0, sizeof(*info)); - -- if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) { -+ if (of_alias_from_compatible(node, info->type, sizeof(info->type)) < 0) { - dev_err(dev, "of_i2c: modalias failure on %pOF\n", node); - return -EINVAL; - } ---- a/drivers/of/base.c -+++ b/drivers/of/base.c -@@ -1208,19 +1208,23 @@ struct device_node *of_find_matching_nod - EXPORT_SYMBOL(of_find_matching_node_and_match); - - /** -- * of_modalias_node - Lookup appropriate modalias for a device node -+ * of_alias_from_compatible - Lookup appropriate alias for a device node -+ * depending on compatible - * @node: pointer to a device tree node -- * @modalias: Pointer to buffer that modalias value will be copied into -- * @len: Length of modalias value -+ * @alias: Pointer to buffer that alias value will be copied into -+ * @len: Length of alias value - * - * Based on the value of the compatible property, this routine will attempt -- * to choose an appropriate modalias value for a particular device tree node. -+ * to choose an appropriate alias value for a particular device tree node. - * It does this by stripping the manufacturer prefix (as delimited by a ',') - * from the first entry in the compatible list property. - * -+ * Note: The matching on just the "product" side of the compatible is a relic -+ * from I2C and SPI. Please do not add any new user. -+ * - * Return: This routine returns 0 on success, <0 on failure. - */ --int of_modalias_node(struct device_node *node, char *modalias, int len) -+int of_alias_from_compatible(const struct device_node *node, char *alias, int len) - { - const char *compatible, *p; - int cplen; -@@ -1229,10 +1233,10 @@ int of_modalias_node(struct device_node - if (!compatible || strlen(compatible) > cplen) - return -ENODEV; - p = strchr(compatible, ','); -- strscpy(modalias, p ? p + 1 : compatible, len); -+ strscpy(alias, p ? p + 1 : compatible, len); - return 0; - } --EXPORT_SYMBOL_GPL(of_modalias_node); -+EXPORT_SYMBOL_GPL(of_alias_from_compatible); - - /** - * of_find_node_by_phandle - Find a node given a phandle ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -2330,8 +2330,8 @@ of_register_spi_device(struct spi_contro - } - - /* Select device driver */ -- rc = of_modalias_node(nc, spi->modalias, -- sizeof(spi->modalias)); -+ rc = of_alias_from_compatible(nc, spi->modalias, -+ sizeof(spi->modalias)); - if (rc < 0) { - dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc); - goto err_out; ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -362,7 +362,8 @@ extern int of_n_addr_cells(struct device - extern int of_n_size_cells(struct device_node *np); - extern const struct of_device_id *of_match_node( - const struct of_device_id *matches, const struct device_node *node); --extern int of_modalias_node(struct device_node *node, char *modalias, int len); -+extern int of_alias_from_compatible(const struct device_node *node, char *alias, -+ int len); - extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args); - extern int __of_parse_phandle_with_args(const struct device_node *np, - const char *list_name, const char *cells_name, int cell_count, diff --git a/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch b/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch deleted file mode 100644 index 39a84161a2..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch +++ /dev/null @@ -1,160 +0,0 @@ -From bd7a7ed774afd1a4174df34227626c95573be517 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:17 +0100 -Subject: [PATCH] of: Move of_modalias() to module.c - -Create a specific .c file for OF related module handling. -Move of_modalias() inside as a first step. - -The helper is exposed through of.h even though it is only used by core -files because the users from device.c will soon be split into an OF-only -helper in module.c as well as a device-oriented inline helper in -of_device.h. Putting this helper in of_private.h would require to -include of_private.h from of_device.h, which is not acceptable. - -Suggested-by: Rob Herring -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-10-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/Makefile | 2 +- - drivers/of/device.c | 37 ------------------------------------- - drivers/of/module.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ - include/linux/of.h | 9 +++++++++ - 4 files changed, 54 insertions(+), 38 deletions(-) - create mode 100644 drivers/of/module.c - ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,5 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 --obj-y = base.o device.o platform.o property.o -+obj-y = base.o device.o module.o platform.o property.o - obj-$(CONFIG_OF_KOBJ) += kobj.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -1,5 +1,4 @@ - // SPDX-License-Identifier: GPL-2.0 --#include - #include - #include - #include -@@ -248,42 +247,6 @@ const void *of_device_get_match_data(con - } - EXPORT_SYMBOL(of_device_get_match_data); - --static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) --{ -- const char *compat; -- char *c; -- struct property *p; -- ssize_t csize; -- ssize_t tsize; -- -- /* Name & Type */ -- /* %p eats all alphanum characters, so %c must be used here */ -- csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', -- of_node_get_device_type(np)); -- tsize = csize; -- len -= csize; -- if (str) -- str += csize; -- -- of_property_for_each_string(np, "compatible", p, compat) { -- csize = strlen(compat) + 1; -- tsize += csize; -- if (csize > len) -- continue; -- -- csize = snprintf(str, len, "C%s", compat); -- for (c = str; c; ) { -- c = strchr(c, ' '); -- if (c) -- *c++ = '_'; -- } -- len -= csize; -- str += csize; -- } -- -- return tsize; --} -- - int of_device_request_module(struct device *dev) - { - char *str; ---- /dev/null -+++ b/drivers/of/module.c -@@ -0,0 +1,44 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Linux kernel module helpers. -+ */ -+ -+#include -+#include -+#include -+ -+ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) -+{ -+ const char *compat; -+ char *c; -+ struct property *p; -+ ssize_t csize; -+ ssize_t tsize; -+ -+ /* Name & Type */ -+ /* %p eats all alphanum characters, so %c must be used here */ -+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', -+ of_node_get_device_type(np)); -+ tsize = csize; -+ len -= csize; -+ if (str) -+ str += csize; -+ -+ of_property_for_each_string(np, "compatible", p, compat) { -+ csize = strlen(compat) + 1; -+ tsize += csize; -+ if (csize > len) -+ continue; -+ -+ csize = snprintf(str, len, "C%s", compat); -+ for (c = str; c; ) { -+ c = strchr(c, ' '); -+ if (c) -+ *c++ = '_'; -+ } -+ len -= csize; -+ str += csize; -+ } -+ -+ return tsize; -+} ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -374,6 +374,9 @@ extern int of_parse_phandle_with_args_ma - extern int of_count_phandle_with_args(const struct device_node *np, - const char *list_name, const char *cells_name); - -+/* module functions */ -+extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len); -+ - /* phandle iterator functions */ - extern int of_phandle_iterator_init(struct of_phandle_iterator *it, - const struct device_node *np, -@@ -731,6 +734,12 @@ static inline int of_count_phandle_with_ - return -ENOSYS; - } - -+static inline ssize_t of_modalias(const struct device_node *np, char *str, -+ ssize_t len) -+{ -+ return -ENODEV; -+} -+ - static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, - const struct device_node *np, - const char *list_name, diff --git a/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch b/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch deleted file mode 100644 index 046c1df561..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch +++ /dev/null @@ -1,131 +0,0 @@ -From e6506f06d5e82765666902ccf9e9162f3e31d518 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:18 +0100 -Subject: [PATCH] of: Move the request module helper logic to module.c - -Depending on device.c for pure OF handling is considered -backwards. Let's extract the content of of_device_request_module() to -have the real logic under module.c. - -The next step will be to convert users of of_device_request_module() to -use the new helper. - -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-11-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 25 ++----------------------- - drivers/of/module.c | 30 ++++++++++++++++++++++++++++++ - include/linux/of.h | 6 ++++++ - 3 files changed, 38 insertions(+), 23 deletions(-) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -8,7 +8,6 @@ - #include /* for bus_dma_region */ - #include - #include --#include - #include - #include - #include -@@ -249,30 +248,10 @@ EXPORT_SYMBOL(of_device_get_match_data); - - int of_device_request_module(struct device *dev) - { -- char *str; -- ssize_t size; -- int ret; -- -- if (!dev || !dev->of_node) -+ if (!dev) - return -ENODEV; - -- size = of_modalias(dev->of_node, NULL, 0); -- if (size < 0) -- return size; -- -- /* Reserve an additional byte for the trailing '\0' */ -- size++; -- -- str = kmalloc(size, GFP_KERNEL); -- if (!str) -- return -ENOMEM; -- -- of_modalias(dev->of_node, str, size); -- str[size - 1] = '\0'; -- ret = request_module(str); -- kfree(str); -- -- return ret; -+ return of_request_module(dev->of_node); - } - EXPORT_SYMBOL_GPL(of_device_request_module); - ---- a/drivers/of/module.c -+++ b/drivers/of/module.c -@@ -4,6 +4,7 @@ - */ - - #include -+#include - #include - #include - -@@ -42,3 +43,32 @@ ssize_t of_modalias(const struct device_ - - return tsize; - } -+ -+int of_request_module(const struct device_node *np) -+{ -+ char *str; -+ ssize_t size; -+ int ret; -+ -+ if (!np) -+ return -ENODEV; -+ -+ size = of_modalias(np, NULL, 0); -+ if (size < 0) -+ return size; -+ -+ /* Reserve an additional byte for the trailing '\0' */ -+ size++; -+ -+ str = kmalloc(size, GFP_KERNEL); -+ if (!str) -+ return -ENOMEM; -+ -+ of_modalias(np, str, size); -+ str[size - 1] = '\0'; -+ ret = request_module(str); -+ kfree(str); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(of_request_module); ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -376,6 +376,7 @@ extern int of_count_phandle_with_args(co - - /* module functions */ - extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len); -+extern int of_request_module(const struct device_node *np); - - /* phandle iterator functions */ - extern int of_phandle_iterator_init(struct of_phandle_iterator *it, -@@ -739,6 +740,11 @@ static inline ssize_t of_modalias(const - { - return -ENODEV; - } -+ -+static inline int of_request_module(const struct device_node *np) -+{ -+ return -ENODEV; -+} - - static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, - const struct device_node *np, diff --git a/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch b/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch deleted file mode 100644 index 3319f431ba..0000000000 --- a/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 77faa07c185c969e742cbb3e6aa487a11b0b616c Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 30 Aug 2022 09:57:42 +0300 -Subject: [PATCH] dt-bindings: arm: qcom: document qcom,msm-id and - qcom,board-id - -The top level qcom,msm-id and qcom,board-id properties are utilized by -bootloaders on Qualcomm MSM platforms to determine which device tree -should be used and passed to the kernel. - -The commit b32e592d3c28 ("devicetree: bindings: Document qcom board -compatible format") from 2015 was a consensus during discussion about -upstreaming qcom,msm-id and qcom,board-id fields. There are however still -problems with that consensus: -1. It was reached 7 years ago but it turned out its implementation did - not reach all possible products. - -2. Initially additional tool (dtbTool) was needed for parsing these - fields to create a QCDT image consisting of multiple DTBs, later the - bootloaders were improved and they use these qcom,msm-id and - qcom,board-id properties directly. - -3. Extracting relevant information from the board compatible requires - this additional tool (dtbTool), which makes the build process more - complicated and not easily reproducible (DTBs are modified after the - kernel build). - -4. Some versions of Qualcomm bootloaders expect these properties even - when booting with a single DTB. The community is stuck with these - bootloaders thus they require properties in the DTBs. - -Since several upstreamed Qualcomm SoC-based boards require these -properties to properly boot and the properties are reportedly used by -bootloaders, document them along with the bindings header with constants -used by: bootloader, some DTS and socinfo driver. - -Link: https://lore.kernel.org/r/a3c932d1-a102-ce18-deea-18cbbd05ecab@linaro.org/ -Co-developed-by: Kumar Gala -Signed-off-by: Kumar Gala -Signed-off-by: Krzysztof Kozlowski -Reviewed-by: Dmitry Baryshkov -Reviewed-by: Rob Herring -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220830065744.161163-2-krzysztof.kozlowski@linaro.org ---- - include/dt-bindings/arm/qcom,ids.h | 155 +++++++++++++++++++++++++++++ - 1 file changed, 155 insertions(+) - create mode 100644 include/dt-bindings/arm/qcom,ids.h - ---- /dev/null -+++ b/include/dt-bindings/arm/qcom,ids.h -@@ -0,0 +1,155 @@ -+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ -+/* -+ * Copyright (c) 2015, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2022 Linaro Ltd -+ * Author: Krzysztof Kozlowski based on previous work of Kumar Gala. -+ */ -+#ifndef _DT_BINDINGS_ARM_QCOM_IDS_H -+#define _DT_BINDINGS_ARM_QCOM_IDS_H -+ -+/* -+ * The MSM chipset and hardware revision used by Qualcomm bootloaders, DTS for -+ * older chipsets (qcom,msm-id) and in socinfo driver: -+ */ -+#define QCOM_ID_MSM8960 87 -+#define QCOM_ID_APQ8064 109 -+#define QCOM_ID_MSM8660A 122 -+#define QCOM_ID_MSM8260A 123 -+#define QCOM_ID_APQ8060A 124 -+#define QCOM_ID_MSM8974 126 -+#define QCOM_ID_MPQ8064 130 -+#define QCOM_ID_MSM8960AB 138 -+#define QCOM_ID_APQ8060AB 139 -+#define QCOM_ID_MSM8260AB 140 -+#define QCOM_ID_MSM8660AB 141 -+#define QCOM_ID_MSM8626 145 -+#define QCOM_ID_MSM8610 147 -+#define QCOM_ID_APQ8064AB 153 -+#define QCOM_ID_MSM8226 158 -+#define QCOM_ID_MSM8526 159 -+#define QCOM_ID_MSM8110 161 -+#define QCOM_ID_MSM8210 162 -+#define QCOM_ID_MSM8810 163 -+#define QCOM_ID_MSM8212 164 -+#define QCOM_ID_MSM8612 165 -+#define QCOM_ID_MSM8112 166 -+#define QCOM_ID_MSM8225Q 168 -+#define QCOM_ID_MSM8625Q 169 -+#define QCOM_ID_MSM8125Q 170 -+#define QCOM_ID_APQ8064AA 172 -+#define QCOM_ID_APQ8084 178 -+#define QCOM_ID_APQ8074 184 -+#define QCOM_ID_MSM8274 185 -+#define QCOM_ID_MSM8674 186 -+#define QCOM_ID_MSM8974PRO_AC 194 -+#define QCOM_ID_MSM8126 198 -+#define QCOM_ID_APQ8026 199 -+#define QCOM_ID_MSM8926 200 -+#define QCOM_ID_MSM8326 205 -+#define QCOM_ID_MSM8916 206 -+#define QCOM_ID_MSM8994 207 -+#define QCOM_ID_APQ8074PRO_AA 208 -+#define QCOM_ID_APQ8074PRO_AB 209 -+#define QCOM_ID_APQ8074PRO_AC 210 -+#define QCOM_ID_MSM8274PRO_AA 211 -+#define QCOM_ID_MSM8274PRO_AB 212 -+#define QCOM_ID_MSM8274PRO_AC 213 -+#define QCOM_ID_MSM8674PRO_AA 214 -+#define QCOM_ID_MSM8674PRO_AB 215 -+#define QCOM_ID_MSM8674PRO_AC 216 -+#define QCOM_ID_MSM8974PRO_AA 217 -+#define QCOM_ID_MSM8974PRO_AB 218 -+#define QCOM_ID_APQ8028 219 -+#define QCOM_ID_MSM8128 220 -+#define QCOM_ID_MSM8228 221 -+#define QCOM_ID_MSM8528 222 -+#define QCOM_ID_MSM8628 223 -+#define QCOM_ID_MSM8928 224 -+#define QCOM_ID_MSM8510 225 -+#define QCOM_ID_MSM8512 226 -+#define QCOM_ID_MSM8936 233 -+#define QCOM_ID_MSM8939 239 -+#define QCOM_ID_APQ8036 240 -+#define QCOM_ID_APQ8039 241 -+#define QCOM_ID_MSM8996 246 -+#define QCOM_ID_APQ8016 247 -+#define QCOM_ID_MSM8216 248 -+#define QCOM_ID_MSM8116 249 -+#define QCOM_ID_MSM8616 250 -+#define QCOM_ID_MSM8992 251 -+#define QCOM_ID_APQ8094 253 -+#define QCOM_ID_MDM9607 290 -+#define QCOM_ID_APQ8096 291 -+#define QCOM_ID_MSM8998 292 -+#define QCOM_ID_MSM8953 293 -+#define QCOM_ID_MDM8207 296 -+#define QCOM_ID_MDM9207 297 -+#define QCOM_ID_MDM9307 298 -+#define QCOM_ID_MDM9628 299 -+#define QCOM_ID_APQ8053 304 -+#define QCOM_ID_MSM8996SG 305 -+#define QCOM_ID_MSM8996AU 310 -+#define QCOM_ID_APQ8096AU 311 -+#define QCOM_ID_APQ8096SG 312 -+#define QCOM_ID_SDM660 317 -+#define QCOM_ID_SDM630 318 -+#define QCOM_ID_APQ8098 319 -+#define QCOM_ID_SDM845 321 -+#define QCOM_ID_MDM9206 322 -+#define QCOM_ID_IPQ8074 323 -+#define QCOM_ID_SDA660 324 -+#define QCOM_ID_SDM658 325 -+#define QCOM_ID_SDA658 326 -+#define QCOM_ID_SDA630 327 -+#define QCOM_ID_SDM450 338 -+#define QCOM_ID_SDA845 341 -+#define QCOM_ID_IPQ8072 342 -+#define QCOM_ID_IPQ8076 343 -+#define QCOM_ID_IPQ8078 344 -+#define QCOM_ID_SDM636 345 -+#define QCOM_ID_SDA636 346 -+#define QCOM_ID_SDM632 349 -+#define QCOM_ID_SDA632 350 -+#define QCOM_ID_SDA450 351 -+#define QCOM_ID_SM8250 356 -+#define QCOM_ID_IPQ8070 375 -+#define QCOM_ID_IPQ8071 376 -+#define QCOM_ID_IPQ8072A 389 -+#define QCOM_ID_IPQ8074A 390 -+#define QCOM_ID_IPQ8076A 391 -+#define QCOM_ID_IPQ8078A 392 -+#define QCOM_ID_SM6125 394 -+#define QCOM_ID_IPQ8070A 395 -+#define QCOM_ID_IPQ8071A 396 -+#define QCOM_ID_IPQ6018 402 -+#define QCOM_ID_IPQ6028 403 -+#define QCOM_ID_IPQ6000 421 -+#define QCOM_ID_IPQ6010 422 -+#define QCOM_ID_SC7180 425 -+#define QCOM_ID_SM6350 434 -+#define QCOM_ID_SM8350 439 -+#define QCOM_ID_SC8280XP 449 -+#define QCOM_ID_IPQ6005 453 -+#define QCOM_ID_QRB5165 455 -+#define QCOM_ID_SM8450 457 -+#define QCOM_ID_SM7225 459 -+#define QCOM_ID_SA8295P 460 -+#define QCOM_ID_SA8540P 461 -+#define QCOM_ID_SM8450_2 480 -+#define QCOM_ID_SM8450_3 482 -+#define QCOM_ID_SC7280 487 -+#define QCOM_ID_SC7180P 495 -+#define QCOM_ID_SM6375 507 -+ -+/* -+ * The board type and revision information, used by Qualcomm bootloaders and -+ * DTS for older chipsets (qcom,board-id): -+ */ -+#define QCOM_BOARD_ID(a, major, minor) \ -+ (((major & 0xff) << 16) | ((minor & 0xff) << 8) | QCOM_BOARD_ID_##a) -+ -+#define QCOM_BOARD_ID_MTP 8 -+#define QCOM_BOARD_ID_DRAGONBOARD 10 -+#define QCOM_BOARD_ID_SBC 24 -+ -+#endif /* _DT_BINDINGS_ARM_QCOM_IDS_H */ diff --git a/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch b/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch deleted file mode 100644 index 394087a27a..0000000000 --- a/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 7cbff3c3f867ff3b24de674f44ca03f54e416a37 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 31 Dec 2022 00:27:42 +0100 -Subject: [PATCH] soc: qcom: socinfo: move SMEM item struct and defines to a - header - -Move SMEM item struct and related defines to a header in order to be able -to reuse them in the Qualcomm NVMEM CPUFreq driver instead of duplicating -them. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-1-robimarko@gmail.com ---- - drivers/soc/qcom/socinfo.c | 58 +-------------------------- - include/linux/soc/qcom/socinfo.h | 67 ++++++++++++++++++++++++++++++++ - 2 files changed, 68 insertions(+), 57 deletions(-) - create mode 100644 include/linux/soc/qcom/socinfo.h - ---- a/drivers/soc/qcom/socinfo.c -+++ b/drivers/soc/qcom/socinfo.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -25,15 +26,6 @@ - #define SOCINFO_MINOR(ver) ((ver) & 0xffff) - #define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff)) - --#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 --#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 -- --/* -- * SMEM item id, used to acquire handles to respective -- * SMEM region. -- */ --#define SMEM_HW_SW_BUILD_ID 137 -- - #ifdef CONFIG_DEBUG_FS - #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 - #define SMEM_IMAGE_VERSION_SIZE 4096 -@@ -116,54 +108,6 @@ static const char *const pmic_models[] = - }; - #endif /* CONFIG_DEBUG_FS */ - --/* Socinfo SMEM item structure */ --struct socinfo { -- __le32 fmt; -- __le32 id; -- __le32 ver; -- char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; -- /* Version 2 */ -- __le32 raw_id; -- __le32 raw_ver; -- /* Version 3 */ -- __le32 hw_plat; -- /* Version 4 */ -- __le32 plat_ver; -- /* Version 5 */ -- __le32 accessory_chip; -- /* Version 6 */ -- __le32 hw_plat_subtype; -- /* Version 7 */ -- __le32 pmic_model; -- __le32 pmic_die_rev; -- /* Version 8 */ -- __le32 pmic_model_1; -- __le32 pmic_die_rev_1; -- __le32 pmic_model_2; -- __le32 pmic_die_rev_2; -- /* Version 9 */ -- __le32 foundry_id; -- /* Version 10 */ -- __le32 serial_num; -- /* Version 11 */ -- __le32 num_pmics; -- __le32 pmic_array_offset; -- /* Version 12 */ -- __le32 chip_family; -- __le32 raw_device_family; -- __le32 raw_device_num; -- /* Version 13 */ -- __le32 nproduct_id; -- char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; -- /* Version 14 */ -- __le32 num_clusters; -- __le32 ncluster_array_offset; -- __le32 num_defective_parts; -- __le32 ndefective_parts_array_offset; -- /* Version 15 */ -- __le32 nmodem_supported; --}; -- - #ifdef CONFIG_DEBUG_FS - struct socinfo_params { - u32 raw_device_family; ---- /dev/null -+++ b/include/linux/soc/qcom/socinfo.h -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2017-2019, Linaro Ltd. -+ */ -+ -+#ifndef __QCOM_SOCINFO_H__ -+#define __QCOM_SOCINFO_H__ -+ -+/* -+ * SMEM item id, used to acquire handles to respective -+ * SMEM region. -+ */ -+#define SMEM_HW_SW_BUILD_ID 137 -+ -+#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 -+#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 -+ -+/* Socinfo SMEM item structure */ -+struct socinfo { -+ __le32 fmt; -+ __le32 id; -+ __le32 ver; -+ char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; -+ /* Version 2 */ -+ __le32 raw_id; -+ __le32 raw_ver; -+ /* Version 3 */ -+ __le32 hw_plat; -+ /* Version 4 */ -+ __le32 plat_ver; -+ /* Version 5 */ -+ __le32 accessory_chip; -+ /* Version 6 */ -+ __le32 hw_plat_subtype; -+ /* Version 7 */ -+ __le32 pmic_model; -+ __le32 pmic_die_rev; -+ /* Version 8 */ -+ __le32 pmic_model_1; -+ __le32 pmic_die_rev_1; -+ __le32 pmic_model_2; -+ __le32 pmic_die_rev_2; -+ /* Version 9 */ -+ __le32 foundry_id; -+ /* Version 10 */ -+ __le32 serial_num; -+ /* Version 11 */ -+ __le32 num_pmics; -+ __le32 pmic_array_offset; -+ /* Version 12 */ -+ __le32 chip_family; -+ __le32 raw_device_family; -+ __le32 raw_device_num; -+ /* Version 13 */ -+ __le32 nproduct_id; -+ char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; -+ /* Version 14 */ -+ __le32 num_clusters; -+ __le32 ncluster_array_offset; -+ __le32 num_defective_parts; -+ __le32 ndefective_parts_array_offset; -+ /* Version 15 */ -+ __le32 nmodem_supported; -+}; -+ -+#endif diff --git a/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch b/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch deleted file mode 100644 index 7c7c3f3635..0000000000 --- a/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 9f1bbff157a69db7684f5da2f73b2325c638a90e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:47:59 +0200 -Subject: [PATCH] soc: qcom: smem: Switch to EXPORT_SYMBOL_GPL() - -SMEM has been GPL licensed from the start, and there is no reason to use -EXPORT_SYMBOL() so switch to the GPL version. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Reviewed-by: Trilok Soni -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-2-robimarko@gmail.com ---- - drivers/soc/qcom/smem.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/soc/qcom/smem.c -+++ b/drivers/soc/qcom/smem.c -@@ -500,7 +500,7 @@ int qcom_smem_alloc(unsigned host, unsig - - return ret; - } --EXPORT_SYMBOL(qcom_smem_alloc); -+EXPORT_SYMBOL_GPL(qcom_smem_alloc); - - static void *qcom_smem_get_global(struct qcom_smem *smem, - unsigned item, -@@ -674,7 +674,7 @@ void *qcom_smem_get(unsigned host, unsig - return ptr; - - } --EXPORT_SYMBOL(qcom_smem_get); -+EXPORT_SYMBOL_GPL(qcom_smem_get); - - /** - * qcom_smem_get_free_space() - retrieve amount of free space in a partition -@@ -719,7 +719,7 @@ int qcom_smem_get_free_space(unsigned ho - - return ret; - } --EXPORT_SYMBOL(qcom_smem_get_free_space); -+EXPORT_SYMBOL_GPL(qcom_smem_get_free_space); - - static bool addr_in_range(void __iomem *base, size_t size, void *addr) - { -@@ -770,7 +770,7 @@ phys_addr_t qcom_smem_virt_to_phys(void - - return 0; - } --EXPORT_SYMBOL(qcom_smem_virt_to_phys); -+EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); - - static int qcom_smem_get_sbl_version(struct qcom_smem *smem) - { diff --git a/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch b/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch deleted file mode 100644 index 4a816bb0f9..0000000000 --- a/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch +++ /dev/null @@ -1,70 +0,0 @@ -From c3ecf2602a32d9b9e5fc997076c0d2836495c085 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:48:00 +0200 -Subject: [PATCH] soc: qcom: smem: introduce qcom_smem_get_soc_id() - -Introduce a helper to return the SoC SMEM ID, which is used to identify the -exact SoC model as there may be differences in the same SoC family. - -Currently, cpufreq-nvmem does this completely in the driver and there has -been more interest expresed for other drivers to use this information so -lets expose a common helper to prevent redoing it in individual drivers -since this field is present on every SMEM table version. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-3-robimarko@gmail.com ---- - drivers/soc/qcom/smem.c | 23 +++++++++++++++++++++++ - include/linux/soc/qcom/smem.h | 2 ++ - 2 files changed, 25 insertions(+) - ---- a/drivers/soc/qcom/smem.c -+++ b/drivers/soc/qcom/smem.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - /* - * The Qualcomm shared memory system is a allocate only heap structure that -@@ -772,6 +773,28 @@ phys_addr_t qcom_smem_virt_to_phys(void - } - EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); - -+/** -+ * qcom_smem_get_soc_id() - return the SoC ID -+ * @id: On success, we return the SoC ID here. -+ * -+ * Look up SoC ID from HW/SW build ID and return it. -+ * -+ * Return: 0 on success, negative errno on failure. -+ */ -+int qcom_smem_get_soc_id(u32 *id) -+{ -+ struct socinfo *info; -+ -+ info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); -+ if (IS_ERR(info)) -+ return PTR_ERR(info); -+ -+ *id = __le32_to_cpu(info->id); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); -+ - static int qcom_smem_get_sbl_version(struct qcom_smem *smem) - { - struct smem_header *header; ---- a/include/linux/soc/qcom/smem.h -+++ b/include/linux/soc/qcom/smem.h -@@ -11,4 +11,6 @@ int qcom_smem_get_free_space(unsigned ho - - phys_addr_t qcom_smem_virt_to_phys(void *p); - -+int qcom_smem_get_soc_id(u32 *id); -+ - #endif diff --git a/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch b/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch deleted file mode 100644 index 9560122ccd..0000000000 --- a/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 2b8634d1468ff498cc91b6adf993c27ae6fa079d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:48:01 +0200 -Subject: [PATCH] cpufreq: qcom-nvmem: use SoC ID-s from bindings - -SMEM SoC ID-s are now stored in DT bindings so lets use those instead of -defining them in the driver again. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Reviewed-by: Bjorn Andersson -Acked-by: Viresh Kumar -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-4-robimarko@gmail.com ---- - drivers/cpufreq/qcom-cpufreq-nvmem.c | 15 +++++---------- - 1 file changed, 5 insertions(+), 10 deletions(-) - ---- a/drivers/cpufreq/qcom-cpufreq-nvmem.c -+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -31,12 +31,7 @@ - - #define MSM_ID_SMEM 137 - --enum _msm_id { -- MSM8996V3 = 0xF6ul, -- APQ8096V3 = 0x123ul, -- MSM8996SG = 0x131ul, -- APQ8096SG = 0x138ul, --}; -+#include - - enum _msm8996_version { - MSM8996_V3, -@@ -154,12 +149,12 @@ static enum _msm8996_version qcom_cpufre - msm_id++; - - switch ((enum _msm_id)*msm_id) { -- case MSM8996V3: -- case APQ8096V3: -+ case QCOM_ID_MSM8996: -+ case QCOM_ID_APQ8096: - version = MSM8996_V3; - break; -- case MSM8996SG: -- case APQ8096SG: -+ case QCOM_ID_MSM8996SG: -+ case QCOM_ID_APQ8096SG: - version = MSM8996_SG; - break; - default: diff --git a/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch b/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch deleted file mode 100644 index 4f37d672ba..0000000000 --- a/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch +++ /dev/null @@ -1,109 +0,0 @@ -From e7992615acacc27baeec310197108143afc77337 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:48:02 +0200 -Subject: [PATCH] cpufreq: qcom-nvmem: use helper to get SMEM SoC ID - -Now that SMEM exports a helper to get the SMEM SoC ID lets utilize it. -Currently qcom_cpufreq_get_msm_id() is encoding the returned SMEM SoC ID -into an enum, however there is no reason to do so and we can just match -directly on the SMEM SoC ID as returned by qcom_smem_get_soc_id(). - -Signed-off-by: Robert Marko -Acked-by: Viresh Kumar -Reviewed-by: Konrad Dybcio -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-5-robimarko@gmail.com ---- - drivers/cpufreq/qcom-cpufreq-nvmem.c | 56 +++++----------------------- - 1 file changed, 10 insertions(+), 46 deletions(-) - ---- a/drivers/cpufreq/qcom-cpufreq-nvmem.c -+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -29,16 +29,8 @@ - #include - #include - --#define MSM_ID_SMEM 137 -- - #include - --enum _msm8996_version { -- MSM8996_V3, -- MSM8996_SG, -- NUM_OF_MSM8996_VERSIONS, --}; -- - struct qcom_cpufreq_drv; - - struct qcom_cpufreq_match_data { -@@ -135,60 +127,32 @@ static void get_krait_bin_format_b(struc - dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver); - } - --static enum _msm8996_version qcom_cpufreq_get_msm_id(void) --{ -- size_t len; -- u32 *msm_id; -- enum _msm8996_version version; -- -- msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); -- if (IS_ERR(msm_id)) -- return NUM_OF_MSM8996_VERSIONS; -- -- /* The first 4 bytes are format, next to them is the actual msm-id */ -- msm_id++; -- -- switch ((enum _msm_id)*msm_id) { -- case QCOM_ID_MSM8996: -- case QCOM_ID_APQ8096: -- version = MSM8996_V3; -- break; -- case QCOM_ID_MSM8996SG: -- case QCOM_ID_APQ8096SG: -- version = MSM8996_SG; -- break; -- default: -- version = NUM_OF_MSM8996_VERSIONS; -- } -- -- return version; --} -- - static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, - struct nvmem_cell *speedbin_nvmem, - char **pvs_name, - struct qcom_cpufreq_drv *drv) - { - size_t len; -+ u32 msm_id; - u8 *speedbin; -- enum _msm8996_version msm8996_version; -+ int ret; - *pvs_name = NULL; - -- msm8996_version = qcom_cpufreq_get_msm_id(); -- if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { -- dev_err(cpu_dev, "Not Snapdragon 820/821!"); -- return -ENODEV; -- } -+ ret = qcom_smem_get_soc_id(&msm_id); -+ if (ret) -+ return ret; - - speedbin = nvmem_cell_read(speedbin_nvmem, &len); - if (IS_ERR(speedbin)) - return PTR_ERR(speedbin); - -- switch (msm8996_version) { -- case MSM8996_V3: -+ switch (msm_id) { -+ case QCOM_ID_MSM8996: -+ case QCOM_ID_APQ8096: - drv->versions = 1 << (unsigned int)(*speedbin); - break; -- case MSM8996_SG: -+ case QCOM_ID_MSM8996SG: -+ case QCOM_ID_APQ8096SG: - drv->versions = 1 << ((unsigned int)(*speedbin) + 4); - break; - default: diff --git a/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch b/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch deleted file mode 100644 index cbb9172032..0000000000 --- a/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch +++ /dev/null @@ -1,170 +0,0 @@ -From fe2b1226656afae56702d1d84c6900f6b67df297 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 1 Dec 2023 11:23:22 +0100 -Subject: [PATCH] leds: trigger: netdev: fix RTNL handling to prevent potential - deadlock - -When working on LED support for r8169 I got the following lockdep -warning. Easiest way to prevent this scenario seems to be to take -the RTNL lock before the trigger_data lock in set_device_name(). - -====================================================== -WARNING: possible circular locking dependency detected -6.7.0-rc2-next-20231124+ #2 Not tainted ------------------------------------------------------- -bash/383 is trying to acquire lock: -ffff888103aa1c68 (&trigger_data->lock){+.+.}-{3:3}, at: netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - -but task is already holding lock: -ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 - -which lock already depends on the new lock. - -the existing dependency chain (in reverse order) is: - --> #1 (rtnl_mutex){+.+.}-{3:3}: - __mutex_lock+0x9b/0xb50 - mutex_lock_nested+0x16/0x20 - rtnl_lock+0x12/0x20 - set_device_name+0xa9/0x120 [ledtrig_netdev] - netdev_trig_activate+0x1a1/0x230 [ledtrig_netdev] - led_trigger_set+0x172/0x2c0 - led_trigger_write+0xf1/0x140 - sysfs_kf_bin_write+0x5d/0x80 - kernfs_fop_write_iter+0x15d/0x210 - vfs_write+0x1f0/0x510 - ksys_write+0x6c/0xf0 - __x64_sys_write+0x14/0x20 - do_syscall_64+0x3f/0xf0 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 - --> #0 (&trigger_data->lock){+.+.}-{3:3}: - __lock_acquire+0x1459/0x25a0 - lock_acquire+0xc8/0x2d0 - __mutex_lock+0x9b/0xb50 - mutex_lock_nested+0x16/0x20 - netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - call_netdevice_register_net_notifiers+0x5a/0x100 - register_netdevice_notifier+0x85/0x120 - netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] - led_trigger_set+0x172/0x2c0 - led_trigger_write+0xf1/0x140 - sysfs_kf_bin_write+0x5d/0x80 - kernfs_fop_write_iter+0x15d/0x210 - vfs_write+0x1f0/0x510 - ksys_write+0x6c/0xf0 - __x64_sys_write+0x14/0x20 - do_syscall_64+0x3f/0xf0 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 - -other info that might help us debug this: - - Possible unsafe locking scenario: - - CPU0 CPU1 - ---- ---- - lock(rtnl_mutex); - lock(&trigger_data->lock); - lock(rtnl_mutex); - lock(&trigger_data->lock); - - *** DEADLOCK *** - -8 locks held by bash/383: - #0: ffff888103ff33f0 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x6c/0xf0 - #1: ffff888103aa1e88 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x114/0x210 - #2: ffff8881036f1890 (kn->active#82){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x11d/0x210 - #3: ffff888108e2c358 (&led_cdev->led_access){+.+.}-{3:3}, at: led_trigger_write+0x30/0x140 - #4: ffffffff8cdd9e10 (triggers_list_lock){++++}-{3:3}, at: led_trigger_write+0x75/0x140 - #5: ffff888108e2c270 (&led_cdev->trigger_lock){++++}-{3:3}, at: led_trigger_write+0xe3/0x140 - #6: ffffffff8cdde3d0 (pernet_ops_rwsem){++++}-{3:3}, at: register_netdevice_notifier+0x1c/0x120 - #7: ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 - -stack backtrace: -CPU: 0 PID: 383 Comm: bash Not tainted 6.7.0-rc2-next-20231124+ #2 -Hardware name: Default string Default string/Default string, BIOS ADLN.M6.SODIMM.ZB.CY.015 08/08/2023 -Call Trace: - - dump_stack_lvl+0x5c/0xd0 - dump_stack+0x10/0x20 - print_circular_bug+0x2dd/0x410 - check_noncircular+0x131/0x150 - __lock_acquire+0x1459/0x25a0 - lock_acquire+0xc8/0x2d0 - ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - __mutex_lock+0x9b/0xb50 - ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - ? __this_cpu_preempt_check+0x13/0x20 - ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - ? __cancel_work_timer+0x11c/0x1b0 - ? __mutex_lock+0x123/0xb50 - mutex_lock_nested+0x16/0x20 - ? mutex_lock_nested+0x16/0x20 - netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - call_netdevice_register_net_notifiers+0x5a/0x100 - register_netdevice_notifier+0x85/0x120 - netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] - led_trigger_set+0x172/0x2c0 - ? preempt_count_add+0x49/0xc0 - led_trigger_write+0xf1/0x140 - sysfs_kf_bin_write+0x5d/0x80 - kernfs_fop_write_iter+0x15d/0x210 - vfs_write+0x1f0/0x510 - ksys_write+0x6c/0xf0 - __x64_sys_write+0x14/0x20 - do_syscall_64+0x3f/0xf0 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 -RIP: 0033:0x7f269055d034 -Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d 35 c3 0d 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 48 89 54 24 18 48 -RSP: 002b:00007ffddb7ef748 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 -RAX: ffffffffffffffda RBX: 0000000000000007 RCX: 00007f269055d034 -RDX: 0000000000000007 RSI: 000055bf5f4af3c0 RDI: 0000000000000001 -RBP: 000055bf5f4af3c0 R08: 0000000000000073 R09: 0000000000000001 -R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000007 -R13: 00007f26906325c0 R14: 00007f269062ff20 R15: 0000000000000000 - - -Fixes: d5e01266e7f5 ("leds: trigger: netdev: add additional specific link speed mode") -Cc: stable@vger.kernel.org -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Link: https://lore.kernel.org/r/fb5c8294-2a10-4bf5-8f10-3d2b77d2757e@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -235,6 +235,11 @@ static int set_device_name(struct led_ne - { - cancel_delayed_work_sync(&trigger_data->work); - -+ /* -+ * Take RTNL lock before trigger_data lock to prevent potential -+ * deadlock with netdev notifier registration. -+ */ -+ rtnl_lock(); - mutex_lock(&trigger_data->lock); - - if (trigger_data->net_dev) { -@@ -254,16 +259,14 @@ static int set_device_name(struct led_ne - trigger_data->carrier_link_up = false; - trigger_data->link_speed = SPEED_UNKNOWN; - trigger_data->duplex = DUPLEX_UNKNOWN; -- if (trigger_data->net_dev != NULL) { -- rtnl_lock(); -+ if (trigger_data->net_dev) - get_device_state(trigger_data); -- rtnl_unlock(); -- } - - trigger_data->last_activity = 0; - - set_baseline_state(trigger_data); - mutex_unlock(&trigger_data->lock); -+ rtnl_unlock(); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch b/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch deleted file mode 100644 index 51b4bbbfcb..0000000000 --- a/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 9b78d919632b7149d311aaad5a977e4b48b10321 Mon Sep 17 00:00:00 2001 -From: Paolo Abeni -Date: Wed, 26 Apr 2023 10:15:31 +0200 -Subject: [PATCH] net: phy: hide the PHYLIB_LEDS knob - -commit 4bb7aac70b5d ("net: phy: fix circular LEDS_CLASS dependencies") -solved a build failure, but introduces a new config knob with a default -'y' value: PHYLIB_LEDS. - -The latter is against the current new config policy. The exception -was raised to allow the user to catch bad configurations without led -support. - -Anyway the current definition of PHYLIB_LEDS does not fit the above -goal: if LEDS_CLASS is disabled, the new config will be available -only with PHYLIB disabled, too. - -Hide the mentioned config, to preserve the randconfig testing done so -far, while respecting the mentioned policy. - -Suggested-by: Andrew Lunn -Suggested-by: Arnd Bergmann -Signed-off-by: Paolo Abeni -Link: https://lore.kernel.org/r/d82489be8ed911c383c3447e9abf469995ccf39a.1682496488.git.pabeni@redhat.com -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/Kconfig | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -45,10 +45,8 @@ config LED_TRIGGER_PHY - for any speed known to the PHY. - - config PHYLIB_LEDS -- bool "Support probing LEDs from device tree" -+ def_bool OF - depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB -- depends on OF -- default y - help - When LED class support is enabled, phylib can automatically - probe LED setting from device tree. diff --git a/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch b/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch deleted file mode 100644 index 38fbc3a3d7..0000000000 --- a/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch +++ /dev/null @@ -1,40 +0,0 @@ -From dbf70fc204d2fbb0d8ad8f42038a60846502efda Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 10 Oct 2022 13:51:09 +0300 -Subject: [PATCH] mtd: spinand: winbond: fix flash identification - -Winbond uses 3 bytes to identify flash: vendor_id, dev_id_0, dev_id_1, -but current driver uses only first 2 bytes of it for devices -identification. As result Winbond W25N02KV flash (id_bytes: EF, AA, 22) -is identified as W25N01GV (id_bytes: EF, AA, 21). - -Fix this by adding missed identification bytes. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: Frieder Schrempf -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221010105110.446674-1-mikhail.kshevetskiy@iopsys.eu ---- - drivers/mtd/nand/spi/winbond.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/nand/spi/winbond.c -+++ b/drivers/mtd/nand/spi/winbond.c -@@ -76,7 +76,7 @@ static int w25m02gv_select_target(struct - - static const struct spinand_info winbond_spinand_table[] = { - SPINAND_INFO("W25M02GV", -- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab), -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), - NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -@@ -86,7 +86,7 @@ static const struct spinand_info winbond - SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), - SPINAND_SELECT_TARGET(w25m02gv_select_target)), - SPINAND_INFO("W25N01GV", -- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa), -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21), - NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_variants, diff --git a/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch b/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch deleted file mode 100644 index d75a1acc57..0000000000 --- a/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 6154c7a583483d7b69f53bea868efdc369edd563 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 10 Oct 2022 13:51:10 +0300 -Subject: [PATCH] mtd: spinand: winbond: add Winbond W25N02KV flash support - -Add support of Winbond W25N02KV flash - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: Frieder Schrempf -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221010105110.446674-2-mikhail.kshevetskiy@iopsys.eu ---- - drivers/mtd/nand/spi/winbond.c | 75 ++++++++++++++++++++++++++++++++++ - 1 file changed, 75 insertions(+) - ---- a/drivers/mtd/nand/spi/winbond.c -+++ b/drivers/mtd/nand/spi/winbond.c -@@ -74,6 +74,72 @@ static int w25m02gv_select_target(struct - return spi_mem_exec_op(spinand->spimem, &op); - } - -+static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = 64 + (16 * section); -+ region->length = 13; -+ -+ return 0; -+} -+ -+static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section) + 2; -+ region->length = 14; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops w25n02kv_ooblayout = { -+ .ecc = w25n02kv_ooblayout_ecc, -+ .free = w25n02kv_ooblayout_free, -+}; -+ -+static int w25n02kv_ecc_get_status(struct spinand_device *spinand, -+ u8 status) -+{ -+ struct nand_device *nand = spinand_to_nand(spinand); -+ u8 mbf = 0; -+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); -+ -+ switch (status & STATUS_ECC_MASK) { -+ case STATUS_ECC_NO_BITFLIPS: -+ return 0; -+ -+ case STATUS_ECC_UNCOR_ERROR: -+ return -EBADMSG; -+ -+ case STATUS_ECC_HAS_BITFLIPS: -+ /* -+ * Let's try to retrieve the real maximum number of bitflips -+ * in order to avoid forcing the wear-leveling layer to move -+ * data around if it's not necessary. -+ */ -+ if (spi_mem_exec_op(spinand->spimem, &op)) -+ return nanddev_get_ecc_conf(nand)->strength; -+ -+ mbf >>= 4; -+ -+ if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) -+ return nanddev_get_ecc_conf(nand)->strength; -+ -+ return mbf; -+ -+ default: -+ break; -+ } -+ -+ return -EINVAL; -+} -+ - static const struct spinand_info winbond_spinand_table[] = { - SPINAND_INFO("W25M02GV", - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), -@@ -94,6 +160,15 @@ static const struct spinand_info winbond - &update_cache_variants), - 0, - SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), -+ SPINAND_INFO("W25N02KV", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22), -+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), -+ NAND_ECCREQ(8, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ 0, -+ SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), - }; - - static int winbond_spinand_init(struct spinand_device *spinand) diff --git a/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch b/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch deleted file mode 100644 index 2f408f5a30..0000000000 --- a/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch +++ /dev/null @@ -1,49 +0,0 @@ -From f5a05060670a4d8d6523afc7963eb559c2e3615f Mon Sep 17 00:00:00 2001 -From: Olivier Maignial -Date: Fri, 23 Jun 2023 17:33:37 +0200 -Subject: [PATCH] mtd: spinand: winbond: Fix ecc_get_status - -Reading ECC status is failing. - -w25n02kv_ecc_get_status() is using on-stack buffer for -SPINAND_GET_FEATURE_OP() output. It is not suitable for -DMA needs of spi-mem. - -Fix this by using the spi-mem operations dedicated buffer -spinand->scratchbuf. - -See -spinand->scratchbuf: -https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/mtd/spinand.h?h=v6.3#n418 -spi_mem_check_op(): -https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/spi/spi-mem.c?h=v6.3#n199 - -Fixes: 6154c7a58348 ("mtd: spinand: winbond: add Winbond W25N02KV flash support") -Cc: stable@vger.kernel.org -Signed-off-by: Olivier Maignial -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/DB4P250MB1032EDB9E36B764A33769039FE23A@DB4P250MB1032.EURP250.PROD.OUTLOOK.COM ---- - drivers/mtd/nand/spi/winbond.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/nand/spi/winbond.c -+++ b/drivers/mtd/nand/spi/winbond.c -@@ -108,7 +108,7 @@ static int w25n02kv_ecc_get_status(struc - { - struct nand_device *nand = spinand_to_nand(spinand); - u8 mbf = 0; -- struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); -+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); - - switch (status & STATUS_ECC_MASK) { - case STATUS_ECC_NO_BITFLIPS: -@@ -126,7 +126,7 @@ static int w25n02kv_ecc_get_status(struc - if (spi_mem_exec_op(spinand->spimem, &op)) - return nanddev_get_ecc_conf(nand)->strength; - -- mbf >>= 4; -+ mbf = *(spinand->scratchbuf) >> 4; - - if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) - return nanddev_get_ecc_conf(nand)->strength;