Merge remote-tracking branch into HEAD

* keystone/mirror-android12-5.10-2022-07: (72 commits)
  ANDROID: Guard hooks with their CONFIG_ options
  FROMGIT: binder: fix redefinition of seq_file attributes
  ANDROID: vendor_hook: Add hook in shmem_writepage()
  BACKPORT: iommu/dma: Fix race condition during iova_domain initialization
  FROMGIT: usb: dwc3: core: Deprecate GCTL.CORESOFTRESET
  FROMGIT: usb: dwc3: gadget: Prevent repeat pullup()
  FROMGIT: Binder: add TF_UPDATE_TXN to replace outdated txn
  BACKPORT: FROMGIT: cgroup: Use separate src/dst nodes when preloading css_sets for migration
  UPSTREAM: usb: gadget: f_uac2: allow changing interface name via configfs
  UPSTREAM: usb: gadget: f_uac1: allow changing interface name via configfs
  UPSTREAM: usb: gadget: f_uac1: Add suspend callback
  UPSTREAM: usb: gadget: f_uac2: Add suspend callback
  UPSTREAM: usb: gadget: u_audio: Add suspend call
  UPSTREAM: usb: gadget: u_audio: Rate ctl notifies about current srate (0=stopped)
  UPSTREAM: usb: gadget: f_uac1: Support multiple sampling rates
  UPSTREAM: usb: gadget: f_uac2: Support multiple sampling rates
  UPSTREAM: usb: gadget:audio: Replace deprecated macro S_IRUGO
  UPSTREAM: usb: gadget: u_audio: Add capture/playback srate getter
  UPSTREAM: usb: gadget: u_audio: Move dynamic srate from params to rtd
  UPSTREAM: usb: gadget: u_audio: Support multiple sampling rates
  ...

Signed-off-by: deyaoren@google.com <deyaoren@google.com>
Change-Id: Ic96b04dbb9844d4f7284090a39ea701b15f41f09
This commit is contained in:
deyaoren@google.com
2022-08-03 17:32:52 +00:00
81 changed files with 6581 additions and 2566 deletions

View File

@@ -4,13 +4,30 @@ KernelVersion: 4.14
Description: Description:
The attributes: The attributes:
========== =================================== ===================== =======================================
c_chmask capture channel mask c_chmask capture channel mask
c_srate capture sampling rate c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes) c_ssize capture sample size (bytes)
p_chmask playback channel mask c_mute_present capture mute control enable
p_srate playback sampling rate c_volume_present capture volume control enable
p_ssize playback sample size (bytes) c_volume_min capture volume control min value
req_number the number of pre-allocated request (in 1/256 dB)
for both capture and playback c_volume_max capture volume control max value
========== =================================== (in 1/256 dB)
c_volume_res capture volume control resolution
(in 1/256 dB)
p_chmask playback channel mask
p_srate list of playback sampling rates (comma-separated)
p_ssize playback sample size (bytes)
p_mute_present playback mute control enable
p_volume_present playback volume control enable
p_volume_min playback volume control min value
(in 1/256 dB)
p_volume_max playback volume control max value
(in 1/256 dB)
p_volume_res playback volume control resolution
(in 1/256 dB)
req_number the number of pre-allocated requests
for both capture and playback
function_name name of the interface
===================== =======================================

View File

@@ -4,13 +4,33 @@ KernelVersion: 3.18
Description: Description:
The attributes: The attributes:
========= ============================ ===================== =======================================
c_chmask capture channel mask c_chmask capture channel mask
c_srate capture sampling rate c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes) c_ssize capture sample size (bytes)
c_sync capture synchronization type (async/adaptive) c_sync capture synchronization type
fb_max maximum extra bandwidth in async mode (async/adaptive)
p_chmask playback channel mask c_mute_present capture mute control enable
p_srate playback sampling rate c_volume_present capture volume control enable
p_ssize playback sample size (bytes) c_volume_min capture volume control min value
========= ============================ (in 1/256 dB)
c_volume_max capture volume control max value
(in 1/256 dB)
c_volume_res capture volume control resolution
(in 1/256 dB)
fb_max maximum extra bandwidth in async mode
p_chmask playback channel mask
p_srate list of playback sampling rates (comma-separated)
p_ssize playback sample size (bytes)
p_mute_present playback mute control enable
p_volume_present playback volume control enable
p_volume_min playback volume control min value
(in 1/256 dB)
p_volume_max playback volume control max value
(in 1/256 dB)
p_volume_res playback volume control resolution
(in 1/256 dB)
req_number the number of pre-allocated requests
for both capture and playback
function_name name of the interface
===================== =======================================

View File

@@ -724,18 +724,29 @@ Function-specific configfs interface
The function name to use when creating the function directory is "uac2". The function name to use when creating the function directory is "uac2".
The uac2 function provides these attributes in its function directory: The uac2 function provides these attributes in its function directory:
=============== ==================================================== ================ ====================================================
c_chmask capture channel mask c_chmask capture channel mask
c_srate capture sampling rate c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes) c_ssize capture sample size (bytes)
c_sync capture synchronization type (async/adaptive) c_sync capture synchronization type (async/adaptive)
fb_max maximum extra bandwidth in async mode c_mute_present capture mute control enable
p_chmask playback channel mask c_volume_present capture volume control enable
p_srate playback sampling rate c_volume_min capture volume control min value (in 1/256 dB)
p_ssize playback sample size (bytes) c_volume_max capture volume control max value (in 1/256 dB)
req_number the number of pre-allocated request for both capture c_volume_res capture volume control resolution (in 1/256 dB)
and playback fb_max maximum extra bandwidth in async mode
=============== ==================================================== p_chmask playback channel mask
p_srate list of playback sampling rates (comma-separated)
p_ssize playback sample size (bytes)
p_mute_present playback mute control enable
p_volume_present playback volume control enable
p_volume_min playback volume control min value (in 1/256 dB)
p_volume_max playback volume control max value (in 1/256 dB)
p_volume_res playback volume control resolution (in 1/256 dB)
req_number the number of pre-allocated request for both capture
and playback
function_name name of the interface
================ ====================================================
The attributes have sane default values. The attributes have sane default values.
@@ -905,16 +916,27 @@ Function-specific configfs interface
The function name to use when creating the function directory is "uac1". The function name to use when creating the function directory is "uac1".
The uac1 function provides these attributes in its function directory: The uac1 function provides these attributes in its function directory:
========== ==================================================== ================ ====================================================
c_chmask capture channel mask c_chmask capture channel mask
c_srate capture sampling rate c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes) c_ssize capture sample size (bytes)
p_chmask playback channel mask c_mute_present capture mute control enable
p_srate playback sampling rate c_volume_present capture volume control enable
p_ssize playback sample size (bytes) c_volume_min capture volume control min value (in 1/256 dB)
req_number the number of pre-allocated request for both capture c_volume_max capture volume control max value (in 1/256 dB)
and playback c_volume_res capture volume control resolution (in 1/256 dB)
========== ==================================================== p_chmask playback channel mask
p_srate list of playback sampling rates (comma-separated)
p_ssize playback sample size (bytes)
p_mute_present playback mute control enable
p_volume_present playback volume control enable
p_volume_min playback volume control min value (in 1/256 dB)
p_volume_max playback volume control max value (in 1/256 dB)
p_volume_res playback volume control resolution (in 1/256 dB)
req_number the number of pre-allocated requests for both capture
and playback
function_name name of the interface
================ ====================================================
The attributes have sane default values. The attributes have sane default values.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
[abi_symbol_list]
get_mem_cgroup_from_mm
is_swap_slot_cache_enabled
swapcache_free_entries
swap_type_to_swap_info
scan_swap_map_slots
swap_alloc_cluster
check_cache_active

View File

@@ -29,6 +29,7 @@ android/abi_gki_aarch64_virtual_device
android/abi_gki_aarch64_vivo android/abi_gki_aarch64_vivo
android/abi_gki_aarch64_xiaomi android/abi_gki_aarch64_xiaomi
android/abi_gki_aarch64_asus android/abi_gki_aarch64_asus
android/abi_gki_aarch64_transsion
" "
FILES="${FILES} FILES="${FILES}

View File

@@ -173,8 +173,32 @@ static inline void binder_stats_created(enum binder_stat_types type)
atomic_inc(&binder_stats.obj_created[type]); atomic_inc(&binder_stats.obj_created[type]);
} }
struct binder_transaction_log binder_transaction_log; struct binder_transaction_log_entry {
struct binder_transaction_log binder_transaction_log_failed; int debug_id;
int debug_id_done;
int call_type;
int from_proc;
int from_thread;
int target_handle;
int to_proc;
int to_thread;
int to_node;
int data_size;
int offsets_size;
int return_error_line;
uint32_t return_error;
uint32_t return_error_param;
char context_name[BINDERFS_MAX_NAME + 1];
};
struct binder_transaction_log {
atomic_t cur;
bool full;
struct binder_transaction_log_entry entry[32];
};
static struct binder_transaction_log binder_transaction_log;
static struct binder_transaction_log binder_transaction_log_failed;
static struct binder_transaction_log_entry *binder_transaction_log_add( static struct binder_transaction_log_entry *binder_transaction_log_add(
struct binder_transaction_log *log) struct binder_transaction_log *log)
@@ -2464,6 +2488,56 @@ static int binder_fixup_parent(struct binder_transaction *t,
return 0; return 0;
} }
/**
* binder_can_update_transaction() - Can a txn be superseded by an updated one?
* @t1: the pending async txn in the frozen process
* @t2: the new async txn to supersede the outdated pending one
*
* Return: true if t2 can supersede t1
* false if t2 can not supersede t1
*/
static bool binder_can_update_transaction(struct binder_transaction *t1,
struct binder_transaction *t2)
{
if ((t1->flags & t2->flags & (TF_ONE_WAY | TF_UPDATE_TXN)) !=
(TF_ONE_WAY | TF_UPDATE_TXN) || !t1->to_proc || !t2->to_proc)
return false;
if (t1->to_proc->tsk == t2->to_proc->tsk && t1->code == t2->code &&
t1->flags == t2->flags && t1->buffer->pid == t2->buffer->pid &&
t1->buffer->target_node->ptr == t2->buffer->target_node->ptr &&
t1->buffer->target_node->cookie == t2->buffer->target_node->cookie)
return true;
return false;
}
/**
* binder_find_outdated_transaction_ilocked() - Find the outdated transaction
* @t: new async transaction
* @target_list: list to find outdated transaction
*
* Return: the outdated transaction if found
* NULL if no outdated transacton can be found
*
* Requires the proc->inner_lock to be held.
*/
static struct binder_transaction *
binder_find_outdated_transaction_ilocked(struct binder_transaction *t,
struct list_head *target_list)
{
struct binder_work *w;
list_for_each_entry(w, target_list, entry) {
struct binder_transaction *t_queued;
if (w->type != BINDER_WORK_TRANSACTION)
continue;
t_queued = container_of(w, struct binder_transaction, work);
if (binder_can_update_transaction(t_queued, t))
return t_queued;
}
return NULL;
}
/** /**
* binder_proc_transaction() - sends a transaction to a process and wakes it up * binder_proc_transaction() - sends a transaction to a process and wakes it up
* @t: transaction to send * @t: transaction to send
@@ -2491,6 +2565,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
bool oneway = !!(t->flags & TF_ONE_WAY); bool oneway = !!(t->flags & TF_ONE_WAY);
bool pending_async = false; bool pending_async = false;
bool skip = false; bool skip = false;
struct binder_transaction *t_outdated = NULL;
BUG_ON(!node); BUG_ON(!node);
binder_node_lock(node); binder_node_lock(node);
@@ -2534,6 +2609,17 @@ static int binder_proc_transaction(struct binder_transaction *t,
} else if (!pending_async) { } else if (!pending_async) {
binder_enqueue_work_ilocked(&t->work, &proc->todo); binder_enqueue_work_ilocked(&t->work, &proc->todo);
} else { } else {
if ((t->flags & TF_UPDATE_TXN) && proc->is_frozen) {
t_outdated = binder_find_outdated_transaction_ilocked(t,
&node->async_todo);
if (t_outdated) {
binder_debug(BINDER_DEBUG_TRANSACTION,
"txn %d supersedes %d\n",
t->debug_id, t_outdated->debug_id);
list_del_init(&t_outdated->work.entry);
proc->outstanding_txns--;
}
}
binder_enqueue_work_ilocked(&t->work, &node->async_todo); binder_enqueue_work_ilocked(&t->work, &node->async_todo);
} }
@@ -2547,6 +2633,22 @@ static int binder_proc_transaction(struct binder_transaction *t,
binder_inner_proc_unlock(proc); binder_inner_proc_unlock(proc);
binder_node_unlock(node); binder_node_unlock(node);
/*
* To reduce potential contention, free the outdated transaction and
* buffer after releasing the locks.
*/
if (t_outdated) {
struct binder_buffer *buffer = t_outdated->buffer;
t_outdated->buffer = NULL;
buffer->transaction = NULL;
trace_binder_transaction_update_buffer_release(buffer);
binder_transaction_buffer_release(proc, NULL, buffer, 0, 0);
binder_alloc_free_buf(&proc->alloc, buffer);
kfree(t_outdated);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
}
return 0; return 0;
} }
@@ -5950,8 +6052,7 @@ static void print_binder_proc_stats(struct seq_file *m,
print_binder_stats(m, " ", &proc->stats); print_binder_stats(m, " ", &proc->stats);
} }
static int state_show(struct seq_file *m, void *unused)
int binder_state_show(struct seq_file *m, void *unused)
{ {
struct binder_proc *proc; struct binder_proc *proc;
struct binder_node *node; struct binder_node *node;
@@ -5990,7 +6091,7 @@ int binder_state_show(struct seq_file *m, void *unused)
return 0; return 0;
} }
int binder_stats_show(struct seq_file *m, void *unused) static int stats_show(struct seq_file *m, void *unused)
{ {
struct binder_proc *proc; struct binder_proc *proc;
@@ -6006,7 +6107,7 @@ int binder_stats_show(struct seq_file *m, void *unused)
return 0; return 0;
} }
int binder_transactions_show(struct seq_file *m, void *unused) static int transactions_show(struct seq_file *m, void *unused)
{ {
struct binder_proc *proc; struct binder_proc *proc;
@@ -6062,7 +6163,7 @@ static void print_binder_transaction_log_entry(struct seq_file *m,
"\n" : " (incomplete)\n"); "\n" : " (incomplete)\n");
} }
int binder_transaction_log_show(struct seq_file *m, void *unused) static int transaction_log_show(struct seq_file *m, void *unused)
{ {
struct binder_transaction_log *log = m->private; struct binder_transaction_log *log = m->private;
unsigned int log_cur = atomic_read(&log->cur); unsigned int log_cur = atomic_read(&log->cur);
@@ -6094,6 +6195,45 @@ const struct file_operations binder_fops = {
.release = binder_release, .release = binder_release,
}; };
DEFINE_SHOW_ATTRIBUTE(state);
DEFINE_SHOW_ATTRIBUTE(stats);
DEFINE_SHOW_ATTRIBUTE(transactions);
DEFINE_SHOW_ATTRIBUTE(transaction_log);
const struct binder_debugfs_entry binder_debugfs_entries[] = {
{
.name = "state",
.mode = 0444,
.fops = &state_fops,
.data = NULL,
},
{
.name = "stats",
.mode = 0444,
.fops = &stats_fops,
.data = NULL,
},
{
.name = "transactions",
.mode = 0444,
.fops = &transactions_fops,
.data = NULL,
},
{
.name = "transaction_log",
.mode = 0444,
.fops = &transaction_log_fops,
.data = &binder_transaction_log,
},
{
.name = "failed_transaction_log",
.mode = 0444,
.fops = &transaction_log_fops,
.data = &binder_transaction_log_failed,
},
{} /* terminator */
};
static int __init init_binder_device(const char *name) static int __init init_binder_device(const char *name)
{ {
int ret; int ret;
@@ -6139,36 +6279,18 @@ static int __init binder_init(void)
atomic_set(&binder_transaction_log_failed.cur, ~0U); atomic_set(&binder_transaction_log_failed.cur, ~0U);
binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
if (binder_debugfs_dir_entry_root) if (binder_debugfs_dir_entry_root) {
const struct binder_debugfs_entry *db_entry;
binder_for_each_debugfs_entry(db_entry)
debugfs_create_file(db_entry->name,
db_entry->mode,
binder_debugfs_dir_entry_root,
db_entry->data,
db_entry->fops);
binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
binder_debugfs_dir_entry_root); binder_debugfs_dir_entry_root);
if (binder_debugfs_dir_entry_root) {
debugfs_create_file("state",
0444,
binder_debugfs_dir_entry_root,
NULL,
&binder_state_fops);
debugfs_create_file("stats",
0444,
binder_debugfs_dir_entry_root,
NULL,
&binder_stats_fops);
debugfs_create_file("transactions",
0444,
binder_debugfs_dir_entry_root,
NULL,
&binder_transactions_fops);
debugfs_create_file("transaction_log",
0444,
binder_debugfs_dir_entry_root,
&binder_transaction_log,
&binder_transaction_log_fops);
debugfs_create_file("failed_transaction_log",
0444,
binder_debugfs_dir_entry_root,
&binder_transaction_log_failed,
&binder_transaction_log_fops);
} }
if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) && if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) &&

View File

@@ -107,41 +107,19 @@ static inline int __init init_binderfs(void)
} }
#endif #endif
int binder_stats_show(struct seq_file *m, void *unused); struct binder_debugfs_entry {
DEFINE_SHOW_ATTRIBUTE(binder_stats); const char *name;
umode_t mode;
int binder_state_show(struct seq_file *m, void *unused); const struct file_operations *fops;
DEFINE_SHOW_ATTRIBUTE(binder_state); void *data;
int binder_transactions_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_transactions);
int binder_transaction_log_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_transaction_log);
struct binder_transaction_log_entry {
int debug_id;
int debug_id_done;
int call_type;
int from_proc;
int from_thread;
int target_handle;
int to_proc;
int to_thread;
int to_node;
int data_size;
int offsets_size;
int return_error_line;
uint32_t return_error;
uint32_t return_error_param;
char context_name[BINDERFS_MAX_NAME + 1];
}; };
struct binder_transaction_log { extern const struct binder_debugfs_entry binder_debugfs_entries[];
atomic_t cur;
bool full; #define binder_for_each_debugfs_entry(entry) \
struct binder_transaction_log_entry entry[32]; for ((entry) = binder_debugfs_entries; \
}; (entry)->name; \
(entry)++)
enum binder_stat_types { enum binder_stat_types {
BINDER_STAT_PROC, BINDER_STAT_PROC,
@@ -620,6 +598,4 @@ struct binder_object {
}; };
}; };
extern struct binder_transaction_log binder_transaction_log;
extern struct binder_transaction_log binder_transaction_log_failed;
#endif /* _LINUX_BINDER_INTERNAL_H */ #endif /* _LINUX_BINDER_INTERNAL_H */

View File

@@ -306,6 +306,10 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
TP_PROTO(struct binder_buffer *buffer), TP_PROTO(struct binder_buffer *buffer),
TP_ARGS(buffer)); TP_ARGS(buffer));
DEFINE_EVENT(binder_buffer_class, binder_transaction_update_buffer_release,
TP_PROTO(struct binder_buffer *buffer),
TP_ARGS(buffer));
TRACE_EVENT(binder_update_page_range, TRACE_EVENT(binder_update_page_range,
TP_PROTO(struct binder_alloc *alloc, bool allocate, TP_PROTO(struct binder_alloc *alloc, bool allocate,
void __user *start, void __user *end), void __user *start, void __user *end),

View File

@@ -584,6 +584,7 @@ out:
static int init_binder_logs(struct super_block *sb) static int init_binder_logs(struct super_block *sb)
{ {
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir; struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
const struct binder_debugfs_entry *db_entry;
struct binderfs_info *info; struct binderfs_info *info;
int ret = 0; int ret = 0;
@@ -594,43 +595,15 @@ static int init_binder_logs(struct super_block *sb)
goto out; goto out;
} }
dentry = binderfs_create_file(binder_logs_root_dir, "stats", binder_for_each_debugfs_entry(db_entry) {
&binder_stats_fops, NULL); dentry = binderfs_create_file(binder_logs_root_dir,
if (IS_ERR(dentry)) { db_entry->name,
ret = PTR_ERR(dentry); db_entry->fops,
goto out; db_entry->data);
} if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
dentry = binderfs_create_file(binder_logs_root_dir, "state", goto out;
&binder_state_fops, NULL); }
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir, "transactions",
&binder_transactions_fops, NULL);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir,
"transaction_log",
&binder_transaction_log_fops,
&binder_transaction_log);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir,
"failed_transaction_log",
&binder_transaction_log_fops,
&binder_transaction_log_failed);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
} }
proc_log_dir = binderfs_create_dir(binder_logs_root_dir, "proc"); proc_log_dir = binderfs_create_dir(binder_logs_root_dir, "proc");

View File

@@ -407,3 +407,27 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_tlb_conf);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_node_memcgs); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_node_memcgs);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ra_tuning_max_page); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ra_tuning_max_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_memcg_scan_type); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_memcg_scan_type);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_pte_fault_end);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cow_user_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapin_add_anon_rmap);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_waiting_for_page_migration);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_migrate_page_states);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_referenced_one_end);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_pswpin);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_pswpout);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_swpout_vm_event);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swap_slot_cache_active);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_drain_slots_cache_cpu);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_swap_slot_cache);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_swap_slot);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_get_swap_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_isolated_for_reclaim);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_inactive_is_low);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_snapshot_refaults);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_account_swap_pages);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_unuse_swap_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_init_swap_info_struct);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_si_swapinfo);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_si);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_shmem_page_flag);

View File

@@ -29,6 +29,47 @@ struct devcd_entry {
struct device devcd_dev; struct device devcd_dev;
void *data; void *data;
size_t datalen; size_t datalen;
/*
* Here, mutex is required to serialize the calls to del_wk work between
* user/kernel space which happens when devcd is added with device_add()
* and that sends uevent to user space. User space reads the uevents,
* and calls to devcd_data_write() which try to modify the work which is
* not even initialized/queued from devcoredump.
*
*
*
* cpu0(X) cpu1(Y)
*
* dev_coredump() uevent sent to user space
* device_add() ======================> user space process Y reads the
* uevents writes to devcd fd
* which results into writes to
*
* devcd_data_write()
* mod_delayed_work()
* try_to_grab_pending()
* del_timer()
* debug_assert_init()
* INIT_DELAYED_WORK()
* schedule_delayed_work()
*
*
* Also, mutex alone would not be enough to avoid scheduling of
* del_wk work after it get flush from a call to devcd_free()
* mentioned as below.
*
* disabled_store()
* devcd_free()
* mutex_lock() devcd_data_write()
* flush_delayed_work()
* mutex_unlock()
* mutex_lock()
* mod_delayed_work()
* mutex_unlock()
* So, delete_work flag is required.
*/
struct mutex mutex;
bool delete_work;
struct module *owner; struct module *owner;
ssize_t (*read)(char *buffer, loff_t offset, size_t count, ssize_t (*read)(char *buffer, loff_t offset, size_t count,
void *data, size_t datalen); void *data, size_t datalen);
@@ -88,7 +129,12 @@ static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj); struct device *dev = kobj_to_dev(kobj);
struct devcd_entry *devcd = dev_to_devcd(dev); struct devcd_entry *devcd = dev_to_devcd(dev);
mod_delayed_work(system_wq, &devcd->del_wk, 0); mutex_lock(&devcd->mutex);
if (!devcd->delete_work) {
devcd->delete_work = true;
mod_delayed_work(system_wq, &devcd->del_wk, 0);
}
mutex_unlock(&devcd->mutex);
return count; return count;
} }
@@ -116,7 +162,12 @@ static int devcd_free(struct device *dev, void *data)
{ {
struct devcd_entry *devcd = dev_to_devcd(dev); struct devcd_entry *devcd = dev_to_devcd(dev);
mutex_lock(&devcd->mutex);
if (!devcd->delete_work)
devcd->delete_work = true;
flush_delayed_work(&devcd->del_wk); flush_delayed_work(&devcd->del_wk);
mutex_unlock(&devcd->mutex);
return 0; return 0;
} }
@@ -126,6 +177,30 @@ static ssize_t disabled_show(struct class *class, struct class_attribute *attr,
return sysfs_emit(buf, "%d\n", devcd_disabled); return sysfs_emit(buf, "%d\n", devcd_disabled);
} }
/*
*
* disabled_store() worker()
* class_for_each_device(&devcd_class,
* NULL, NULL, devcd_free)
* ...
* ...
* while ((dev = class_dev_iter_next(&iter))
* devcd_del()
* device_del()
* put_device() <- last reference
* error = fn(dev, data) devcd_dev_release()
* devcd_free(dev, data) kfree(devcd)
* mutex_lock(&devcd->mutex);
*
*
* In the above diagram, It looks like disabled_store() would be racing with parallely
* running devcd_del() and result in memory abort while acquiring devcd->mutex which
* is called after kfree of devcd memory after dropping its last reference with
* put_device(). However, this will not happens as fn(dev, data) runs
* with its own reference to device via klist_node so it is not its last reference.
* so, above situation would not occur.
*/
static ssize_t disabled_store(struct class *class, struct class_attribute *attr, static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
@@ -282,13 +357,16 @@ void dev_coredumpm(struct device *dev, struct module *owner,
devcd->read = read; devcd->read = read;
devcd->free = free; devcd->free = free;
devcd->failing_dev = get_device(dev); devcd->failing_dev = get_device(dev);
devcd->delete_work = false;
mutex_init(&devcd->mutex);
device_initialize(&devcd->devcd_dev); device_initialize(&devcd->devcd_dev);
dev_set_name(&devcd->devcd_dev, "devcd%d", dev_set_name(&devcd->devcd_dev, "devcd%d",
atomic_inc_return(&devcd_count)); atomic_inc_return(&devcd_count));
devcd->devcd_dev.class = &devcd_class; devcd->devcd_dev.class = &devcd_class;
mutex_lock(&devcd->mutex);
if (device_add(&devcd->devcd_dev)) if (device_add(&devcd->devcd_dev))
goto put_device; goto put_device;
@@ -302,10 +380,11 @@ void dev_coredumpm(struct device *dev, struct module *owner,
INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT); schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
mutex_unlock(&devcd->mutex);
return; return;
put_device: put_device:
put_device(&devcd->devcd_dev); put_device(&devcd->devcd_dev);
mutex_unlock(&devcd->mutex);
put_module: put_module:
module_put(owner); module_put(owner);
free: free:

View File

@@ -50,6 +50,11 @@ struct iommu_dma_cookie {
struct iommu_domain *fq_domain; struct iommu_domain *fq_domain;
}; };
struct iommu_dma_cookie_ext {
struct iommu_dma_cookie cookie;
struct mutex mutex;
};
static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie) static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
{ {
if (cookie->type == IOMMU_DMA_IOVA_COOKIE) if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
@@ -59,14 +64,15 @@ static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type) static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
{ {
struct iommu_dma_cookie *cookie; struct iommu_dma_cookie_ext *cookie;
cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (cookie) { if (cookie) {
INIT_LIST_HEAD(&cookie->msi_page_list); INIT_LIST_HEAD(&cookie->cookie.msi_page_list);
cookie->type = type; cookie->cookie.type = type;
mutex_init(&cookie->mutex);
} }
return cookie; return &cookie->cookie;
} }
/** /**
@@ -305,9 +311,11 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
u64 size, struct device *dev) u64 size, struct device *dev)
{ {
struct iommu_dma_cookie *cookie = domain->iova_cookie; struct iommu_dma_cookie *cookie = domain->iova_cookie;
struct iommu_dma_cookie_ext *cookie_ext;
unsigned long order, base_pfn; unsigned long order, base_pfn;
struct iova_domain *iovad; struct iova_domain *iovad;
int attr; int attr;
int ret;
if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE) if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
return -EINVAL; return -EINVAL;
@@ -331,14 +339,18 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
} }
/* start_pfn is always nonzero for an already-initialised domain */ /* start_pfn is always nonzero for an already-initialised domain */
cookie_ext = container_of(cookie, struct iommu_dma_cookie_ext, cookie);
mutex_lock(&cookie_ext->mutex);
if (iovad->start_pfn) { if (iovad->start_pfn) {
if (1UL << order != iovad->granule || if (1UL << order != iovad->granule ||
base_pfn != iovad->start_pfn) { base_pfn != iovad->start_pfn) {
pr_warn("Incompatible range for DMA domain\n"); pr_warn("Incompatible range for DMA domain\n");
return -EFAULT; ret = -EFAULT;
goto done_unlock;
} }
return 0; ret = 0;
goto done_unlock;
} }
init_iova_domain(iovad, 1UL << order, base_pfn); init_iova_domain(iovad, 1UL << order, base_pfn);
@@ -352,10 +364,16 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
cookie->fq_domain = domain; cookie->fq_domain = domain;
} }
if (!dev) if (!dev) {
return 0; ret = 0;
goto done_unlock;
}
return iova_reserve_iommu_regions(dev, domain); ret = iova_reserve_iommu_regions(dev, domain);
done_unlock:
mutex_unlock(&cookie_ext->mutex);
return ret;
} }
static int iommu_dma_deferred_attach(struct device *dev, static int iommu_dma_deferred_attach(struct device *dev,

View File

@@ -194,6 +194,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
{ {
struct nci_dev *ndev = priv->ndev; struct nci_dev *ndev = priv->ndev;
nci_unregister_device(ndev);
if (priv->ndev->nfc_dev->fw_download_in_progress) if (priv->ndev->nfc_dev->fw_download_in_progress)
nfcmrvl_fw_dnld_abort(priv); nfcmrvl_fw_dnld_abort(priv);
@@ -202,7 +203,6 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
if (gpio_is_valid(priv->config.reset_n_io)) if (gpio_is_valid(priv->config.reset_n_io))
gpio_free(priv->config.reset_n_io); gpio_free(priv->config.reset_n_io);
nci_unregister_device(ndev);
nci_free_device(ndev); nci_free_device(ndev);
kfree(priv); kfree(priv);
} }

View File

@@ -275,6 +275,7 @@ static int usb_conn_probe(struct platform_device *pdev)
} }
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
device_set_wakeup_capable(&pdev->dev, true);
/* Perform initial detection */ /* Perform initial detection */
usb_conn_queue_dwork(info, 0); usb_conn_queue_dwork(info, 0);
@@ -304,6 +305,14 @@ static int __maybe_unused usb_conn_suspend(struct device *dev)
{ {
struct usb_conn_info *info = dev_get_drvdata(dev); struct usb_conn_info *info = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
if (info->id_gpiod)
enable_irq_wake(info->id_irq);
if (info->vbus_gpiod)
enable_irq_wake(info->vbus_irq);
return 0;
}
if (info->id_gpiod) if (info->id_gpiod)
disable_irq(info->id_irq); disable_irq(info->id_irq);
if (info->vbus_gpiod) if (info->vbus_gpiod)
@@ -318,6 +327,14 @@ static int __maybe_unused usb_conn_resume(struct device *dev)
{ {
struct usb_conn_info *info = dev_get_drvdata(dev); struct usb_conn_info *info = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
if (info->id_gpiod)
disable_irq_wake(info->id_irq);
if (info->vbus_gpiod)
disable_irq_wake(info->vbus_irq);
return 0;
}
pinctrl_pm_select_default_state(dev); pinctrl_pm_select_default_state(dev);
if (info->id_gpiod) if (info->id_gpiod)

View File

@@ -157,7 +157,8 @@ static void __dwc3_set_mode(struct work_struct *work)
} }
/* For DRD host or device mode only */ /* For DRD host or device mode only */
if (dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) { if ((DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC31, 190A)) &&
dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) {
reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg |= DWC3_GCTL_CORESOFTRESET; reg |= DWC3_GCTL_CORESOFTRESET;
dwc3_writel(dwc->regs, DWC3_GCTL, reg); dwc3_writel(dwc->regs, DWC3_GCTL, reg);

View File

@@ -2471,6 +2471,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
int ret; int ret;
is_on = !!is_on; is_on = !!is_on;
if (dwc->pullups_connected == is_on)
return 0;
vdwc->softconnect = is_on; vdwc->softconnect = is_on;
/* /*

View File

@@ -122,8 +122,6 @@ struct ffs_ep {
struct usb_endpoint_descriptor *descs[3]; struct usb_endpoint_descriptor *descs[3];
u8 num; u8 num;
int status; /* P: epfile->mutex */
}; };
struct ffs_epfile { struct ffs_epfile {
@@ -227,6 +225,9 @@ struct ffs_io_data {
bool use_sg; bool use_sg;
struct ffs_data *ffs; struct ffs_data *ffs;
int status;
struct completion done;
}; };
struct ffs_desc_helper { struct ffs_desc_helper {
@@ -705,12 +706,15 @@ static const struct file_operations ffs_ep0_operations = {
static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req) static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
{ {
struct ffs_io_data *io_data = req->context;
ENTER(); ENTER();
if (likely(req->context)) { if (req->status)
struct ffs_ep *ep = _ep->driver_data; io_data->status = req->status;
ep->status = req->status ? req->status : req->actual; else
complete(req->context); io_data->status = req->actual;
}
complete(&io_data->done);
} }
static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter) static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter)
@@ -1048,7 +1052,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
WARN(1, "%s: data_len == -EINVAL\n", __func__); WARN(1, "%s: data_len == -EINVAL\n", __func__);
ret = -EINVAL; ret = -EINVAL;
} else if (!io_data->aio) { } else if (!io_data->aio) {
DECLARE_COMPLETION_ONSTACK(done);
bool interrupted = false; bool interrupted = false;
req = ep->req; req = ep->req;
@@ -1064,7 +1067,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
io_data->buf = data; io_data->buf = data;
req->context = &done; init_completion(&io_data->done);
req->context = io_data;
req->complete = ffs_epfile_io_complete; req->complete = ffs_epfile_io_complete;
ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
@@ -1073,7 +1077,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
spin_unlock_irq(&epfile->ffs->eps_lock); spin_unlock_irq(&epfile->ffs->eps_lock);
if (unlikely(wait_for_completion_interruptible(&done))) { if (unlikely(wait_for_completion_interruptible(&io_data->done))) {
spin_lock_irq(&epfile->ffs->eps_lock);
if (epfile->ep != ep) {
ret = -ESHUTDOWN;
goto error_lock;
}
/* /*
* To avoid race condition with ffs_epfile_io_complete, * To avoid race condition with ffs_epfile_io_complete,
* dequeue the request first then check * dequeue the request first then check
@@ -1081,17 +1090,18 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
* condition with req->complete callback. * condition with req->complete callback.
*/ */
usb_ep_dequeue(ep->ep, req); usb_ep_dequeue(ep->ep, req);
wait_for_completion(&done); spin_unlock_irq(&epfile->ffs->eps_lock);
interrupted = ep->status < 0; wait_for_completion(&io_data->done);
interrupted = io_data->status < 0;
} }
if (interrupted) if (interrupted)
ret = -EINTR; ret = -EINTR;
else if (io_data->read && ep->status > 0) else if (io_data->read && io_data->status > 0)
ret = __ffs_epfile_read_data(epfile, data, ep->status, ret = __ffs_epfile_read_data(epfile, data, io_data->status,
&io_data->data); &io_data->data);
else else
ret = ep->status; ret = io_data->status;
goto error_mutex; goto error_mutex;
} else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) {
ret = -ENOMEM; ret = -ENOMEM;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -12,11 +12,14 @@
* Jaswinder Singh (jaswinder.singh@linaro.org) * Jaswinder Singh (jaswinder.singh@linaro.org)
*/ */
#include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/tlv.h>
#include <linux/usb/audio.h>
#include "u_audio.h" #include "u_audio.h"
@@ -24,6 +27,14 @@
#define PRD_SIZE_MAX PAGE_SIZE #define PRD_SIZE_MAX PAGE_SIZE
#define MIN_PERIODS 4 #define MIN_PERIODS 4
enum {
UAC_FBACK_CTRL,
UAC_P_PITCH_CTRL,
UAC_MUTE_CTRL,
UAC_VOLUME_CTRL,
UAC_RATE_CTRL,
};
/* Runtime data params for one stream */ /* Runtime data params for one stream */
struct uac_rtd_params { struct uac_rtd_params {
struct snd_uac_chip *uac; /* parent chip */ struct snd_uac_chip *uac; /* parent chip */
@@ -43,6 +54,21 @@ struct uac_rtd_params {
struct usb_request *req_fback; /* Feedback endpoint request */ struct usb_request *req_fback; /* Feedback endpoint request */
bool fb_ep_enabled; /* if the ep is enabled */ bool fb_ep_enabled; /* if the ep is enabled */
/* Volume/Mute controls and their state */
int fu_id; /* Feature Unit ID */
struct snd_kcontrol *snd_kctl_volume;
struct snd_kcontrol *snd_kctl_mute;
s16 volume_min, volume_max, volume_res;
s16 volume;
int mute;
struct snd_kcontrol *snd_kctl_rate; /* read-only current rate */
int srate; /* selected samplerate */
int active; /* playback/capture running */
spinlock_t lock; /* lock for control transfers */
}; };
struct snd_uac_chip { struct snd_uac_chip {
@@ -54,13 +80,9 @@ struct snd_uac_chip {
struct snd_card *card; struct snd_card *card;
struct snd_pcm *pcm; struct snd_pcm *pcm;
/* timekeeping for the playback endpoint */
unsigned int p_interval;
unsigned int p_residue;
/* pre-calculated values for playback iso completion */ /* pre-calculated values for playback iso completion */
unsigned int p_pktsize; unsigned long long p_residue_mil;
unsigned int p_pktsize_residue; unsigned int p_interval;
unsigned int p_framesize; unsigned int p_framesize;
}; };
@@ -133,6 +155,9 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
struct uac_rtd_params *prm = req->context; struct uac_rtd_params *prm = req->context;
struct snd_uac_chip *uac = prm->uac; struct snd_uac_chip *uac = prm->uac;
unsigned int frames, p_pktsize;
unsigned long long pitched_rate_mil, p_pktsize_residue_mil,
residue_frames_mil, div_result;
/* i/f shutting down */ /* i/f shutting down */
if (!prm->ep_enabled) { if (!prm->ep_enabled) {
@@ -172,19 +197,44 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
* If there is a residue from this division, add it to the * If there is a residue from this division, add it to the
* residue accumulator. * residue accumulator.
*/ */
req->length = uac->p_pktsize; unsigned long long p_interval_mil = uac->p_interval * 1000000ULL;
uac->p_residue += uac->p_pktsize_residue;
pitched_rate_mil = (unsigned long long) prm->srate * prm->pitch;
div_result = pitched_rate_mil;
do_div(div_result, uac->p_interval);
do_div(div_result, 1000000);
frames = (unsigned int) div_result;
pr_debug("p_srate %d, pitch %d, interval_mil %llu, frames %d\n",
prm->srate, prm->pitch, p_interval_mil, frames);
p_pktsize = min_t(unsigned int,
uac->p_framesize * frames,
ep->maxpacket);
if (p_pktsize < ep->maxpacket) {
residue_frames_mil = pitched_rate_mil - frames * p_interval_mil;
p_pktsize_residue_mil = uac->p_framesize * residue_frames_mil;
} else
p_pktsize_residue_mil = 0;
req->length = p_pktsize;
uac->p_residue_mil += p_pktsize_residue_mil;
/* /*
* Whenever there are more bytes in the accumulator than we * Whenever there are more bytes in the accumulator p_residue_mil than we
* need to add one more sample frame, increase this packet's * need to add one more sample frame, increase this packet's
* size and decrease the accumulator. * size and decrease the accumulator.
*/ */
if (uac->p_residue / uac->p_interval >= uac->p_framesize) { div_result = uac->p_residue_mil;
do_div(div_result, uac->p_interval);
do_div(div_result, 1000000);
if ((unsigned int) div_result >= uac->p_framesize) {
req->length += uac->p_framesize; req->length += uac->p_framesize;
uac->p_residue -= uac->p_framesize * uac->p_residue_mil -= uac->p_framesize * p_interval_mil;
uac->p_interval; pr_debug("increased req length to %d\n", req->length);
} }
pr_debug("remains uac->p_residue_mil %llu\n", uac->p_residue_mil);
req->actual = req->length; req->actual = req->length;
} }
@@ -233,7 +283,6 @@ static void u_audio_iso_fback_complete(struct usb_ep *ep,
struct uac_rtd_params *prm = req->context; struct uac_rtd_params *prm = req->context;
struct snd_uac_chip *uac = prm->uac; struct snd_uac_chip *uac = prm->uac;
struct g_audio *audio_dev = uac->audio_dev; struct g_audio *audio_dev = uac->audio_dev;
struct uac_params *params = &audio_dev->params;
int status = req->status; int status = req->status;
/* i/f shutting down */ /* i/f shutting down */
@@ -255,7 +304,7 @@ static void u_audio_iso_fback_complete(struct usb_ep *ep,
__func__, status, req->actual, req->length); __func__, status, req->actual, req->length);
u_audio_set_fback_frequency(audio_dev->gadget->speed, audio_dev->out_ep, u_audio_set_fback_frequency(audio_dev->gadget->speed, audio_dev->out_ep,
params->c_srate, prm->pitch, prm->srate, prm->pitch,
req->buf); req->buf);
if (usb_ep_queue(ep, req, GFP_ATOMIC)) if (usb_ep_queue(ep, req, GFP_ATOMIC))
@@ -339,36 +388,33 @@ static int uac_pcm_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct g_audio *audio_dev; struct g_audio *audio_dev;
struct uac_params *params; struct uac_params *params;
struct uac_rtd_params *prm;
int p_ssize, c_ssize; int p_ssize, c_ssize;
int p_srate, c_srate;
int p_chmask, c_chmask; int p_chmask, c_chmask;
audio_dev = uac->audio_dev; audio_dev = uac->audio_dev;
params = &audio_dev->params; params = &audio_dev->params;
p_ssize = params->p_ssize; p_ssize = params->p_ssize;
c_ssize = params->c_ssize; c_ssize = params->c_ssize;
p_srate = params->p_srate;
c_srate = params->c_srate;
p_chmask = params->p_chmask; p_chmask = params->p_chmask;
c_chmask = params->c_chmask; c_chmask = params->c_chmask;
uac->p_residue = 0; uac->p_residue_mil = 0;
runtime->hw = uac_pcm_hardware; runtime->hw = uac_pcm_hardware;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
runtime->hw.rate_min = p_srate;
runtime->hw.formats = uac_ssize_to_fmt(p_ssize); runtime->hw.formats = uac_ssize_to_fmt(p_ssize);
runtime->hw.channels_min = num_channels(p_chmask); runtime->hw.channels_min = num_channels(p_chmask);
runtime->hw.period_bytes_min = 2 * uac->p_prm.max_psize prm = &uac->p_prm;
/ runtime->hw.periods_min;
} else { } else {
runtime->hw.rate_min = c_srate;
runtime->hw.formats = uac_ssize_to_fmt(c_ssize); runtime->hw.formats = uac_ssize_to_fmt(c_ssize);
runtime->hw.channels_min = num_channels(c_chmask); runtime->hw.channels_min = num_channels(c_chmask);
runtime->hw.period_bytes_min = 2 * uac->c_prm.max_psize prm = &uac->c_prm;
/ runtime->hw.periods_min;
} }
runtime->hw.period_bytes_min = 2 * prm->max_psize
/ runtime->hw.periods_min;
runtime->hw.rate_min = prm->srate;
runtime->hw.rate_max = runtime->hw.rate_min; runtime->hw.rate_max = runtime->hw.rate_min;
runtime->hw.channels_max = runtime->hw.channels_min; runtime->hw.channels_max = runtime->hw.channels_min;
@@ -445,6 +491,99 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep)
dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__); dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
} }
static void set_active(struct uac_rtd_params *prm, bool active)
{
// notifying through the Rate ctrl
struct snd_kcontrol *kctl = prm->snd_kctl_rate;
unsigned long flags;
spin_lock_irqsave(&prm->lock, flags);
if (prm->active != active) {
prm->active = active;
snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
&kctl->id);
}
spin_unlock_irqrestore(&prm->lock, flags);
}
int u_audio_set_capture_srate(struct g_audio *audio_dev, int srate)
{
struct uac_params *params = &audio_dev->params;
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
int i;
unsigned long flags;
dev_dbg(&audio_dev->gadget->dev, "%s: srate %d\n", __func__, srate);
prm = &uac->c_prm;
for (i = 0; i < UAC_MAX_RATES; i++) {
if (params->c_srates[i] == srate) {
spin_lock_irqsave(&prm->lock, flags);
prm->srate = srate;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
if (params->c_srates[i] == 0)
break;
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(u_audio_set_capture_srate);
int u_audio_get_capture_srate(struct g_audio *audio_dev, u32 *val)
{
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
unsigned long flags;
prm = &uac->c_prm;
spin_lock_irqsave(&prm->lock, flags);
*val = prm->srate;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(u_audio_get_capture_srate);
int u_audio_set_playback_srate(struct g_audio *audio_dev, int srate)
{
struct uac_params *params = &audio_dev->params;
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
int i;
unsigned long flags;
dev_dbg(&audio_dev->gadget->dev, "%s: srate %d\n", __func__, srate);
prm = &uac->p_prm;
for (i = 0; i < UAC_MAX_RATES; i++) {
if (params->p_srates[i] == srate) {
spin_lock_irqsave(&prm->lock, flags);
prm->srate = srate;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
if (params->p_srates[i] == 0)
break;
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(u_audio_set_playback_srate);
int u_audio_get_playback_srate(struct g_audio *audio_dev, u32 *val)
{
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
unsigned long flags;
prm = &uac->p_prm;
spin_lock_irqsave(&prm->lock, flags);
*val = prm->srate;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(u_audio_get_playback_srate);
int u_audio_start_capture(struct g_audio *audio_dev) int u_audio_start_capture(struct g_audio *audio_dev)
{ {
struct snd_uac_chip *uac = audio_dev->uac; struct snd_uac_chip *uac = audio_dev->uac;
@@ -456,8 +595,9 @@ int u_audio_start_capture(struct g_audio *audio_dev)
struct uac_params *params = &audio_dev->params; struct uac_params *params = &audio_dev->params;
int req_len, i; int req_len, i;
ep = audio_dev->out_ep;
prm = &uac->c_prm; prm = &uac->c_prm;
dev_dbg(dev, "start capture with rate %d\n", prm->srate);
ep = audio_dev->out_ep;
config_ep_by_speed(gadget, &audio_dev->func, ep); config_ep_by_speed(gadget, &audio_dev->func, ep);
req_len = ep->maxpacket; req_len = ep->maxpacket;
@@ -483,6 +623,8 @@ int u_audio_start_capture(struct g_audio *audio_dev)
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
} }
set_active(&uac->c_prm, true);
ep_fback = audio_dev->in_ep_fback; ep_fback = audio_dev->in_ep_fback;
if (!ep_fback) if (!ep_fback)
return 0; return 0;
@@ -514,7 +656,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
*/ */
prm->pitch = 1000000; prm->pitch = 1000000;
u_audio_set_fback_frequency(audio_dev->gadget->speed, ep, u_audio_set_fback_frequency(audio_dev->gadget->speed, ep,
params->c_srate, prm->pitch, prm->srate, prm->pitch,
req_fback->buf); req_fback->buf);
if (usb_ep_queue(ep_fback, req_fback, GFP_ATOMIC)) if (usb_ep_queue(ep_fback, req_fback, GFP_ATOMIC))
@@ -528,6 +670,7 @@ void u_audio_stop_capture(struct g_audio *audio_dev)
{ {
struct snd_uac_chip *uac = audio_dev->uac; struct snd_uac_chip *uac = audio_dev->uac;
set_active(&uac->c_prm, false);
if (audio_dev->in_ep_fback) if (audio_dev->in_ep_fback)
free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback); free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback);
free_ep(&uac->c_prm, audio_dev->out_ep); free_ep(&uac->c_prm, audio_dev->out_ep);
@@ -546,12 +689,18 @@ int u_audio_start_playback(struct g_audio *audio_dev)
unsigned int factor; unsigned int factor;
const struct usb_endpoint_descriptor *ep_desc; const struct usb_endpoint_descriptor *ep_desc;
int req_len, i; int req_len, i;
unsigned int p_pktsize;
ep = audio_dev->in_ep;
prm = &uac->p_prm; prm = &uac->p_prm;
dev_dbg(dev, "start playback with rate %d\n", prm->srate);
ep = audio_dev->in_ep;
config_ep_by_speed(gadget, &audio_dev->func, ep); config_ep_by_speed(gadget, &audio_dev->func, ep);
ep_desc = ep->desc; ep_desc = ep->desc;
/*
* Always start with original frequency
*/
prm->pitch = 1000000;
/* pre-calculate the playback endpoint's interval */ /* pre-calculate the playback endpoint's interval */
if (gadget->speed == USB_SPEED_FULL) if (gadget->speed == USB_SPEED_FULL)
@@ -563,19 +712,13 @@ int u_audio_start_playback(struct g_audio *audio_dev)
uac->p_framesize = params->p_ssize * uac->p_framesize = params->p_ssize *
num_channels(params->p_chmask); num_channels(params->p_chmask);
uac->p_interval = factor / (1 << (ep_desc->bInterval - 1)); uac->p_interval = factor / (1 << (ep_desc->bInterval - 1));
uac->p_pktsize = min_t(unsigned int, p_pktsize = min_t(unsigned int,
uac->p_framesize * uac->p_framesize *
(params->p_srate / uac->p_interval), (prm->srate / uac->p_interval),
ep->maxpacket); ep->maxpacket);
if (uac->p_pktsize < ep->maxpacket) req_len = p_pktsize;
uac->p_pktsize_residue = uac->p_framesize * uac->p_residue_mil = 0;
(params->p_srate % uac->p_interval);
else
uac->p_pktsize_residue = 0;
req_len = uac->p_pktsize;
uac->p_residue = 0;
prm->ep_enabled = true; prm->ep_enabled = true;
usb_ep_enable(ep); usb_ep_enable(ep);
@@ -599,6 +742,8 @@ int u_audio_start_playback(struct g_audio *audio_dev)
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
} }
set_active(&uac->p_prm, true);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(u_audio_start_playback); EXPORT_SYMBOL_GPL(u_audio_start_playback);
@@ -607,10 +752,117 @@ void u_audio_stop_playback(struct g_audio *audio_dev)
{ {
struct snd_uac_chip *uac = audio_dev->uac; struct snd_uac_chip *uac = audio_dev->uac;
set_active(&uac->p_prm, false);
free_ep(&uac->p_prm, audio_dev->in_ep); free_ep(&uac->p_prm, audio_dev->in_ep);
} }
EXPORT_SYMBOL_GPL(u_audio_stop_playback); EXPORT_SYMBOL_GPL(u_audio_stop_playback);
void u_audio_suspend(struct g_audio *audio_dev)
{
struct snd_uac_chip *uac = audio_dev->uac;
set_active(&uac->p_prm, false);
set_active(&uac->c_prm, false);
}
EXPORT_SYMBOL_GPL(u_audio_suspend);
int u_audio_get_volume(struct g_audio *audio_dev, int playback, s16 *val)
{
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
unsigned long flags;
if (playback)
prm = &uac->p_prm;
else
prm = &uac->c_prm;
spin_lock_irqsave(&prm->lock, flags);
*val = prm->volume;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(u_audio_get_volume);
int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
{
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
unsigned long flags;
int change = 0;
if (playback)
prm = &uac->p_prm;
else
prm = &uac->c_prm;
spin_lock_irqsave(&prm->lock, flags);
val = clamp(val, prm->volume_min, prm->volume_max);
if (prm->volume != val) {
prm->volume = val;
change = 1;
}
spin_unlock_irqrestore(&prm->lock, flags);
if (change)
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
&prm->snd_kctl_volume->id);
return 0;
}
EXPORT_SYMBOL_GPL(u_audio_set_volume);
int u_audio_get_mute(struct g_audio *audio_dev, int playback, int *val)
{
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
unsigned long flags;
if (playback)
prm = &uac->p_prm;
else
prm = &uac->c_prm;
spin_lock_irqsave(&prm->lock, flags);
*val = prm->mute;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(u_audio_get_mute);
int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
{
struct snd_uac_chip *uac = audio_dev->uac;
struct uac_rtd_params *prm;
unsigned long flags;
int change = 0;
int mute;
if (playback)
prm = &uac->p_prm;
else
prm = &uac->c_prm;
mute = val ? 1 : 0;
spin_lock_irqsave(&prm->lock, flags);
if (prm->mute != mute) {
prm->mute = mute;
change = 1;
}
spin_unlock_irqrestore(&prm->lock, flags);
if (change)
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
&prm->snd_kctl_mute->id);
return 0;
}
EXPORT_SYMBOL_GPL(u_audio_set_mute);
static int u_audio_pitch_info(struct snd_kcontrol *kcontrol, static int u_audio_pitch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo) struct snd_ctl_elem_info *uinfo)
{ {
@@ -670,14 +922,234 @@ static int u_audio_pitch_put(struct snd_kcontrol *kcontrol,
return change; return change;
} }
static const struct snd_kcontrol_new u_audio_controls[] = { static int u_audio_mute_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{ {
.iface = SNDRV_CTL_ELEM_IFACE_PCM, uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
.name = "Capture Pitch 1000000", uinfo->count = 1;
.info = u_audio_pitch_info, uinfo->value.integer.min = 0;
.get = u_audio_pitch_get, uinfo->value.integer.max = 1;
.put = u_audio_pitch_put, uinfo->value.integer.step = 1;
},
return 0;
}
static int u_audio_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&prm->lock, flags);
ucontrol->value.integer.value[0] = !prm->mute;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
static int u_audio_mute_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
struct snd_uac_chip *uac = prm->uac;
struct g_audio *audio_dev = uac->audio_dev;
unsigned int val;
unsigned long flags;
int change = 0;
val = !ucontrol->value.integer.value[0];
spin_lock_irqsave(&prm->lock, flags);
if (val != prm->mute) {
prm->mute = val;
change = 1;
}
spin_unlock_irqrestore(&prm->lock, flags);
if (change && audio_dev->notify)
audio_dev->notify(audio_dev, prm->fu_id, UAC_FU_MUTE);
return change;
}
/*
* TLV callback for mixer volume controls
*/
static int u_audio_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv)
{
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
DECLARE_TLV_DB_MINMAX(scale, 0, 0);
if (size < sizeof(scale))
return -ENOMEM;
/* UAC volume resolution is 1/256 dB, TLV is 1/100 dB */
scale[2] = (prm->volume_min * 100) / 256;
scale[3] = (prm->volume_max * 100) / 256;
if (copy_to_user(_tlv, scale, sizeof(scale)))
return -EFAULT;
return 0;
}
static int u_audio_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max =
(prm->volume_max - prm->volume_min + prm->volume_res - 1)
/ prm->volume_res;
uinfo->value.integer.step = 1;
return 0;
}
static int u_audio_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&prm->lock, flags);
ucontrol->value.integer.value[0] =
(prm->volume - prm->volume_min) / prm->volume_res;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
static int u_audio_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
struct snd_uac_chip *uac = prm->uac;
struct g_audio *audio_dev = uac->audio_dev;
unsigned int val;
s16 volume;
unsigned long flags;
int change = 0;
val = ucontrol->value.integer.value[0];
spin_lock_irqsave(&prm->lock, flags);
volume = (val * prm->volume_res) + prm->volume_min;
volume = clamp(volume, prm->volume_min, prm->volume_max);
if (volume != prm->volume) {
prm->volume = volume;
change = 1;
}
spin_unlock_irqrestore(&prm->lock, flags);
if (change && audio_dev->notify)
audio_dev->notify(audio_dev, prm->fu_id, UAC_FU_VOLUME);
return change;
}
static int get_max_srate(const int *srates)
{
int i, max_srate = 0;
for (i = 0; i < UAC_MAX_RATES; i++) {
if (srates[i] == 0)
break;
if (srates[i] > max_srate)
max_srate = srates[i];
}
return max_srate;
}
static int get_min_srate(const int *srates)
{
int i, min_srate = INT_MAX;
for (i = 0; i < UAC_MAX_RATES; i++) {
if (srates[i] == 0)
break;
if (srates[i] < min_srate)
min_srate = srates[i];
}
return min_srate;
}
static int u_audio_rate_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
const int *srates;
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
struct snd_uac_chip *uac = prm->uac;
struct g_audio *audio_dev = uac->audio_dev;
struct uac_params *params = &audio_dev->params;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
if (prm == &uac->c_prm)
srates = params->c_srates;
else
srates = params->p_srates;
uinfo->value.integer.min = get_min_srate(srates);
uinfo->value.integer.max = get_max_srate(srates);
return 0;
}
static int u_audio_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&prm->lock, flags);
if (prm->active)
ucontrol->value.integer.value[0] = prm->srate;
else
/* not active: reporting zero rate */
ucontrol->value.integer.value[0] = 0;
spin_unlock_irqrestore(&prm->lock, flags);
return 0;
}
static struct snd_kcontrol_new u_audio_controls[] = {
[UAC_FBACK_CTRL] {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "Capture Pitch 1000000",
.info = u_audio_pitch_info,
.get = u_audio_pitch_get,
.put = u_audio_pitch_put,
},
[UAC_P_PITCH_CTRL] {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "Playback Pitch 1000000",
.info = u_audio_pitch_info,
.get = u_audio_pitch_get,
.put = u_audio_pitch_put,
},
[UAC_MUTE_CTRL] {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "", /* will be filled later */
.info = u_audio_mute_info,
.get = u_audio_mute_get,
.put = u_audio_mute_put,
},
[UAC_VOLUME_CTRL] {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "", /* will be filled later */
.info = u_audio_volume_info,
.get = u_audio_volume_get,
.put = u_audio_volume_put,
},
[UAC_RATE_CTRL] {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "", /* will be filled later */
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = u_audio_rate_info,
.get = u_audio_rate_get,
},
}; };
int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
@@ -689,7 +1161,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
struct snd_kcontrol *kctl; struct snd_kcontrol *kctl;
struct uac_params *params; struct uac_params *params;
int p_chmask, c_chmask; int p_chmask, c_chmask;
int err; int i, err;
if (!g_audio) if (!g_audio)
return -EINVAL; return -EINVAL;
@@ -707,8 +1179,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
if (c_chmask) { if (c_chmask) {
struct uac_rtd_params *prm = &uac->c_prm; struct uac_rtd_params *prm = &uac->c_prm;
uac->c_prm.uac = uac; spin_lock_init(&prm->lock);
uac->c_prm.uac = uac;
prm->max_psize = g_audio->out_ep_maxpsize; prm->max_psize = g_audio->out_ep_maxpsize;
prm->srate = params->c_srates[0];
prm->reqs = kcalloc(params->req_number, prm->reqs = kcalloc(params->req_number,
sizeof(struct usb_request *), sizeof(struct usb_request *),
@@ -730,8 +1204,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
if (p_chmask) { if (p_chmask) {
struct uac_rtd_params *prm = &uac->p_prm; struct uac_rtd_params *prm = &uac->p_prm;
spin_lock_init(&prm->lock);
uac->p_prm.uac = uac; uac->p_prm.uac = uac;
prm->max_psize = g_audio->in_ep_maxpsize; prm->max_psize = g_audio->in_ep_maxpsize;
prm->srate = params->p_srates[0];
prm->reqs = kcalloc(params->req_number, prm->reqs = kcalloc(params->req_number,
sizeof(struct usb_request *), sizeof(struct usb_request *),
@@ -774,10 +1250,18 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops);
if (c_chmask && g_audio->in_ep_fback) { /*
* Create mixer and controls
* Create only if it's required on USB side
*/
if ((c_chmask && g_audio->in_ep_fback)
|| (p_chmask && params->p_fu.id)
|| (c_chmask && params->c_fu.id))
strscpy(card->mixername, card_name, sizeof(card->driver)); strscpy(card->mixername, card_name, sizeof(card->driver));
kctl = snd_ctl_new1(&u_audio_controls[0], &uac->c_prm); if (c_chmask && g_audio->in_ep_fback) {
kctl = snd_ctl_new1(&u_audio_controls[UAC_FBACK_CTRL],
&uac->c_prm);
if (!kctl) { if (!kctl) {
err = -ENOMEM; err = -ENOMEM;
goto snd_fail; goto snd_fail;
@@ -791,6 +1275,117 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
goto snd_fail; goto snd_fail;
} }
if (p_chmask) {
kctl = snd_ctl_new1(&u_audio_controls[UAC_P_PITCH_CTRL],
&uac->p_prm);
if (!kctl) {
err = -ENOMEM;
goto snd_fail;
}
kctl->id.device = pcm->device;
kctl->id.subdevice = 0;
err = snd_ctl_add(card, kctl);
if (err < 0)
goto snd_fail;
}
for (i = 0; i <= SNDRV_PCM_STREAM_LAST; i++) {
struct uac_rtd_params *prm;
struct uac_fu_params *fu;
char ctrl_name[24];
char *direction;
if (!pcm->streams[i].substream_count)
continue;
if (i == SNDRV_PCM_STREAM_PLAYBACK) {
prm = &uac->p_prm;
fu = &params->p_fu;
direction = "Playback";
} else {
prm = &uac->c_prm;
fu = &params->c_fu;
direction = "Capture";
}
prm->fu_id = fu->id;
if (fu->mute_present) {
snprintf(ctrl_name, sizeof(ctrl_name),
"PCM %s Switch", direction);
u_audio_controls[UAC_MUTE_CTRL].name = ctrl_name;
kctl = snd_ctl_new1(&u_audio_controls[UAC_MUTE_CTRL],
prm);
if (!kctl) {
err = -ENOMEM;
goto snd_fail;
}
kctl->id.device = pcm->device;
kctl->id.subdevice = 0;
err = snd_ctl_add(card, kctl);
if (err < 0)
goto snd_fail;
prm->snd_kctl_mute = kctl;
prm->mute = 0;
}
if (fu->volume_present) {
snprintf(ctrl_name, sizeof(ctrl_name),
"PCM %s Volume", direction);
u_audio_controls[UAC_VOLUME_CTRL].name = ctrl_name;
kctl = snd_ctl_new1(&u_audio_controls[UAC_VOLUME_CTRL],
prm);
if (!kctl) {
err = -ENOMEM;
goto snd_fail;
}
kctl->id.device = pcm->device;
kctl->id.subdevice = 0;
kctl->tlv.c = u_audio_volume_tlv;
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
err = snd_ctl_add(card, kctl);
if (err < 0)
goto snd_fail;
prm->snd_kctl_volume = kctl;
prm->volume = fu->volume_max;
prm->volume_max = fu->volume_max;
prm->volume_min = fu->volume_min;
prm->volume_res = fu->volume_res;
}
/* Add rate control */
snprintf(ctrl_name, sizeof(ctrl_name),
"%s Rate", direction);
u_audio_controls[UAC_RATE_CTRL].name = ctrl_name;
kctl = snd_ctl_new1(&u_audio_controls[UAC_RATE_CTRL], prm);
if (!kctl) {
err = -ENOMEM;
goto snd_fail;
}
kctl->id.device = pcm->device;
kctl->id.subdevice = 0;
err = snd_ctl_add(card, kctl);
if (err < 0)
goto snd_fail;
prm->snd_kctl_rate = kctl;
}
strscpy(card->driver, card_name, sizeof(card->driver)); strscpy(card->driver, card_name, sizeof(card->driver));
strscpy(card->shortname, card_name, sizeof(card->shortname)); strscpy(card->shortname, card_name, sizeof(card->shortname));
sprintf(card->longname, "%s %i", card_name, card->dev->id); sprintf(card->longname, "%s %i", card_name, card->dev->id);

View File

@@ -10,25 +10,48 @@
#define __U_AUDIO_H #define __U_AUDIO_H
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include "uac_common.h"
/* /*
* Same maximum frequency deviation on the slower side as in * Same maximum frequency deviation on the slower side as in
* sound/usb/endpoint.c. Value is expressed in per-mil deviation. * sound/usb/endpoint.c. Value is expressed in per-mil deviation.
* The maximum deviation on the faster side will be provided as
* parameter, as it impacts the endpoint required bandwidth.
*/ */
#define FBACK_SLOW_MAX 250 #define FBACK_SLOW_MAX 250
/*
* Maximum frequency deviation on the faster side, default value for UAC1/2.
* Value is expressed in per-mil deviation.
* UAC2 provides the value as a parameter as it impacts the endpoint required
* bandwidth.
*/
#define FBACK_FAST_MAX 5
/* Feature Unit parameters */
struct uac_fu_params {
int id; /* Feature Unit ID */
bool mute_present; /* mute control enable */
bool volume_present; /* volume control enable */
s16 volume_min; /* min volume in 1/256 dB */
s16 volume_max; /* max volume in 1/256 dB */
s16 volume_res; /* volume resolution in 1/256 dB */
};
struct uac_params { struct uac_params {
/* playback */ /* playback */
int p_chmask; /* channel mask */ int p_chmask; /* channel mask */
int p_srate; /* rate in Hz */ int p_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */
int p_ssize; /* sample size */ int p_ssize; /* sample size */
struct uac_fu_params p_fu; /* Feature Unit parameters */
/* capture */ /* capture */
int c_chmask; /* channel mask */ int c_chmask; /* channel mask */
int c_srate; /* rate in Hz */ int c_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */
int c_ssize; /* sample size */ int c_ssize; /* sample size */
struct uac_fu_params c_fu; /* Feature Unit parameters */
/* rates are dynamic, in uac_rtd_params */
int req_number; /* number of preallocated requests */ int req_number; /* number of preallocated requests */
int fb_max; /* upper frequency drift feedback limit per-mil */ int fb_max; /* upper frequency drift feedback limit per-mil */
@@ -49,6 +72,9 @@ struct g_audio {
/* Max packet size for all out_ep possible speeds */ /* Max packet size for all out_ep possible speeds */
unsigned int out_ep_maxpsize; unsigned int out_ep_maxpsize;
/* Notify UAC driver about control change */
int (*notify)(struct g_audio *g_audio, int unit_id, int cs);
/* The ALSA Sound Card it represents on the USB-Client side */ /* The ALSA Sound Card it represents on the USB-Client side */
struct snd_uac_chip *uac; struct snd_uac_chip *uac;
@@ -94,4 +120,16 @@ void u_audio_stop_capture(struct g_audio *g_audio);
int u_audio_start_playback(struct g_audio *g_audio); int u_audio_start_playback(struct g_audio *g_audio);
void u_audio_stop_playback(struct g_audio *g_audio); void u_audio_stop_playback(struct g_audio *g_audio);
int u_audio_get_capture_srate(struct g_audio *audio_dev, u32 *val);
int u_audio_set_capture_srate(struct g_audio *audio_dev, int srate);
int u_audio_get_playback_srate(struct g_audio *audio_dev, u32 *val);
int u_audio_set_playback_srate(struct g_audio *audio_dev, int srate);
int u_audio_get_volume(struct g_audio *g_audio, int playback, s16 *val);
int u_audio_set_volume(struct g_audio *g_audio, int playback, s16 val);
int u_audio_get_mute(struct g_audio *g_audio, int playback, int *val);
int u_audio_set_mute(struct g_audio *g_audio, int playback, int val);
void u_audio_suspend(struct g_audio *g_audio);
#endif /* __U_AUDIO_H */ #endif /* __U_AUDIO_H */

View File

@@ -9,6 +9,7 @@
#define __U_UAC1_H #define __U_UAC1_H
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include "uac_common.h"
#define UAC1_OUT_EP_MAX_PACKET_SIZE 200 #define UAC1_OUT_EP_MAX_PACKET_SIZE 200
#define UAC1_DEF_CCHMASK 0x3 #define UAC1_DEF_CCHMASK 0x3
@@ -18,19 +19,41 @@
#define UAC1_DEF_PSRATE 48000 #define UAC1_DEF_PSRATE 48000
#define UAC1_DEF_PSSIZE 2 #define UAC1_DEF_PSSIZE 2
#define UAC1_DEF_REQ_NUM 2 #define UAC1_DEF_REQ_NUM 2
#define UAC1_DEF_INT_REQ_NUM 10
#define UAC1_DEF_MUTE_PRESENT 1
#define UAC1_DEF_VOLUME_PRESENT 1
#define UAC1_DEF_MIN_DB (-100*256) /* -100 dB */
#define UAC1_DEF_MAX_DB 0 /* 0 dB */
#define UAC1_DEF_RES_DB (1*256) /* 1 dB */
struct f_uac1_opts { struct f_uac1_opts {
struct usb_function_instance func_inst; struct usb_function_instance func_inst;
int c_chmask; int c_chmask;
int c_srate; int c_srates[UAC_MAX_RATES];
int c_ssize; int c_ssize;
int p_chmask; int p_chmask;
int p_srate; int p_srates[UAC_MAX_RATES];
int p_ssize; int p_ssize;
bool p_mute_present;
bool p_volume_present;
s16 p_volume_min;
s16 p_volume_max;
s16 p_volume_res;
bool c_mute_present;
bool c_volume_present;
s16 c_volume_min;
s16 c_volume_max;
s16 c_volume_res;
int req_number; int req_number;
unsigned bound:1; unsigned bound:1;
char function_name[32];
struct mutex lock; struct mutex lock;
int refcnt; int refcnt;
}; };

View File

@@ -14,6 +14,7 @@
#define U_UAC2_H #define U_UAC2_H
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include "uac_common.h"
#define UAC2_DEF_PCHMASK 0x3 #define UAC2_DEF_PCHMASK 0x3
#define UAC2_DEF_PSRATE 48000 #define UAC2_DEF_PSRATE 48000
@@ -22,21 +23,43 @@
#define UAC2_DEF_CSRATE 64000 #define UAC2_DEF_CSRATE 64000
#define UAC2_DEF_CSSIZE 2 #define UAC2_DEF_CSSIZE 2
#define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC #define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC
#define UAC2_DEF_MUTE_PRESENT 1
#define UAC2_DEF_VOLUME_PRESENT 1
#define UAC2_DEF_MIN_DB (-100*256) /* -100 dB */
#define UAC2_DEF_MAX_DB 0 /* 0 dB */
#define UAC2_DEF_RES_DB (1*256) /* 1 dB */
#define UAC2_DEF_REQ_NUM 2 #define UAC2_DEF_REQ_NUM 2
#define UAC2_DEF_FB_MAX 5 #define UAC2_DEF_INT_REQ_NUM 10
struct f_uac2_opts { struct f_uac2_opts {
struct usb_function_instance func_inst; struct usb_function_instance func_inst;
int p_chmask; int p_chmask;
int p_srate; int p_srates[UAC_MAX_RATES];
int p_ssize; int p_ssize;
int c_chmask; int c_chmask;
int c_srate; int c_srates[UAC_MAX_RATES];
int c_ssize; int c_ssize;
int c_sync; int c_sync;
bool p_mute_present;
bool p_volume_present;
s16 p_volume_min;
s16 p_volume_max;
s16 p_volume_res;
bool c_mute_present;
bool c_volume_present;
s16 c_volume_min;
s16 c_volume_max;
s16 c_volume_res;
int req_number; int req_number;
int fb_max; int fb_max;
bool bound; bool bound;
char function_name[32];
struct mutex lock; struct mutex lock;
int refcnt; int refcnt;

View File

@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
*/
#ifndef UAC_COMMON_H
#define UAC_COMMON_H
#define UAC_MAX_RATES 10 /* maximum number of rates configurable by f_uac1/2 */
#endif

View File

@@ -302,6 +302,9 @@ static void uvcg_video_pump(struct work_struct *work)
uvcg_queue_cancel(queue, 0); uvcg_queue_cancel(queue, 0);
break; break;
} }
/* Endpoint now owns the request */
req = NULL;
} }
if (!req) if (!req)

View File

@@ -22,32 +22,34 @@ USB_GADGET_COMPOSITE_OPTIONS();
/* Playback(USB-IN) Default Stereo - Fl/Fr */ /* Playback(USB-IN) Default Stereo - Fl/Fr */
static int p_chmask = UAC2_DEF_PCHMASK; static int p_chmask = UAC2_DEF_PCHMASK;
module_param(p_chmask, uint, S_IRUGO); module_param(p_chmask, uint, 0444);
MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
/* Playback Default 48 KHz */ /* Playback Default 48 KHz */
static int p_srate = UAC2_DEF_PSRATE; static int p_srates[UAC_MAX_RATES] = {UAC2_DEF_PSRATE};
module_param(p_srate, uint, S_IRUGO); static int p_srates_cnt = 1;
MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); module_param_array_named(p_srate, p_srates, uint, &p_srates_cnt, 0444);
MODULE_PARM_DESC(p_srate, "Playback Sampling Rates (array)");
/* Playback Default 16bits/sample */ /* Playback Default 16bits/sample */
static int p_ssize = UAC2_DEF_PSSIZE; static int p_ssize = UAC2_DEF_PSSIZE;
module_param(p_ssize, uint, S_IRUGO); module_param(p_ssize, uint, 0444);
MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
/* Capture(USB-OUT) Default Stereo - Fl/Fr */ /* Capture(USB-OUT) Default Stereo - Fl/Fr */
static int c_chmask = UAC2_DEF_CCHMASK; static int c_chmask = UAC2_DEF_CCHMASK;
module_param(c_chmask, uint, S_IRUGO); module_param(c_chmask, uint, 0444);
MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
/* Capture Default 64 KHz */ /* Capture Default 64 KHz */
static int c_srate = UAC2_DEF_CSRATE; static int c_srates[UAC_MAX_RATES] = {UAC2_DEF_CSRATE};
module_param(c_srate, uint, S_IRUGO); static int c_srates_cnt = 1;
MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); module_param_array_named(c_srate, c_srates, uint, &c_srates_cnt, 0444);
MODULE_PARM_DESC(c_srate, "Capture Sampling Rates (array)");
/* Capture Default 16bits/sample */ /* Capture Default 16bits/sample */
static int c_ssize = UAC2_DEF_CSSIZE; static int c_ssize = UAC2_DEF_CSSIZE;
module_param(c_ssize, uint, S_IRUGO); module_param(c_ssize, uint, 0444);
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
#else #else
#ifndef CONFIG_GADGET_UAC1_LEGACY #ifndef CONFIG_GADGET_UAC1_LEGACY
@@ -55,58 +57,60 @@ MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
/* Playback(USB-IN) Default Stereo - Fl/Fr */ /* Playback(USB-IN) Default Stereo - Fl/Fr */
static int p_chmask = UAC1_DEF_PCHMASK; static int p_chmask = UAC1_DEF_PCHMASK;
module_param(p_chmask, uint, S_IRUGO); module_param(p_chmask, uint, 0444);
MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
/* Playback Default 48 KHz */ /* Playback Default 48 KHz */
static int p_srate = UAC1_DEF_PSRATE; static int p_srates[UAC_MAX_RATES] = {UAC1_DEF_PSRATE};
module_param(p_srate, uint, S_IRUGO); static int p_srates_cnt = 1;
MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); module_param_array_named(p_srate, p_srates, uint, &p_srates_cnt, 0444);
MODULE_PARM_DESC(p_srate, "Playback Sampling Rates (array)");
/* Playback Default 16bits/sample */ /* Playback Default 16bits/sample */
static int p_ssize = UAC1_DEF_PSSIZE; static int p_ssize = UAC1_DEF_PSSIZE;
module_param(p_ssize, uint, S_IRUGO); module_param(p_ssize, uint, 0444);
MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
/* Capture(USB-OUT) Default Stereo - Fl/Fr */ /* Capture(USB-OUT) Default Stereo - Fl/Fr */
static int c_chmask = UAC1_DEF_CCHMASK; static int c_chmask = UAC1_DEF_CCHMASK;
module_param(c_chmask, uint, S_IRUGO); module_param(c_chmask, uint, 0444);
MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
/* Capture Default 48 KHz */ /* Capture Default 48 KHz */
static int c_srate = UAC1_DEF_CSRATE; static int c_srates[UAC_MAX_RATES] = {UAC1_DEF_CSRATE};
module_param(c_srate, uint, S_IRUGO); static int c_srates_cnt = 1;
MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); module_param_array_named(c_srate, c_srates, uint, &c_srates_cnt, 0444);
MODULE_PARM_DESC(c_srate, "Capture Sampling Rates (array)");
/* Capture Default 16bits/sample */ /* Capture Default 16bits/sample */
static int c_ssize = UAC1_DEF_CSSIZE; static int c_ssize = UAC1_DEF_CSSIZE;
module_param(c_ssize, uint, S_IRUGO); module_param(c_ssize, uint, 0444);
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
#else /* CONFIG_GADGET_UAC1_LEGACY */ #else /* CONFIG_GADGET_UAC1_LEGACY */
#include "u_uac1_legacy.h" #include "u_uac1_legacy.h"
static char *fn_play = FILE_PCM_PLAYBACK; static char *fn_play = FILE_PCM_PLAYBACK;
module_param(fn_play, charp, S_IRUGO); module_param(fn_play, charp, 0444);
MODULE_PARM_DESC(fn_play, "Playback PCM device file name"); MODULE_PARM_DESC(fn_play, "Playback PCM device file name");
static char *fn_cap = FILE_PCM_CAPTURE; static char *fn_cap = FILE_PCM_CAPTURE;
module_param(fn_cap, charp, S_IRUGO); module_param(fn_cap, charp, 0444);
MODULE_PARM_DESC(fn_cap, "Capture PCM device file name"); MODULE_PARM_DESC(fn_cap, "Capture PCM device file name");
static char *fn_cntl = FILE_CONTROL; static char *fn_cntl = FILE_CONTROL;
module_param(fn_cntl, charp, S_IRUGO); module_param(fn_cntl, charp, 0444);
MODULE_PARM_DESC(fn_cntl, "Control device file name"); MODULE_PARM_DESC(fn_cntl, "Control device file name");
static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE;
module_param(req_buf_size, int, S_IRUGO); module_param(req_buf_size, int, 0444);
MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size");
static int req_count = UAC1_REQ_COUNT; static int req_count = UAC1_REQ_COUNT;
module_param(req_count, int, S_IRUGO); module_param(req_count, int, 0444);
MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count"); MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count");
static int audio_buf_size = UAC1_AUDIO_BUF_SIZE; static int audio_buf_size = UAC1_AUDIO_BUF_SIZE;
module_param(audio_buf_size, int, S_IRUGO); module_param(audio_buf_size, int, 0444);
MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); MODULE_PARM_DESC(audio_buf_size, "Audio buffer size");
#endif /* CONFIG_GADGET_UAC1_LEGACY */ #endif /* CONFIG_GADGET_UAC1_LEGACY */
#endif #endif
@@ -237,9 +241,11 @@ static int audio_bind(struct usb_composite_dev *cdev)
{ {
#ifndef CONFIG_GADGET_UAC1 #ifndef CONFIG_GADGET_UAC1
struct f_uac2_opts *uac2_opts; struct f_uac2_opts *uac2_opts;
int i;
#else #else
#ifndef CONFIG_GADGET_UAC1_LEGACY #ifndef CONFIG_GADGET_UAC1_LEGACY
struct f_uac1_opts *uac1_opts; struct f_uac1_opts *uac1_opts;
int i;
#else #else
struct f_uac1_legacy_opts *uac1_opts; struct f_uac1_legacy_opts *uac1_opts;
#endif #endif
@@ -263,20 +269,32 @@ static int audio_bind(struct usb_composite_dev *cdev)
#ifndef CONFIG_GADGET_UAC1 #ifndef CONFIG_GADGET_UAC1
uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst); uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst);
uac2_opts->p_chmask = p_chmask; uac2_opts->p_chmask = p_chmask;
uac2_opts->p_srate = p_srate;
for (i = 0; i < p_srates_cnt; ++i)
uac2_opts->p_srates[i] = p_srates[i];
uac2_opts->p_ssize = p_ssize; uac2_opts->p_ssize = p_ssize;
uac2_opts->c_chmask = c_chmask; uac2_opts->c_chmask = c_chmask;
uac2_opts->c_srate = c_srate;
for (i = 0; i < c_srates_cnt; ++i)
uac2_opts->c_srates[i] = c_srates[i];
uac2_opts->c_ssize = c_ssize; uac2_opts->c_ssize = c_ssize;
uac2_opts->req_number = UAC2_DEF_REQ_NUM; uac2_opts->req_number = UAC2_DEF_REQ_NUM;
#else #else
#ifndef CONFIG_GADGET_UAC1_LEGACY #ifndef CONFIG_GADGET_UAC1_LEGACY
uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
uac1_opts->p_chmask = p_chmask; uac1_opts->p_chmask = p_chmask;
uac1_opts->p_srate = p_srate;
for (i = 0; i < p_srates_cnt; ++i)
uac1_opts->p_srates[i] = p_srates[i];
uac1_opts->p_ssize = p_ssize; uac1_opts->p_ssize = p_ssize;
uac1_opts->c_chmask = c_chmask; uac1_opts->c_chmask = c_chmask;
uac1_opts->c_srate = c_srate;
for (i = 0; i < c_srates_cnt; ++i)
uac1_opts->c_srates[i] = c_srates[i];
uac1_opts->c_ssize = c_ssize; uac1_opts->c_ssize = c_ssize;
uac1_opts->req_number = UAC1_DEF_REQ_NUM; uac1_opts->req_number = UAC1_DEF_REQ_NUM;
#else /* CONFIG_GADGET_UAC1_LEGACY */ #else /* CONFIG_GADGET_UAC1_LEGACY */

View File

@@ -282,6 +282,13 @@ struct css_set {
struct rcu_head rcu_head; struct rcu_head rcu_head;
}; };
struct ext_css_set {
struct css_set cset;
struct list_head mg_src_preload_node;
struct list_head mg_dst_preload_node;
};
struct cgroup_base_stat { struct cgroup_base_stat {
struct task_cputime cputime; struct task_cputime cputime;
}; };

View File

@@ -72,7 +72,8 @@ struct css_task_iter {
}; };
extern struct cgroup_root cgrp_dfl_root; extern struct cgroup_root cgrp_dfl_root;
extern struct css_set init_css_set; extern struct ext_css_set init_ext_css_set;
#define init_css_set init_ext_css_set.cset
#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys; #define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
#include <linux/cgroup_subsys.h> #include <linux/cgroup_subsys.h>

View File

@@ -3362,7 +3362,6 @@ unsigned long wp_shared_mapping_range(struct address_space *mapping,
extern int sysctl_nr_trim_pages; extern int sysctl_nr_trim_pages;
extern bool pte_map_lock_addr(struct vm_fault *vmf, unsigned long addr); extern bool pte_map_lock_addr(struct vm_fault *vmf, unsigned long addr);
extern int reclaim_shmem_address_space(struct address_space *mapping); extern int reclaim_shmem_address_space(struct address_space *mapping);
extern int reclaim_pages_from_list(struct list_head *page_list);
/** /**
* seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it * seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it

View File

@@ -156,6 +156,20 @@ struct uac2_feature_unit_descriptor {
__u8 bmaControls[]; /* variable length */ __u8 bmaControls[]; /* variable length */
} __attribute__((packed)); } __attribute__((packed));
#define UAC2_DT_FEATURE_UNIT_SIZE(ch) (6 + ((ch) + 1) * 4)
/* As above, but more useful for defining your own descriptors: */
#define DECLARE_UAC2_FEATURE_UNIT_DESCRIPTOR(ch) \
struct uac2_feature_unit_descriptor_##ch { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubtype; \
__u8 bUnitID; \
__u8 bSourceID; \
__le32 bmaControls[ch + 1]; \
__u8 iFeature; \
} __packed
/* 4.7.2.10 Effect Unit Descriptor */ /* 4.7.2.10 Effect Unit Descriptor */
struct uac2_effect_unit_descriptor { struct uac2_effect_unit_descriptor {

View File

@@ -11,13 +11,31 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
struct binder_transaction; #if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_ANDROID_BINDER_IPC)
struct task_struct;
struct binder_alloc; struct binder_alloc;
struct binder_proc; struct binder_proc;
struct binder_thread; struct binder_thread;
struct binder_transaction;
struct binder_transaction_data; struct binder_transaction_data;
#else
/* struct binder_alloc */
#include <../drivers/android/binder_alloc.h>
/* struct binder_proc, struct binder_thread, struct binder_transaction */
#include <../drivers/android/binder_internal.h>
#endif
#ifdef __GENKSYMS__
struct task_struct;
struct seq_file; struct seq_file;
#else
/* struct task_struct */
#include <linux/sched.h>
/* struct seq_file */
#include <linux/seq_file.h>
/* struct binder_transaction_data */
#include <uapi/linux/android/binder.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_binder_transaction_init, DECLARE_HOOK(android_vh_binder_transaction_init,
TP_PROTO(struct binder_transaction *t), TP_PROTO(struct binder_transaction *t),
TP_ARGS(t)); TP_ARGS(t));
@@ -30,8 +48,6 @@ DECLARE_HOOK(android_vh_binder_set_priority,
DECLARE_HOOK(android_vh_binder_restore_priority, DECLARE_HOOK(android_vh_binder_restore_priority,
TP_PROTO(struct binder_transaction *t, struct task_struct *task), TP_PROTO(struct binder_transaction *t, struct task_struct *task),
TP_ARGS(t, task)); TP_ARGS(t, task));
struct binder_proc;
struct binder_thread;
DECLARE_HOOK(android_vh_binder_wakeup_ilocked, DECLARE_HOOK(android_vh_binder_wakeup_ilocked,
TP_PROTO(struct task_struct *task, bool sync, struct binder_proc *proc), TP_PROTO(struct task_struct *task, bool sync, struct binder_proc *proc),
TP_ARGS(task, sync, proc)); TP_ARGS(task, sync, proc));

View File

@@ -10,9 +10,18 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
struct blk_mq_tag_set; #if defined(__GENKSYMS__) || !defined(CONFIG_BLOCK)
struct blk_mq_tags; struct blk_mq_tags;
struct blk_mq_alloc_data; struct blk_mq_alloc_data;
struct blk_mq_tag_set;
#else
/* struct blk_mq_tags */
#include <../block/blk-mq-tag.h>
/* struct blk_mq_alloc_data */
#include <../block/blk-mq.h>
/* struct blk_mq_tag_set */
#include <linux/blk-mq.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_blk_alloc_rqs, DECLARE_HOOK(android_vh_blk_alloc_rqs,
TP_PROTO(size_t *rq_size, struct blk_mq_tag_set *set, TP_PROTO(size_t *rq_size, struct blk_mq_tag_set *set,

View File

@@ -8,7 +8,16 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
struct cgroup_taskset;
#ifdef __GENKSYMS__
struct cgroup_subsys;
struct task_struct; struct task_struct;
#else
/* struct cgroup_subsys */
#include <linux/cgroup-defs.h>
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_cgroup_set_task, DECLARE_HOOK(android_vh_cgroup_set_task,
TP_PROTO(int ret, struct task_struct *task), TP_PROTO(int ret, struct task_struct *task),
TP_ARGS(ret, task)); TP_ARGS(ret, task));
@@ -22,8 +31,6 @@ DECLARE_RESTRICTED_HOOK(android_rvh_refrigerator,
TP_PROTO(bool f), TP_PROTO(bool f),
TP_ARGS(f), 1); TP_ARGS(f), 1);
struct cgroup_subsys;
struct cgroup_taskset;
DECLARE_HOOK(android_vh_cgroup_attach, DECLARE_HOOK(android_vh_cgroup_attach,
TP_PROTO(struct cgroup_subsys *ss, struct cgroup_taskset *tset), TP_PROTO(struct cgroup_subsys *ss, struct cgroup_taskset *tset),
TP_ARGS(ss, tset)) TP_ARGS(ss, tset))

View File

@@ -10,7 +10,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct cpuidle_device; struct cpuidle_device;
#else
/* struct cpuidle_device */
#include <linux/cpuidle.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_cpu_idle_enter, DECLARE_HOOK(android_vh_cpu_idle_enter,
TP_PROTO(int *state, struct cpuidle_device *dev), TP_PROTO(int *state, struct cpuidle_device *dev),

View File

@@ -11,7 +11,12 @@
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct cpuidle_device; struct cpuidle_device;
#else
/* struct cpuidle_device */
#include <linux/cpuidle.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_cpuidle_psci_enter, DECLARE_HOOK(android_vh_cpuidle_psci_enter,
TP_PROTO(struct cpuidle_device *dev, bool s2idle), TP_PROTO(struct cpuidle_device *dev, bool s2idle),
TP_ARGS(dev, s2idle)); TP_ARGS(dev, s2idle));

View File

@@ -11,8 +11,15 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct cred; struct cred;
struct task_struct; struct task_struct;
#else
/* struct cred */
#include <linux/cred.h>
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_commit_creds, DECLARE_HOOK(android_vh_commit_creds,
TP_PROTO(const struct task_struct *task, const struct cred *new), TP_PROTO(const struct task_struct *task, const struct cred *new),
TP_ARGS(task, new)); TP_ARGS(task, new));

View File

@@ -11,7 +11,12 @@
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS) #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS)
#ifdef __GENKSYMS__
struct pt_regs; struct pt_regs;
#else
/* struct pt_regs */
#include <asm/ptrace.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_ipi_stop, DECLARE_HOOK(android_vh_ipi_stop,
TP_PROTO(struct pt_regs *regs), TP_PROTO(struct pt_regs *regs),

View File

@@ -11,7 +11,21 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct mutex; struct mutex;
struct rt_mutex;
struct rw_semaphore;
struct task_struct;
#else
/* struct mutex */
#include <linux/mutex.h>
/* struct rt_mutex */
#include <linux/rtmutex.h>
/* struct rw_semaphore */
#include <linux/rwsem.h>
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_mutex_wait_start, DECLARE_HOOK(android_vh_mutex_wait_start,
TP_PROTO(struct mutex *lock), TP_PROTO(struct mutex *lock),
TP_ARGS(lock)); TP_ARGS(lock));
@@ -19,7 +33,6 @@ DECLARE_HOOK(android_vh_mutex_wait_finish,
TP_PROTO(struct mutex *lock), TP_PROTO(struct mutex *lock),
TP_ARGS(lock)); TP_ARGS(lock));
struct rt_mutex;
DECLARE_HOOK(android_vh_rtmutex_wait_start, DECLARE_HOOK(android_vh_rtmutex_wait_start,
TP_PROTO(struct rt_mutex *lock), TP_PROTO(struct rt_mutex *lock),
TP_ARGS(lock)); TP_ARGS(lock));
@@ -27,7 +40,6 @@ DECLARE_HOOK(android_vh_rtmutex_wait_finish,
TP_PROTO(struct rt_mutex *lock), TP_PROTO(struct rt_mutex *lock),
TP_ARGS(lock)); TP_ARGS(lock));
struct rw_semaphore;
DECLARE_HOOK(android_vh_rwsem_read_wait_start, DECLARE_HOOK(android_vh_rwsem_read_wait_start,
TP_PROTO(struct rw_semaphore *sem), TP_PROTO(struct rw_semaphore *sem),
TP_ARGS(sem)); TP_ARGS(sem));
@@ -41,7 +53,6 @@ DECLARE_HOOK(android_vh_rwsem_write_wait_finish,
TP_PROTO(struct rw_semaphore *sem), TP_PROTO(struct rw_semaphore *sem),
TP_ARGS(sem)); TP_ARGS(sem));
struct task_struct;
DECLARE_HOOK(android_vh_sched_show_task, DECLARE_HOOK(android_vh_sched_show_task,
TP_PROTO(struct task_struct *task), TP_PROTO(struct task_struct *task),
TP_ARGS(task)); TP_ARGS(task));

View File

@@ -11,7 +11,12 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct pt_regs; struct pt_regs;
#else
/* struct pt_regs */
#include <asm/ptrace.h>
#endif /* __GENKSYMS__ */
DECLARE_RESTRICTED_HOOK(android_rvh_die_kernel_fault, DECLARE_RESTRICTED_HOOK(android_rvh_die_kernel_fault,
TP_PROTO(struct pt_regs *regs, unsigned int esr, unsigned long addr, const char *msg), TP_PROTO(struct pt_regs *regs, unsigned int esr, unsigned long addr, const char *msg),
TP_ARGS(regs, esr, addr, msg), 1); TP_ARGS(regs, esr, addr, msg), 1);

View File

@@ -8,7 +8,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct crypto_aes_ctx; struct crypto_aes_ctx;
#else
/* struct crypto_aes_ctx */
#include <crypto/aes.h>
#endif /* __GENKSYMS__ */
/* /*
* These hooks exist only for the benefit of the FIPS140 crypto module, which * These hooks exist only for the benefit of the FIPS140 crypto module, which

View File

@@ -10,7 +10,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct task_struct; struct task_struct;
#else
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_is_fpsimd_save, DECLARE_HOOK(android_vh_is_fpsimd_save,
TP_PROTO(struct task_struct *prev, struct task_struct *next), TP_PROTO(struct task_struct *prev, struct task_struct *next),

View File

@@ -10,8 +10,15 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
struct irq_data; #ifdef __GENKSYMS__
struct cpumask; struct cpumask;
struct irq_data;
#else
/* struct cpumask */
#include <linux/cpumask.h>
/* struct irq_data */
#include <linux/irq.h>
#endif /* __GENKSYMS__ */
DECLARE_RESTRICTED_HOOK(android_rvh_gic_v3_set_affinity, DECLARE_RESTRICTED_HOOK(android_rvh_gic_v3_set_affinity,
TP_PROTO(struct irq_data *d, const struct cpumask *mask_val, TP_PROTO(struct irq_data *d, const struct cpumask *mask_val,
u64 *affinity, bool force, void __iomem *base), u64 *affinity, bool force, void __iomem *base),

View File

@@ -12,6 +12,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct iova_domain;
#else
/* struct iova_domain */
#include <linux/iova.h>
#endif /* __GENKSYMS__ */
DECLARE_RESTRICTED_HOOK(android_rvh_iommu_setup_dma_ops, DECLARE_RESTRICTED_HOOK(android_rvh_iommu_setup_dma_ops,
TP_PROTO(struct device *dev, u64 dma_base, u64 size), TP_PROTO(struct device *dev, u64 dma_base, u64 size),
TP_ARGS(dev, dma_base, size), 1); TP_ARGS(dev, dma_base, size), 1);
@@ -24,7 +30,6 @@ DECLARE_HOOK(android_vh_iommu_alloc_iova,
TP_PROTO(struct device *dev, dma_addr_t iova, size_t size), TP_PROTO(struct device *dev, dma_addr_t iova, size_t size),
TP_ARGS(dev, iova, size)); TP_ARGS(dev, iova, size));
struct iova_domain;
DECLARE_HOOK(android_vh_iommu_iovad_alloc_iova, DECLARE_HOOK(android_vh_iommu_iovad_alloc_iova,
TP_PROTO(struct device *dev, struct iova_domain *iovad, dma_addr_t iova, size_t size), TP_PROTO(struct device *dev, struct iova_domain *iovad, dma_addr_t iova, size_t size),

View File

@@ -10,8 +10,13 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
struct printk_ringbuffer; #if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_PRINTK)
struct printk_record; struct printk_record;
struct printk_ringbuffer;
#else
/* struct printk_record, struct printk_ringbuffer */
#include <../kernel/printk/printk_ringbuffer.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_logbuf, DECLARE_HOOK(android_vh_logbuf,
TP_PROTO(struct printk_ringbuffer *rb, struct printk_record *r), TP_PROTO(struct printk_ringbuffer *rb, struct printk_record *r),

View File

@@ -14,7 +14,26 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct slabinfo;
struct cgroup_subsys_state;
struct device;
struct mem_cgroup;
struct readahead_control;
#else
/* struct slabinfo */
#include <../mm/slab.h>
/* struct cgroup_subsys_state */
#include <linux/cgroup-defs.h>
/* struct device */
#include <linux/device.h>
/* struct mem_cgroup */
#include <linux/memcontrol.h>
/* struct readahead_control */
#include <linux/pagemap.h>
#endif /* __GENKSYMS__ */
struct cma; struct cma;
struct swap_slots_cache;
DECLARE_RESTRICTED_HOOK(android_rvh_set_skip_swapcache_flags, DECLARE_RESTRICTED_HOOK(android_rvh_set_skip_swapcache_flags,
TP_PROTO(gfp_t *flags), TP_PROTO(gfp_t *flags),
@@ -68,7 +87,6 @@ DECLARE_HOOK(android_vh_include_reserved_zone,
DECLARE_HOOK(android_vh_show_mem, DECLARE_HOOK(android_vh_show_mem,
TP_PROTO(unsigned int filter, nodemask_t *nodemask), TP_PROTO(unsigned int filter, nodemask_t *nodemask),
TP_ARGS(filter, nodemask)); TP_ARGS(filter, nodemask));
struct slabinfo;
struct dirty_throttle_control; struct dirty_throttle_control;
DECLARE_HOOK(android_vh_mm_dirty_limits, DECLARE_HOOK(android_vh_mm_dirty_limits,
TP_PROTO(struct dirty_throttle_control *const gdtc, bool strictlimit, TP_PROTO(struct dirty_throttle_control *const gdtc, bool strictlimit,
@@ -88,7 +106,6 @@ DECLARE_HOOK(android_vh_show_stack_hash,
DECLARE_HOOK(android_vh_save_track_hash, DECLARE_HOOK(android_vh_save_track_hash,
TP_PROTO(bool alloc, unsigned long p), TP_PROTO(bool alloc, unsigned long p),
TP_ARGS(alloc, p)); TP_ARGS(alloc, p));
struct mem_cgroup;
DECLARE_HOOK(android_vh_vmpressure, DECLARE_HOOK(android_vh_vmpressure,
TP_PROTO(struct mem_cgroup *memcg, bool *bypass), TP_PROTO(struct mem_cgroup *memcg, bool *bypass),
TP_ARGS(memcg, bypass)); TP_ARGS(memcg, bypass));
@@ -101,7 +118,6 @@ DECLARE_HOOK(android_vh_mem_cgroup_free,
DECLARE_HOOK(android_vh_mem_cgroup_id_remove, DECLARE_HOOK(android_vh_mem_cgroup_id_remove,
TP_PROTO(struct mem_cgroup *memcg), TP_PROTO(struct mem_cgroup *memcg),
TP_ARGS(memcg)); TP_ARGS(memcg));
struct cgroup_subsys_state;
DECLARE_HOOK(android_vh_mem_cgroup_css_online, DECLARE_HOOK(android_vh_mem_cgroup_css_online,
TP_PROTO(struct cgroup_subsys_state *css, struct mem_cgroup *memcg), TP_PROTO(struct cgroup_subsys_state *css, struct mem_cgroup *memcg),
TP_ARGS(css, memcg)); TP_ARGS(css, memcg));
@@ -128,14 +144,80 @@ DECLARE_HOOK(android_vh_cma_drain_all_pages_bypass,
DECLARE_HOOK(android_vh_pcplist_add_cma_pages_bypass, DECLARE_HOOK(android_vh_pcplist_add_cma_pages_bypass,
TP_PROTO(int migratetype, bool *bypass), TP_PROTO(int migratetype, bool *bypass),
TP_ARGS(migratetype, bypass)); TP_ARGS(migratetype, bypass));
struct device;
DECLARE_HOOK(android_vh_subpage_dma_contig_alloc, DECLARE_HOOK(android_vh_subpage_dma_contig_alloc,
TP_PROTO(bool *allow_subpage_alloc, struct device *dev, size_t *size), TP_PROTO(bool *allow_subpage_alloc, struct device *dev, size_t *size),
TP_ARGS(allow_subpage_alloc, dev, size)); TP_ARGS(allow_subpage_alloc, dev, size));
struct readahead_control;
DECLARE_HOOK(android_vh_ra_tuning_max_page, DECLARE_HOOK(android_vh_ra_tuning_max_page,
TP_PROTO(struct readahead_control *ractl, unsigned long *max_page), TP_PROTO(struct readahead_control *ractl, unsigned long *max_page),
TP_ARGS(ractl, max_page)); TP_ARGS(ractl, max_page));
DECLARE_HOOK(android_vh_handle_pte_fault_end,
TP_PROTO(struct vm_fault *vmf, unsigned long highest_memmap_pfn),
TP_ARGS(vmf, highest_memmap_pfn));
DECLARE_HOOK(android_vh_cow_user_page,
TP_PROTO(struct vm_fault *vmf, struct page *page),
TP_ARGS(vmf, page));
DECLARE_HOOK(android_vh_swapin_add_anon_rmap,
TP_PROTO(struct vm_fault *vmf, struct page *page),
TP_ARGS(vmf, page));
DECLARE_HOOK(android_vh_waiting_for_page_migration,
TP_PROTO(struct page *page),
TP_ARGS(page));
DECLARE_HOOK(android_vh_migrate_page_states,
TP_PROTO(struct page *page, struct page *newpage),
TP_ARGS(page, newpage));
DECLARE_HOOK(android_vh_page_referenced_one_end,
TP_PROTO(struct vm_area_struct *vma, struct page *page, int referenced),
TP_ARGS(vma, page, referenced));
DECLARE_HOOK(android_vh_count_pswpin,
TP_PROTO(struct swap_info_struct *sis),
TP_ARGS(sis));
DECLARE_HOOK(android_vh_count_pswpout,
TP_PROTO(struct swap_info_struct *sis),
TP_ARGS(sis));
DECLARE_HOOK(android_vh_count_swpout_vm_event,
TP_PROTO(struct swap_info_struct *sis, struct page *page, bool *skip),
TP_ARGS(sis, page, skip));
DECLARE_HOOK(android_vh_swap_slot_cache_active,
TP_PROTO(bool swap_slot_cache_active),
TP_ARGS(swap_slot_cache_active));
DECLARE_HOOK(android_vh_drain_slots_cache_cpu,
TP_PROTO(struct swap_slots_cache *cache, unsigned int type,
bool free_slots, bool *skip),
TP_ARGS(cache, type, free_slots, skip));
DECLARE_HOOK(android_vh_alloc_swap_slot_cache,
TP_PROTO(struct swap_slots_cache *cache, int *ret, bool *skip),
TP_ARGS(cache, ret, skip));
DECLARE_HOOK(android_vh_free_swap_slot,
TP_PROTO(swp_entry_t entry, struct swap_slots_cache *cache, bool *skip),
TP_ARGS(entry, cache, skip));
DECLARE_HOOK(android_vh_get_swap_page,
TP_PROTO(struct page *page, swp_entry_t *entry,
struct swap_slots_cache *cache, bool *found),
TP_ARGS(page, entry, cache, found));
DECLARE_HOOK(android_vh_page_isolated_for_reclaim,
TP_PROTO(struct mm_struct *mm, struct page *page),
TP_ARGS(mm, page));
DECLARE_HOOK(android_vh_account_swap_pages,
TP_PROTO(struct swap_info_struct *si, bool *skip),
TP_ARGS(si, skip));
DECLARE_HOOK(android_vh_unuse_swap_page,
TP_PROTO(struct swap_info_struct *si, struct page *page),
TP_ARGS(si, page));
DECLARE_HOOK(android_vh_init_swap_info_struct,
TP_PROTO(struct swap_info_struct *p, struct plist_head *swap_avail_heads),
TP_ARGS(p, swap_avail_heads));
DECLARE_HOOK(android_vh_si_swapinfo,
TP_PROTO(struct swap_info_struct *si, bool *skip),
TP_ARGS(si, skip));
DECLARE_HOOK(android_vh_alloc_si,
TP_PROTO(struct swap_info_struct **p, bool *skip),
TP_ARGS(p, skip));
DECLARE_HOOK(android_vh_free_pages,
TP_PROTO(struct page *page, unsigned int order),
TP_ARGS(page, order));
DECLARE_HOOK(android_vh_set_shmem_page_flag,
TP_PROTO(struct page *page),
TP_ARGS(page));
/* macro versions of hooks are no longer required */ /* macro versions of hooks are no longer required */
#endif /* _TRACE_HOOK_MM_H */ #endif /* _TRACE_HOOK_MM_H */

View File

@@ -10,9 +10,22 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
struct mmc_host; #if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_MMC_SDHCI)
struct mmc_card;
struct sdhci_host; struct sdhci_host;
#else
/* struct sdhci_host */
#include <../drivers/mmc/host/sdhci.h>
#endif
#ifdef __GENKSYMS__
struct mmc_card;
struct mmc_host;
#else
/* struct mmc_card */
#include <linux/mmc/card.h>
/* struct mmc_host */
#include <linux/mmc/host.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_mmc_blk_reset, DECLARE_HOOK(android_vh_mmc_blk_reset,
TP_PROTO(struct mmc_host *host, int err, bool *allow), TP_PROTO(struct mmc_host *host, int err, bool *allow),

View File

@@ -11,7 +11,12 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct module; struct module;
#else
/* struct module */
#include <linux/module.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_set_module_permit_before_init, DECLARE_HOOK(android_vh_set_module_permit_before_init,
TP_PROTO(const struct module *mod), TP_PROTO(const struct module *mod),
TP_ARGS(mod)); TP_ARGS(mod));

View File

@@ -9,9 +9,18 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct packet_type; struct packet_type;
struct list_head;
struct sk_buff; struct sk_buff;
struct list_head;
#else
/* struct packet_type */
#include <linux/netdevice.h>
/* struct sk_buff */
#include <linux/skbuff.h>
/* struct list_head */
#include <linux/types.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_ptype_head, DECLARE_HOOK(android_vh_ptype_head,
TP_PROTO(const struct packet_type *pt, struct list_head *vendor_pt), TP_PROTO(const struct packet_type *pt, struct list_head *vendor_pt),
TP_ARGS(pt, vendor_pt)); TP_ARGS(pt, vendor_pt));

View File

@@ -11,7 +11,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct generic_pm_domain; struct generic_pm_domain;
#else
/* struct generic_pm_domain */
#include <linux/pm_domain.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_allow_domain_state, DECLARE_HOOK(android_vh_allow_domain_state,
TP_PROTO(struct generic_pm_domain *genpd, uint32_t idx, bool *allow), TP_PROTO(struct generic_pm_domain *genpd, uint32_t idx, bool *allow),
TP_ARGS(genpd, idx, allow)) TP_ARGS(genpd, idx, allow))

View File

@@ -11,7 +11,17 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
enum freq_qos_req_type;
struct freq_constraints;
struct freq_qos_request;
struct task_struct; struct task_struct;
#else
/* enum freq_qos_req_type, struct freq_constraints, struct freq_qos_request */
#include <linux/pm_qos.h>
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_try_to_freeze_todo, DECLARE_HOOK(android_vh_try_to_freeze_todo,
TP_PROTO(unsigned int todo, unsigned int elapsed_msecs, bool wq_busy), TP_PROTO(unsigned int todo, unsigned int elapsed_msecs, bool wq_busy),
TP_ARGS(todo, elapsed_msecs, wq_busy)); TP_ARGS(todo, elapsed_msecs, wq_busy));
@@ -20,9 +30,6 @@ DECLARE_HOOK(android_vh_try_to_freeze_todo_unfrozen,
TP_PROTO(struct task_struct *p), TP_PROTO(struct task_struct *p),
TP_ARGS(p)); TP_ARGS(p));
enum freq_qos_req_type;
struct freq_qos_request;
struct freq_constraints;
DECLARE_HOOK(android_vh_freq_qos_add_request, DECLARE_HOOK(android_vh_freq_qos_add_request,
TP_PROTO(struct freq_constraints *qos, struct freq_qos_request *req, TP_PROTO(struct freq_constraints *qos, struct freq_qos_request *req,

View File

@@ -12,8 +12,13 @@
#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS) #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS)
struct psi_trigger; #if defined(__GENKSYMS__) || !defined(CONFIG_PSI)
struct psi_group; struct psi_group;
struct psi_trigger;
#else
/* struct psi_group, struct psi_trigger */
#include <linux/psi_types.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_psi_event, DECLARE_HOOK(android_vh_psi_event,
TP_PROTO(struct psi_trigger *t), TP_PROTO(struct psi_trigger *t),
TP_ARGS(t)); TP_ARGS(t));

View File

@@ -10,7 +10,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct rproc; struct rproc;
#else
/* struct rproc */
#include <linux/remoteproc.h>
#endif /* __GENKSYMS__ */
/* When recovery succeeds */ /* When recovery succeeds */
DECLARE_HOOK(android_vh_rproc_recovery, DECLARE_HOOK(android_vh_rproc_recovery,

View File

@@ -10,8 +10,13 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct rw_semaphore; struct rw_semaphore;
struct rwsem_waiter; struct rwsem_waiter;
#else
/* struct rw_semaphore, struct rwsem_waiter */
#include <linux/rwsem.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_rwsem_init, DECLARE_HOOK(android_vh_rwsem_init,
TP_PROTO(struct rw_semaphore *sem), TP_PROTO(struct rw_semaphore *sem),
TP_ARGS(sem)); TP_ARGS(sem));

View File

@@ -10,7 +10,25 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
struct cgroup_taskset;
#ifdef __GENKSYMS__
struct cgroup_subsys_state;
struct cpufreq_policy;
struct em_perf_domain;
enum uclamp_id;
struct sched_entity;
struct task_struct; struct task_struct;
struct uclamp_se;
#else
/* struct cgroup_subsys_state */
#include <linux/cgroup-defs.h>
/* struct cpufreq_policy */
#include <linux/cpufreq.h>
/* struct em_perf_domain */
#include <linux/energy_model.h>
/* enum uclamp_id, struct sched_entity, struct task_struct, struct uclamp_se */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_RESTRICTED_HOOK(android_rvh_select_task_rq_fair, DECLARE_RESTRICTED_HOOK(android_rvh_select_task_rq_fair,
TP_PROTO(struct task_struct *p, int prev_cpu, int sd_flag, int wake_flags, int *new_cpu), TP_PROTO(struct task_struct *p, int prev_cpu, int sd_flag, int wake_flags, int *new_cpu),
TP_ARGS(p, prev_cpu, sd_flag, wake_flags, new_cpu), 1); TP_ARGS(p, prev_cpu, sd_flag, wake_flags, new_cpu), 1);
@@ -178,7 +196,6 @@ DECLARE_RESTRICTED_HOOK(android_rvh_account_irq,
TP_PROTO(struct task_struct *curr, int cpu, s64 delta), TP_PROTO(struct task_struct *curr, int cpu, s64 delta),
TP_ARGS(curr, cpu, delta), 1); TP_ARGS(curr, cpu, delta), 1);
struct sched_entity;
DECLARE_RESTRICTED_HOOK(android_rvh_place_entity, DECLARE_RESTRICTED_HOOK(android_rvh_place_entity,
TP_PROTO(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial, u64 vruntime), TP_PROTO(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial, u64 vruntime),
TP_ARGS(cfs_rq, se, initial, vruntime), 1); TP_ARGS(cfs_rq, se, initial, vruntime), 1);
@@ -195,7 +212,6 @@ DECLARE_RESTRICTED_HOOK(android_rvh_update_misfit_status,
TP_PROTO(struct task_struct *p, struct rq *rq, bool *need_update), TP_PROTO(struct task_struct *p, struct rq *rq, bool *need_update),
TP_ARGS(p, rq, need_update), 1); TP_ARGS(p, rq, need_update), 1);
struct cgroup_taskset;
DECLARE_RESTRICTED_HOOK(android_rvh_cpu_cgroup_attach, DECLARE_RESTRICTED_HOOK(android_rvh_cpu_cgroup_attach,
TP_PROTO(struct cgroup_taskset *tset), TP_PROTO(struct cgroup_taskset *tset),
TP_ARGS(tset), 1); TP_ARGS(tset), 1);
@@ -204,7 +220,6 @@ DECLARE_RESTRICTED_HOOK(android_rvh_cpu_cgroup_can_attach,
TP_PROTO(struct cgroup_taskset *tset, int *retval), TP_PROTO(struct cgroup_taskset *tset, int *retval),
TP_ARGS(tset, retval), 1); TP_ARGS(tset, retval), 1);
struct cgroup_subsys_state;
DECLARE_RESTRICTED_HOOK(android_rvh_cpu_cgroup_online, DECLARE_RESTRICTED_HOOK(android_rvh_cpu_cgroup_online,
TP_PROTO(struct cgroup_subsys_state *css), TP_PROTO(struct cgroup_subsys_state *css),
TP_ARGS(css), 1); TP_ARGS(css), 1);
@@ -225,14 +240,12 @@ DECLARE_RESTRICTED_HOOK(android_rvh_sched_exec,
TP_PROTO(bool *cond), TP_PROTO(bool *cond),
TP_ARGS(cond), 1); TP_ARGS(cond), 1);
struct cpufreq_policy;
DECLARE_HOOK(android_vh_map_util_freq, DECLARE_HOOK(android_vh_map_util_freq,
TP_PROTO(unsigned long util, unsigned long freq, TP_PROTO(unsigned long util, unsigned long freq,
unsigned long cap, unsigned long *next_freq, struct cpufreq_policy *policy, unsigned long cap, unsigned long *next_freq, struct cpufreq_policy *policy,
bool *need_freq_update), bool *need_freq_update),
TP_ARGS(util, freq, cap, next_freq, policy, need_freq_update)); TP_ARGS(util, freq, cap, next_freq, policy, need_freq_update));
struct em_perf_domain;
DECLARE_HOOK(android_vh_em_cpu_energy, DECLARE_HOOK(android_vh_em_cpu_energy,
TP_PROTO(struct em_perf_domain *pd, TP_PROTO(struct em_perf_domain *pd,
unsigned long max_util, unsigned long sum_util, unsigned long max_util, unsigned long sum_util,
@@ -268,7 +281,7 @@ DECLARE_HOOK(android_vh_set_wake_flags,
TP_PROTO(int *wake_flags, unsigned int *mode), TP_PROTO(int *wake_flags, unsigned int *mode),
TP_ARGS(wake_flags, mode)); TP_ARGS(wake_flags, mode));
enum uclamp_id; /* Conditionally defined upon CONFIG_UCLAMP_TASK */
struct uclamp_se; struct uclamp_se;
DECLARE_RESTRICTED_HOOK(android_rvh_uclamp_eff_get, DECLARE_RESTRICTED_HOOK(android_rvh_uclamp_eff_get,
TP_PROTO(struct task_struct *p, enum uclamp_id clamp_id, TP_PROTO(struct task_struct *p, enum uclamp_id clamp_id,
@@ -329,7 +342,6 @@ DECLARE_RESTRICTED_HOOK(android_rvh_after_dequeue_task,
TP_ARGS(rq, p), 1); TP_ARGS(rq, p), 1);
struct cfs_rq; struct cfs_rq;
struct sched_entity;
struct rq_flags; struct rq_flags;
DECLARE_RESTRICTED_HOOK(android_rvh_enqueue_entity, DECLARE_RESTRICTED_HOOK(android_rvh_enqueue_entity,
TP_PROTO(struct cfs_rq *cfs, struct sched_entity *se), TP_PROTO(struct cfs_rq *cfs, struct sched_entity *se),

View File

@@ -8,7 +8,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct page; struct page;
#else
/* struct page */
#include <linux/mm_types.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_shmem_alloc_page, DECLARE_HOOK(android_vh_shmem_alloc_page,
TP_PROTO(struct page **page), TP_PROTO(struct page **page),
TP_ARGS(page)); TP_ARGS(page));

View File

@@ -8,7 +8,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct task_struct; struct task_struct;
#else
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_do_send_sig_info, DECLARE_HOOK(android_vh_do_send_sig_info,
TP_PROTO(int sig, struct task_struct *killer, struct task_struct *dst), TP_PROTO(int sig, struct task_struct *killer, struct task_struct *dst),
TP_ARGS(sig, killer, dst)); TP_ARGS(sig, killer, dst));

View File

@@ -11,7 +11,12 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct pt_regs; struct pt_regs;
#else
/* struct pt_regs */
#include <asm/ptrace.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_watchdog_timer_softlockup, DECLARE_HOOK(android_vh_watchdog_timer_softlockup,
TP_PROTO(int duration, struct pt_regs *regs, bool is_panic), TP_PROTO(int duration, struct pt_regs *regs, bool is_panic),
TP_ARGS(duration, regs, is_panic)); TP_ARGS(duration, regs, is_panic));

View File

@@ -8,7 +8,12 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct task_struct; struct task_struct;
#else
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_syscall_prctl_finished, DECLARE_HOOK(android_vh_syscall_prctl_finished,
TP_PROTO(int option, struct task_struct *task), TP_PROTO(int option, struct task_struct *task),
TP_ARGS(option, task)); TP_ARGS(option, task));

View File

@@ -11,8 +11,15 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct file; struct file;
union bpf_attr; union bpf_attr;
#else
/* struct file */
#include <linux/fs.h>
/* union bpf_attr */
#include <uapi/linux/bpf.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_check_mmap_file, DECLARE_HOOK(android_vh_check_mmap_file,
TP_PROTO(const struct file *file, unsigned long prot, TP_PROTO(const struct file *file, unsigned long prot,
unsigned long flag, unsigned long ret), unsigned long flag, unsigned long ret),

View File

@@ -10,11 +10,16 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct thermal_zone_device;
#else
/* struct thermal_zone_device */
#include <linux/thermal.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_enable_thermal_genl_check, DECLARE_HOOK(android_vh_enable_thermal_genl_check,
TP_PROTO(int event, int tz_id, int *enable_thermal_genl), TP_PROTO(int event, int tz_id, int *enable_thermal_genl),
TP_ARGS(event, tz_id, enable_thermal_genl)); TP_ARGS(event, tz_id, enable_thermal_genl));
struct thermal_zone_device;
DECLARE_HOOK(android_vh_thermal_pm_notify_suspend, DECLARE_HOOK(android_vh_thermal_pm_notify_suspend,
TP_PROTO(struct thermal_zone_device *tz, int *irq_wakeable), TP_PROTO(struct thermal_zone_device *tz, int *irq_wakeable),
TP_ARGS(tz, irq_wakeable)); TP_ARGS(tz, irq_wakeable));

View File

@@ -11,7 +11,12 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#ifdef __GENKSYMS__
struct pt_regs; struct pt_regs;
#else
/* struct pt_regs */
#include <asm/ptrace.h>
#endif /* __GENKSYMS__ */
DECLARE_RESTRICTED_HOOK(android_rvh_do_undefinstr, DECLARE_RESTRICTED_HOOK(android_rvh_do_undefinstr,
TP_PROTO(struct pt_regs *regs, bool user), TP_PROTO(struct pt_regs *regs, bool user),
TP_ARGS(regs, user), TP_ARGS(regs, user),

View File

@@ -6,13 +6,19 @@
#define _TRACE_HOOK_TYPEC_H #define _TRACE_HOOK_TYPEC_H
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <linux/usb/pd.h> #include <linux/usb/pd.h>
#include <linux/usb/tcpm.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
/* /*
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
struct tcpci; #if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_TYPEC_TCPCI)
struct tcpci_data; struct tcpci_data;
#else
/* struct tcpci_data */
#include <../drivers/usb/typec/tcpm/tcpci.h>
#endif /* __GENKSYMS__ */
struct tcpci;
struct tcpm_port; struct tcpm_port;
#ifndef TYPEC_TIMER #ifndef TYPEC_TIMER

View File

@@ -10,9 +10,20 @@
* Following tracepoints are not exported in tracefs and provide a * Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality * mechanism for vendor modules to hook and extend functionality
*/ */
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_SCSI_UFSHCD)
struct ufs_hba; struct ufs_hba;
struct request;
struct ufshcd_lrb; struct ufshcd_lrb;
struct uic_command;
struct request;
struct scsi_device;
#else
/* struct ufs_hba, struct ufshcd_lrb, struct uic_command */
#include <../drivers/scsi/ufs/ufshcd.h>
/* struct request */
#include <linux/blkdev.h>
/* struct scsi_device */
#include <scsi/scsi_device.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_ufs_fill_prdt, DECLARE_HOOK(android_vh_ufs_fill_prdt,
TP_PROTO(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, TP_PROTO(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
@@ -44,7 +55,6 @@ DECLARE_HOOK(android_vh_ufs_compl_command,
TP_PROTO(struct ufs_hba *hba, struct ufshcd_lrb *lrbp), TP_PROTO(struct ufs_hba *hba, struct ufshcd_lrb *lrbp),
TP_ARGS(hba, lrbp)); TP_ARGS(hba, lrbp));
struct uic_command;
DECLARE_HOOK(android_vh_ufs_send_uic_command, DECLARE_HOOK(android_vh_ufs_send_uic_command,
TP_PROTO(struct ufs_hba *hba, struct uic_command *ucmd, TP_PROTO(struct ufs_hba *hba, struct uic_command *ucmd,
const char *str), const char *str),
@@ -58,7 +68,6 @@ DECLARE_HOOK(android_vh_ufs_check_int_errors,
TP_PROTO(struct ufs_hba *hba, bool queue_eh_work), TP_PROTO(struct ufs_hba *hba, bool queue_eh_work),
TP_ARGS(hba, queue_eh_work)); TP_ARGS(hba, queue_eh_work));
struct scsi_device;
DECLARE_HOOK(android_vh_ufs_update_sdev, DECLARE_HOOK(android_vh_ufs_update_sdev,
TP_PROTO(struct scsi_device *sdev), TP_PROTO(struct scsi_device *sdev),
TP_ARGS(sdev)); TP_ARGS(sdev));

View File

@@ -10,12 +10,26 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct v4l2_subdev;
struct v4l2_subdev_pad_config;
struct v4l2_subdev_format;
struct v4l2_subdev_frame_interval;
struct v4l2_subdev_selection;
struct v4l2_fmtdesc;
struct v4l2_format; struct v4l2_format;
#else
/* struct v4l2_subdev, struct v4l2_subdev_pad_config */
#include <media/v4l2-subdev.h>
/* struct v4l2_subdev_format, struct v4l2_subdev_frame_interval, struct v4l2_subdev_selection */
#include <uapi/linux/v4l2-subdev.h>
/* struct v4l2_fmtdesc, struct v4l2_format */
#include <uapi/linux/videodev2.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_clear_reserved_fmt_fields, DECLARE_HOOK(android_vh_clear_reserved_fmt_fields,
TP_PROTO(struct v4l2_format *fmt, int *ret), TP_PROTO(struct v4l2_format *fmt, int *ret),
TP_ARGS(fmt, ret)); TP_ARGS(fmt, ret));
struct v4l2_fmtdesc;
DECLARE_HOOK(android_vh_fill_ext_fmtdesc, DECLARE_HOOK(android_vh_fill_ext_fmtdesc,
TP_PROTO(struct v4l2_fmtdesc *fmtd, const char **descr), TP_PROTO(struct v4l2_fmtdesc *fmtd, const char **descr),
TP_ARGS(fmtd, descr)); TP_ARGS(fmtd, descr));
@@ -24,21 +38,16 @@ DECLARE_HOOK(android_vh_clear_mask_adjust,
TP_PROTO(unsigned int ctrl, int *n), TP_PROTO(unsigned int ctrl, int *n),
TP_ARGS(ctrl, n)); TP_ARGS(ctrl, n));
struct v4l2_subdev;
struct v4l2_subdev_pad_config;
struct v4l2_subdev_selection;
DECLARE_HOOK(android_vh_v4l2subdev_set_selection, DECLARE_HOOK(android_vh_v4l2subdev_set_selection,
TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *pad, TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *pad,
struct v4l2_subdev_selection *sel, int *ret), struct v4l2_subdev_selection *sel, int *ret),
TP_ARGS(sd, pad, sel, ret)); TP_ARGS(sd, pad, sel, ret));
struct v4l2_subdev_format;
DECLARE_HOOK(android_vh_v4l2subdev_set_fmt, DECLARE_HOOK(android_vh_v4l2subdev_set_fmt,
TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *pad, TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *pad,
struct v4l2_subdev_format *format, int *ret), struct v4l2_subdev_format *format, int *ret),
TP_ARGS(sd, pad, format, ret)); TP_ARGS(sd, pad, format, ret));
struct v4l2_subdev_frame_interval;
DECLARE_HOOK(android_vh_v4l2subdev_set_frame_interval, DECLARE_HOOK(android_vh_v4l2subdev_set_frame_interval,
TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *fi, TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *fi,
int *ret), int *ret),

View File

@@ -10,8 +10,15 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h> #include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct media_link; struct media_link;
struct media_link_desc; struct media_link_desc;
#else
/* struct media_link */
#include <media/media-entity.h>
/* struct media_link_desc */
#include <uapi/linux/media.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_media_device_setup_link, DECLARE_HOOK(android_vh_media_device_setup_link,
TP_PROTO(struct media_link *link, struct media_link_desc *linkd, int *ret), TP_PROTO(struct media_link *link, struct media_link_desc *linkd, int *ret),
TP_ARGS(link, linkd, ret)); TP_ARGS(link, linkd, ret));

View File

@@ -34,6 +34,13 @@ DECLARE_HOOK(android_vh_shrink_node_memcgs,
DECLARE_HOOK(android_vh_tune_memcg_scan_type, DECLARE_HOOK(android_vh_tune_memcg_scan_type,
TP_PROTO(struct mem_cgroup *memcg, char *scan_type), TP_PROTO(struct mem_cgroup *memcg, char *scan_type),
TP_ARGS(memcg, scan_type)); TP_ARGS(memcg, scan_type));
DECLARE_HOOK(android_vh_inactive_is_low,
TP_PROTO(unsigned long gb, unsigned long *inactive_ratio,
enum lru_list inactive_lru, bool *skip),
TP_ARGS(gb, inactive_ratio, inactive_lru, skip));
DECLARE_HOOK(android_vh_snapshot_refaults,
TP_PROTO(struct lruvec *target_lruvec),
TP_ARGS(target_lruvec));
#endif /* _TRACE_HOOK_VMSCAN_H */ #endif /* _TRACE_HOOK_VMSCAN_H */
/* This part must be outside protection */ /* This part must be outside protection */
#include <trace/define_trace.h> #include <trace/define_trace.h>

View File

@@ -319,6 +319,7 @@ enum transaction_flags {
TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */ TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */ TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */ TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
TF_UPDATE_TXN = 0x40, /* update the outdated pending async txn */
}; };
struct binder_transaction_data { struct binder_transaction_data {

View File

@@ -746,25 +746,28 @@ EXPORT_SYMBOL_GPL(of_css);
* reference-counted, to improve performance when child cgroups * reference-counted, to improve performance when child cgroups
* haven't been created. * haven't been created.
*/ */
struct css_set init_css_set = { struct ext_css_set init_ext_css_set = {
.refcount = REFCOUNT_INIT(1), .cset = {
.dom_cset = &init_css_set, .refcount = REFCOUNT_INIT(1),
.tasks = LIST_HEAD_INIT(init_css_set.tasks), .dom_cset = &init_css_set,
.mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks), .tasks = LIST_HEAD_INIT(init_css_set.tasks),
.dying_tasks = LIST_HEAD_INIT(init_css_set.dying_tasks), .mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks),
.task_iters = LIST_HEAD_INIT(init_css_set.task_iters), .dying_tasks = LIST_HEAD_INIT(init_css_set.dying_tasks),
.threaded_csets = LIST_HEAD_INIT(init_css_set.threaded_csets), .task_iters = LIST_HEAD_INIT(init_css_set.task_iters),
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links), .threaded_csets = LIST_HEAD_INIT(init_css_set.threaded_csets),
.mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node), .cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
.mg_node = LIST_HEAD_INIT(init_css_set.mg_node), .mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node),
.mg_node = LIST_HEAD_INIT(init_css_set.mg_node),
/* /*
* The following field is re-initialized when this cset gets linked * The following field is re-initialized when this cset gets linked
* in cgroup_init(). However, let's initialize the field * in cgroup_init(). However, let's initialize the field
* statically too so that the default cgroup can be accessed safely * statically too so that the default cgroup can be accessed safely
* early during boot. * early during boot.
*/ */
.dfl_cgrp = &cgrp_dfl_root.cgrp, .dfl_cgrp = &cgrp_dfl_root.cgrp,
},
.mg_src_preload_node = LIST_HEAD_INIT(init_ext_css_set.mg_src_preload_node),
.mg_dst_preload_node = LIST_HEAD_INIT(init_ext_css_set.mg_dst_preload_node),
}; };
static int css_set_count = 1; /* 1 for init_css_set */ static int css_set_count = 1; /* 1 for init_css_set */
@@ -1191,6 +1194,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
struct cgroup *cgrp) struct cgroup *cgrp)
{ {
struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT] = { }; struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT] = { };
struct ext_css_set *ext_cset;
struct css_set *cset; struct css_set *cset;
struct list_head tmp_links; struct list_head tmp_links;
struct cgrp_cset_link *link; struct cgrp_cset_link *link;
@@ -1211,9 +1215,10 @@ static struct css_set *find_css_set(struct css_set *old_cset,
if (cset) if (cset)
return cset; return cset;
cset = kzalloc(sizeof(*cset), GFP_KERNEL); ext_cset = kzalloc(sizeof(*ext_cset), GFP_KERNEL);
if (!cset) if (!ext_cset)
return NULL; return NULL;
cset = &ext_cset->cset;
/* Allocate all the cgrp_cset_link objects that we'll need */ /* Allocate all the cgrp_cset_link objects that we'll need */
if (allocate_cgrp_cset_links(cgroup_root_count, &tmp_links) < 0) { if (allocate_cgrp_cset_links(cgroup_root_count, &tmp_links) < 0) {
@@ -1231,6 +1236,8 @@ static struct css_set *find_css_set(struct css_set *old_cset,
INIT_HLIST_NODE(&cset->hlist); INIT_HLIST_NODE(&cset->hlist);
INIT_LIST_HEAD(&cset->cgrp_links); INIT_LIST_HEAD(&cset->cgrp_links);
INIT_LIST_HEAD(&cset->mg_preload_node); INIT_LIST_HEAD(&cset->mg_preload_node);
INIT_LIST_HEAD(&ext_cset->mg_src_preload_node);
INIT_LIST_HEAD(&ext_cset->mg_dst_preload_node);
INIT_LIST_HEAD(&cset->mg_node); INIT_LIST_HEAD(&cset->mg_node);
/* Copy the set of subsystem state objects generated in /* Copy the set of subsystem state objects generated in
@@ -2578,22 +2585,28 @@ int cgroup_migrate_vet_dst(struct cgroup *dst_cgrp)
*/ */
void cgroup_migrate_finish(struct cgroup_mgctx *mgctx) void cgroup_migrate_finish(struct cgroup_mgctx *mgctx)
{ {
LIST_HEAD(preloaded); struct ext_css_set *cset, *tmp_cset;
struct css_set *cset, *tmp_cset;
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
spin_lock_irq(&css_set_lock); spin_lock_irq(&css_set_lock);
list_splice_tail_init(&mgctx->preloaded_src_csets, &preloaded); list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_src_csets,
list_splice_tail_init(&mgctx->preloaded_dst_csets, &preloaded); mg_src_preload_node) {
cset->cset.mg_src_cgrp = NULL;
cset->cset.mg_dst_cgrp = NULL;
cset->cset.mg_dst_cset = NULL;
list_del_init(&cset->mg_src_preload_node);
put_css_set_locked(&cset->cset);
}
list_for_each_entry_safe(cset, tmp_cset, &preloaded, mg_preload_node) { list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_dst_csets,
cset->mg_src_cgrp = NULL; mg_dst_preload_node) {
cset->mg_dst_cgrp = NULL; cset->cset.mg_src_cgrp = NULL;
cset->mg_dst_cset = NULL; cset->cset.mg_dst_cgrp = NULL;
list_del_init(&cset->mg_preload_node); cset->cset.mg_dst_cset = NULL;
put_css_set_locked(cset); list_del_init(&cset->mg_dst_preload_node);
put_css_set_locked(&cset->cset);
} }
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);
@@ -2620,6 +2633,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
struct cgroup_mgctx *mgctx) struct cgroup_mgctx *mgctx)
{ {
struct cgroup *src_cgrp; struct cgroup *src_cgrp;
struct ext_css_set *ext_src_cset;
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
lockdep_assert_held(&css_set_lock); lockdep_assert_held(&css_set_lock);
@@ -2633,8 +2647,9 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
return; return;
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root); src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
ext_src_cset = container_of(src_cset, struct ext_css_set, cset);
if (!list_empty(&src_cset->mg_preload_node)) if (!list_empty(&ext_src_cset->mg_src_preload_node))
return; return;
WARN_ON(src_cset->mg_src_cgrp); WARN_ON(src_cset->mg_src_cgrp);
@@ -2645,7 +2660,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
src_cset->mg_src_cgrp = src_cgrp; src_cset->mg_src_cgrp = src_cgrp;
src_cset->mg_dst_cgrp = dst_cgrp; src_cset->mg_dst_cgrp = dst_cgrp;
get_css_set(src_cset); get_css_set(src_cset);
list_add_tail(&src_cset->mg_preload_node, &mgctx->preloaded_src_csets); list_add_tail(&ext_src_cset->mg_src_preload_node, &mgctx->preloaded_src_csets);
} }
/** /**
@@ -2664,20 +2679,23 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
*/ */
int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx) int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
{ {
struct css_set *src_cset, *tmp_cset; struct ext_css_set *ext_src_set, *tmp_cset;
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
/* look up the dst cset for each src cset and link it to src */ /* look up the dst cset for each src cset and link it to src */
list_for_each_entry_safe(src_cset, tmp_cset, &mgctx->preloaded_src_csets, list_for_each_entry_safe(ext_src_set, tmp_cset, &mgctx->preloaded_src_csets,
mg_preload_node) { mg_src_preload_node) {
struct css_set *src_cset = &ext_src_set->cset;
struct css_set *dst_cset; struct css_set *dst_cset;
struct ext_css_set *ext_dst_cset;
struct cgroup_subsys *ss; struct cgroup_subsys *ss;
int ssid; int ssid;
dst_cset = find_css_set(src_cset, src_cset->mg_dst_cgrp); dst_cset = find_css_set(src_cset, src_cset->mg_dst_cgrp);
if (!dst_cset) if (!dst_cset)
return -ENOMEM; return -ENOMEM;
ext_dst_cset = container_of(dst_cset, struct ext_css_set, cset);
WARN_ON_ONCE(src_cset->mg_dst_cset || dst_cset->mg_dst_cset); WARN_ON_ONCE(src_cset->mg_dst_cset || dst_cset->mg_dst_cset);
@@ -2689,7 +2707,7 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
if (src_cset == dst_cset) { if (src_cset == dst_cset) {
src_cset->mg_src_cgrp = NULL; src_cset->mg_src_cgrp = NULL;
src_cset->mg_dst_cgrp = NULL; src_cset->mg_dst_cgrp = NULL;
list_del_init(&src_cset->mg_preload_node); list_del_init(&ext_src_set->mg_src_preload_node);
put_css_set(src_cset); put_css_set(src_cset);
put_css_set(dst_cset); put_css_set(dst_cset);
continue; continue;
@@ -2697,8 +2715,8 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
src_cset->mg_dst_cset = dst_cset; src_cset->mg_dst_cset = dst_cset;
if (list_empty(&dst_cset->mg_preload_node)) if (list_empty(&ext_dst_cset->mg_dst_preload_node))
list_add_tail(&dst_cset->mg_preload_node, list_add_tail(&ext_dst_cset->mg_dst_preload_node,
&mgctx->preloaded_dst_csets); &mgctx->preloaded_dst_csets);
else else
put_css_set(dst_cset); put_css_set(dst_cset);
@@ -2926,7 +2944,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
DEFINE_CGROUP_MGCTX(mgctx); DEFINE_CGROUP_MGCTX(mgctx);
struct cgroup_subsys_state *d_css; struct cgroup_subsys_state *d_css;
struct cgroup *dsct; struct cgroup *dsct;
struct css_set *src_cset; struct ext_css_set *ext_src_set;
int ret; int ret;
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
@@ -2949,11 +2967,12 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
goto out_finish; goto out_finish;
spin_lock_irq(&css_set_lock); spin_lock_irq(&css_set_lock);
list_for_each_entry(src_cset, &mgctx.preloaded_src_csets, mg_preload_node) { list_for_each_entry(ext_src_set, &mgctx.preloaded_src_csets,
mg_src_preload_node) {
struct task_struct *task, *ntask; struct task_struct *task, *ntask;
/* all tasks in src_csets need to be migrated */ /* all tasks in src_csets need to be migrated */
list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list) list_for_each_entry_safe(task, ntask, &ext_src_set->cset.tasks, cg_list)
cgroup_migrate_add_task(task, &mgctx); cgroup_migrate_add_task(task, &mgctx);
} }
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);

View File

@@ -1147,10 +1147,11 @@ static void check_sync(struct device *dev,
dir2name[entry->direction], dir2name[entry->direction],
dir2name[ref->direction]); dir2name[ref->direction]);
/* sg list count can be less than map count when partial cache sync */
if (ref->sg_call_ents && ref->type == dma_debug_sg && if (ref->sg_call_ents && ref->type == dma_debug_sg &&
ref->sg_call_ents != entry->sg_call_ents) { ref->sg_call_ents > entry->sg_call_ents) {
err_printk(ref->dev, entry, "device driver syncs " err_printk(ref->dev, entry, "device driver syncs "
"DMA sg list with different entry count " "DMA sg list count larger than map count "
"[map count=%d] [sync count=%d]\n", "[map count=%d] [sync count=%d]\n",
entry->sg_call_ents, ref->sg_call_ents); entry->sg_call_ents, ref->sg_call_ents);
} }

View File

@@ -29,6 +29,7 @@
#include <linux/swapops.h> #include <linux/swapops.h>
#include <linux/shmem_fs.h> #include <linux/shmem_fs.h>
#include <linux/mmu_notifier.h> #include <linux/mmu_notifier.h>
#include <trace/hooks/mm.h>
#include <asm/tlb.h> #include <asm/tlb.h>
@@ -462,8 +463,10 @@ regular_page:
if (!isolate_lru_page(page)) { if (!isolate_lru_page(page)) {
if (PageUnevictable(page)) if (PageUnevictable(page))
putback_lru_page(page); putback_lru_page(page);
else else {
list_add(&page->lru, &page_list); list_add(&page->lru, &page_list);
trace_android_vh_page_isolated_for_reclaim(mm, page);
}
} }
} else } else
deactivate_page(page); deactivate_page(page);

View File

@@ -86,6 +86,7 @@
#include "pgalloc-track.h" #include "pgalloc-track.h"
#include "internal.h" #include "internal.h"
#include <trace/hooks/mm.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/pagefault.h> #include <trace/events/pagefault.h>
@@ -3141,6 +3142,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
put_page(old_page); put_page(old_page);
return 0; return 0;
} }
trace_android_vh_cow_user_page(vmf, new_page);
} }
if (mem_cgroup_charge(new_page, mm, GFP_KERNEL)) if (mem_cgroup_charge(new_page, mm, GFP_KERNEL))
@@ -3782,6 +3784,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
do_page_add_anon_rmap(page, vma, vmf->address, exclusive); do_page_add_anon_rmap(page, vma, vmf->address, exclusive);
} }
trace_android_vh_swapin_add_anon_rmap(vmf, page);
swap_free(entry); swap_free(entry);
if (mem_cgroup_swap_full(page) || if (mem_cgroup_swap_full(page) ||
(vmf->vma_flags & VM_LOCKED) || PageMlocked(page)) (vmf->vma_flags & VM_LOCKED) || PageMlocked(page))
@@ -4760,6 +4763,7 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
if (vmf->flags & FAULT_FLAG_WRITE) if (vmf->flags & FAULT_FLAG_WRITE)
flush_tlb_fix_spurious_fault(vmf->vma, vmf->address); flush_tlb_fix_spurious_fault(vmf->vma, vmf->address);
} }
trace_android_vh_handle_pte_fault_end(vmf, highest_memmap_pfn);
unlock: unlock:
pte_unmap_unlock(vmf->pte, vmf->ptl); pte_unmap_unlock(vmf->pte, vmf->ptl);
return ret; return ret;

View File

@@ -54,6 +54,8 @@
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/migrate.h> #include <trace/events/migrate.h>
#undef CREATE_TRACE_POINTS
#include <trace/hooks/mm.h>
#include "internal.h" #include "internal.h"
@@ -311,6 +313,7 @@ void __migration_entry_wait(struct mm_struct *mm, pte_t *ptep,
if (!get_page_unless_zero(page)) if (!get_page_unless_zero(page))
goto out; goto out;
pte_unmap_unlock(ptep, ptl); pte_unmap_unlock(ptep, ptl);
trace_android_vh_waiting_for_page_migration(page);
put_and_wait_on_page_locked(page); put_and_wait_on_page_locked(page);
return; return;
out: out:
@@ -584,6 +587,8 @@ void migrate_page_states(struct page *newpage, struct page *page)
{ {
int cpupid; int cpupid;
trace_android_vh_migrate_page_states(page, newpage);
if (PageError(page)) if (PageError(page))
SetPageError(newpage); SetPageError(newpage);
if (PageReferenced(page)) if (PageReferenced(page))

View File

@@ -5180,6 +5180,7 @@ static inline void free_the_page(struct page *page, unsigned int order)
void __free_pages(struct page *page, unsigned int order) void __free_pages(struct page *page, unsigned int order)
{ {
trace_android_vh_free_pages(page, order);
if (put_page_testzero(page)) if (put_page_testzero(page))
free_the_page(page, order); free_the_page(page, order);
else if (!PageHead(page)) else if (!PageHead(page))

View File

@@ -25,6 +25,7 @@
#include <linux/psi.h> #include <linux/psi.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/sched/task.h> #include <linux/sched/task.h>
#include <trace/hooks/mm.h>
static struct bio *get_swap_bio(gfp_t gfp_flags, static struct bio *get_swap_bio(gfp_t gfp_flags,
struct page *page, bio_end_io_t end_io) struct page *page, bio_end_io_t end_io)
@@ -256,6 +257,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
struct bio *bio; struct bio *bio;
int ret; int ret;
struct swap_info_struct *sis = page_swap_info(page); struct swap_info_struct *sis = page_swap_info(page);
bool skip = false;
VM_BUG_ON_PAGE(!PageSwapCache(page), page); VM_BUG_ON_PAGE(!PageSwapCache(page), page);
if (data_race(sis->flags & SWP_FS_OPS)) { if (data_race(sis->flags & SWP_FS_OPS)) {
@@ -277,6 +279,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
unlock_page(page); unlock_page(page);
ret = mapping->a_ops->direct_IO(&kiocb, &from); ret = mapping->a_ops->direct_IO(&kiocb, &from);
if (ret == PAGE_SIZE) { if (ret == PAGE_SIZE) {
trace_android_vh_count_pswpout(sis);
count_vm_event(PSWPOUT); count_vm_event(PSWPOUT);
ret = 0; ret = 0;
} else { } else {
@@ -301,7 +304,9 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc); ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc);
if (!ret) { if (!ret) {
count_swpout_vm_event(page); trace_android_vh_count_swpout_vm_event(sis, page, &skip);
if (!skip)
count_swpout_vm_event(page);
return 0; return 0;
} }
@@ -313,7 +318,9 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
} }
bio->bi_opf = REQ_OP_WRITE | REQ_SWAP | wbc_to_write_flags(wbc); bio->bi_opf = REQ_OP_WRITE | REQ_SWAP | wbc_to_write_flags(wbc);
bio_associate_blkg_from_page(bio, page); bio_associate_blkg_from_page(bio, page);
count_swpout_vm_event(page); trace_android_vh_count_swpout_vm_event(sis, page, &skip);
if (!skip)
count_swpout_vm_event(page);
set_page_writeback(page); set_page_writeback(page);
unlock_page(page); unlock_page(page);
submit_bio(bio); submit_bio(bio);
@@ -352,14 +359,17 @@ int swap_readpage(struct page *page, bool synchronous)
struct address_space *mapping = swap_file->f_mapping; struct address_space *mapping = swap_file->f_mapping;
ret = mapping->a_ops->readpage(swap_file, page); ret = mapping->a_ops->readpage(swap_file, page);
if (!ret) if (!ret) {
trace_android_vh_count_pswpin(sis);
count_vm_event(PSWPIN); count_vm_event(PSWPIN);
}
goto out; goto out;
} }
if (sis->flags & SWP_SYNCHRONOUS_IO) { if (sis->flags & SWP_SYNCHRONOUS_IO) {
ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); ret = bdev_read_page(sis->bdev, swap_page_sector(page), page);
if (!ret) { if (!ret) {
trace_android_vh_count_pswpin(sis);
count_vm_event(PSWPIN); count_vm_event(PSWPIN);
goto out; goto out;
} }
@@ -383,6 +393,7 @@ int swap_readpage(struct page *page, bool synchronous)
get_task_struct(current); get_task_struct(current);
bio->bi_private = current; bio->bi_private = current;
} }
trace_android_vh_count_pswpin(sis);
count_vm_event(PSWPIN); count_vm_event(PSWPIN);
bio_get(bio); bio_get(bio);
qc = submit_bio(bio); qc = submit_bio(bio);

View File

@@ -819,6 +819,7 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma,
pra->vm_flags |= vma->vm_flags; pra->vm_flags |= vma->vm_flags;
} }
trace_android_vh_page_referenced_one_end(vma, page, referenced);
if (!pra->mapcount) if (!pra->mapcount)
return false; /* To break the loop */ return false; /* To break the loop */

View File

@@ -46,6 +46,7 @@
#undef CREATE_TRACE_POINTS #undef CREATE_TRACE_POINTS
#include <trace/hooks/shmem_fs.h> #include <trace/hooks/shmem_fs.h>
#include <trace/hooks/mm.h>
static struct vfsmount *shm_mnt; static struct vfsmount *shm_mnt;
@@ -1430,6 +1431,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
SetPageUptodate(page); SetPageUptodate(page);
} }
trace_android_vh_set_shmem_page_flag(page);
swap = get_swap_page(page); swap = get_swap_page(page);
if (!swap.val) if (!swap.val)
goto redirty; goto redirty;
@@ -4311,7 +4313,6 @@ int reclaim_shmem_address_space(struct address_space *mapping)
pgoff_t start = 0; pgoff_t start = 0;
struct page *page; struct page *page;
LIST_HEAD(page_list); LIST_HEAD(page_list);
int reclaimed;
XA_STATE(xas, &mapping->i_pages, start); XA_STATE(xas, &mapping->i_pages, start);
if (!shmem_mapping(mapping)) if (!shmem_mapping(mapping))
@@ -4329,8 +4330,6 @@ int reclaim_shmem_address_space(struct address_space *mapping)
continue; continue;
list_add(&page->lru, &page_list); list_add(&page->lru, &page_list);
inc_node_page_state(page, NR_ISOLATED_ANON +
page_is_file_lru(page));
if (need_resched()) { if (need_resched()) {
xas_pause(&xas); xas_pause(&xas);
@@ -4338,9 +4337,8 @@ int reclaim_shmem_address_space(struct address_space *mapping)
} }
} }
rcu_read_unlock(); rcu_read_unlock();
reclaimed = reclaim_pages_from_list(&page_list);
return reclaimed; return reclaim_pages(&page_list);
#else #else
return 0; return 0;
#endif #endif

View File

@@ -33,6 +33,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <trace/hooks/mm.h>
static DEFINE_PER_CPU(struct swap_slots_cache, swp_slots); static DEFINE_PER_CPU(struct swap_slots_cache, swp_slots);
static bool swap_slot_cache_active; static bool swap_slot_cache_active;
@@ -54,6 +55,7 @@ static void deactivate_swap_slots_cache(void)
{ {
mutex_lock(&swap_slots_cache_mutex); mutex_lock(&swap_slots_cache_mutex);
swap_slot_cache_active = false; swap_slot_cache_active = false;
trace_android_vh_swap_slot_cache_active(false);
__drain_swap_slots_cache(SLOTS_CACHE|SLOTS_CACHE_RET); __drain_swap_slots_cache(SLOTS_CACHE|SLOTS_CACHE_RET);
mutex_unlock(&swap_slots_cache_mutex); mutex_unlock(&swap_slots_cache_mutex);
} }
@@ -62,6 +64,7 @@ static void reactivate_swap_slots_cache(void)
{ {
mutex_lock(&swap_slots_cache_mutex); mutex_lock(&swap_slots_cache_mutex);
swap_slot_cache_active = true; swap_slot_cache_active = true;
trace_android_vh_swap_slot_cache_active(true);
mutex_unlock(&swap_slots_cache_mutex); mutex_unlock(&swap_slots_cache_mutex);
} }
@@ -89,7 +92,13 @@ void reenable_swap_slots_cache_unlock(void)
mutex_unlock(&swap_slots_cache_enable_mutex); mutex_unlock(&swap_slots_cache_enable_mutex);
} }
static bool check_cache_active(void) bool is_swap_slot_cache_enabled(void)
{
return swap_slot_cache_enabled;
}
EXPORT_SYMBOL_GPL(is_swap_slot_cache_enabled);
bool check_cache_active(void)
{ {
long pages; long pages;
@@ -110,17 +119,24 @@ static bool check_cache_active(void)
out: out:
return swap_slot_cache_active; return swap_slot_cache_active;
} }
EXPORT_SYMBOL_GPL(check_cache_active);
static int alloc_swap_slot_cache(unsigned int cpu) static int alloc_swap_slot_cache(unsigned int cpu)
{ {
struct swap_slots_cache *cache; struct swap_slots_cache *cache;
swp_entry_t *slots, *slots_ret; swp_entry_t *slots, *slots_ret;
bool skip = false;
int ret = 0;
/* /*
* Do allocation outside swap_slots_cache_mutex * Do allocation outside swap_slots_cache_mutex
* as kvzalloc could trigger reclaim and get_swap_page, * as kvzalloc could trigger reclaim and get_swap_page,
* which can lock swap_slots_cache_mutex. * which can lock swap_slots_cache_mutex.
*/ */
trace_android_vh_alloc_swap_slot_cache(&per_cpu(swp_slots, cpu),
&ret, &skip);
if (skip)
return ret;
slots = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t), slots = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t),
GFP_KERNEL); GFP_KERNEL);
if (!slots) if (!slots)
@@ -171,8 +187,13 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
{ {
struct swap_slots_cache *cache; struct swap_slots_cache *cache;
swp_entry_t *slots = NULL; swp_entry_t *slots = NULL;
bool skip = false;
cache = &per_cpu(swp_slots, cpu); cache = &per_cpu(swp_slots, cpu);
trace_android_vh_drain_slots_cache_cpu(cache, type,
free_slots, &skip);
if (skip)
return;
if ((type & SLOTS_CACHE) && cache->slots) { if ((type & SLOTS_CACHE) && cache->slots) {
mutex_lock(&cache->alloc_lock); mutex_lock(&cache->alloc_lock);
swapcache_free_entries(cache->slots + cache->cur, cache->nr); swapcache_free_entries(cache->slots + cache->cur, cache->nr);
@@ -274,8 +295,12 @@ static int refill_swap_slots_cache(struct swap_slots_cache *cache)
int free_swap_slot(swp_entry_t entry) int free_swap_slot(swp_entry_t entry)
{ {
struct swap_slots_cache *cache; struct swap_slots_cache *cache;
bool skip = false;
cache = raw_cpu_ptr(&swp_slots); cache = raw_cpu_ptr(&swp_slots);
trace_android_vh_free_swap_slot(entry, cache, &skip);
if (skip)
return 0;
if (likely(use_swap_slot_cache && cache->slots_ret)) { if (likely(use_swap_slot_cache && cache->slots_ret)) {
spin_lock_irq(&cache->free_lock); spin_lock_irq(&cache->free_lock);
/* Swap slots cache may be deactivated before acquiring lock */ /* Swap slots cache may be deactivated before acquiring lock */
@@ -307,9 +332,13 @@ swp_entry_t get_swap_page(struct page *page)
{ {
swp_entry_t entry; swp_entry_t entry;
struct swap_slots_cache *cache; struct swap_slots_cache *cache;
bool found = false;
entry.val = 0; entry.val = 0;
trace_android_vh_get_swap_page(page, &entry, raw_cpu_ptr(&swp_slots), &found);
if (found)
goto out;
if (PageTransHuge(page)) { if (PageTransHuge(page)) {
if (IS_ENABLED(CONFIG_THP_SWAP)) if (IS_ENABLED(CONFIG_THP_SWAP))
get_swap_pages(1, &entry, HPAGE_PMD_NR); get_swap_pages(1, &entry, HPAGE_PMD_NR);

View File

@@ -43,6 +43,7 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <linux/swapops.h> #include <linux/swapops.h>
#include <linux/swap_cgroup.h> #include <linux/swap_cgroup.h>
#include <trace/hooks/mm.h>
static bool swap_count_continued(struct swap_info_struct *, pgoff_t, static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
unsigned char); unsigned char);
@@ -98,7 +99,7 @@ static atomic_t proc_poll_event = ATOMIC_INIT(0);
atomic_t nr_rotate_swap = ATOMIC_INIT(0); atomic_t nr_rotate_swap = ATOMIC_INIT(0);
static struct swap_info_struct *swap_type_to_swap_info(int type) struct swap_info_struct *swap_type_to_swap_info(int type)
{ {
if (type >= READ_ONCE(nr_swapfiles)) if (type >= READ_ONCE(nr_swapfiles))
return NULL; return NULL;
@@ -106,6 +107,7 @@ static struct swap_info_struct *swap_type_to_swap_info(int type)
smp_rmb(); /* Pairs with smp_wmb in alloc_swap_info. */ smp_rmb(); /* Pairs with smp_wmb in alloc_swap_info. */
return READ_ONCE(swap_info[type]); return READ_ONCE(swap_info[type]);
} }
EXPORT_SYMBOL_GPL(swap_type_to_swap_info);
static inline unsigned char swap_count(unsigned char ent) static inline unsigned char swap_count(unsigned char ent)
{ {
@@ -712,6 +714,7 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset,
unsigned long begin = offset; unsigned long begin = offset;
unsigned long end = offset + nr_entries - 1; unsigned long end = offset + nr_entries - 1;
void (*swap_slot_free_notify)(struct block_device *, unsigned long); void (*swap_slot_free_notify)(struct block_device *, unsigned long);
bool skip = false;
if (offset < si->lowest_bit) if (offset < si->lowest_bit)
si->lowest_bit = offset; si->lowest_bit = offset;
@@ -722,7 +725,9 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset,
if (was_full && (si->flags & SWP_WRITEOK)) if (was_full && (si->flags & SWP_WRITEOK))
add_to_avail_list(si); add_to_avail_list(si);
} }
atomic_long_add(nr_entries, &nr_swap_pages); trace_android_vh_account_swap_pages(si, &skip);
if (!skip)
atomic_long_add(nr_entries, &nr_swap_pages);
si->inuse_pages -= nr_entries; si->inuse_pages -= nr_entries;
if (si->flags & SWP_BLKDEV) if (si->flags & SWP_BLKDEV)
swap_slot_free_notify = swap_slot_free_notify =
@@ -767,7 +772,7 @@ static void set_cluster_next(struct swap_info_struct *si, unsigned long next)
this_cpu_write(*si->cluster_next_cpu, next); this_cpu_write(*si->cluster_next_cpu, next);
} }
static int scan_swap_map_slots(struct swap_info_struct *si, int scan_swap_map_slots(struct swap_info_struct *si,
unsigned char usage, int nr, unsigned char usage, int nr,
swp_entry_t slots[]) swp_entry_t slots[])
{ {
@@ -983,8 +988,9 @@ no_page:
si->flags -= SWP_SCANNING; si->flags -= SWP_SCANNING;
return n_ret; return n_ret;
} }
EXPORT_SYMBOL_GPL(scan_swap_map_slots);
static int swap_alloc_cluster(struct swap_info_struct *si, swp_entry_t *slot) int swap_alloc_cluster(struct swap_info_struct *si, swp_entry_t *slot)
{ {
unsigned long idx; unsigned long idx;
struct swap_cluster_info *ci; struct swap_cluster_info *ci;
@@ -1018,6 +1024,7 @@ static int swap_alloc_cluster(struct swap_info_struct *si, swp_entry_t *slot)
return 1; return 1;
} }
EXPORT_SYMBOL_GPL(swap_alloc_cluster);
static void swap_free_cluster(struct swap_info_struct *si, unsigned long idx) static void swap_free_cluster(struct swap_info_struct *si, unsigned long idx)
{ {
@@ -1137,6 +1144,7 @@ swp_entry_t get_swap_page_of_type(int type)
{ {
struct swap_info_struct *si = swap_type_to_swap_info(type); struct swap_info_struct *si = swap_type_to_swap_info(type);
pgoff_t offset; pgoff_t offset;
bool skip = false;
if (!si) if (!si)
goto fail; goto fail;
@@ -1146,7 +1154,9 @@ swp_entry_t get_swap_page_of_type(int type)
/* This is called for allocating swap entry, not cache */ /* This is called for allocating swap entry, not cache */
offset = scan_swap_map(si, 1); offset = scan_swap_map(si, 1);
if (offset) { if (offset) {
atomic_long_dec(&nr_swap_pages); trace_android_vh_account_swap_pages(si, &skip);
if (!skip)
atomic_long_dec(&nr_swap_pages);
spin_unlock(&si->lock); spin_unlock(&si->lock);
return swp_entry(type, offset); return swp_entry(type, offset);
} }
@@ -1478,6 +1488,7 @@ void swapcache_free_entries(swp_entry_t *entries, int n)
if (p) if (p)
spin_unlock(&p->lock); spin_unlock(&p->lock);
} }
EXPORT_SYMBOL_GPL(swapcache_free_entries);
/* /*
* How many references to page are currently swapped out? * How many references to page are currently swapped out?
@@ -2007,6 +2018,7 @@ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
} }
try_to_free_swap(page); try_to_free_swap(page);
trace_android_vh_unuse_swap_page(si, page);
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);
@@ -2245,6 +2257,7 @@ retry:
lock_page(page); lock_page(page);
wait_on_page_writeback(page); wait_on_page_writeback(page);
try_to_free_swap(page); try_to_free_swap(page);
trace_android_vh_unuse_swap_page(si, page);
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);
@@ -2499,10 +2512,14 @@ static void setup_swap_info(struct swap_info_struct *p, int prio,
static void _enable_swap_info(struct swap_info_struct *p) static void _enable_swap_info(struct swap_info_struct *p)
{ {
p->flags |= SWP_WRITEOK | SWP_VALID; bool skip = false;
atomic_long_add(p->pages, &nr_swap_pages);
total_swap_pages += p->pages;
p->flags |= SWP_WRITEOK | SWP_VALID;
trace_android_vh_account_swap_pages(p, &skip);
if (!skip) {
atomic_long_add(p->pages, &nr_swap_pages);
total_swap_pages += p->pages;
}
assert_spin_locked(&swap_lock); assert_spin_locked(&swap_lock);
/* /*
* both lists are plists, and thus priority ordered. * both lists are plists, and thus priority ordered.
@@ -2574,6 +2591,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
struct filename *pathname; struct filename *pathname;
int err, found = 0; int err, found = 0;
unsigned int old_block_size; unsigned int old_block_size;
bool skip = false;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
@@ -2628,8 +2646,11 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
least_priority++; least_priority++;
} }
plist_del(&p->list, &swap_active_head); plist_del(&p->list, &swap_active_head);
atomic_long_sub(p->pages, &nr_swap_pages); trace_android_vh_account_swap_pages(p, &skip);
total_swap_pages -= p->pages; if (!skip) {
atomic_long_sub(p->pages, &nr_swap_pages);
total_swap_pages -= p->pages;
}
p->flags &= ~SWP_WRITEOK; p->flags &= ~SWP_WRITEOK;
spin_unlock(&p->lock); spin_unlock(&p->lock);
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
@@ -2881,12 +2902,15 @@ late_initcall(max_swapfiles_check);
static struct swap_info_struct *alloc_swap_info(void) static struct swap_info_struct *alloc_swap_info(void)
{ {
struct swap_info_struct *p; struct swap_info_struct *p = NULL;
struct swap_info_struct *defer = NULL; struct swap_info_struct *defer = NULL;
unsigned int type; unsigned int type;
int i; int i;
bool skip = false;
p = kvzalloc(struct_size(p, avail_lists, nr_node_ids), GFP_KERNEL); trace_android_vh_alloc_si(&p, &skip);
if (!skip)
p = kvzalloc(struct_size(p, avail_lists, nr_node_ids), GFP_KERNEL);
if (!p) if (!p)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@@ -3369,6 +3393,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
(swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT; (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
enable_swap_info(p, prio, swap_map, cluster_info, frontswap_map); enable_swap_info(p, prio, swap_map, cluster_info, frontswap_map);
trace_android_vh_init_swap_info_struct(p, swap_avail_heads);
pr_info("Adding %uk swap on %s. Priority:%d extents:%d across:%lluk %s%s%s%s%s\n", pr_info("Adding %uk swap on %s. Priority:%d extents:%d across:%lluk %s%s%s%s%s\n",
p->pages<<(PAGE_SHIFT-10), name->name, p->prio, p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10), nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
@@ -3433,8 +3458,10 @@ void si_swapinfo(struct sysinfo *val)
spin_lock(&swap_lock); spin_lock(&swap_lock);
for (type = 0; type < nr_swapfiles; type++) { for (type = 0; type < nr_swapfiles; type++) {
struct swap_info_struct *si = swap_info[type]; struct swap_info_struct *si = swap_info[type];
bool skip = false;
if ((si->flags & SWP_USED) && !(si->flags & SWP_WRITEOK)) trace_android_vh_si_swapinfo(si, &skip);
if (!skip && (si->flags & SWP_USED) && !(si->flags & SWP_WRITEOK))
nr_to_be_unused += si->inuse_pages; nr_to_be_unused += si->inuse_pages;
} }
val->freeswap = atomic_long_read(&nr_swap_pages) + nr_to_be_unused; val->freeswap = atomic_long_read(&nr_swap_pages) + nr_to_be_unused;

View File

@@ -1564,36 +1564,6 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
return nr_reclaimed; return nr_reclaimed;
} }
int reclaim_pages_from_list(struct list_head *page_list)
{
struct scan_control sc = {
.gfp_mask = GFP_KERNEL,
.priority = DEF_PRIORITY,
.may_writepage = 1,
.may_unmap = 1,
.may_swap = 1,
};
unsigned long nr_reclaimed;
struct reclaim_stat dummy_stat;
struct page *page;
list_for_each_entry(page, page_list, lru)
ClearPageActive(page);
nr_reclaimed = shrink_page_list(page_list, NULL, &sc,
&dummy_stat, false);
while (!list_empty(page_list)) {
page = lru_to_page(page_list);
list_del(&page->lru);
dec_node_page_state(page, NR_ISOLATED_ANON +
page_is_file_lru(page));
putback_lru_page(page);
}
return nr_reclaimed;
}
/* /*
* Attempt to remove the specified page from its LRU. Only take this page * Attempt to remove the specified page from its LRU. Only take this page
* if it is of the appropriate PageActive status. Pages which are being * if it is of the appropriate PageActive status. Pages which are being
@@ -2270,11 +2240,16 @@ static bool inactive_is_low(struct lruvec *lruvec, enum lru_list inactive_lru)
unsigned long inactive, active; unsigned long inactive, active;
unsigned long inactive_ratio; unsigned long inactive_ratio;
unsigned long gb; unsigned long gb;
bool skip = false;
inactive = lruvec_page_state(lruvec, NR_LRU_BASE + inactive_lru); inactive = lruvec_page_state(lruvec, NR_LRU_BASE + inactive_lru);
active = lruvec_page_state(lruvec, NR_LRU_BASE + active_lru); active = lruvec_page_state(lruvec, NR_LRU_BASE + active_lru);
gb = (inactive + active) >> (30 - PAGE_SHIFT); gb = (inactive + active) >> (30 - PAGE_SHIFT);
trace_android_vh_inactive_is_low(gb, &inactive_ratio, inactive_lru, &skip);
if (skip)
goto out;
if (gb) if (gb)
inactive_ratio = int_sqrt(10 * gb); inactive_ratio = int_sqrt(10 * gb);
else else
@@ -2282,6 +2257,7 @@ static bool inactive_is_low(struct lruvec *lruvec, enum lru_list inactive_lru)
trace_android_vh_tune_inactive_ratio(&inactive_ratio, is_file_lru(inactive_lru)); trace_android_vh_tune_inactive_ratio(&inactive_ratio, is_file_lru(inactive_lru));
out:
return inactive * inactive_ratio < active; return inactive * inactive_ratio < active;
} }
@@ -3079,6 +3055,7 @@ static void snapshot_refaults(struct mem_cgroup *target_memcg, pg_data_t *pgdat)
target_lruvec->refaults[0] = refaults; target_lruvec->refaults[0] = refaults;
refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_FILE); refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_FILE);
target_lruvec->refaults[1] = refaults; target_lruvec->refaults[1] = refaults;
trace_android_vh_snapshot_refaults(target_lruvec);
} }
/* /*