Re: [PATCH -next v6 0/2] Make memory reclamation measurable
ping~ 在 2024/1/5 9:36, Bixuan Cui 写道: When the system memory is low, kswapd reclaims the memory. The key steps of memory reclamation include 1.shrink_lruvec * shrink_active_list, moves folios from the active LRU to the inactive LRU * shrink_inactive_list, shrink lru from inactive LRU list 2.shrink_slab * shrinker->count_objects(), calculates the freeable memory * shrinker->scan_objects(), reclaims the slab memory The existing tracers in the vmscan are as follows: --do_try_to_free_pages --shrink_zones --trace_mm_vmscan_node_reclaim_begin (tracer) --shrink_node --shrink_node_memcgs --trace_mm_vmscan_memcg_shrink_begin (tracer) --shrink_lruvec --shrink_list --shrink_active_list --trace_mm_vmscan_lru_shrink_active (tracer) --shrink_inactive_list --trace_mm_vmscan_lru_shrink_inactive (tracer) --shrink_active_list --shrink_slab --do_shrink_slab --shrinker->count_objects() --trace_mm_shrink_slab_start (tracer) --shrinker->scan_objects() --trace_mm_shrink_slab_end (tracer) --trace_mm_vmscan_memcg_shrink_end (tracer) --trace_mm_vmscan_node_reclaim_end (tracer) If we get the duration and quantity of shrink lru and slab, then we can measure the memory recycling, as follows Measuring memory reclamation with bpf: LRU FILE: CPU COMMShrinkActive(us) ShrinkInactive(us) Reclaim(page) 7 kswapd0 26 51 32 7 kswapd0 52 47 13 SLAB: CPU COMMOBJ_NAMECount_Dur(us) Freeable(page) Scan_Dur(us) Reclaim(page) 1 kswapd0 super_cache_scan.cfi_jt 2 341 3225 128 7 kswapd0 super_cache_scan.cfi_jt 0 2247 8524 1024 7 kswapd0 super_cache_scan.cfi_jt 23670 00 For this, add the new tracer to shrink_active_list/shrink_inactive_list and shrinker->count_objects(). Changes: v6: * Add Reviewed-by from Steven Rostedt. v5: * Use 'DECLARE_EVENT_CLASS(mm_vmscan_lru_shrink_start_template' to replace 'RACE_EVENT(mm_vmscan_lru_shrink_inactive/active_start' * Add the explanation for adding new shrink lru events into 'mm: vmscan: add new event to trace shrink lru' v4: Add Reviewed-by and Changlog to every patch. v3: Swap the positions of 'nid' and 'freeable' to prevent the hole in the trace event. v2: Modify trace_mm_vmscan_lru_shrink_inactive() in evict_folios() at the same time to fix build error. cuibixuan (2): mm: shrinker: add new event to trace shrink count mm: vmscan: add new event to trace shrink lru include/trace/events/vmscan.h | 80 ++- mm/shrinker.c | 4 ++ mm/vmscan.c | 11 +++-- 3 files changed, 90 insertions(+), 5 deletions(-)
[RFC PATCH 4/4] mm/damon: introduce DAMOS_PROMOTE action for promotion
From: Hyeongtak Ji This patch introduces DAMOS_PROMOTE action for paddr mode. It includes renaming alloc_demote_folio to alloc_migrate_folio to use it for promotion as well. The execution sequence of DAMOS_DEMOTE and DAMOS_PROMOTE look as follows for comparison. DAMOS_DEMOTE action damo_pa_apply_scheme -> damon_pa_reclaim -> demote_pages -> do_demote_folio_list -> __demote_folio_list -> demote_folio_list DAMOS_PROMOTE action damo_pa_apply_scheme -> damon_pa_promote -> promote_pages -> do_promote_folio_list -> __promote_folio_list -> promote_folio_list Signed-off-by: Hyeongtak Ji Signed-off-by: Honggyu Kim --- include/linux/damon.h | 2 + include/linux/migrate_mode.h | 1 + include/linux/vm_event_item.h | 1 + include/trace/events/migrate.h | 3 +- mm/damon/paddr.c | 29 mm/damon/sysfs-schemes.c | 1 + mm/internal.h | 1 + mm/vmscan.c| 129 - mm/vmstat.c| 1 + 9 files changed, 165 insertions(+), 3 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index 4c0a0fef09c5..477060bb6718 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -107,6 +107,7 @@ struct damon_target { * @DAMOS_LRU_DEPRIO: Deprioritize the region on its LRU lists. * @DAMOS_STAT:Do nothing but count the stat. * @DAMOS_DEMOTE: Do demotion for the current region. + * @DAMOS_PROMOTE: Do promotion if possible, otherwise do nothing. * @NR_DAMOS_ACTIONS: Total number of DAMOS actions * * The support of each action is up to running damon_operations. @@ -125,6 +126,7 @@ enum damos_action { DAMOS_LRU_DEPRIO, DAMOS_STAT, /* Do nothing but only record the stat */ DAMOS_DEMOTE, + DAMOS_PROMOTE, NR_DAMOS_ACTIONS, }; diff --git a/include/linux/migrate_mode.h b/include/linux/migrate_mode.h index f37cc03f9369..63f75eb9abf3 100644 --- a/include/linux/migrate_mode.h +++ b/include/linux/migrate_mode.h @@ -29,6 +29,7 @@ enum migrate_reason { MR_CONTIG_RANGE, MR_LONGTERM_PIN, MR_DEMOTION, + MR_PROMOTION, MR_TYPES }; diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index 8abfa1240040..63cf920afeaa 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -44,6 +44,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, PGDEMOTE_KSWAPD, PGDEMOTE_DIRECT, PGDEMOTE_KHUGEPAGED, + PGPROMOTE, PGSCAN_KSWAPD, PGSCAN_DIRECT, PGSCAN_KHUGEPAGED, diff --git a/include/trace/events/migrate.h b/include/trace/events/migrate.h index 0190ef725b43..f0dd569c1e62 100644 --- a/include/trace/events/migrate.h +++ b/include/trace/events/migrate.h @@ -22,7 +22,8 @@ EM( MR_NUMA_MISPLACED, "numa_misplaced") \ EM( MR_CONTIG_RANGE,"contig_range") \ EM( MR_LONGTERM_PIN,"longterm_pin") \ - EMe(MR_DEMOTION,"demotion") + EM( MR_DEMOTION,"demotion") \ + EMe(MR_PROMOTION, "promotion") /* * First define the enums in the above macros to be exported to userspace diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c index d3e3f077cd00..360ce69d5898 100644 --- a/mm/damon/paddr.c +++ b/mm/damon/paddr.c @@ -257,6 +257,32 @@ static unsigned long damon_pa_reclaim(struct damon_region *r, struct damos *s, b return applied * PAGE_SIZE; } +static unsigned long damon_pa_promote(struct damon_region *r, struct damos *s) +{ + unsigned long addr, applied; + LIST_HEAD(folio_list); + + for (addr = r->ar.start; addr < r->ar.end; addr += PAGE_SIZE) { + struct folio *folio = damon_get_folio(PHYS_PFN(addr)); + + if (!folio) + continue; + + if (damos_pa_filter_out(s, folio)) + goto put_folio; + + if (!folio_isolate_lru(folio)) + goto put_folio; + + list_add(>lru, _list); +put_folio: + folio_put(folio); + } + applied = promote_pages(_list); + cond_resched(); + return applied * PAGE_SIZE; +} + static inline unsigned long damon_pa_mark_accessed_or_deactivate( struct damon_region *r, struct damos *s, bool mark_accessed) { @@ -309,6 +335,8 @@ static unsigned long damon_pa_apply_scheme(struct damon_ctx *ctx, break; case DAMOS_DEMOTE: return damon_pa_reclaim(r, scheme, true); + case DAMOS_PROMOTE: + return damon_pa_promote(r, scheme); default: /* DAMOS actions that not yet supported by 'paddr'. */ break; @@ -326,6 +354,7 @@ static int
[RFC PATCH 2/4] mm/damon: introduce DAMOS_DEMOTE action for demotion
This patch introduces DAMOS_DEMOTE action, which is similar to DAMOS_PAGEOUT, but demote folios instead of swapping them out. Since there are some common routines with pageout, many functions have similar logics between pageout and demote. The execution sequence of DAMOS_PAGEOUT and DAMOS_DEMOTE look as follows. DAMOS_PAGEOUT action damo_pa_apply_scheme -> damon_pa_reclaim -> reclaim_pages -> reclaim_folio_list -> shrink_folio_list DAMOS_DEMOTE action damo_pa_apply_scheme -> damon_pa_reclaim -> demote_pages -> do_demote_folio_list -> __demote_folio_list -> demote_folio_list __demote_folio_list() is a minimized version of shrink_folio_list(), but it's minified only for demotion. Signed-off-by: Honggyu Kim --- include/linux/damon.h| 2 + mm/damon/paddr.c | 17 +--- mm/damon/sysfs-schemes.c | 1 + mm/internal.h| 1 + mm/vmscan.c | 84 5 files changed, 99 insertions(+), 6 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index e00ddf1ed39c..4c0a0fef09c5 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -106,6 +106,7 @@ struct damon_target { * @DAMOS_LRU_PRIO:Prioritize the region on its LRU lists. * @DAMOS_LRU_DEPRIO: Deprioritize the region on its LRU lists. * @DAMOS_STAT:Do nothing but count the stat. + * @DAMOS_DEMOTE: Do demotion for the current region. * @NR_DAMOS_ACTIONS: Total number of DAMOS actions * * The support of each action is up to running damon_operations. @@ -123,6 +124,7 @@ enum damos_action { DAMOS_LRU_PRIO, DAMOS_LRU_DEPRIO, DAMOS_STAT, /* Do nothing but only record the stat */ + DAMOS_DEMOTE, NR_DAMOS_ACTIONS, }; diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c index 081e2a325778..d3e3f077cd00 100644 --- a/mm/damon/paddr.c +++ b/mm/damon/paddr.c @@ -224,7 +224,7 @@ static bool damos_pa_filter_out(struct damos *scheme, struct folio *folio) return false; } -static unsigned long damon_pa_pageout(struct damon_region *r, struct damos *s) +static unsigned long damon_pa_reclaim(struct damon_region *r, struct damos *s, bool is_demote) { unsigned long addr, applied; LIST_HEAD(folio_list); @@ -242,14 +242,17 @@ static unsigned long damon_pa_pageout(struct damon_region *r, struct damos *s) folio_test_clear_young(folio); if (!folio_isolate_lru(folio)) goto put_folio; - if (folio_test_unevictable(folio)) + if (folio_test_unevictable(folio) && !is_demote) folio_putback_lru(folio); else list_add(>lru, _list); put_folio: folio_put(folio); } - applied = reclaim_pages(_list); + if (is_demote) + applied = demote_pages(_list); + else + applied = reclaim_pages(_list); cond_resched(); return applied * PAGE_SIZE; } @@ -297,13 +300,15 @@ static unsigned long damon_pa_apply_scheme(struct damon_ctx *ctx, { switch (scheme->action) { case DAMOS_PAGEOUT: - return damon_pa_pageout(r, scheme); + return damon_pa_reclaim(r, scheme, false); case DAMOS_LRU_PRIO: return damon_pa_mark_accessed(r, scheme); case DAMOS_LRU_DEPRIO: return damon_pa_deactivate_pages(r, scheme); case DAMOS_STAT: break; + case DAMOS_DEMOTE: + return damon_pa_reclaim(r, scheme, true); default: /* DAMOS actions that not yet supported by 'paddr'. */ break; @@ -317,11 +322,11 @@ static int damon_pa_scheme_score(struct damon_ctx *context, { switch (scheme->action) { case DAMOS_PAGEOUT: + case DAMOS_LRU_DEPRIO: + case DAMOS_DEMOTE: return damon_cold_score(context, r, scheme); case DAMOS_LRU_PRIO: return damon_hot_score(context, r, scheme); - case DAMOS_LRU_DEPRIO: - return damon_cold_score(context, r, scheme); default: break; } diff --git a/mm/damon/sysfs-schemes.c b/mm/damon/sysfs-schemes.c index fe0fe2562000..ac7cd3f17b12 100644 --- a/mm/damon/sysfs-schemes.c +++ b/mm/damon/sysfs-schemes.c @@ -1187,6 +1187,7 @@ static const char * const damon_sysfs_damos_action_strs[] = { "lru_prio", "lru_deprio", "stat", + "demote", }; static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( diff --git a/mm/internal.h b/mm/internal.h index b61034bd50f5..2380397ec2f3 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -869,6 +869,7 @@ extern void set_pageblock_order(void); unsigned long reclaim_pages(struct list_head *folio_list); unsigned int reclaim_clean_pages_from_list(struct zone *zone,
[RFC PATCH 3/4] mm/memory-tiers: add next_promotion_node to find promotion target
From: Hyeongtak Ji This patch adds next_promotion_node that can be used to identify the appropriate promotion target based on memory tiers. When multiple promotion target nodes are available, the nearest node is selected based on numa distance. Signed-off-by: Hyeongtak Ji --- include/linux/memory-tiers.h | 11 + mm/memory-tiers.c| 43 2 files changed, 54 insertions(+) diff --git a/include/linux/memory-tiers.h b/include/linux/memory-tiers.h index 1e39d27bee41..0788e435fc50 100644 --- a/include/linux/memory-tiers.h +++ b/include/linux/memory-tiers.h @@ -50,6 +50,7 @@ int mt_set_default_dram_perf(int nid, struct node_hmem_attrs *perf, int mt_perf_to_adistance(struct node_hmem_attrs *perf, int *adist); #ifdef CONFIG_MIGRATION int next_demotion_node(int node); +int next_promotion_node(int node); void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets); bool node_is_toptier(int node); #else @@ -58,6 +59,11 @@ static inline int next_demotion_node(int node) return NUMA_NO_NODE; } +static inline int next_promotion_node(int node) +{ + return NUMA_NO_NODE; +} + static inline void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets) { *targets = NODE_MASK_NONE; @@ -101,6 +107,11 @@ static inline int next_demotion_node(int node) return NUMA_NO_NODE; } +static inline int next_promotion_node(int node) +{ + return NUMA_NO_NODE; +} + static inline void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets) { *targets = NODE_MASK_NONE; diff --git a/mm/memory-tiers.c b/mm/memory-tiers.c index 8d5291add2bc..0060ee571cf4 100644 --- a/mm/memory-tiers.c +++ b/mm/memory-tiers.c @@ -335,6 +335,49 @@ int next_demotion_node(int node) return target; } +/* + * Select a promotion target that is close to the from node among the given + * two nodes. + * + * TODO: consider other decision policy as node_distance may not be precise. + */ +static int select_promotion_target(int a, int b, int from) +{ + if (node_distance(from, a) < node_distance(from, b)) + return a; + else + return b; +} + +/** + * next_promotion_node() - Get the next node in the promotion path + * @node: The starting node to lookup the next node + * + * Return: node id for next memory node in the promotion path hierarchy + * from @node; NUMA_NO_NODE if @node is the toptier. + */ +int next_promotion_node(int node) +{ + int target = NUMA_NO_NODE; + int nid; + + if (node_is_toptier(node)) + return NUMA_NO_NODE; + + rcu_read_lock(); + for_each_node_state(nid, N_MEMORY) { + if (node_isset(node, node_demotion[nid].preferred)) { + if (target == NUMA_NO_NODE) + target = nid; + else + target = select_promotion_target(nid, target, node); + } + } + rcu_read_unlock(); + + return target; +} + static void disable_all_demotion_targets(void) { struct memory_tier *memtier; -- 2.34.1
[RFC PATCH 1/4] mm/vmscan: refactor reclaim_pages with reclaim_or_migrate_folios
Since we will introduce reclaim_pages like functions such as demote_pages and promote_pages, the most of the code can be shared. This is a preparation patch that introduces reclaim_or_migrate_folios() to cover all the logics, but it provides a handler for the different actions. No functional changes applied. Signed-off-by: Honggyu Kim --- mm/vmscan.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index bba207f41b14..7ca2396ccc3b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2107,15 +2107,16 @@ static unsigned int reclaim_folio_list(struct list_head *folio_list, return nr_reclaimed; } -unsigned long reclaim_pages(struct list_head *folio_list) +static unsigned long reclaim_or_migrate_folios(struct list_head *folio_list, + unsigned int (*handler)(struct list_head *, struct pglist_data *)) { int nid; - unsigned int nr_reclaimed = 0; + unsigned int nr_folios = 0; LIST_HEAD(node_folio_list); unsigned int noreclaim_flag; if (list_empty(folio_list)) - return nr_reclaimed; + return nr_folios; noreclaim_flag = memalloc_noreclaim_save(); @@ -2129,15 +2130,20 @@ unsigned long reclaim_pages(struct list_head *folio_list) continue; } - nr_reclaimed += reclaim_folio_list(_folio_list, NODE_DATA(nid)); + nr_folios += handler(_folio_list, NODE_DATA(nid)); nid = folio_nid(lru_to_folio(folio_list)); } while (!list_empty(folio_list)); - nr_reclaimed += reclaim_folio_list(_folio_list, NODE_DATA(nid)); + nr_folios += handler(_folio_list, NODE_DATA(nid)); memalloc_noreclaim_restore(noreclaim_flag); - return nr_reclaimed; + return nr_folios; +} + +unsigned long reclaim_pages(struct list_head *folio_list) +{ + return reclaim_or_migrate_folios(folio_list, reclaim_folio_list); } static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan, -- 2.34.1
[RFC PATCH 0/4] DAMON based 2-tier memory management for CXL memory
There was an RFC IDEA "DAMOS-based Tiered-Memory Management" previously posted at [1]. It says there is no implementation of the demote/promote DAMOS action are made. This RFC is about its implementation for physical address space. Introduction With the advent of CXL/PCIe attached DRAM, which will be called simply as CXL memory in this cover letter, some systems are becoming more heterogenous having memory systems with different latency and bandwidth characteristics. They are usually handled as different NUMA nodes in separate memory tiers and CXL memory is used as slow tiers because of its protocol overhead compared to local DRAM. In this kind of systems, we need to be careful placing memory pages on proper NUMA nodes based on the memory access frequency. Otherwise, some frequently accessed pages might reside on slow tiers and it makes performance degradation unexpectedly. Moreover, the memory access patterns can be changed at runtime. To handle this problem, we need a way to monitor the memory access patterns and migrate pages based on their access temperature. The DAMON(Data Access MONitor) framework and its DAMOS(DAMON-based Operation Schemes) can be useful features for monitoring and migrating pages. DAMOS provides multiple actions based on DAMON monitoring results and it can be used for proactive reclaim, which means swapping cold pages out with DAMOS_PAGEOUT action, but it doesn't support migration actions such as demotion and promotion between tiered memory nodes. This series supports two new DAMOS actions; DAMOS_DEMOTE for demotion from fast tiers and DAMOS_PROMOTE for promotion from slow tiers. This prevents hot pages from being stuck on slow tiers, which makes performance degradation and cold pages can be proactively demoted to slow tiers so that the system can increase the chance to allocate more hot pages to fast tiers. The DAMON provides various tuning knobs but we found that the proactive demotion for cold pages is especially useful when the system is running out of memory on its fast tier nodes. Our evaluation result shows that it reduces the performance slowdown compared to the default memory policy from 15~17% to 4~5% when the system runs under high memory pressure on its fast tier DRAM nodes. DAMON configuration === The specific DAMON configuration doesn't have to be in the scope of this patch series, but some rough idea is better to be shared to explain the evaluation result. The DAMON provides many knobs for fine tuning but its configuration file is generated by HMSDK[2]. It includes gen_config.py script that generates a json file with the full config of DAMON knobs and it creates multiple kdamonds for each NUMA node when the DAMON is enabled so that it can run hot/cold based migration for tiered memory. Evaluation Workload === The performance evaluation is done with redis[3], which is a widely used in-memory database and the memory access patterns are generated via YCSB[4]. We have measured two different workloads with zipfian and latest distributions but their configs are slightly modified to make memory usage higher and execution time longer for better evaluation. The idea of evaluation using these demote and promote actions covers system-wide memory management rather than partitioning hot/cold pages of a single workload. The default memory allocation policy creates pages to the fast tier DRAM node first, then allocates newly created pages to the slow tier CXL node when the DRAM node has insufficient free space. Once the page allocation is done then those pages never move between NUMA nodes. It's not true when using numa balancing, but it is not the scope of this DAMON based 2-tier memory management support. If the working set of redis can be fit fully into the DRAM node, then the redis will access the fast DRAM only. Since the performance of DRAM only is faster than partially accessing CXL memory in slow tiers, this environment is not useful to evaluate this patch series. To make pages of redis be distributed across fast DRAM node and slow CXL node to evaluate our demote and promote actions, we pre-allocate some cold memory externally using mmap and memset before launching redis-server. We assumed that there are enough amount of cold memory in datacenters as TMO[5] and TPP[6] papers mentioned. The evaluation sequence is as follows. 1. Turn on DAMON with DAMOS_DEMOTE action for DRAM node and DAMOS_PROMOTE action for CXL node. It demotes cold pages on DRAM node and promotes hot pages on CXL node in a regular interval. 2. Allocate a huge block of cold memory by calling mmap and memset at the fast tier DRAM node, then make the process sleep to make the fast tier has insufficient memory for redis-server. 3. Launch redis-server and load prebaked snapshot image, dump.rdb. The redis-server consumes 52GB of anon pages and 33GB of file pages, but due to the cold memory allocated at 2, it fails
Re: [PATCH v11 2/5] ring-buffer: Introducing ring-buffer mapping functions
On Thu, 11 Jan 2024 16:17:09 + Vincent Donnefort wrote: > In preparation for allowing the user-space to map a ring-buffer, add > a set of mapping functions: > > ring_buffer_{map,unmap}() > ring_buffer_map_fault() > > And controls on the ring-buffer: > > ring_buffer_map_get_reader() /* swap reader and head */ > > Mapping the ring-buffer also involves: > > A unique ID for each subbuf of the ring-buffer, currently they are > only identified through their in-kernel VA. > > A meta-page, where are stored ring-buffer statistics and a > description for the current reader > > The linear mapping exposes the meta-page, and each subbuf of the > ring-buffer, ordered following their unique ID, assigned during the > first mapping. > > Once mapped, no subbuf can get in or out of the ring-buffer: the buffer > size will remain unmodified and the splice enabling functions will in > reality simply memcpy the data instead of swapping subbufs. > > Signed-off-by: Vincent Donnefort > > diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h > index fa802db216f9..0841ba8bab14 100644 > --- a/include/linux/ring_buffer.h > +++ b/include/linux/ring_buffer.h > @@ -6,6 +6,8 @@ > #include > #include > > +#include > + > struct trace_buffer; > struct ring_buffer_iter; > > @@ -221,4 +223,9 @@ int trace_rb_cpu_prepare(unsigned int cpu, struct > hlist_node *node); > #define trace_rb_cpu_prepare NULL > #endif > > +int ring_buffer_map(struct trace_buffer *buffer, int cpu); > +int ring_buffer_unmap(struct trace_buffer *buffer, int cpu); > +struct page *ring_buffer_map_fault(struct trace_buffer *buffer, int cpu, > +unsigned long pgoff); > +int ring_buffer_map_get_reader(struct trace_buffer *buffer, int cpu); > #endif /* _LINUX_RING_BUFFER_H */ > diff --git a/include/uapi/linux/trace_mmap.h b/include/uapi/linux/trace_mmap.h > new file mode 100644 > index ..bde39a73ce65 > --- /dev/null > +++ b/include/uapi/linux/trace_mmap.h > @@ -0,0 +1,45 @@ > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > +#ifndef _TRACE_MMAP_H_ > +#define _TRACE_MMAP_H_ > + > +#include > + > +/** > + * struct trace_buffer_meta - Ring-buffer Meta-page description > + * @entries: Number of entries in the ring-buffer. > + * @overrun: Number of entries lost in the ring-buffer. > + * @read:Number of entries that have been read. > + * @subbufs_touched: Number of subbufs that have been filled. > + * @subbufs_lost:Number of subbufs lost to overrun. > + * @subbufs_read:Number of subbufs that have been read. > + * @reader.lost_events: Number of events lost at the time of the reader > swap. > + * @reader.id: subbuf ID of the current reader. From 0 to > @nr_subbufs - 1 > + * @reader.read: Number of bytes read on the reader subbuf. > + * @subbuf_size: Size of each subbuf, including the header. > + * @nr_subbufs: Number of subbfs in the ring-buffer. > + * @meta_page_size: Size of this meta-page. > + * @meta_struct_len: Size of this structure. > + */ > +struct trace_buffer_meta { > + unsigned long entries; > + unsigned long overrun; > + unsigned long read; > + > + unsigned long subbufs_touched; > + unsigned long subbufs_lost; > + unsigned long subbufs_read; > + > + struct { > + unsigned long lost_events; > + __u32 id; > + __u32 read; > + } reader; > + > + __u32 subbuf_size; > + __u32 nr_subbufs; > + > + __u32 meta_page_size; > + __u32 meta_struct_len; > +}; > + > +#endif /* _TRACE_MMAP_H_ */ > diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c > index db73e326fa04..e9ff1c95e896 100644 > --- a/kernel/trace/ring_buffer.c > +++ b/kernel/trace/ring_buffer.c > @@ -338,6 +338,7 @@ struct buffer_page { > local_t entries; /* entries on this page */ > unsigned longreal_end; /* real end of data */ > unsigned order; /* order of the page */ > + u32 id;/* ID for external mapping */ > struct buffer_data_page *page; /* Actual data page */ > }; > > @@ -484,6 +485,12 @@ struct ring_buffer_per_cpu { > u64 read_stamp; > /* pages removed since last reset */ > unsigned long pages_removed; > + > + int mapped; > + struct mutexmapping_lock; > + unsigned long *subbuf_ids;/* ID to addr */ > + struct trace_buffer_meta*meta_page; > + > /* ring buffer pages to update, > 0 to add, < 0 to remove */ > longnr_pages_to_update; > struct list_headnew_pages; /* new pages to add */ > @@ -1542,6 +1549,7 @@ rb_allocate_cpu_buffer(struct
[GIT PULL] hwspinlock updates to v6.8
The following changes since commit b85ea95d086471afb4ad062012a4d73cd328fa86: Linux 6.7-rc1 (2023-11-12 16:19:07 -0800) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux.git tags/hwlock-v6.8 for you to fetch changes up to bcd0f5d18b0b1134ccf9ef68e7a0cf637aab380d: hwspinlock/core: fix kernel-doc warnings (2023-12-07 14:51:38 -0800) hwspinlock updates to v6.8 Correct kernel-doc through the hwspinlock core, to address build warnings (and improve the documentation). Drop unused compatible in the Qualcomm TCSR mutex driver. Randy Dunlap (1): hwspinlock/core: fix kernel-doc warnings Vignesh Viswanathan (1): hwspinlock: qcom: Remove IPQ6018 SOC specific compatible drivers/hwspinlock/hwspinlock_core.c | 53 drivers/hwspinlock/qcom_hwspinlock.c | 1 - 2 files changed, 29 insertions(+), 25 deletions(-)
[GIT PULL] remoteproc updates for v6.8
The following changes since commit 98b1cc82c4affc16f5598d4fa14b1858671b2263: Linux 6.7-rc2 (2023-11-19 15:02:14 -0800) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux.git tags/rproc-v6.8 for you to fetch changes up to 300ed425dfa99f6926299ec196a1eedf05f47b21: remoteproc: qcom_q6v5_pas: Add SC7280 ADSP, CDSP & WPSS (2023-12-17 10:06:32 -0800) remoteproc updates for v6.8 The i.MX DSP remoteproc driver adds support for providing a resource table, in order to enable IPC with the core. The TI K3 DSP driver is transitioned to remove_new, error messages are changed to use symbolic error codes, and dev_err_probe() is used where applicable. Support for the Qualcomm SC7280 audio, compute and WiFi co-processors are added to the Qualcomm TrustZone based remoteproc driver. Iuliana Prodan (2): remoteproc: imx_dsp_rproc: Add mandatory find_loaded_rsc_table op arm64: dts: imx8mp: Add reserve-memory nodes for DSP Luca Weiss (3): dt-bindings: remoteproc: qcom: sc7180-pas: Fix SC7280 MPSS PD-names dt-bindings: remoteproc: qcom: sc7180-pas: Add SC7280 compatibles remoteproc: qcom_q6v5_pas: Add SC7280 ADSP, CDSP & WPSS Uwe Kleine-König (3): remoteproc: k3-dsp: Suppress duplicate error message in .remove() remoteproc: k3-dsp: Use symbolic error codes in error messages remoteproc: k3-dsp: Convert to platform remove callback returning void .../bindings/remoteproc/qcom,sc7180-pas.yaml | 21 ++ arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 22 ++ drivers/remoteproc/imx_dsp_rproc.c | 1 + drivers/remoteproc/qcom_q6v5_pas.c | 19 + drivers/remoteproc/ti_k3_dsp_remoteproc.c | 87 ++ 5 files changed, 101 insertions(+), 49 deletions(-)
[GIT PULL] rpmsg updates for v6.8
The following changes since commit 98b1cc82c4affc16f5598d4fa14b1858671b2263: Linux 6.7-rc2 (2023-11-19 15:02:14 -0800) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux.git tags/rpmsg-v6.8 for you to fetch changes up to d5362c37e1f8a40096452fc201c30e705750e687: rpmsg: virtio: Free driver_override when rpmsg_remove() (2023-12-18 10:56:03 -0700) rpmsg updates for v6.8 This make virtio free driver_override upon removal. It also updates the rpmsg documentation after earlier API updates. Adrien Leravat (1): doc: rmpsg: Update with rpmsg_endpoint Xiaolei Wang (1): rpmsg: virtio: Free driver_override when rpmsg_remove() Documentation/staging/rpmsg.rst | 50 ++-- drivers/rpmsg/virtio_rpmsg_bus.c | 1 + 2 files changed, 28 insertions(+), 23 deletions(-)
Re: [PATCH v11 4/5] Documentation: tracing: Add ring-buffer mapping
On Sun, 14 Jan 2024 11:23:24 -0500 Steven Rostedt wrote: > On Sun, 14 Jan 2024 23:26:43 +0900 > Masami Hiramatsu (Google) wrote: > > > Hi Vincent, > > > > On Thu, 11 Jan 2024 16:17:11 + > > Vincent Donnefort wrote: > > > > > It is now possible to mmap() a ring-buffer to stream its content. Add > > > some documentation and a code example. > > > > > > Signed-off-by: Vincent Donnefort > > > > > > diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst > > > index 5092d6c13af5..0b300901fd75 100644 > > > --- a/Documentation/trace/index.rst > > > +++ b/Documentation/trace/index.rst > > > @@ -29,6 +29,7 @@ Linux Tracing Technologies > > > timerlat-tracer > > > intel_th > > > ring-buffer-design > > > + ring-buffer-map > > > stm > > > sys-t > > > coresight/index > > > diff --git a/Documentation/trace/ring-buffer-map.rst > > > b/Documentation/trace/ring-buffer-map.rst > > > new file mode 100644 > > > index ..2ba7b5339178 > > > --- /dev/null > > > +++ b/Documentation/trace/ring-buffer-map.rst > > > @@ -0,0 +1,105 @@ > > > +.. SPDX-License-Identifier: GPL-2.0 > > > + > > > +== > > > +Tracefs ring-buffer memory mapping > > > +== > > > + > > > +:Author: Vincent Donnefort > > > + > > > +Overview > > > + > > > +Tracefs ring-buffer memory map provides an efficient method to stream > > > data > > > +as no memory copy is necessary. The application mapping the ring-buffer > > > becomes > > > +then a consumer for that ring-buffer, in a similar fashion to trace_pipe. > > > + > > > +Memory mapping setup > > > + > > > +The mapping works with a mmap() of the trace_pipe_raw interface. > > > + > > > +The first system page of the mapping contains ring-buffer statistics and > > > +description. It is referred as the meta-page. One of the most important > > > field of > > > +the meta-page is the reader. It contains the subbuf ID which can be > > > safely read > > > +by the mapper (see ring-buffer-design.rst). > > > + > > > +The meta-page is followed by all the subbuf, ordered by ascendant ID. It > > > is > > > +therefore effortless to know where the reader starts in the mapping: > > > + > > > +.. code-block:: c > > > + > > > +reader_id = meta->reader->id; > > > +reader_offset = meta->meta_page_size + reader_id * > > > meta->subbuf_size; > > > + > > > +When the application is done with the current reader, it can get a new > > > one using > > > +the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also > > > updates > > > +the meta-page fields. > > > + > > > +Limitations > > > +=== > > > +When a mapping is in place on a Tracefs ring-buffer, it is not possible > > > to > > > +either resize it (either by increasing the entire size of the > > > ring-buffer or > > > +each subbuf). It is also not possible to use snapshot or splice. > > > > I've played with the sample code. > > > > - "free_buffer" just doesn't work when the process is mmap the ring buffer. > > - After mmap the buffers, when the snapshot took, the IOCTL returns an > > error. > > > > OK, but I rather like to fail snapshot with -EBUSY when the buffer is > > mmaped. > > > > > + > > > +Concurrent readers (either another application mapping that ring-buffer > > > or the > > > +kernel with trace_pipe) are allowed but not recommended. They will > > > compete for > > > +the ring-buffer and the output is unpredictable. > > > + > > > +Example > > > +=== > > > + > > > +.. code-block:: c > > > + > > > +#include > > > +#include > > > +#include > > > +#include > > > + > > > +#include > > > + > > > +#include > > > +#include > > > + > > > +#define TRACE_PIPE_RAW > > > "/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw" > > > + > > > +int main(void) > > > +{ > > > +int page_size = getpagesize(), fd, reader_id; > > > +unsigned long meta_len, data_len; > > > +struct trace_buffer_meta *meta; > > > +void *map, *reader, *data; > > > + > > > +fd = open(TRACE_PIPE_RAW, O_RDONLY); > > > +if (fd < 0) > > > +exit(EXIT_FAILURE); > > > + > > > +map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, > > > 0); > > > +if (map == MAP_FAILED) > > > +exit(EXIT_FAILURE); > > > + > > > +meta = (struct trace_buffer_meta *)map; > > > +meta_len = meta->meta_page_size; > > > + > > > +printf("entries:%lu\n", meta->entries); > > > +printf("overrun:%lu\n", meta->overrun); > > > +printf("read: %lu\n", meta->read); > > > +printf("subbufs_touched:%lu\n", meta->subbufs_touched); > > > +printf("subbufs_lost:
Re: [PATCH v11 4/5] Documentation: tracing: Add ring-buffer mapping
On Sun, 14 Jan 2024 23:26:43 +0900 Masami Hiramatsu (Google) wrote: > Hi Vincent, > > On Thu, 11 Jan 2024 16:17:11 + > Vincent Donnefort wrote: > > > It is now possible to mmap() a ring-buffer to stream its content. Add > > some documentation and a code example. > > > > Signed-off-by: Vincent Donnefort > > > > diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst > > index 5092d6c13af5..0b300901fd75 100644 > > --- a/Documentation/trace/index.rst > > +++ b/Documentation/trace/index.rst > > @@ -29,6 +29,7 @@ Linux Tracing Technologies > > timerlat-tracer > > intel_th > > ring-buffer-design > > + ring-buffer-map > > stm > > sys-t > > coresight/index > > diff --git a/Documentation/trace/ring-buffer-map.rst > > b/Documentation/trace/ring-buffer-map.rst > > new file mode 100644 > > index ..2ba7b5339178 > > --- /dev/null > > +++ b/Documentation/trace/ring-buffer-map.rst > > @@ -0,0 +1,105 @@ > > +.. SPDX-License-Identifier: GPL-2.0 > > + > > +== > > +Tracefs ring-buffer memory mapping > > +== > > + > > +:Author: Vincent Donnefort > > + > > +Overview > > + > > +Tracefs ring-buffer memory map provides an efficient method to stream data > > +as no memory copy is necessary. The application mapping the ring-buffer > > becomes > > +then a consumer for that ring-buffer, in a similar fashion to trace_pipe. > > + > > +Memory mapping setup > > + > > +The mapping works with a mmap() of the trace_pipe_raw interface. > > + > > +The first system page of the mapping contains ring-buffer statistics and > > +description. It is referred as the meta-page. One of the most important > > field of > > +the meta-page is the reader. It contains the subbuf ID which can be safely > > read > > +by the mapper (see ring-buffer-design.rst). > > + > > +The meta-page is followed by all the subbuf, ordered by ascendant ID. It is > > +therefore effortless to know where the reader starts in the mapping: > > + > > +.. code-block:: c > > + > > +reader_id = meta->reader->id; > > +reader_offset = meta->meta_page_size + reader_id * > > meta->subbuf_size; > > + > > +When the application is done with the current reader, it can get a new one > > using > > +the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also > > updates > > +the meta-page fields. > > + > > +Limitations > > +=== > > +When a mapping is in place on a Tracefs ring-buffer, it is not possible to > > +either resize it (either by increasing the entire size of the ring-buffer > > or > > +each subbuf). It is also not possible to use snapshot or splice. > > I've played with the sample code. > > - "free_buffer" just doesn't work when the process is mmap the ring buffer. > - After mmap the buffers, when the snapshot took, the IOCTL returns an error. > > OK, but I rather like to fail snapshot with -EBUSY when the buffer is mmaped. > > > + > > +Concurrent readers (either another application mapping that ring-buffer or > > the > > +kernel with trace_pipe) are allowed but not recommended. They will compete > > for > > +the ring-buffer and the output is unpredictable. > > + > > +Example > > +=== > > + > > +.. code-block:: c > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > + > > +#include > > +#include > > + > > +#define TRACE_PIPE_RAW > > "/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw" > > + > > +int main(void) > > +{ > > +int page_size = getpagesize(), fd, reader_id; > > +unsigned long meta_len, data_len; > > +struct trace_buffer_meta *meta; > > +void *map, *reader, *data; > > + > > +fd = open(TRACE_PIPE_RAW, O_RDONLY); > > +if (fd < 0) > > +exit(EXIT_FAILURE); > > + > > +map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); > > +if (map == MAP_FAILED) > > +exit(EXIT_FAILURE); > > + > > +meta = (struct trace_buffer_meta *)map; > > +meta_len = meta->meta_page_size; > > + > > +printf("entries:%lu\n", meta->entries); > > +printf("overrun:%lu\n", meta->overrun); > > +printf("read: %lu\n", meta->read); > > +printf("subbufs_touched:%lu\n", meta->subbufs_touched); > > +printf("subbufs_lost: %lu\n", meta->subbufs_lost); > > +printf("subbufs_read: %lu\n", meta->subbufs_read); > > +printf("nr_subbufs: %u\n", meta->nr_subbufs); > > + > > +data_len = meta->subbuf_size * meta->nr_subbufs; > > +data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, > > data_len); The above is buggy. It
Re: [PATCH v11 4/5] Documentation: tracing: Add ring-buffer mapping
Hi Vincent, On Thu, 11 Jan 2024 16:17:11 + Vincent Donnefort wrote: > It is now possible to mmap() a ring-buffer to stream its content. Add > some documentation and a code example. > > Signed-off-by: Vincent Donnefort > > diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst > index 5092d6c13af5..0b300901fd75 100644 > --- a/Documentation/trace/index.rst > +++ b/Documentation/trace/index.rst > @@ -29,6 +29,7 @@ Linux Tracing Technologies > timerlat-tracer > intel_th > ring-buffer-design > + ring-buffer-map > stm > sys-t > coresight/index > diff --git a/Documentation/trace/ring-buffer-map.rst > b/Documentation/trace/ring-buffer-map.rst > new file mode 100644 > index ..2ba7b5339178 > --- /dev/null > +++ b/Documentation/trace/ring-buffer-map.rst > @@ -0,0 +1,105 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +== > +Tracefs ring-buffer memory mapping > +== > + > +:Author: Vincent Donnefort > + > +Overview > + > +Tracefs ring-buffer memory map provides an efficient method to stream data > +as no memory copy is necessary. The application mapping the ring-buffer > becomes > +then a consumer for that ring-buffer, in a similar fashion to trace_pipe. > + > +Memory mapping setup > + > +The mapping works with a mmap() of the trace_pipe_raw interface. > + > +The first system page of the mapping contains ring-buffer statistics and > +description. It is referred as the meta-page. One of the most important > field of > +the meta-page is the reader. It contains the subbuf ID which can be safely > read > +by the mapper (see ring-buffer-design.rst). > + > +The meta-page is followed by all the subbuf, ordered by ascendant ID. It is > +therefore effortless to know where the reader starts in the mapping: > + > +.. code-block:: c > + > +reader_id = meta->reader->id; > +reader_offset = meta->meta_page_size + reader_id * meta->subbuf_size; > + > +When the application is done with the current reader, it can get a new one > using > +the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also > updates > +the meta-page fields. > + > +Limitations > +=== > +When a mapping is in place on a Tracefs ring-buffer, it is not possible to > +either resize it (either by increasing the entire size of the ring-buffer or > +each subbuf). It is also not possible to use snapshot or splice. I've played with the sample code. - "free_buffer" just doesn't work when the process is mmap the ring buffer. - After mmap the buffers, when the snapshot took, the IOCTL returns an error. OK, but I rather like to fail snapshot with -EBUSY when the buffer is mmaped. > + > +Concurrent readers (either another application mapping that ring-buffer or > the > +kernel with trace_pipe) are allowed but not recommended. They will compete > for > +the ring-buffer and the output is unpredictable. > + > +Example > +=== > + > +.. code-block:: c > + > +#include > +#include > +#include > +#include > + > +#include > + > +#include > +#include > + > +#define TRACE_PIPE_RAW > "/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw" > + > +int main(void) > +{ > +int page_size = getpagesize(), fd, reader_id; > +unsigned long meta_len, data_len; > +struct trace_buffer_meta *meta; > +void *map, *reader, *data; > + > +fd = open(TRACE_PIPE_RAW, O_RDONLY); > +if (fd < 0) > +exit(EXIT_FAILURE); > + > +map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); > +if (map == MAP_FAILED) > +exit(EXIT_FAILURE); > + > +meta = (struct trace_buffer_meta *)map; > +meta_len = meta->meta_page_size; > + > +printf("entries:%lu\n", meta->entries); > +printf("overrun:%lu\n", meta->overrun); > +printf("read: %lu\n", meta->read); > +printf("subbufs_touched:%lu\n", meta->subbufs_touched); > +printf("subbufs_lost: %lu\n", meta->subbufs_lost); > +printf("subbufs_read: %lu\n", meta->subbufs_read); > +printf("nr_subbufs: %u\n", meta->nr_subbufs); > + > +data_len = meta->subbuf_size * meta->nr_subbufs; > +data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, > data_len); > +if (data == MAP_FAILED) > +exit(EXIT_FAILURE); > + > +if (ioctl(fd, TRACE_MMAP_IOCTL_GET_READER) < 0) > +exit(EXIT_FAILURE); > + > +reader_id = meta->reader.id; > +reader = data + meta->subbuf_size * reader_id; Also, this caused a bus error if I add below 2
[PATCH] rpmsg: Remove usage of the deprecated ida_simple_xx() API
ida_alloc() and ida_free() should be preferred to the deprecated ida_simple_get() and ida_simple_remove(). Note that the upper limit of ida_simple_get() is exclusive, but the one of ida_alloc_max() is inclusive. So a -1 has been added when needed. Signed-off-by: Christophe JAILLET --- drivers/rpmsg/rpmsg_char.c | 12 ++-- drivers/rpmsg/rpmsg_ctrl.c | 12 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index 09833ad05da7..1cb8d7474428 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -399,8 +399,8 @@ static void rpmsg_eptdev_release_device(struct device *dev) { struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev); - ida_simple_remove(_ept_ida, dev->id); - ida_simple_remove(_minor_ida, MINOR(eptdev->dev.devt)); + ida_free(_ept_ida, dev->id); + ida_free(_minor_ida, MINOR(eptdev->dev.devt)); kfree(eptdev); } @@ -441,12 +441,12 @@ static int rpmsg_chrdev_eptdev_add(struct rpmsg_eptdev *eptdev, struct rpmsg_cha eptdev->chinfo = chinfo; - ret = ida_simple_get(_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL); + ret = ida_alloc_max(_minor_ida, RPMSG_DEV_MAX - 1, GFP_KERNEL); if (ret < 0) goto free_eptdev; dev->devt = MKDEV(MAJOR(rpmsg_major), ret); - ret = ida_simple_get(_ept_ida, 0, 0, GFP_KERNEL); + ret = ida_alloc(_ept_ida, GFP_KERNEL); if (ret < 0) goto free_minor_ida; dev->id = ret; @@ -462,9 +462,9 @@ static int rpmsg_chrdev_eptdev_add(struct rpmsg_eptdev *eptdev, struct rpmsg_cha return ret; free_ept_ida: - ida_simple_remove(_ept_ida, dev->id); + ida_free(_ept_ida, dev->id); free_minor_ida: - ida_simple_remove(_minor_ida, MINOR(dev->devt)); + ida_free(_minor_ida, MINOR(dev->devt)); free_eptdev: put_device(dev); kfree(eptdev); diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c index 433253835690..c312794ba4b3 100644 --- a/drivers/rpmsg/rpmsg_ctrl.c +++ b/drivers/rpmsg/rpmsg_ctrl.c @@ -130,8 +130,8 @@ static void rpmsg_ctrldev_release_device(struct device *dev) { struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev); - ida_simple_remove(_ctrl_ida, dev->id); - ida_simple_remove(_minor_ida, MINOR(dev->devt)); + ida_free(_ctrl_ida, dev->id); + ida_free(_minor_ida, MINOR(dev->devt)); kfree(ctrldev); } @@ -156,12 +156,12 @@ static int rpmsg_ctrldev_probe(struct rpmsg_device *rpdev) cdev_init(>cdev, _ctrldev_fops); ctrldev->cdev.owner = THIS_MODULE; - ret = ida_simple_get(_minor_ida, 0, RPMSG_DEV_MAX, GFP_KERNEL); + ret = ida_alloc_max(_minor_ida, RPMSG_DEV_MAX - 1, GFP_KERNEL); if (ret < 0) goto free_ctrldev; dev->devt = MKDEV(MAJOR(rpmsg_major), ret); - ret = ida_simple_get(_ctrl_ida, 0, 0, GFP_KERNEL); + ret = ida_alloc(_ctrl_ida, GFP_KERNEL); if (ret < 0) goto free_minor_ida; dev->id = ret; @@ -179,9 +179,9 @@ static int rpmsg_ctrldev_probe(struct rpmsg_device *rpdev) return ret; free_ctrl_ida: - ida_simple_remove(_ctrl_ida, dev->id); + ida_free(_ctrl_ida, dev->id); free_minor_ida: - ida_simple_remove(_minor_ida, MINOR(dev->devt)); + ida_free(_minor_ida, MINOR(dev->devt)); free_ctrldev: put_device(dev); kfree(ctrldev); -- 2.43.0