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:
The attributes:
========== ===================================
c_chmask capture channel mask
c_srate capture sampling rate
c_ssize capture sample size (bytes)
p_chmask playback channel mask
p_srate playback sampling rate
p_ssize playback sample size (bytes)
req_number the number of pre-allocated request
for both capture and playback
========== ===================================
===================== =======================================
c_chmask capture channel mask
c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes)
c_mute_present capture mute control enable
c_volume_present capture volume control enable
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)
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:
The attributes:
========= ============================
c_chmask capture channel mask
c_srate capture sampling rate
c_ssize capture sample size (bytes)
c_sync capture synchronization type (async/adaptive)
fb_max maximum extra bandwidth in async mode
p_chmask playback channel mask
p_srate playback sampling rate
p_ssize playback sample size (bytes)
========= ============================
===================== =======================================
c_chmask capture channel mask
c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes)
c_sync capture synchronization type
(async/adaptive)
c_mute_present capture mute control enable
c_volume_present capture volume control enable
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 uac2 function provides these attributes in its function directory:
=============== ====================================================
c_chmask capture channel mask
c_srate capture sampling rate
c_ssize capture sample size (bytes)
c_sync capture synchronization type (async/adaptive)
fb_max maximum extra bandwidth in async mode
p_chmask playback channel mask
p_srate playback sampling rate
p_ssize playback sample size (bytes)
req_number the number of pre-allocated request for both capture
and playback
=============== ====================================================
================ ====================================================
c_chmask capture channel mask
c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes)
c_sync capture synchronization type (async/adaptive)
c_mute_present capture mute control enable
c_volume_present capture volume control enable
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 request for both capture
and playback
function_name name of the interface
================ ====================================================
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 uac1 function provides these attributes in its function directory:
========== ====================================================
c_chmask capture channel mask
c_srate capture sampling rate
c_ssize capture sample size (bytes)
p_chmask playback channel mask
p_srate playback sampling rate
p_ssize playback sample size (bytes)
req_number the number of pre-allocated request for both capture
and playback
========== ====================================================
================ ====================================================
c_chmask capture channel mask
c_srate list of capture sampling rates (comma-separated)
c_ssize capture sample size (bytes)
c_mute_present capture mute control enable
c_volume_present capture volume control enable
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)
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.

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_xiaomi
android/abi_gki_aarch64_asus
android/abi_gki_aarch64_transsion
"
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]);
}
struct binder_transaction_log binder_transaction_log;
struct binder_transaction_log binder_transaction_log_failed;
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 {
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(
struct binder_transaction_log *log)
@@ -2464,6 +2488,56 @@ static int binder_fixup_parent(struct binder_transaction *t,
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
* @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 pending_async = false;
bool skip = false;
struct binder_transaction *t_outdated = NULL;
BUG_ON(!node);
binder_node_lock(node);
@@ -2534,6 +2609,17 @@ static int binder_proc_transaction(struct binder_transaction *t,
} else if (!pending_async) {
binder_enqueue_work_ilocked(&t->work, &proc->todo);
} 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);
}
@@ -2547,6 +2633,22 @@ static int binder_proc_transaction(struct binder_transaction *t,
binder_inner_proc_unlock(proc);
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;
}
@@ -5950,8 +6052,7 @@ static void print_binder_proc_stats(struct seq_file *m,
print_binder_stats(m, " ", &proc->stats);
}
int binder_state_show(struct seq_file *m, void *unused)
static int state_show(struct seq_file *m, void *unused)
{
struct binder_proc *proc;
struct binder_node *node;
@@ -5990,7 +6091,7 @@ int binder_state_show(struct seq_file *m, void *unused)
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;
@@ -6006,7 +6107,7 @@ int binder_stats_show(struct seq_file *m, void *unused)
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;
@@ -6062,7 +6163,7 @@ static void print_binder_transaction_log_entry(struct seq_file *m,
"\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;
unsigned int log_cur = atomic_read(&log->cur);
@@ -6094,6 +6195,45 @@ const struct file_operations binder_fops = {
.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)
{
int ret;
@@ -6139,36 +6279,18 @@ static int __init binder_init(void)
atomic_set(&binder_transaction_log_failed.cur, ~0U);
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_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) &&

View File

@@ -107,41 +107,19 @@ static inline int __init init_binderfs(void)
}
#endif
int binder_stats_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_stats);
int binder_state_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_state);
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_debugfs_entry {
const char *name;
umode_t mode;
const struct file_operations *fops;
void *data;
};
struct binder_transaction_log {
atomic_t cur;
bool full;
struct binder_transaction_log_entry entry[32];
};
extern const struct binder_debugfs_entry binder_debugfs_entries[];
#define binder_for_each_debugfs_entry(entry) \
for ((entry) = binder_debugfs_entries; \
(entry)->name; \
(entry)++)
enum binder_stat_types {
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 */

View File

@@ -306,6 +306,10 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
TP_PROTO(struct binder_buffer *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,
TP_PROTO(struct binder_alloc *alloc, bool allocate,
void __user *start, void __user *end),

View File

@@ -584,6 +584,7 @@ out:
static int init_binder_logs(struct super_block *sb)
{
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
const struct binder_debugfs_entry *db_entry;
struct binderfs_info *info;
int ret = 0;
@@ -594,43 +595,15 @@ static int init_binder_logs(struct super_block *sb)
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir, "stats",
&binder_stats_fops, NULL);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir, "state",
&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;
binder_for_each_debugfs_entry(db_entry) {
dentry = binderfs_create_file(binder_logs_root_dir,
db_entry->name,
db_entry->fops,
db_entry->data);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
}
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_ra_tuning_max_page);
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;
void *data;
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;
ssize_t (*read)(char *buffer, loff_t offset, size_t count,
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 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;
}
@@ -116,7 +162,12 @@ static int devcd_free(struct device *dev, void *data)
{
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);
mutex_unlock(&devcd->mutex);
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);
}
/*
*
* 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,
const char *buf, size_t count)
{
@@ -282,13 +357,16 @@ void dev_coredumpm(struct device *dev, struct module *owner,
devcd->read = read;
devcd->free = free;
devcd->failing_dev = get_device(dev);
devcd->delete_work = false;
mutex_init(&devcd->mutex);
device_initialize(&devcd->devcd_dev);
dev_set_name(&devcd->devcd_dev, "devcd%d",
atomic_inc_return(&devcd_count));
devcd->devcd_dev.class = &devcd_class;
mutex_lock(&devcd->mutex);
if (device_add(&devcd->devcd_dev))
goto put_device;
@@ -302,10 +380,11 @@ void dev_coredumpm(struct device *dev, struct module *owner,
INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
mutex_unlock(&devcd->mutex);
return;
put_device:
put_device(&devcd->devcd_dev);
mutex_unlock(&devcd->mutex);
put_module:
module_put(owner);
free:

View File

@@ -50,6 +50,11 @@ struct iommu_dma_cookie {
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)
{
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)
{
struct iommu_dma_cookie *cookie;
struct iommu_dma_cookie_ext *cookie;
cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (cookie) {
INIT_LIST_HEAD(&cookie->msi_page_list);
cookie->type = type;
INIT_LIST_HEAD(&cookie->cookie.msi_page_list);
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)
{
struct iommu_dma_cookie *cookie = domain->iova_cookie;
struct iommu_dma_cookie_ext *cookie_ext;
unsigned long order, base_pfn;
struct iova_domain *iovad;
int attr;
int ret;
if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
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 */
cookie_ext = container_of(cookie, struct iommu_dma_cookie_ext, cookie);
mutex_lock(&cookie_ext->mutex);
if (iovad->start_pfn) {
if (1UL << order != iovad->granule ||
base_pfn != iovad->start_pfn) {
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);
@@ -352,10 +364,16 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
cookie->fq_domain = domain;
}
if (!dev)
return 0;
if (!dev) {
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,

View File

@@ -194,6 +194,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
{
struct nci_dev *ndev = priv->ndev;
nci_unregister_device(ndev);
if (priv->ndev->nfc_dev->fw_download_in_progress)
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))
gpio_free(priv->config.reset_n_io);
nci_unregister_device(ndev);
nci_free_device(ndev);
kfree(priv);
}

View File

@@ -275,6 +275,7 @@ static int usb_conn_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, info);
device_set_wakeup_capable(&pdev->dev, true);
/* Perform initial detection */
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);
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)
disable_irq(info->id_irq);
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);
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);
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 */
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_GCTL_CORESOFTRESET;
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;
is_on = !!is_on;
if (dwc->pullups_connected == is_on)
return 0;
vdwc->softconnect = is_on;
/*

View File

@@ -122,8 +122,6 @@ struct ffs_ep {
struct usb_endpoint_descriptor *descs[3];
u8 num;
int status; /* P: epfile->mutex */
};
struct ffs_epfile {
@@ -227,6 +225,9 @@ struct ffs_io_data {
bool use_sg;
struct ffs_data *ffs;
int status;
struct completion done;
};
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)
{
struct ffs_io_data *io_data = req->context;
ENTER();
if (likely(req->context)) {
struct ffs_ep *ep = _ep->driver_data;
ep->status = req->status ? req->status : req->actual;
complete(req->context);
}
if (req->status)
io_data->status = req->status;
else
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)
@@ -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__);
ret = -EINVAL;
} else if (!io_data->aio) {
DECLARE_COMPLETION_ONSTACK(done);
bool interrupted = false;
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;
req->context = &done;
init_completion(&io_data->done);
req->context = io_data;
req->complete = ffs_epfile_io_complete;
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);
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,
* 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.
*/
usb_ep_dequeue(ep->ep, req);
wait_for_completion(&done);
interrupted = ep->status < 0;
spin_unlock_irq(&epfile->ffs->eps_lock);
wait_for_completion(&io_data->done);
interrupted = io_data->status < 0;
}
if (interrupted)
ret = -EINTR;
else if (io_data->read && ep->status > 0)
ret = __ffs_epfile_read_data(epfile, data, ep->status,
else if (io_data->read && io_data->status > 0)
ret = __ffs_epfile_read_data(epfile, data, io_data->status,
&io_data->data);
else
ret = ep->status;
ret = io_data->status;
goto error_mutex;
} else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) {
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)
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/control.h>
#include <sound/tlv.h>
#include <linux/usb/audio.h>
#include "u_audio.h"
@@ -24,6 +27,14 @@
#define PRD_SIZE_MAX PAGE_SIZE
#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 */
struct uac_rtd_params {
struct snd_uac_chip *uac; /* parent chip */
@@ -43,6 +54,21 @@ struct uac_rtd_params {
struct usb_request *req_fback; /* Feedback endpoint request */
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 {
@@ -54,13 +80,9 @@ struct snd_uac_chip {
struct snd_card *card;
struct snd_pcm *pcm;
/* timekeeping for the playback endpoint */
unsigned int p_interval;
unsigned int p_residue;
/* pre-calculated values for playback iso completion */
unsigned int p_pktsize;
unsigned int p_pktsize_residue;
unsigned long long p_residue_mil;
unsigned int p_interval;
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 uac_rtd_params *prm = req->context;
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 */
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
* residue accumulator.
*/
req->length = uac->p_pktsize;
uac->p_residue += uac->p_pktsize_residue;
unsigned long long p_interval_mil = uac->p_interval * 1000000ULL;
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
* 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;
uac->p_residue -= uac->p_framesize *
uac->p_interval;
uac->p_residue_mil -= uac->p_framesize * p_interval_mil;
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;
}
@@ -233,7 +283,6 @@ static void u_audio_iso_fback_complete(struct usb_ep *ep,
struct uac_rtd_params *prm = req->context;
struct snd_uac_chip *uac = prm->uac;
struct g_audio *audio_dev = uac->audio_dev;
struct uac_params *params = &audio_dev->params;
int status = req->status;
/* 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);
u_audio_set_fback_frequency(audio_dev->gadget->speed, audio_dev->out_ep,
params->c_srate, prm->pitch,
prm->srate, prm->pitch,
req->buf);
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 g_audio *audio_dev;
struct uac_params *params;
struct uac_rtd_params *prm;
int p_ssize, c_ssize;
int p_srate, c_srate;
int p_chmask, c_chmask;
audio_dev = uac->audio_dev;
params = &audio_dev->params;
p_ssize = params->p_ssize;
c_ssize = params->c_ssize;
p_srate = params->p_srate;
c_srate = params->c_srate;
p_chmask = params->p_chmask;
c_chmask = params->c_chmask;
uac->p_residue = 0;
uac->p_residue_mil = 0;
runtime->hw = uac_pcm_hardware;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
runtime->hw.rate_min = p_srate;
runtime->hw.formats = uac_ssize_to_fmt(p_ssize);
runtime->hw.channels_min = num_channels(p_chmask);
runtime->hw.period_bytes_min = 2 * uac->p_prm.max_psize
/ runtime->hw.periods_min;
prm = &uac->p_prm;
} else {
runtime->hw.rate_min = c_srate;
runtime->hw.formats = uac_ssize_to_fmt(c_ssize);
runtime->hw.channels_min = num_channels(c_chmask);
runtime->hw.period_bytes_min = 2 * uac->c_prm.max_psize
/ runtime->hw.periods_min;
prm = &uac->c_prm;
}
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.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__);
}
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)
{
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;
int req_len, i;
ep = audio_dev->out_ep;
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);
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__);
}
set_active(&uac->c_prm, true);
ep_fback = audio_dev->in_ep_fback;
if (!ep_fback)
return 0;
@@ -514,7 +656,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
*/
prm->pitch = 1000000;
u_audio_set_fback_frequency(audio_dev->gadget->speed, ep,
params->c_srate, prm->pitch,
prm->srate, prm->pitch,
req_fback->buf);
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;
set_active(&uac->c_prm, false);
if (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);
@@ -546,12 +689,18 @@ int u_audio_start_playback(struct g_audio *audio_dev)
unsigned int factor;
const struct usb_endpoint_descriptor *ep_desc;
int req_len, i;
unsigned int p_pktsize;
ep = audio_dev->in_ep;
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);
ep_desc = ep->desc;
/*
* Always start with original frequency
*/
prm->pitch = 1000000;
/* pre-calculate the playback endpoint's interval */
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 *
num_channels(params->p_chmask);
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 *
(params->p_srate / uac->p_interval),
(prm->srate / uac->p_interval),
ep->maxpacket);
if (uac->p_pktsize < ep->maxpacket)
uac->p_pktsize_residue = uac->p_framesize *
(params->p_srate % uac->p_interval);
else
uac->p_pktsize_residue = 0;
req_len = uac->p_pktsize;
uac->p_residue = 0;
req_len = p_pktsize;
uac->p_residue_mil = 0;
prm->ep_enabled = true;
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__);
}
set_active(&uac->p_prm, true);
return 0;
}
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;
set_active(&uac->p_prm, false);
free_ep(&uac->p_prm, audio_dev->in_ep);
}
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,
struct snd_ctl_elem_info *uinfo)
{
@@ -670,14 +922,234 @@ static int u_audio_pitch_put(struct snd_kcontrol *kcontrol,
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,
.name = "Capture Pitch 1000000",
.info = u_audio_pitch_info,
.get = u_audio_pitch_get,
.put = u_audio_pitch_put,
},
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 1;
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,
@@ -689,7 +1161,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
struct snd_kcontrol *kctl;
struct uac_params *params;
int p_chmask, c_chmask;
int err;
int i, err;
if (!g_audio)
return -EINVAL;
@@ -707,8 +1179,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
if (c_chmask) {
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->srate = params->c_srates[0];
prm->reqs = kcalloc(params->req_number,
sizeof(struct usb_request *),
@@ -730,8 +1204,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
if (p_chmask) {
struct uac_rtd_params *prm = &uac->p_prm;
spin_lock_init(&prm->lock);
uac->p_prm.uac = uac;
prm->max_psize = g_audio->in_ep_maxpsize;
prm->srate = params->p_srates[0];
prm->reqs = kcalloc(params->req_number,
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_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));
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) {
err = -ENOMEM;
goto snd_fail;
@@ -791,6 +1275,117 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
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->shortname, card_name, sizeof(card->shortname));
sprintf(card->longname, "%s %i", card_name, card->dev->id);

View File

@@ -10,25 +10,48 @@
#define __U_AUDIO_H
#include <linux/usb/composite.h>
#include "uac_common.h"
/*
* Same maximum frequency deviation on the slower side as in
* 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
/*
* 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 {
/* playback */
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 */
struct uac_fu_params p_fu; /* Feature Unit parameters */
/* capture */
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 */
struct uac_fu_params c_fu; /* Feature Unit parameters */
/* rates are dynamic, in uac_rtd_params */
int req_number; /* number of preallocated requests */
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 */
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 */
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);
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 */

View File

@@ -9,6 +9,7 @@
#define __U_UAC1_H
#include <linux/usb/composite.h>
#include "uac_common.h"
#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
#define UAC1_DEF_CCHMASK 0x3
@@ -18,19 +19,41 @@
#define UAC1_DEF_PSRATE 48000
#define UAC1_DEF_PSSIZE 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 usb_function_instance func_inst;
int c_chmask;
int c_srate;
int c_srates[UAC_MAX_RATES];
int c_ssize;
int p_chmask;
int p_srate;
int p_srates[UAC_MAX_RATES];
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;
unsigned bound:1;
char function_name[32];
struct mutex lock;
int refcnt;
};

View File

@@ -14,6 +14,7 @@
#define U_UAC2_H
#include <linux/usb/composite.h>
#include "uac_common.h"
#define UAC2_DEF_PCHMASK 0x3
#define UAC2_DEF_PSRATE 48000
@@ -22,21 +23,43 @@
#define UAC2_DEF_CSRATE 64000
#define UAC2_DEF_CSSIZE 2
#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_FB_MAX 5
#define UAC2_DEF_INT_REQ_NUM 10
struct f_uac2_opts {
struct usb_function_instance func_inst;
int p_chmask;
int p_srate;
int p_srates[UAC_MAX_RATES];
int p_ssize;
int c_chmask;
int c_srate;
int c_srates[UAC_MAX_RATES];
int c_ssize;
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 fb_max;
bool bound;
bool bound;
char function_name[32];
struct mutex lock;
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);
break;
}
/* Endpoint now owns the request */
req = NULL;
}
if (!req)

View File

@@ -22,32 +22,34 @@ USB_GADGET_COMPOSITE_OPTIONS();
/* Playback(USB-IN) Default Stereo - Fl/Fr */
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");
/* Playback Default 48 KHz */
static int p_srate = UAC2_DEF_PSRATE;
module_param(p_srate, uint, S_IRUGO);
MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
static int p_srates[UAC_MAX_RATES] = {UAC2_DEF_PSRATE};
static int p_srates_cnt = 1;
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 */
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)");
/* Capture(USB-OUT) Default Stereo - Fl/Fr */
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");
/* Capture Default 64 KHz */
static int c_srate = UAC2_DEF_CSRATE;
module_param(c_srate, uint, S_IRUGO);
MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
static int c_srates[UAC_MAX_RATES] = {UAC2_DEF_CSRATE};
static int c_srates_cnt = 1;
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 */
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)");
#else
#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 */
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");
/* Playback Default 48 KHz */
static int p_srate = UAC1_DEF_PSRATE;
module_param(p_srate, uint, S_IRUGO);
MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
static int p_srates[UAC_MAX_RATES] = {UAC1_DEF_PSRATE};
static int p_srates_cnt = 1;
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 */
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)");
/* Capture(USB-OUT) Default Stereo - Fl/Fr */
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");
/* Capture Default 48 KHz */
static int c_srate = UAC1_DEF_CSRATE;
module_param(c_srate, uint, S_IRUGO);
MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
static int c_srates[UAC_MAX_RATES] = {UAC1_DEF_CSRATE};
static int c_srates_cnt = 1;
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 */
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)");
#else /* CONFIG_GADGET_UAC1_LEGACY */
#include "u_uac1_legacy.h"
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");
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");
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");
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");
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");
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");
#endif /* CONFIG_GADGET_UAC1_LEGACY */
#endif
@@ -237,9 +241,11 @@ static int audio_bind(struct usb_composite_dev *cdev)
{
#ifndef CONFIG_GADGET_UAC1
struct f_uac2_opts *uac2_opts;
int i;
#else
#ifndef CONFIG_GADGET_UAC1_LEGACY
struct f_uac1_opts *uac1_opts;
int i;
#else
struct f_uac1_legacy_opts *uac1_opts;
#endif
@@ -263,20 +269,32 @@ static int audio_bind(struct usb_composite_dev *cdev)
#ifndef CONFIG_GADGET_UAC1
uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst);
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->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->req_number = UAC2_DEF_REQ_NUM;
#else
#ifndef CONFIG_GADGET_UAC1_LEGACY
uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
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->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->req_number = UAC1_DEF_REQ_NUM;
#else /* CONFIG_GADGET_UAC1_LEGACY */

View File

@@ -282,6 +282,13 @@ struct css_set {
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 task_cputime cputime;
};

View File

@@ -72,7 +72,8 @@ struct css_task_iter {
};
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;
#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 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_pages_from_list(struct list_head *page_list);
/**
* 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 */
} __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 */
struct uac2_effect_unit_descriptor {

View File

@@ -11,13 +11,31 @@
* Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality
*/
struct binder_transaction;
struct task_struct;
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_ANDROID_BINDER_IPC)
struct binder_alloc;
struct binder_proc;
struct binder_thread;
struct binder_transaction;
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;
#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,
TP_PROTO(struct binder_transaction *t),
TP_ARGS(t));
@@ -30,8 +48,6 @@ DECLARE_HOOK(android_vh_binder_set_priority,
DECLARE_HOOK(android_vh_binder_restore_priority,
TP_PROTO(struct binder_transaction *t, struct task_struct *task),
TP_ARGS(t, task));
struct binder_proc;
struct binder_thread;
DECLARE_HOOK(android_vh_binder_wakeup_ilocked,
TP_PROTO(struct task_struct *task, bool sync, struct binder_proc *proc),
TP_ARGS(task, sync, proc));

View File

@@ -10,9 +10,18 @@
#include <linux/tracepoint.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_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,
TP_PROTO(size_t *rq_size, struct blk_mq_tag_set *set,

View File

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

View File

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

View File

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

View File

@@ -11,8 +11,15 @@
* Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality
*/
#ifdef __GENKSYMS__
struct cred;
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,
TP_PROTO(const struct task_struct *task, const struct cred *new),
TP_ARGS(task, new));

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,12 @@
#include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
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

View File

@@ -10,7 +10,12 @@
#include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct task_struct;
#else
/* struct task_struct */
#include <linux/sched.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_is_fpsimd_save,
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
* mechanism for vendor modules to hook and extend functionality
*/
struct irq_data;
#ifdef __GENKSYMS__
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,
TP_PROTO(struct irq_data *d, const struct cpumask *mask_val,
u64 *affinity, bool force, void __iomem *base),

View File

@@ -12,6 +12,12 @@
#include <linux/tracepoint.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,
TP_PROTO(struct device *dev, u64 dma_base, u64 size),
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_ARGS(dev, iova, size));
struct iova_domain;
DECLARE_HOOK(android_vh_iommu_iovad_alloc_iova,
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 <trace/hooks/vendor_hooks.h>
struct printk_ringbuffer;
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_PRINTK)
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,
TP_PROTO(struct printk_ringbuffer *rb, struct printk_record *r),

View File

@@ -14,7 +14,26 @@
#include <linux/tracepoint.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 swap_slots_cache;
DECLARE_RESTRICTED_HOOK(android_rvh_set_skip_swapcache_flags,
TP_PROTO(gfp_t *flags),
@@ -68,7 +87,6 @@ DECLARE_HOOK(android_vh_include_reserved_zone,
DECLARE_HOOK(android_vh_show_mem,
TP_PROTO(unsigned int filter, nodemask_t *nodemask),
TP_ARGS(filter, nodemask));
struct slabinfo;
struct dirty_throttle_control;
DECLARE_HOOK(android_vh_mm_dirty_limits,
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,
TP_PROTO(bool alloc, unsigned long p),
TP_ARGS(alloc, p));
struct mem_cgroup;
DECLARE_HOOK(android_vh_vmpressure,
TP_PROTO(struct mem_cgroup *memcg, bool *bypass),
TP_ARGS(memcg, bypass));
@@ -101,7 +118,6 @@ DECLARE_HOOK(android_vh_mem_cgroup_free,
DECLARE_HOOK(android_vh_mem_cgroup_id_remove,
TP_PROTO(struct mem_cgroup *memcg),
TP_ARGS(memcg));
struct cgroup_subsys_state;
DECLARE_HOOK(android_vh_mem_cgroup_css_online,
TP_PROTO(struct cgroup_subsys_state *css, struct mem_cgroup *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,
TP_PROTO(int migratetype, bool *bypass),
TP_ARGS(migratetype, bypass));
struct device;
DECLARE_HOOK(android_vh_subpage_dma_contig_alloc,
TP_PROTO(bool *allow_subpage_alloc, struct device *dev, size_t *size),
TP_ARGS(allow_subpage_alloc, dev, size));
struct readahead_control;
DECLARE_HOOK(android_vh_ra_tuning_max_page,
TP_PROTO(struct readahead_control *ractl, unsigned long *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 */
#endif /* _TRACE_HOOK_MM_H */

View File

@@ -10,9 +10,22 @@
#include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h>
struct mmc_host;
struct mmc_card;
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_MMC_SDHCI)
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,
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
* mechanism for vendor modules to hook and extend functionality
*/
#ifdef __GENKSYMS__
struct module;
#else
/* struct module */
#include <linux/module.h>
#endif /* __GENKSYMS__ */
DECLARE_HOOK(android_vh_set_module_permit_before_init,
TP_PROTO(const struct module *mod),
TP_ARGS(mod));

View File

@@ -9,9 +9,18 @@
#include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct packet_type;
struct list_head;
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,
TP_PROTO(const struct packet_type *pt, struct list_head *vendor_pt),
TP_ARGS(pt, vendor_pt));

View File

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

View File

@@ -11,7 +11,17 @@
* Following tracepoints are not exported in tracefs and provide a
* 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;
#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,
TP_PROTO(unsigned int todo, unsigned int elapsed_msecs, bool 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_ARGS(p));
enum freq_qos_req_type;
struct freq_qos_request;
struct freq_constraints;
DECLARE_HOOK(android_vh_freq_qos_add_request,
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)
struct psi_trigger;
#if defined(__GENKSYMS__) || !defined(CONFIG_PSI)
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,
TP_PROTO(struct psi_trigger *t),
TP_ARGS(t));

View File

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

View File

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

View File

@@ -10,7 +10,25 @@
* Following tracepoints are not exported in tracefs and provide a
* 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 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,
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);
@@ -178,7 +196,6 @@ DECLARE_RESTRICTED_HOOK(android_rvh_account_irq,
TP_PROTO(struct task_struct *curr, int cpu, s64 delta),
TP_ARGS(curr, cpu, delta), 1);
struct sched_entity;
DECLARE_RESTRICTED_HOOK(android_rvh_place_entity,
TP_PROTO(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial, u64 vruntime),
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_ARGS(p, rq, need_update), 1);
struct cgroup_taskset;
DECLARE_RESTRICTED_HOOK(android_rvh_cpu_cgroup_attach,
TP_PROTO(struct cgroup_taskset *tset),
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_ARGS(tset, retval), 1);
struct cgroup_subsys_state;
DECLARE_RESTRICTED_HOOK(android_rvh_cpu_cgroup_online,
TP_PROTO(struct cgroup_subsys_state *css),
TP_ARGS(css), 1);
@@ -225,14 +240,12 @@ DECLARE_RESTRICTED_HOOK(android_rvh_sched_exec,
TP_PROTO(bool *cond),
TP_ARGS(cond), 1);
struct cpufreq_policy;
DECLARE_HOOK(android_vh_map_util_freq,
TP_PROTO(unsigned long util, unsigned long freq,
unsigned long cap, unsigned long *next_freq, struct cpufreq_policy *policy,
bool *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,
TP_PROTO(struct em_perf_domain *pd,
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_ARGS(wake_flags, mode));
enum uclamp_id;
/* Conditionally defined upon CONFIG_UCLAMP_TASK */
struct uclamp_se;
DECLARE_RESTRICTED_HOOK(android_rvh_uclamp_eff_get,
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);
struct cfs_rq;
struct sched_entity;
struct rq_flags;
DECLARE_RESTRICTED_HOOK(android_rvh_enqueue_entity,
TP_PROTO(struct cfs_rq *cfs, struct sched_entity *se),

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,8 +11,15 @@
* Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality
*/
#ifdef __GENKSYMS__
struct file;
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,
TP_PROTO(const struct file *file, unsigned long prot,
unsigned long flag, unsigned long ret),

View File

@@ -10,11 +10,16 @@
#include <linux/tracepoint.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,
TP_PROTO(int event, int tz_id, int *enable_thermal_genl),
TP_ARGS(event, tz_id, enable_thermal_genl));
struct thermal_zone_device;
DECLARE_HOOK(android_vh_thermal_pm_notify_suspend,
TP_PROTO(struct thermal_zone_device *tz, int *irq_wakeable),
TP_ARGS(tz, irq_wakeable));

View File

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

View File

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

View File

@@ -10,9 +10,20 @@
* Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality
*/
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_SCSI_UFSHCD)
struct ufs_hba;
struct request;
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,
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_ARGS(hba, lrbp));
struct uic_command;
DECLARE_HOOK(android_vh_ufs_send_uic_command,
TP_PROTO(struct ufs_hba *hba, struct uic_command *ucmd,
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_ARGS(hba, queue_eh_work));
struct scsi_device;
DECLARE_HOOK(android_vh_ufs_update_sdev,
TP_PROTO(struct scsi_device *sdev),
TP_ARGS(sdev));

View File

@@ -10,12 +10,26 @@
#include <linux/tracepoint.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;
#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,
TP_PROTO(struct v4l2_format *fmt, int *ret),
TP_ARGS(fmt, ret));
struct v4l2_fmtdesc;
DECLARE_HOOK(android_vh_fill_ext_fmtdesc,
TP_PROTO(struct v4l2_fmtdesc *fmtd, const char **descr),
TP_ARGS(fmtd, descr));
@@ -24,21 +38,16 @@ DECLARE_HOOK(android_vh_clear_mask_adjust,
TP_PROTO(unsigned int ctrl, int *n),
TP_ARGS(ctrl, n));
struct v4l2_subdev;
struct v4l2_subdev_pad_config;
struct v4l2_subdev_selection;
DECLARE_HOOK(android_vh_v4l2subdev_set_selection,
TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *pad,
struct v4l2_subdev_selection *sel, int *ret),
TP_ARGS(sd, pad, sel, ret));
struct v4l2_subdev_format;
DECLARE_HOOK(android_vh_v4l2subdev_set_fmt,
TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *pad,
struct v4l2_subdev_format *format, int *ret),
TP_ARGS(sd, pad, format, ret));
struct v4l2_subdev_frame_interval;
DECLARE_HOOK(android_vh_v4l2subdev_set_frame_interval,
TP_PROTO(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *fi,
int *ret),

View File

@@ -10,8 +10,15 @@
#include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h>
#ifdef __GENKSYMS__
struct media_link;
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,
TP_PROTO(struct media_link *link, struct media_link_desc *linkd, int *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,
TP_PROTO(struct mem_cgroup *memcg, char *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 */
/* This part must be outside protection */
#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_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
TF_UPDATE_TXN = 0x40, /* update the outdated pending async txn */
};
struct binder_transaction_data {

View File

@@ -746,25 +746,28 @@ EXPORT_SYMBOL_GPL(of_css);
* reference-counted, to improve performance when child cgroups
* haven't been created.
*/
struct css_set init_css_set = {
.refcount = REFCOUNT_INIT(1),
.dom_cset = &init_css_set,
.tasks = LIST_HEAD_INIT(init_css_set.tasks),
.mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks),
.dying_tasks = LIST_HEAD_INIT(init_css_set.dying_tasks),
.task_iters = LIST_HEAD_INIT(init_css_set.task_iters),
.threaded_csets = LIST_HEAD_INIT(init_css_set.threaded_csets),
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
.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
* in cgroup_init(). However, let's initialize the field
* statically too so that the default cgroup can be accessed safely
* early during boot.
*/
.dfl_cgrp = &cgrp_dfl_root.cgrp,
struct ext_css_set init_ext_css_set = {
.cset = {
.refcount = REFCOUNT_INIT(1),
.dom_cset = &init_css_set,
.tasks = LIST_HEAD_INIT(init_css_set.tasks),
.mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks),
.dying_tasks = LIST_HEAD_INIT(init_css_set.dying_tasks),
.task_iters = LIST_HEAD_INIT(init_css_set.task_iters),
.threaded_csets = LIST_HEAD_INIT(init_css_set.threaded_csets),
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
.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
* in cgroup_init(). However, let's initialize the field
* statically too so that the default cgroup can be accessed safely
* early during boot.
*/
.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 */
@@ -1191,6 +1194,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
struct cgroup *cgrp)
{
struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT] = { };
struct ext_css_set *ext_cset;
struct css_set *cset;
struct list_head tmp_links;
struct cgrp_cset_link *link;
@@ -1211,9 +1215,10 @@ static struct css_set *find_css_set(struct css_set *old_cset,
if (cset)
return cset;
cset = kzalloc(sizeof(*cset), GFP_KERNEL);
if (!cset)
ext_cset = kzalloc(sizeof(*ext_cset), GFP_KERNEL);
if (!ext_cset)
return NULL;
cset = &ext_cset->cset;
/* Allocate all the cgrp_cset_link objects that we'll need */
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_LIST_HEAD(&cset->cgrp_links);
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);
/* 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)
{
LIST_HEAD(preloaded);
struct css_set *cset, *tmp_cset;
struct ext_css_set *cset, *tmp_cset;
lockdep_assert_held(&cgroup_mutex);
spin_lock_irq(&css_set_lock);
list_splice_tail_init(&mgctx->preloaded_src_csets, &preloaded);
list_splice_tail_init(&mgctx->preloaded_dst_csets, &preloaded);
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_src_csets,
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) {
cset->mg_src_cgrp = NULL;
cset->mg_dst_cgrp = NULL;
cset->mg_dst_cset = NULL;
list_del_init(&cset->mg_preload_node);
put_css_set_locked(cset);
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_dst_csets,
mg_dst_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_dst_preload_node);
put_css_set_locked(&cset->cset);
}
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 *src_cgrp;
struct ext_css_set *ext_src_cset;
lockdep_assert_held(&cgroup_mutex);
lockdep_assert_held(&css_set_lock);
@@ -2633,8 +2647,9 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
return;
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;
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_dst_cgrp = dst_cgrp;
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)
{
struct css_set *src_cset, *tmp_cset;
struct ext_css_set *ext_src_set, *tmp_cset;
lockdep_assert_held(&cgroup_mutex);
/* 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,
mg_preload_node) {
list_for_each_entry_safe(ext_src_set, tmp_cset, &mgctx->preloaded_src_csets,
mg_src_preload_node) {
struct css_set *src_cset = &ext_src_set->cset;
struct css_set *dst_cset;
struct ext_css_set *ext_dst_cset;
struct cgroup_subsys *ss;
int ssid;
dst_cset = find_css_set(src_cset, src_cset->mg_dst_cgrp);
if (!dst_cset)
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);
@@ -2689,7 +2707,7 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
if (src_cset == dst_cset) {
src_cset->mg_src_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(dst_cset);
continue;
@@ -2697,8 +2715,8 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
src_cset->mg_dst_cset = dst_cset;
if (list_empty(&dst_cset->mg_preload_node))
list_add_tail(&dst_cset->mg_preload_node,
if (list_empty(&ext_dst_cset->mg_dst_preload_node))
list_add_tail(&ext_dst_cset->mg_dst_preload_node,
&mgctx->preloaded_dst_csets);
else
put_css_set(dst_cset);
@@ -2926,7 +2944,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
DEFINE_CGROUP_MGCTX(mgctx);
struct cgroup_subsys_state *d_css;
struct cgroup *dsct;
struct css_set *src_cset;
struct ext_css_set *ext_src_set;
int ret;
lockdep_assert_held(&cgroup_mutex);
@@ -2949,11 +2967,12 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
goto out_finish;
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;
/* 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);
}
spin_unlock_irq(&css_set_lock);

View File

@@ -1147,10 +1147,11 @@ static void check_sync(struct device *dev,
dir2name[entry->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 &&
ref->sg_call_ents != entry->sg_call_ents) {
ref->sg_call_ents > entry->sg_call_ents) {
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",
entry->sg_call_ents, ref->sg_call_ents);
}

View File

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

View File

@@ -86,6 +86,7 @@
#include "pgalloc-track.h"
#include "internal.h"
#include <trace/hooks/mm.h>
#define CREATE_TRACE_POINTS
#include <trace/events/pagefault.h>
@@ -3141,6 +3142,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
put_page(old_page);
return 0;
}
trace_android_vh_cow_user_page(vmf, new_page);
}
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);
}
trace_android_vh_swapin_add_anon_rmap(vmf, page);
swap_free(entry);
if (mem_cgroup_swap_full(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)
flush_tlb_fix_spurious_fault(vmf->vma, vmf->address);
}
trace_android_vh_handle_pte_fault_end(vmf, highest_memmap_pfn);
unlock:
pte_unmap_unlock(vmf->pte, vmf->ptl);
return ret;

View File

@@ -54,6 +54,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/migrate.h>
#undef CREATE_TRACE_POINTS
#include <trace/hooks/mm.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))
goto out;
pte_unmap_unlock(ptep, ptl);
trace_android_vh_waiting_for_page_migration(page);
put_and_wait_on_page_locked(page);
return;
out:
@@ -584,6 +587,8 @@ void migrate_page_states(struct page *newpage, struct page *page)
{
int cpupid;
trace_android_vh_migrate_page_states(page, newpage);
if (PageError(page))
SetPageError(newpage);
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)
{
trace_android_vh_free_pages(page, order);
if (put_page_testzero(page))
free_the_page(page, order);
else if (!PageHead(page))

View File

@@ -25,6 +25,7 @@
#include <linux/psi.h>
#include <linux/uio.h>
#include <linux/sched/task.h>
#include <trace/hooks/mm.h>
static struct bio *get_swap_bio(gfp_t gfp_flags,
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;
int ret;
struct swap_info_struct *sis = page_swap_info(page);
bool skip = false;
VM_BUG_ON_PAGE(!PageSwapCache(page), page);
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);
ret = mapping->a_ops->direct_IO(&kiocb, &from);
if (ret == PAGE_SIZE) {
trace_android_vh_count_pswpout(sis);
count_vm_event(PSWPOUT);
ret = 0;
} 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);
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;
}
@@ -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_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);
unlock_page(page);
submit_bio(bio);
@@ -352,14 +359,17 @@ int swap_readpage(struct page *page, bool synchronous)
struct address_space *mapping = swap_file->f_mapping;
ret = mapping->a_ops->readpage(swap_file, page);
if (!ret)
if (!ret) {
trace_android_vh_count_pswpin(sis);
count_vm_event(PSWPIN);
}
goto out;
}
if (sis->flags & SWP_SYNCHRONOUS_IO) {
ret = bdev_read_page(sis->bdev, swap_page_sector(page), page);
if (!ret) {
trace_android_vh_count_pswpin(sis);
count_vm_event(PSWPIN);
goto out;
}
@@ -383,6 +393,7 @@ int swap_readpage(struct page *page, bool synchronous)
get_task_struct(current);
bio->bi_private = current;
}
trace_android_vh_count_pswpin(sis);
count_vm_event(PSWPIN);
bio_get(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;
}
trace_android_vh_page_referenced_one_end(vma, page, referenced);
if (!pra->mapcount)
return false; /* To break the loop */

View File

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

View File

@@ -33,6 +33,7 @@
#include <linux/vmalloc.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <trace/hooks/mm.h>
static DEFINE_PER_CPU(struct swap_slots_cache, swp_slots);
static bool swap_slot_cache_active;
@@ -54,6 +55,7 @@ static void deactivate_swap_slots_cache(void)
{
mutex_lock(&swap_slots_cache_mutex);
swap_slot_cache_active = false;
trace_android_vh_swap_slot_cache_active(false);
__drain_swap_slots_cache(SLOTS_CACHE|SLOTS_CACHE_RET);
mutex_unlock(&swap_slots_cache_mutex);
}
@@ -62,6 +64,7 @@ static void reactivate_swap_slots_cache(void)
{
mutex_lock(&swap_slots_cache_mutex);
swap_slot_cache_active = true;
trace_android_vh_swap_slot_cache_active(true);
mutex_unlock(&swap_slots_cache_mutex);
}
@@ -89,7 +92,13 @@ void reenable_swap_slots_cache_unlock(void)
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;
@@ -110,17 +119,24 @@ static bool check_cache_active(void)
out:
return swap_slot_cache_active;
}
EXPORT_SYMBOL_GPL(check_cache_active);
static int alloc_swap_slot_cache(unsigned int cpu)
{
struct swap_slots_cache *cache;
swp_entry_t *slots, *slots_ret;
bool skip = false;
int ret = 0;
/*
* Do allocation outside swap_slots_cache_mutex
* as kvzalloc could trigger reclaim and get_swap_page,
* 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),
GFP_KERNEL);
if (!slots)
@@ -171,8 +187,13 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
{
struct swap_slots_cache *cache;
swp_entry_t *slots = NULL;
bool skip = false;
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) {
mutex_lock(&cache->alloc_lock);
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)
{
struct swap_slots_cache *cache;
bool skip = false;
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)) {
spin_lock_irq(&cache->free_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;
struct swap_slots_cache *cache;
bool found = false;
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 (IS_ENABLED(CONFIG_THP_SWAP))
get_swap_pages(1, &entry, HPAGE_PMD_NR);

View File

@@ -43,6 +43,7 @@
#include <asm/tlbflush.h>
#include <linux/swapops.h>
#include <linux/swap_cgroup.h>
#include <trace/hooks/mm.h>
static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
unsigned char);
@@ -98,7 +99,7 @@ static atomic_t proc_poll_event = 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))
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. */
return READ_ONCE(swap_info[type]);
}
EXPORT_SYMBOL_GPL(swap_type_to_swap_info);
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 end = offset + nr_entries - 1;
void (*swap_slot_free_notify)(struct block_device *, unsigned long);
bool skip = false;
if (offset < si->lowest_bit)
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))
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;
if (si->flags & SWP_BLKDEV)
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);
}
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,
swp_entry_t slots[])
{
@@ -983,8 +988,9 @@ no_page:
si->flags -= SWP_SCANNING;
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;
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;
}
EXPORT_SYMBOL_GPL(swap_alloc_cluster);
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);
pgoff_t offset;
bool skip = false;
if (!si)
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 */
offset = scan_swap_map(si, 1);
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);
return swp_entry(type, offset);
}
@@ -1478,6 +1488,7 @@ void swapcache_free_entries(swp_entry_t *entries, int n)
if (p)
spin_unlock(&p->lock);
}
EXPORT_SYMBOL_GPL(swapcache_free_entries);
/*
* 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);
trace_android_vh_unuse_swap_page(si, page);
unlock_page(page);
put_page(page);
@@ -2245,6 +2257,7 @@ retry:
lock_page(page);
wait_on_page_writeback(page);
try_to_free_swap(page);
trace_android_vh_unuse_swap_page(si, page);
unlock_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)
{
p->flags |= SWP_WRITEOK | SWP_VALID;
atomic_long_add(p->pages, &nr_swap_pages);
total_swap_pages += p->pages;
bool skip = false;
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);
/*
* both lists are plists, and thus priority ordered.
@@ -2574,6 +2591,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
struct filename *pathname;
int err, found = 0;
unsigned int old_block_size;
bool skip = false;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -2628,8 +2646,11 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
least_priority++;
}
plist_del(&p->list, &swap_active_head);
atomic_long_sub(p->pages, &nr_swap_pages);
total_swap_pages -= p->pages;
trace_android_vh_account_swap_pages(p, &skip);
if (!skip) {
atomic_long_sub(p->pages, &nr_swap_pages);
total_swap_pages -= p->pages;
}
p->flags &= ~SWP_WRITEOK;
spin_unlock(&p->lock);
spin_unlock(&swap_lock);
@@ -2881,12 +2902,15 @@ late_initcall(max_swapfiles_check);
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;
unsigned int type;
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)
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;
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",
p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
@@ -3433,8 +3458,10 @@ void si_swapinfo(struct sysinfo *val)
spin_lock(&swap_lock);
for (type = 0; type < nr_swapfiles; 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;
}
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;
}
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
* 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_ratio;
unsigned long gb;
bool skip = false;
inactive = lruvec_page_state(lruvec, NR_LRU_BASE + inactive_lru);
active = lruvec_page_state(lruvec, NR_LRU_BASE + active_lru);
gb = (inactive + active) >> (30 - PAGE_SHIFT);
trace_android_vh_inactive_is_low(gb, &inactive_ratio, inactive_lru, &skip);
if (skip)
goto out;
if (gb)
inactive_ratio = int_sqrt(10 * gb);
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));
out:
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;
refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_FILE);
target_lruvec->refaults[1] = refaults;
trace_android_vh_snapshot_refaults(target_lruvec);
}
/*