Merge branch 'android12-5.10' into branch 'android12-5.10-lts'
Sync up with android12-5.10 for the following commits:fb39cdb9ea
ANDROID: export reclaim_pages1f8f6d59a2
ANDROID: vendor_hook: Add hook to not be stuck ro rmap lock in kswapd or direct_reclaim91bfc78bc0
ANDROID: Update symbol list for mtk02df0b2661
ANDROID: GKI: rockchip: Add symbols for cryptoefdf581d14
ANDROID: GKI: rockchip: Add symbol pci_disable_link_state504ce2d3a6
ANDROID: GKI: rockchip: Add symbols for sounda6b6bc98b7
ANDROID: GKI: rockchip: Add symbols for videof3a311b456
BACKPORT: f2fs: do not set compression bit if kernel doesn't supportb0988144b0
UPSTREAM: exfat: improve performance of exfat_free_cluster when using dirsync mount00d3b8c0cc
ANDROID: GKI: rockchip: Add symbols for drm dp936f1e35d1
UPSTREAM: arm64: perf: Support new DT compatiblesed931dc8ff
UPSTREAM: arm64: perf: Simplify registration boilerplatebb6c018ab6
UPSTREAM: arm64: perf: Support Denver and Carmel PMUsd306fd9d47
UPSTREAM: arm64: perf: add support for Cortex-A7809f78c3f7e
ANDROID: GKI: rockchip: Update symbol for devfreqe7ed66854e
ANDROID: GKI: rockchip: Update symbols for drma3e70ff5bf
ANDROID: GKI: Update symbols to symbol lista09241c6dd
UPSTREAM: ASoC: hdmi-codec: make hdmi_codec_controls static9eda09e511
UPSTREAM: ASoC: hdmi-codec: Add a prepare hook4ad97b395f
UPSTREAM: ASoC: hdmi-codec: Add iec958 controlsc0c2f6962d
UPSTREAM: ASoC: hdmi-codec: Rework to support more controls4c6eb3db8a
UPSTREAM: ALSA: iec958: Split status creation and fill580d2e7c78
UPSTREAM: ALSA: doc: Clarify IEC958 controls iface8b4bb1bca0
UPSTREAM: ASoC: hdmi-codec: remove unused spk_mask member5a2c4a5d1e
UPSTREAM: ASoC: hdmi-codec: remove useless initialization49e502f0c0
UPSTREAM: ASoC: codec: hdmi-codec: Support IEC958 encoded PCM format9bf69acb92
UPSTREAM: ASoC: hdmi-codec: Fix return value in hdmi_codec_set_jack()056409c7dc
UPSTREAM: ASoC: hdmi-codec: Add RX support5e75deab3a
UPSTREAM: ASoC: hdmi-codec: Get ELD in before reporting plugged eventd6207c39cb
ANDROID: GKI: rockchip: Add symbols for display driver1c3ed9d481
BACKPORT: KVM: x86/mmu: fix NULL pointer dereference on guest INVPCID843d3cb41b
BACKPORT: io_uring: always grab file table for deferred statx784cc16aed
BACKPORT: Bluetooth: L2CAP: Fix use-after-free caused by l2cap_chan_put2b377175a3
ANDROID: add two func in mm/memcontrol.ce56f8712cf
ANDROID: vendor_hooks: protect multi-mapcount pages in kernel3f775b9367
ANDROID: vendor_hooks: account page-mapcount1d2287f56e
FROMGIT: io_uring: Use original task for req identity in io_identity_cow()e0c9da25b2
FROMLIST: binder: fix UAF of ref->proc caused by race condition12f4322442
ANDROID: vendor_hooks: Guard cgroup struct with CONFIG_CGROUPS6532784c78
ANDROID: vendor_hooks: add hooks for remove_vm_area.c9a70dd592
ANDROID: GKI: allow mm vendor hooks header inclusion from header files039080d064
ANDROID: Update symbol list of mediatek9e8dedef1e
ANDROID: sched: add vendor hook to PELT multiplier573c7f061d
ANDROID: Guard hooks with their CONFIG_ options14f646cca5
ANDROID: fix kernelci issue for allnoconfig builds4442801a43
ANDROID: sched: Introducing PELT multiplierb2e5773ea4
FROMGIT: binder: fix redefinition of seq_file attributes9c2a5eef8f
Merge tag 'android12-5.10.117_r00' into 'android12-5.10'5fa1e1affc
ANDROID: GKI: pcie: Fix the broken dw_pcie structure51b3e17071
UPSTREAM: PCI: dwc: Support multiple ATU memory regionsa8d7f6518e
ANDROID: oplus: Update the ABI xml and symbol list4536de1b70
ANDROID: vendor_hooks: add hooks in __alloc_pages_slowpathd63c961c9d
ANDROID: GKI: Update symbols to symbol list41cbbe08f9
FROMGIT: arm64: fix oops in concurrently setting insn_emulation sysctlsc301d142e8
FROMGIT: usb: dwc3: core: Do not perform GCTL_CORE_SOFTRESET during bootup8b19ed264b
ANDROID: vendor_hooks:vendor hook for mmput242b11e574
ANDROID: vendor_hooks:vendor hook for pidfd_open0e1cb27700
ANDROID: vendor_hook: Add hook in shmem_writepage()8ee37d0bcd
BACKPORT: iommu/dma: Fix race condition during iova_domain initialization321bf845e1
FROMGIT: usb: dwc3: core: Deprecate GCTL.CORESOFTRESETc5eb0edfde
FROMGIT: usb: dwc3: gadget: Prevent repeat pullup()8de633b735
FROMGIT: Binder: add TF_UPDATE_TXN to replace outdated txne8fce59434
BACKPORT: FROMGIT: cgroup: Use separate src/dst nodes when preloading css_sets for migrationf26c566455
UPSTREAM: usb: gadget: f_uac2: allow changing interface name via configfs98fa7f7dfd
UPSTREAM: usb: gadget: f_uac1: allow changing interface name via configfs29172165ca
UPSTREAM: usb: gadget: f_uac1: Add suspend callbackff5468c71e
UPSTREAM: usb: gadget: f_uac2: Add suspend callback31e6d620c1
UPSTREAM: usb: gadget: u_audio: Add suspend call17643c1fdd
UPSTREAM: usb: gadget: u_audio: Rate ctl notifies about current srate (0=stopped)308955e3a6
UPSTREAM: usb: gadget: f_uac1: Support multiple sampling ratesae03eadb42
UPSTREAM: usb: gadget: f_uac2: Support multiple sampling ratesbedc53fae4
UPSTREAM: usb: gadget:audio: Replace deprecated macro S_IRUGO37e0d5eddb
UPSTREAM: usb: gadget: u_audio: Add capture/playback srate getter3251bb3250
UPSTREAM: usb: gadget: u_audio: Move dynamic srate from params to rtd530916be97
UPSTREAM: usb: gadget: u_audio: Support multiple sampling rates7f496d5a99
UPSTREAM: docs: ABI: fixed formatting in configfs-usb-gadget-uac22500cb53e6
UPSTREAM: usb: gadget: u_audio: Subdevice 0 for capture ctlsc386f34bd4
UPSTREAM: usb: gadget: u_audio: fix calculations for small bIntervalf74e3e2fe4
UPSTREAM: docs: ABI: fixed req_number desc in UAC102949bae5c
UPSTREAM: docs: ABI: added missing num_requests param to UAC2e1377ac38f
UPSTREAM: usb:gadget: f_uac1: fixed sync playback4b7c8905c5
UPSTREAM: usb: gadget: u_audio.c: Adding Playback Pitch ctl for sync playbacke29d2b5178
UPSTREAM: ABI: configfs-usb-gadget-uac2: fix a broken tableec313ae88d
UPSTREAM: ABI: configfs-usb-gadget-uac1: fix a broken tablebf46bbe087
UPSTREAM: usb: gadget: f_uac1: fixing inconsistent indentingb9c4cbbf7a
UPSTREAM: docs: usb: fix malformed tablea380b466e0
UPSTREAM: usb: gadget: f_uac1: add volume and mute supporte2c0816af2
BACKPORT: usb: gadget: f_uac2: add volume and mute support8430eb0243
UPSTREAM: usb: gadget: u_audio: add bi-directional volume and mute support257d21b184
UPSTREAM: usb: audio-v2: add ability to define feature unit descriptor1002747429
ANDROID: mm: shmem: use reclaim_pages() to recalim pages from a list6719763187
UPSTREAM: usb: gadget: f_uac1: disable IN/OUT ep if unused And add the new symbols being tracked due to abi additions from the android12-5.10 branch: Leaf changes summary: 85 artifacts changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 69 Added functions Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 16 Added variables 69 Added functions: [A] 'function void __dev_kfree_skb_irq(sk_buff*, skb_free_reason)' [A] 'function int __page_mapcount(page*)' [A] 'function int __traceiter_android_vh_add_page_to_lrulist(void*, page*, bool, lru_list)' [A] 'function int __traceiter_android_vh_alloc_pages_slowpath_begin(void*, gfp_t, unsigned int, unsigned long int*)' [A] 'function int __traceiter_android_vh_alloc_pages_slowpath_end(void*, gfp_t, unsigned int, unsigned long int)' [A] 'function int __traceiter_android_vh_del_page_from_lrulist(void*, page*, bool, lru_list)' [A] 'function int __traceiter_android_vh_do_traversal_lruvec(void*, lruvec*)' [A] 'function int __traceiter_android_vh_mark_page_accessed(void*, page*)' [A] 'function int __traceiter_android_vh_mutex_unlock_slowpath_end(void*, mutex*, task_struct*)' [A] 'function int __traceiter_android_vh_page_should_be_protected(void*, page*, bool*)' [A] 'function int __traceiter_android_vh_rwsem_mark_wake_readers(void*, rw_semaphore*, rwsem_waiter*)' [A] 'function int __traceiter_android_vh_rwsem_set_owner(void*, rw_semaphore*)' [A] 'function int __traceiter_android_vh_rwsem_set_reader_owned(void*, rw_semaphore*)' [A] 'function int __traceiter_android_vh_rwsem_up_read_end(void*, rw_semaphore*)' [A] 'function int __traceiter_android_vh_rwsem_up_write_end(void*, rw_semaphore*)' [A] 'function int __traceiter_android_vh_sched_pelt_multiplier(void*, unsigned int, unsigned int, int*)' [A] 'function int __traceiter_android_vh_show_mapcount_pages(void*, void*)' [A] 'function int __traceiter_android_vh_update_page_mapcount(void*, page*, bool, bool, bool*, bool*)' [A] 'function int __v4l2_ctrl_handler_setup(v4l2_ctrl_handler*)' [A] 'function int crypto_ahash_final(ahash_request*)' [A] 'function crypto_akcipher* crypto_alloc_akcipher(const char*, u32, u32)' [A] 'function int crypto_register_akcipher(akcipher_alg*)' [A] 'function void crypto_unregister_akcipher(akcipher_alg*)' [A] 'function int des_expand_key(des_ctx*, const u8*, unsigned int)' [A] 'function void dev_pm_opp_unregister_set_opp_helper(opp_table*)' [A] 'function net_device* devm_alloc_etherdev_mqs(device*, int, unsigned int, unsigned int)' [A] 'function mii_bus* devm_mdiobus_alloc_size(device*, int)' [A] 'function int devm_of_mdiobus_register(device*, mii_bus*, device_node*)' [A] 'function int devm_register_netdev(device*, net_device*)' [A] 'function bool disable_hardirq(unsigned int)' [A] 'function void do_traversal_all_lruvec()' [A] 'function drm_connector_status drm_bridge_detect(drm_bridge*)' [A] 'function edid* drm_bridge_get_edid(drm_bridge*, drm_connector*)' [A] 'function int drm_bridge_get_modes(drm_bridge*, drm_connector*)' [A] 'function int drm_dp_get_phy_test_pattern(drm_dp_aux*, drm_dp_phy_test_params*)' [A] 'function int drm_dp_read_desc(drm_dp_aux*, drm_dp_desc*, bool)' [A] 'function int drm_dp_read_dpcd_caps(drm_dp_aux*, u8*)' [A] 'function int drm_dp_read_sink_count(drm_dp_aux*)' [A] 'function int drm_dp_set_phy_test_pattern(drm_dp_aux*, drm_dp_phy_test_params*, u8)' [A] 'function uint64_t drm_format_info_min_pitch(const drm_format_info*, int, unsigned int)' [A] 'function int drm_mm_reserve_node(drm_mm*, drm_mm_node*)' [A] 'function bool drm_probe_ddc(i2c_adapter*)' [A] 'function void drm_self_refresh_helper_cleanup(drm_crtc*)' [A] 'function int drm_self_refresh_helper_init(drm_crtc*)' [A] 'function int get_pelt_halflife()' [A] 'function ssize_t hdmi_avi_infoframe_pack_only(const hdmi_avi_infoframe*, void*, size_t)' [A] 'function ssize_t iio_read_const_attr(device*, device_attribute*, char*)' [A] 'function bool mipi_dsi_packet_format_is_short(u8)' [A] 'function platform_device* of_device_alloc(device_node*, const char*, device*)' [A] 'function lruvec* page_to_lruvec(page*, pg_data_t*)' [A] 'function int pci_disable_link_state(pci_dev*, int)' [A] 'function int regmap_test_bits(regmap*, unsigned int, unsigned int)' [A] 'function unsigned int regulator_get_linear_step(regulator*)' [A] 'function int regulator_suspend_enable(regulator_dev*, suspend_state_t)' [A] 'function int rsa_parse_priv_key(rsa_key*, void*, unsigned int)' [A] 'function int rsa_parse_pub_key(rsa_key*, void*, unsigned int)' [A] 'function int sg_nents(scatterlist*)' [A] 'function int snd_pcm_create_iec958_consumer_default(u8*, size_t)' [A] 'function int snd_pcm_fill_iec958_consumer(snd_pcm_runtime*, u8*, size_t)' [A] 'function int snd_pcm_fill_iec958_consumer_hw_params(snd_pcm_hw_params*, u8*, size_t)' [A] 'function int snd_soc_dapm_force_bias_level(snd_soc_dapm_context*, snd_soc_bias_level)' [A] 'function int snd_soc_jack_add_zones(snd_soc_jack*, int, snd_soc_jack_zone*)' [A] 'function int snd_soc_jack_get_type(snd_soc_jack*, int)' [A] 'function void tcpm_tcpc_reset(tcpm_port*)' [A] 'function int v4l2_enum_dv_timings_cap(v4l2_enum_dv_timings*, const v4l2_dv_timings_cap*, v4l2_check_dv_timings_fnc*, void*)' [A] 'function void v4l2_print_dv_timings(const char*, const char*, const v4l2_dv_timings*, bool)' [A] 'function int v4l2_src_change_event_subdev_subscribe(v4l2_subdev*, v4l2_fh*, v4l2_event_subscription*)' [A] 'function void v4l2_subdev_notify_event(v4l2_subdev*, const v4l2_event*)' [A] 'function bool v4l2_valid_dv_timings(const v4l2_dv_timings*, const v4l2_dv_timings_cap*, v4l2_check_dv_timings_fnc*, void*)' 16 Added variables: [A] 'tracepoint __tracepoint_android_vh_add_page_to_lrulist' [A] 'tracepoint __tracepoint_android_vh_alloc_pages_slowpath_begin' [A] 'tracepoint __tracepoint_android_vh_alloc_pages_slowpath_end' [A] 'tracepoint __tracepoint_android_vh_del_page_from_lrulist' [A] 'tracepoint __tracepoint_android_vh_do_traversal_lruvec' [A] 'tracepoint __tracepoint_android_vh_mark_page_accessed' [A] 'tracepoint __tracepoint_android_vh_mutex_unlock_slowpath_end' [A] 'tracepoint __tracepoint_android_vh_page_should_be_protected' [A] 'tracepoint __tracepoint_android_vh_rwsem_mark_wake_readers' [A] 'tracepoint __tracepoint_android_vh_rwsem_set_owner' [A] 'tracepoint __tracepoint_android_vh_rwsem_set_reader_owned' [A] 'tracepoint __tracepoint_android_vh_rwsem_up_read_end' [A] 'tracepoint __tracepoint_android_vh_rwsem_up_write_end' [A] 'tracepoint __tracepoint_android_vh_sched_pelt_multiplier' [A] 'tracepoint __tracepoint_android_vh_show_mapcount_pages' [A] 'tracepoint __tracepoint_android_vh_update_page_mapcount' Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I47eefe85b949d3f358da95a9b6553660b9be0791
This commit is contained in:
@@ -4,13 +4,30 @@ KernelVersion: 4.14
|
|||||||
Description:
|
Description:
|
||||||
The attributes:
|
The attributes:
|
||||||
|
|
||||||
========== ===================================
|
===================== =======================================
|
||||||
c_chmask capture channel mask
|
c_chmask capture channel mask
|
||||||
c_srate capture sampling rate
|
c_srate list of capture sampling rates (comma-separated)
|
||||||
c_ssize capture sample size (bytes)
|
c_ssize capture sample size (bytes)
|
||||||
|
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_chmask playback channel mask
|
||||||
p_srate playback sampling rate
|
p_srate list of playback sampling rates (comma-separated)
|
||||||
p_ssize playback sample size (bytes)
|
p_ssize playback sample size (bytes)
|
||||||
req_number the number of pre-allocated request
|
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
|
for both capture and playback
|
||||||
========== ===================================
|
function_name name of the interface
|
||||||
|
===================== =======================================
|
||||||
|
@@ -4,13 +4,33 @@ KernelVersion: 3.18
|
|||||||
Description:
|
Description:
|
||||||
The attributes:
|
The attributes:
|
||||||
|
|
||||||
========= ============================
|
===================== =======================================
|
||||||
c_chmask capture channel mask
|
c_chmask capture channel mask
|
||||||
c_srate capture sampling rate
|
c_srate list of capture sampling rates (comma-separated)
|
||||||
c_ssize capture sample size (bytes)
|
c_ssize capture sample size (bytes)
|
||||||
c_sync capture synchronization type (async/adaptive)
|
c_sync capture synchronization type
|
||||||
|
(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
|
fb_max maximum extra bandwidth in async mode
|
||||||
p_chmask playback channel mask
|
p_chmask playback channel mask
|
||||||
p_srate playback sampling rate
|
p_srate list of playback sampling rates (comma-separated)
|
||||||
p_ssize playback sample size (bytes)
|
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
|
||||||
|
===================== =======================================
|
||||||
|
@@ -3508,14 +3508,15 @@ field must be set, though).
|
|||||||
|
|
||||||
“IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958
|
“IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958
|
||||||
status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask”
|
status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask”
|
||||||
returns the bitmask for professional mode. They are read-only controls,
|
returns the bitmask for professional mode. They are read-only controls.
|
||||||
and are defined as MIXER controls (iface =
|
|
||||||
``SNDRV_CTL_ELEM_IFACE_MIXER``).
|
|
||||||
|
|
||||||
Meanwhile, “IEC958 Playback Default” control is defined for getting and
|
Meanwhile, “IEC958 Playback Default” control is defined for getting and
|
||||||
setting the current default IEC958 bits. Note that this one is usually
|
setting the current default IEC958 bits.
|
||||||
defined as a PCM control (iface = ``SNDRV_CTL_ELEM_IFACE_PCM``),
|
|
||||||
although in some places it's defined as a MIXER control.
|
Due to historical reasons, both variants of the Playback Mask and the
|
||||||
|
Playback Default controls can be implemented on either a
|
||||||
|
``SNDRV_CTL_ELEM_IFACE_PCM`` or a ``SNDRV_CTL_ELEM_IFACE_MIXER`` iface.
|
||||||
|
Drivers should expose the mask and default on the same iface though.
|
||||||
|
|
||||||
In addition, you can define the control switches to enable/disable or to
|
In addition, you can define the control switches to enable/disable or to
|
||||||
set the raw bit mode. The implementation will depend on the chip, but
|
set the raw bit mode. The implementation will depend on the chip, but
|
||||||
|
@@ -724,18 +724,29 @@ Function-specific configfs interface
|
|||||||
The function name to use when creating the function directory is "uac2".
|
The function name to use when creating the function directory is "uac2".
|
||||||
The uac2 function provides these attributes in its function directory:
|
The uac2 function provides these attributes in its function directory:
|
||||||
|
|
||||||
=============== ====================================================
|
================ ====================================================
|
||||||
c_chmask capture channel mask
|
c_chmask capture channel mask
|
||||||
c_srate capture sampling rate
|
c_srate list of capture sampling rates (comma-separated)
|
||||||
c_ssize capture sample size (bytes)
|
c_ssize capture sample size (bytes)
|
||||||
c_sync capture synchronization type (async/adaptive)
|
c_sync capture synchronization type (async/adaptive)
|
||||||
|
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
|
fb_max maximum extra bandwidth in async mode
|
||||||
p_chmask playback channel mask
|
p_chmask playback channel mask
|
||||||
p_srate playback sampling rate
|
p_srate list of playback sampling rates (comma-separated)
|
||||||
p_ssize playback sample size (bytes)
|
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
|
req_number the number of pre-allocated request for both capture
|
||||||
and playback
|
and playback
|
||||||
=============== ====================================================
|
function_name name of the interface
|
||||||
|
================ ====================================================
|
||||||
|
|
||||||
The attributes have sane default values.
|
The attributes have sane default values.
|
||||||
|
|
||||||
@@ -905,16 +916,27 @@ Function-specific configfs interface
|
|||||||
The function name to use when creating the function directory is "uac1".
|
The function name to use when creating the function directory is "uac1".
|
||||||
The uac1 function provides these attributes in its function directory:
|
The uac1 function provides these attributes in its function directory:
|
||||||
|
|
||||||
========== ====================================================
|
================ ====================================================
|
||||||
c_chmask capture channel mask
|
c_chmask capture channel mask
|
||||||
c_srate capture sampling rate
|
c_srate list of capture sampling rates (comma-separated)
|
||||||
c_ssize capture sample size (bytes)
|
c_ssize capture sample size (bytes)
|
||||||
|
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_chmask playback channel mask
|
||||||
p_srate playback sampling rate
|
p_srate list of playback sampling rates (comma-separated)
|
||||||
p_ssize playback sample size (bytes)
|
p_ssize playback sample size (bytes)
|
||||||
req_number the number of pre-allocated request for both capture
|
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
|
and playback
|
||||||
========== ====================================================
|
function_name name of the interface
|
||||||
|
================ ====================================================
|
||||||
|
|
||||||
The attributes have sane default values.
|
The attributes have sane default values.
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -371,7 +371,10 @@
|
|||||||
device_unregister
|
device_unregister
|
||||||
_dev_info
|
_dev_info
|
||||||
__dev_kfree_skb_any
|
__dev_kfree_skb_any
|
||||||
|
__dev_kfree_skb_irq
|
||||||
|
devm_add_action
|
||||||
__devm_alloc_percpu
|
__devm_alloc_percpu
|
||||||
|
devm_alloc_etherdev_mqs
|
||||||
devm_blk_ksm_init
|
devm_blk_ksm_init
|
||||||
devm_clk_bulk_get
|
devm_clk_bulk_get
|
||||||
devm_clk_bulk_get_optional
|
devm_clk_bulk_get_optional
|
||||||
@@ -412,11 +415,13 @@
|
|||||||
devm_led_classdev_register_ext
|
devm_led_classdev_register_ext
|
||||||
devm_led_classdev_unregister
|
devm_led_classdev_unregister
|
||||||
devm_mbox_controller_register
|
devm_mbox_controller_register
|
||||||
|
devm_mdiobus_alloc_size
|
||||||
devm_memremap
|
devm_memremap
|
||||||
devm_mfd_add_devices
|
devm_mfd_add_devices
|
||||||
devm_nvmem_cell_get
|
devm_nvmem_cell_get
|
||||||
devm_nvmem_device_get
|
devm_nvmem_device_get
|
||||||
devm_nvmem_register
|
devm_nvmem_register
|
||||||
|
devm_of_mdiobus_register
|
||||||
devm_of_phy_get_by_index
|
devm_of_phy_get_by_index
|
||||||
__devm_of_phy_provider_register
|
__devm_of_phy_provider_register
|
||||||
devm_of_platform_populate
|
devm_of_platform_populate
|
||||||
@@ -433,6 +438,7 @@
|
|||||||
devm_power_supply_register
|
devm_power_supply_register
|
||||||
devm_rc_allocate_device
|
devm_rc_allocate_device
|
||||||
devm_rc_register_device
|
devm_rc_register_device
|
||||||
|
devm_register_netdev
|
||||||
devm_regmap_add_irq_chip
|
devm_regmap_add_irq_chip
|
||||||
devm_regmap_field_alloc
|
devm_regmap_field_alloc
|
||||||
devm_regmap_field_bulk_alloc
|
devm_regmap_field_bulk_alloc
|
||||||
@@ -584,6 +590,7 @@
|
|||||||
down_write
|
down_write
|
||||||
d_path
|
d_path
|
||||||
dput
|
dput
|
||||||
|
dql_completed
|
||||||
drain_workqueue
|
drain_workqueue
|
||||||
driver_create_file
|
driver_create_file
|
||||||
driver_remove_file
|
driver_remove_file
|
||||||
@@ -809,7 +816,13 @@
|
|||||||
genlmsg_put
|
genlmsg_put
|
||||||
genl_register_family
|
genl_register_family
|
||||||
genl_unregister_family
|
genl_unregister_family
|
||||||
|
__genphy_config_aneg
|
||||||
|
genphy_read_abilities
|
||||||
|
genphy_read_mmd_unsupported
|
||||||
|
genphy_read_status
|
||||||
genphy_resume
|
genphy_resume
|
||||||
|
genphy_suspend
|
||||||
|
genphy_write_mmd_unsupported
|
||||||
gen_pool_add_owner
|
gen_pool_add_owner
|
||||||
gen_pool_alloc_algo_owner
|
gen_pool_alloc_algo_owner
|
||||||
gen_pool_avail
|
gen_pool_avail
|
||||||
@@ -835,6 +848,7 @@
|
|||||||
get_kernel_pages
|
get_kernel_pages
|
||||||
get_net_ns_by_fd
|
get_net_ns_by_fd
|
||||||
get_net_ns_by_pid
|
get_net_ns_by_pid
|
||||||
|
get_pelt_halflife
|
||||||
get_pid_task
|
get_pid_task
|
||||||
get_random_bytes
|
get_random_bytes
|
||||||
get_random_u32
|
get_random_u32
|
||||||
@@ -957,11 +971,13 @@
|
|||||||
init_uts_ns
|
init_uts_ns
|
||||||
init_wait_entry
|
init_wait_entry
|
||||||
__init_waitqueue_head
|
__init_waitqueue_head
|
||||||
|
input_alloc_absinfo
|
||||||
input_allocate_device
|
input_allocate_device
|
||||||
input_event
|
input_event
|
||||||
input_free_device
|
input_free_device
|
||||||
input_mt_init_slots
|
input_mt_init_slots
|
||||||
input_mt_report_slot_state
|
input_mt_report_slot_state
|
||||||
|
input_mt_sync_frame
|
||||||
input_register_device
|
input_register_device
|
||||||
input_set_abs_params
|
input_set_abs_params
|
||||||
input_set_capability
|
input_set_capability
|
||||||
@@ -1169,8 +1185,12 @@
|
|||||||
mbox_send_message
|
mbox_send_message
|
||||||
mdiobus_alloc_size
|
mdiobus_alloc_size
|
||||||
mdiobus_free
|
mdiobus_free
|
||||||
|
__mdiobus_read
|
||||||
|
mdiobus_read
|
||||||
__mdiobus_register
|
__mdiobus_register
|
||||||
mdiobus_unregister
|
mdiobus_unregister
|
||||||
|
__mdiobus_write
|
||||||
|
mdiobus_write
|
||||||
media_create_intf_link
|
media_create_intf_link
|
||||||
media_create_pad_link
|
media_create_pad_link
|
||||||
media_device_cleanup
|
media_device_cleanup
|
||||||
@@ -1270,10 +1290,12 @@
|
|||||||
mutex_lock_killable
|
mutex_lock_killable
|
||||||
mutex_trylock
|
mutex_trylock
|
||||||
mutex_unlock
|
mutex_unlock
|
||||||
|
napi_complete_done
|
||||||
napi_disable
|
napi_disable
|
||||||
napi_gro_flush
|
napi_gro_flush
|
||||||
napi_gro_receive
|
napi_gro_receive
|
||||||
__napi_schedule
|
__napi_schedule
|
||||||
|
__napi_schedule_irqoff
|
||||||
napi_schedule_prep
|
napi_schedule_prep
|
||||||
__ndelay
|
__ndelay
|
||||||
nd_tbl
|
nd_tbl
|
||||||
@@ -1292,6 +1314,7 @@
|
|||||||
netif_receive_skb_list
|
netif_receive_skb_list
|
||||||
netif_rx
|
netif_rx
|
||||||
netif_rx_ni
|
netif_rx_ni
|
||||||
|
netif_schedule_queue
|
||||||
netif_tx_stop_all_queues
|
netif_tx_stop_all_queues
|
||||||
netif_tx_wake_queue
|
netif_tx_wake_queue
|
||||||
netlink_broadcast
|
netlink_broadcast
|
||||||
@@ -1372,6 +1395,7 @@
|
|||||||
of_get_next_child
|
of_get_next_child
|
||||||
of_get_next_parent
|
of_get_next_parent
|
||||||
of_get_parent
|
of_get_parent
|
||||||
|
of_get_phy_mode
|
||||||
of_get_property
|
of_get_property
|
||||||
of_get_regulator_init_data
|
of_get_regulator_init_data
|
||||||
of_graph_get_next_endpoint
|
of_graph_get_next_endpoint
|
||||||
@@ -1392,6 +1416,7 @@
|
|||||||
of_parse_phandle_with_fixed_args
|
of_parse_phandle_with_fixed_args
|
||||||
of_phandle_iterator_init
|
of_phandle_iterator_init
|
||||||
of_phandle_iterator_next
|
of_phandle_iterator_next
|
||||||
|
of_phy_connect
|
||||||
of_phy_simple_xlate
|
of_phy_simple_xlate
|
||||||
of_platform_depopulate
|
of_platform_depopulate
|
||||||
of_platform_device_create
|
of_platform_device_create
|
||||||
@@ -1459,19 +1484,29 @@
|
|||||||
phy_connect
|
phy_connect
|
||||||
phy_disconnect
|
phy_disconnect
|
||||||
phy_do_ioctl_running
|
phy_do_ioctl_running
|
||||||
|
phy_drivers_register
|
||||||
|
phy_drivers_unregister
|
||||||
phy_ethtool_get_link_ksettings
|
phy_ethtool_get_link_ksettings
|
||||||
phy_ethtool_nway_reset
|
phy_ethtool_nway_reset
|
||||||
phy_ethtool_set_link_ksettings
|
phy_ethtool_set_link_ksettings
|
||||||
phy_exit
|
phy_exit
|
||||||
phy_get
|
phy_get
|
||||||
phy_init
|
phy_init
|
||||||
|
phy_mii_ioctl
|
||||||
|
__phy_modify
|
||||||
|
phy_modify
|
||||||
|
phy_modify_paged_changed
|
||||||
phy_power_off
|
phy_power_off
|
||||||
phy_power_on
|
phy_power_on
|
||||||
phy_print_status
|
phy_print_status
|
||||||
phy_put
|
phy_put
|
||||||
|
phy_read_paged
|
||||||
|
phy_restore_page
|
||||||
|
phy_select_page
|
||||||
phy_set_mode_ext
|
phy_set_mode_ext
|
||||||
phy_start
|
phy_start
|
||||||
phy_stop
|
phy_stop
|
||||||
|
phy_write_paged
|
||||||
pid_task
|
pid_task
|
||||||
pinconf_generic_parse_dt_config
|
pinconf_generic_parse_dt_config
|
||||||
pinctrl_dev_get_drvdata
|
pinctrl_dev_get_drvdata
|
||||||
@@ -1660,6 +1695,7 @@
|
|||||||
regmap_raw_read
|
regmap_raw_read
|
||||||
regmap_raw_write
|
regmap_raw_write
|
||||||
regmap_read
|
regmap_read
|
||||||
|
regmap_test_bits
|
||||||
regmap_update_bits_base
|
regmap_update_bits_base
|
||||||
regmap_write
|
regmap_write
|
||||||
regulator_count_voltages
|
regulator_count_voltages
|
||||||
@@ -2091,6 +2127,8 @@
|
|||||||
timer_unstable_counter_workaround
|
timer_unstable_counter_workaround
|
||||||
topology_set_thermal_pressure
|
topology_set_thermal_pressure
|
||||||
_totalram_pages
|
_totalram_pages
|
||||||
|
touchscreen_parse_properties
|
||||||
|
touchscreen_report_pos
|
||||||
__trace_bprintk
|
__trace_bprintk
|
||||||
__trace_bputs
|
__trace_bputs
|
||||||
trace_event_buffer_commit
|
trace_event_buffer_commit
|
||||||
@@ -2153,6 +2191,7 @@
|
|||||||
__traceiter_android_vh_rwsem_init
|
__traceiter_android_vh_rwsem_init
|
||||||
__traceiter_android_vh_rwsem_wake
|
__traceiter_android_vh_rwsem_wake
|
||||||
__traceiter_android_vh_rwsem_write_finished
|
__traceiter_android_vh_rwsem_write_finished
|
||||||
|
__traceiter_android_vh_sched_pelt_multiplier
|
||||||
__traceiter_android_vh_scheduler_tick
|
__traceiter_android_vh_scheduler_tick
|
||||||
__traceiter_android_vh_selinux_avc_insert
|
__traceiter_android_vh_selinux_avc_insert
|
||||||
__traceiter_android_vh_selinux_avc_lookup
|
__traceiter_android_vh_selinux_avc_lookup
|
||||||
@@ -2237,6 +2276,7 @@
|
|||||||
__tracepoint_android_vh_rwsem_init
|
__tracepoint_android_vh_rwsem_init
|
||||||
__tracepoint_android_vh_rwsem_wake
|
__tracepoint_android_vh_rwsem_wake
|
||||||
__tracepoint_android_vh_rwsem_write_finished
|
__tracepoint_android_vh_rwsem_write_finished
|
||||||
|
__tracepoint_android_vh_sched_pelt_multiplier
|
||||||
__tracepoint_android_vh_scheduler_tick
|
__tracepoint_android_vh_scheduler_tick
|
||||||
__tracepoint_android_vh_selinux_avc_insert
|
__tracepoint_android_vh_selinux_avc_insert
|
||||||
__tracepoint_android_vh_selinux_avc_lookup
|
__tracepoint_android_vh_selinux_avc_lookup
|
||||||
@@ -2790,10 +2830,13 @@
|
|||||||
fwnode_graph_parse_endpoint
|
fwnode_graph_parse_endpoint
|
||||||
fwnode_property_get_reference_args
|
fwnode_property_get_reference_args
|
||||||
fwnode_property_read_u64_array
|
fwnode_property_read_u64_array
|
||||||
|
gen_pool_avail
|
||||||
gen_pool_dma_alloc_align
|
gen_pool_dma_alloc_align
|
||||||
gen_pool_has_addr
|
gen_pool_has_addr
|
||||||
|
gen_pool_size
|
||||||
getboottime64
|
getboottime64
|
||||||
get_governor_parent_kobj
|
get_governor_parent_kobj
|
||||||
|
get_pelt_halflife
|
||||||
get_task_exe_file
|
get_task_exe_file
|
||||||
get_vaddr_frames
|
get_vaddr_frames
|
||||||
get_zeroed_page
|
get_zeroed_page
|
||||||
@@ -3070,6 +3113,7 @@
|
|||||||
__traceiter_android_vh_rwsem_init
|
__traceiter_android_vh_rwsem_init
|
||||||
__traceiter_android_vh_rwsem_wake
|
__traceiter_android_vh_rwsem_wake
|
||||||
__traceiter_android_vh_rwsem_write_finished
|
__traceiter_android_vh_rwsem_write_finished
|
||||||
|
__traceiter_android_vh_sched_pelt_multiplier
|
||||||
__traceiter_android_vh_scmi_timeout_sync
|
__traceiter_android_vh_scmi_timeout_sync
|
||||||
__traceiter_android_vh_show_resume_epoch_val
|
__traceiter_android_vh_show_resume_epoch_val
|
||||||
__traceiter_android_vh_show_suspend_epoch_val
|
__traceiter_android_vh_show_suspend_epoch_val
|
||||||
@@ -3123,6 +3167,7 @@
|
|||||||
__tracepoint_android_vh_rwsem_init
|
__tracepoint_android_vh_rwsem_init
|
||||||
__tracepoint_android_vh_rwsem_wake
|
__tracepoint_android_vh_rwsem_wake
|
||||||
__tracepoint_android_vh_rwsem_write_finished
|
__tracepoint_android_vh_rwsem_write_finished
|
||||||
|
__tracepoint_android_vh_sched_pelt_multiplier
|
||||||
__tracepoint_android_vh_scmi_timeout_sync
|
__tracepoint_android_vh_scmi_timeout_sync
|
||||||
__tracepoint_android_vh_show_resume_epoch_val
|
__tracepoint_android_vh_show_resume_epoch_val
|
||||||
__tracepoint_android_vh_show_suspend_epoch_val
|
__tracepoint_android_vh_show_suspend_epoch_val
|
||||||
@@ -3193,6 +3238,7 @@
|
|||||||
usb_otg_state_string
|
usb_otg_state_string
|
||||||
usb_phy_set_charger_current
|
usb_phy_set_charger_current
|
||||||
usb_remove_phy
|
usb_remove_phy
|
||||||
|
usb_role_switch_set_role
|
||||||
v4l2_async_notifier_add_subdev
|
v4l2_async_notifier_add_subdev
|
||||||
v4l2_async_notifier_cleanup
|
v4l2_async_notifier_cleanup
|
||||||
v4l2_async_subdev_notifier_register
|
v4l2_async_subdev_notifier_register
|
||||||
|
@@ -681,6 +681,7 @@
|
|||||||
dma_unmap_sg_attrs
|
dma_unmap_sg_attrs
|
||||||
do_exit
|
do_exit
|
||||||
do_wait_intr_irq
|
do_wait_intr_irq
|
||||||
|
do_traversal_all_lruvec
|
||||||
down
|
down
|
||||||
down_interruptible
|
down_interruptible
|
||||||
down_read
|
down_read
|
||||||
@@ -1802,10 +1803,12 @@
|
|||||||
page_endio
|
page_endio
|
||||||
__page_file_index
|
__page_file_index
|
||||||
__page_file_mapping
|
__page_file_mapping
|
||||||
|
__page_mapcount
|
||||||
page_get_link
|
page_get_link
|
||||||
page_mapping
|
page_mapping
|
||||||
__page_pinner_migration_failed
|
__page_pinner_migration_failed
|
||||||
page_symlink
|
page_symlink
|
||||||
|
page_to_lruvec
|
||||||
panic
|
panic
|
||||||
panic_notifier_list
|
panic_notifier_list
|
||||||
panic_timeout
|
panic_timeout
|
||||||
@@ -2802,6 +2805,7 @@
|
|||||||
__traceiter_android_vh_ipi_stop
|
__traceiter_android_vh_ipi_stop
|
||||||
__traceiter_android_vh_ipv6_gen_linklocal_addr
|
__traceiter_android_vh_ipv6_gen_linklocal_addr
|
||||||
__traceiter_android_vh_jiffies_update
|
__traceiter_android_vh_jiffies_update
|
||||||
|
__traceiter_android_vh_killed_process
|
||||||
__traceiter_android_vh_kmalloc_slab
|
__traceiter_android_vh_kmalloc_slab
|
||||||
__traceiter_android_vh_logbuf
|
__traceiter_android_vh_logbuf
|
||||||
__traceiter_android_vh_mem_cgroup_alloc
|
__traceiter_android_vh_mem_cgroup_alloc
|
||||||
@@ -2810,19 +2814,33 @@
|
|||||||
__traceiter_android_vh_mem_cgroup_free
|
__traceiter_android_vh_mem_cgroup_free
|
||||||
__traceiter_android_vh_mem_cgroup_id_remove
|
__traceiter_android_vh_mem_cgroup_id_remove
|
||||||
__traceiter_android_vh_meminfo_proc_show
|
__traceiter_android_vh_meminfo_proc_show
|
||||||
|
__traceiter_android_vh_alloc_pages_slowpath_begin
|
||||||
|
__traceiter_android_vh_alloc_pages_slowpath_end
|
||||||
__traceiter_android_vh_mutex_unlock_slowpath
|
__traceiter_android_vh_mutex_unlock_slowpath
|
||||||
|
__traceiter_android_vh_mutex_unlock_slowpath_end
|
||||||
__traceiter_android_vh_mutex_wait_finish
|
__traceiter_android_vh_mutex_wait_finish
|
||||||
__traceiter_android_vh_mutex_wait_start
|
__traceiter_android_vh_mutex_wait_start
|
||||||
__traceiter_android_vh_override_creds
|
__traceiter_android_vh_override_creds
|
||||||
__traceiter_android_vh_page_referenced_check_bypass
|
__traceiter_android_vh_page_referenced_check_bypass
|
||||||
|
__traceiter_android_vh_page_should_be_protected
|
||||||
|
__traceiter_android_vh_mark_page_accessed
|
||||||
|
__traceiter_android_vh_show_mapcount_pages
|
||||||
|
__traceiter_android_vh_do_traversal_lruvec
|
||||||
|
__traceiter_android_vh_update_page_mapcount
|
||||||
|
__traceiter_android_vh_add_page_to_lrulist
|
||||||
|
__traceiter_android_vh_del_page_from_lrulist
|
||||||
__traceiter_android_vh_pcplist_add_cma_pages_bypass
|
__traceiter_android_vh_pcplist_add_cma_pages_bypass
|
||||||
__traceiter_android_vh_prepare_update_load_avg_se
|
__traceiter_android_vh_prepare_update_load_avg_se
|
||||||
__traceiter_android_vh_printk_hotplug
|
__traceiter_android_vh_printk_hotplug
|
||||||
__traceiter_android_vh_process_killed
|
__traceiter_android_vh_process_killed
|
||||||
__traceiter_android_vh_killed_process
|
|
||||||
__traceiter_android_vh_revert_creds
|
__traceiter_android_vh_revert_creds
|
||||||
__traceiter_android_vh_rmqueue
|
__traceiter_android_vh_rmqueue
|
||||||
__traceiter_android_vh_rwsem_init
|
__traceiter_android_vh_rwsem_init
|
||||||
|
__traceiter_android_vh_rwsem_mark_wake_readers
|
||||||
|
__traceiter_android_vh_rwsem_set_owner
|
||||||
|
__traceiter_android_vh_rwsem_set_reader_owned
|
||||||
|
__traceiter_android_vh_rwsem_up_read_end
|
||||||
|
__traceiter_android_vh_rwsem_up_write_end
|
||||||
__traceiter_android_vh_rwsem_wake
|
__traceiter_android_vh_rwsem_wake
|
||||||
__traceiter_android_vh_rwsem_wake_finish
|
__traceiter_android_vh_rwsem_wake_finish
|
||||||
__traceiter_android_vh_rwsem_write_finished
|
__traceiter_android_vh_rwsem_write_finished
|
||||||
@@ -3010,6 +3028,7 @@
|
|||||||
__tracepoint_android_vh_ipi_stop
|
__tracepoint_android_vh_ipi_stop
|
||||||
__tracepoint_android_vh_ipv6_gen_linklocal_addr
|
__tracepoint_android_vh_ipv6_gen_linklocal_addr
|
||||||
__tracepoint_android_vh_jiffies_update
|
__tracepoint_android_vh_jiffies_update
|
||||||
|
__tracepoint_android_vh_killed_process
|
||||||
__tracepoint_android_vh_kmalloc_slab
|
__tracepoint_android_vh_kmalloc_slab
|
||||||
__tracepoint_android_vh_logbuf
|
__tracepoint_android_vh_logbuf
|
||||||
__tracepoint_android_vh_mem_cgroup_alloc
|
__tracepoint_android_vh_mem_cgroup_alloc
|
||||||
@@ -3018,19 +3037,33 @@
|
|||||||
__tracepoint_android_vh_mem_cgroup_free
|
__tracepoint_android_vh_mem_cgroup_free
|
||||||
__tracepoint_android_vh_mem_cgroup_id_remove
|
__tracepoint_android_vh_mem_cgroup_id_remove
|
||||||
__tracepoint_android_vh_meminfo_proc_show
|
__tracepoint_android_vh_meminfo_proc_show
|
||||||
|
__tracepoint_android_vh_alloc_pages_slowpath_begin
|
||||||
|
__tracepoint_android_vh_alloc_pages_slowpath_end
|
||||||
__tracepoint_android_vh_mutex_unlock_slowpath
|
__tracepoint_android_vh_mutex_unlock_slowpath
|
||||||
|
__tracepoint_android_vh_mutex_unlock_slowpath_end
|
||||||
__tracepoint_android_vh_mutex_wait_finish
|
__tracepoint_android_vh_mutex_wait_finish
|
||||||
__tracepoint_android_vh_mutex_wait_start
|
__tracepoint_android_vh_mutex_wait_start
|
||||||
__tracepoint_android_vh_override_creds
|
__tracepoint_android_vh_override_creds
|
||||||
__tracepoint_android_vh_page_referenced_check_bypass
|
__tracepoint_android_vh_page_referenced_check_bypass
|
||||||
|
__tracepoint_android_vh_page_should_be_protected
|
||||||
|
__tracepoint_android_vh_mark_page_accessed
|
||||||
|
__tracepoint_android_vh_show_mapcount_pages
|
||||||
|
__tracepoint_android_vh_do_traversal_lruvec
|
||||||
|
__tracepoint_android_vh_update_page_mapcount
|
||||||
|
__tracepoint_android_vh_add_page_to_lrulist
|
||||||
|
__tracepoint_android_vh_del_page_from_lrulist
|
||||||
__tracepoint_android_vh_pcplist_add_cma_pages_bypass
|
__tracepoint_android_vh_pcplist_add_cma_pages_bypass
|
||||||
__tracepoint_android_vh_prepare_update_load_avg_se
|
__tracepoint_android_vh_prepare_update_load_avg_se
|
||||||
__tracepoint_android_vh_printk_hotplug
|
__tracepoint_android_vh_printk_hotplug
|
||||||
__tracepoint_android_vh_process_killed
|
__tracepoint_android_vh_process_killed
|
||||||
__tracepoint_android_vh_killed_process
|
|
||||||
__tracepoint_android_vh_revert_creds
|
__tracepoint_android_vh_revert_creds
|
||||||
__tracepoint_android_vh_rmqueue
|
__tracepoint_android_vh_rmqueue
|
||||||
__tracepoint_android_vh_rwsem_init
|
__tracepoint_android_vh_rwsem_init
|
||||||
|
__tracepoint_android_vh_rwsem_mark_wake_readers
|
||||||
|
__tracepoint_android_vh_rwsem_set_owner
|
||||||
|
__tracepoint_android_vh_rwsem_set_reader_owned
|
||||||
|
__tracepoint_android_vh_rwsem_up_read_end
|
||||||
|
__tracepoint_android_vh_rwsem_up_write_end
|
||||||
__tracepoint_android_vh_rwsem_wake
|
__tracepoint_android_vh_rwsem_wake
|
||||||
__tracepoint_android_vh_rwsem_wake_finish
|
__tracepoint_android_vh_rwsem_wake_finish
|
||||||
__tracepoint_android_vh_rwsem_write_finished
|
__tracepoint_android_vh_rwsem_write_finished
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -59,6 +59,7 @@ struct insn_emulation {
|
|||||||
static LIST_HEAD(insn_emulation);
|
static LIST_HEAD(insn_emulation);
|
||||||
static int nr_insn_emulated __initdata;
|
static int nr_insn_emulated __initdata;
|
||||||
static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
|
static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
|
||||||
|
static DEFINE_MUTEX(insn_emulation_mutex);
|
||||||
|
|
||||||
static void register_emulation_hooks(struct insn_emulation_ops *ops)
|
static void register_emulation_hooks(struct insn_emulation_ops *ops)
|
||||||
{
|
{
|
||||||
@@ -207,10 +208,10 @@ static int emulation_proc_handler(struct ctl_table *table, int write,
|
|||||||
loff_t *ppos)
|
loff_t *ppos)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct insn_emulation *insn = (struct insn_emulation *) table->data;
|
struct insn_emulation *insn = container_of(table->data, struct insn_emulation, current_mode);
|
||||||
enum insn_emulation_mode prev_mode = insn->current_mode;
|
enum insn_emulation_mode prev_mode = insn->current_mode;
|
||||||
|
|
||||||
table->data = &insn->current_mode;
|
mutex_lock(&insn_emulation_mutex);
|
||||||
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
||||||
|
|
||||||
if (ret || !write || prev_mode == insn->current_mode)
|
if (ret || !write || prev_mode == insn->current_mode)
|
||||||
@@ -223,7 +224,7 @@ static int emulation_proc_handler(struct ctl_table *table, int write,
|
|||||||
update_insn_emulation_mode(insn, INSN_UNDEF);
|
update_insn_emulation_mode(insn, INSN_UNDEF);
|
||||||
}
|
}
|
||||||
ret:
|
ret:
|
||||||
table->data = insn;
|
mutex_unlock(&insn_emulation_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +248,7 @@ static void __init register_insn_emulation_sysctl(void)
|
|||||||
sysctl->maxlen = sizeof(int);
|
sysctl->maxlen = sizeof(int);
|
||||||
|
|
||||||
sysctl->procname = insn->ops->name;
|
sysctl->procname = insn->ops->name;
|
||||||
sysctl->data = insn;
|
sysctl->data = &insn->current_mode;
|
||||||
sysctl->extra1 = &insn->min;
|
sysctl->extra1 = &insn->min;
|
||||||
sysctl->extra2 = &insn->max;
|
sysctl->extra2 = &insn->max;
|
||||||
sysctl->proc_handler = emulation_proc_handler;
|
sysctl->proc_handler = emulation_proc_handler;
|
||||||
|
@@ -1116,17 +1116,32 @@ static int armv8_pmu_init_nogroups(struct arm_pmu *cpu_pmu, char *name,
|
|||||||
return armv8_pmu_init(cpu_pmu, name, map_event, NULL, NULL, NULL);
|
return armv8_pmu_init(cpu_pmu, name, map_event, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv8_pmuv3_init(struct arm_pmu *cpu_pmu)
|
#define PMUV3_INIT_SIMPLE(name) \
|
||||||
{
|
static int name##_pmu_init(struct arm_pmu *cpu_pmu) \
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_pmuv3",
|
{ \
|
||||||
armv8_pmuv3_map_event);
|
return armv8_pmu_init_nogroups(cpu_pmu, #name, armv8_pmuv3_map_event);\
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv8_a34_pmu_init(struct arm_pmu *cpu_pmu)
|
PMUV3_INIT_SIMPLE(armv8_pmuv3)
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a34",
|
PMUV3_INIT_SIMPLE(armv8_cortex_a34)
|
||||||
armv8_pmuv3_map_event);
|
PMUV3_INIT_SIMPLE(armv8_cortex_a55)
|
||||||
}
|
PMUV3_INIT_SIMPLE(armv8_cortex_a65)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_cortex_a75)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_cortex_a76)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_cortex_a77)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_cortex_a78)
|
||||||
|
PMUV3_INIT_SIMPLE(armv9_cortex_a510)
|
||||||
|
PMUV3_INIT_SIMPLE(armv9_cortex_a710)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_cortex_x1)
|
||||||
|
PMUV3_INIT_SIMPLE(armv9_cortex_x2)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_neoverse_e1)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_neoverse_n1)
|
||||||
|
PMUV3_INIT_SIMPLE(armv9_neoverse_n2)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_neoverse_v1)
|
||||||
|
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_nvidia_carmel)
|
||||||
|
PMUV3_INIT_SIMPLE(armv8_nvidia_denver)
|
||||||
|
|
||||||
static int armv8_a35_pmu_init(struct arm_pmu *cpu_pmu)
|
static int armv8_a35_pmu_init(struct arm_pmu *cpu_pmu)
|
||||||
{
|
{
|
||||||
@@ -1140,24 +1155,12 @@ static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu)
|
|||||||
armv8_a53_map_event);
|
armv8_a53_map_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv8_a55_pmu_init(struct arm_pmu *cpu_pmu)
|
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a55",
|
|
||||||
armv8_pmuv3_map_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu)
|
static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu)
|
||||||
{
|
{
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a57",
|
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a57",
|
||||||
armv8_a57_map_event);
|
armv8_a57_map_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv8_a65_pmu_init(struct arm_pmu *cpu_pmu)
|
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a65",
|
|
||||||
armv8_pmuv3_map_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu)
|
static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu)
|
||||||
{
|
{
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a72",
|
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a72",
|
||||||
@@ -1170,36 +1173,6 @@ static int armv8_a73_pmu_init(struct arm_pmu *cpu_pmu)
|
|||||||
armv8_a73_map_event);
|
armv8_a73_map_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armv8_a75_pmu_init(struct arm_pmu *cpu_pmu)
|
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a75",
|
|
||||||
armv8_pmuv3_map_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int armv8_a76_pmu_init(struct arm_pmu *cpu_pmu)
|
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a76",
|
|
||||||
armv8_pmuv3_map_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int armv8_a77_pmu_init(struct arm_pmu *cpu_pmu)
|
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cortex_a77",
|
|
||||||
armv8_pmuv3_map_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int armv8_e1_pmu_init(struct arm_pmu *cpu_pmu)
|
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_neoverse_e1",
|
|
||||||
armv8_pmuv3_map_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int armv8_n1_pmu_init(struct arm_pmu *cpu_pmu)
|
|
||||||
{
|
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_neoverse_n1",
|
|
||||||
armv8_pmuv3_map_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu)
|
static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu)
|
||||||
{
|
{
|
||||||
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cavium_thunder",
|
return armv8_pmu_init_nogroups(cpu_pmu, "armv8_cavium_thunder",
|
||||||
@@ -1213,22 +1186,31 @@ static int armv8_vulcan_pmu_init(struct arm_pmu *cpu_pmu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id armv8_pmu_of_device_ids[] = {
|
static const struct of_device_id armv8_pmu_of_device_ids[] = {
|
||||||
{.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_init},
|
{.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_pmu_init},
|
||||||
{.compatible = "arm,cortex-a34-pmu", .data = armv8_a34_pmu_init},
|
{.compatible = "arm,cortex-a34-pmu", .data = armv8_cortex_a34_pmu_init},
|
||||||
{.compatible = "arm,cortex-a35-pmu", .data = armv8_a35_pmu_init},
|
{.compatible = "arm,cortex-a35-pmu", .data = armv8_a35_pmu_init},
|
||||||
{.compatible = "arm,cortex-a53-pmu", .data = armv8_a53_pmu_init},
|
{.compatible = "arm,cortex-a53-pmu", .data = armv8_a53_pmu_init},
|
||||||
{.compatible = "arm,cortex-a55-pmu", .data = armv8_a55_pmu_init},
|
{.compatible = "arm,cortex-a55-pmu", .data = armv8_cortex_a55_pmu_init},
|
||||||
{.compatible = "arm,cortex-a57-pmu", .data = armv8_a57_pmu_init},
|
{.compatible = "arm,cortex-a57-pmu", .data = armv8_a57_pmu_init},
|
||||||
{.compatible = "arm,cortex-a65-pmu", .data = armv8_a65_pmu_init},
|
{.compatible = "arm,cortex-a65-pmu", .data = armv8_cortex_a65_pmu_init},
|
||||||
{.compatible = "arm,cortex-a72-pmu", .data = armv8_a72_pmu_init},
|
{.compatible = "arm,cortex-a72-pmu", .data = armv8_a72_pmu_init},
|
||||||
{.compatible = "arm,cortex-a73-pmu", .data = armv8_a73_pmu_init},
|
{.compatible = "arm,cortex-a73-pmu", .data = armv8_a73_pmu_init},
|
||||||
{.compatible = "arm,cortex-a75-pmu", .data = armv8_a75_pmu_init},
|
{.compatible = "arm,cortex-a75-pmu", .data = armv8_cortex_a75_pmu_init},
|
||||||
{.compatible = "arm,cortex-a76-pmu", .data = armv8_a76_pmu_init},
|
{.compatible = "arm,cortex-a76-pmu", .data = armv8_cortex_a76_pmu_init},
|
||||||
{.compatible = "arm,cortex-a77-pmu", .data = armv8_a77_pmu_init},
|
{.compatible = "arm,cortex-a77-pmu", .data = armv8_cortex_a77_pmu_init},
|
||||||
{.compatible = "arm,neoverse-e1-pmu", .data = armv8_e1_pmu_init},
|
{.compatible = "arm,cortex-a78-pmu", .data = armv8_cortex_a78_pmu_init},
|
||||||
{.compatible = "arm,neoverse-n1-pmu", .data = armv8_n1_pmu_init},
|
{.compatible = "arm,cortex-a510-pmu", .data = armv9_cortex_a510_pmu_init},
|
||||||
|
{.compatible = "arm,cortex-a710-pmu", .data = armv9_cortex_a710_pmu_init},
|
||||||
|
{.compatible = "arm,cortex-x1-pmu", .data = armv8_cortex_x1_pmu_init},
|
||||||
|
{.compatible = "arm,cortex-x2-pmu", .data = armv9_cortex_x2_pmu_init},
|
||||||
|
{.compatible = "arm,neoverse-e1-pmu", .data = armv8_neoverse_e1_pmu_init},
|
||||||
|
{.compatible = "arm,neoverse-n1-pmu", .data = armv8_neoverse_n1_pmu_init},
|
||||||
|
{.compatible = "arm,neoverse-n2-pmu", .data = armv9_neoverse_n2_pmu_init},
|
||||||
|
{.compatible = "arm,neoverse-v1-pmu", .data = armv8_neoverse_v1_pmu_init},
|
||||||
{.compatible = "cavium,thunder-pmu", .data = armv8_thunder_pmu_init},
|
{.compatible = "cavium,thunder-pmu", .data = armv8_thunder_pmu_init},
|
||||||
{.compatible = "brcm,vulcan-pmu", .data = armv8_vulcan_pmu_init},
|
{.compatible = "brcm,vulcan-pmu", .data = armv8_vulcan_pmu_init},
|
||||||
|
{.compatible = "nvidia,carmel-pmu", .data = armv8_nvidia_carmel_pmu_init},
|
||||||
|
{.compatible = "nvidia,denver-pmu", .data = armv8_nvidia_denver_pmu_init},
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1251,7 +1233,7 @@ static int __init armv8_pmu_driver_init(void)
|
|||||||
if (acpi_disabled)
|
if (acpi_disabled)
|
||||||
return platform_driver_register(&armv8_pmu_driver);
|
return platform_driver_register(&armv8_pmu_driver);
|
||||||
else
|
else
|
||||||
return arm_pmu_acpi_probe(armv8_pmuv3_init);
|
return arm_pmu_acpi_probe(armv8_pmuv3_pmu_init);
|
||||||
}
|
}
|
||||||
device_initcall(armv8_pmu_driver_init)
|
device_initcall(armv8_pmu_driver_init)
|
||||||
|
|
||||||
|
@@ -173,8 +173,32 @@ static inline void binder_stats_created(enum binder_stat_types type)
|
|||||||
atomic_inc(&binder_stats.obj_created[type]);
|
atomic_inc(&binder_stats.obj_created[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct binder_transaction_log binder_transaction_log;
|
struct binder_transaction_log_entry {
|
||||||
struct binder_transaction_log binder_transaction_log_failed;
|
int debug_id;
|
||||||
|
int debug_id_done;
|
||||||
|
int call_type;
|
||||||
|
int from_proc;
|
||||||
|
int from_thread;
|
||||||
|
int target_handle;
|
||||||
|
int to_proc;
|
||||||
|
int to_thread;
|
||||||
|
int to_node;
|
||||||
|
int data_size;
|
||||||
|
int offsets_size;
|
||||||
|
int return_error_line;
|
||||||
|
uint32_t return_error;
|
||||||
|
uint32_t return_error_param;
|
||||||
|
char context_name[BINDERFS_MAX_NAME + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct binder_transaction_log {
|
||||||
|
atomic_t cur;
|
||||||
|
bool full;
|
||||||
|
struct binder_transaction_log_entry entry[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct binder_transaction_log binder_transaction_log;
|
||||||
|
static struct binder_transaction_log binder_transaction_log_failed;
|
||||||
|
|
||||||
static struct binder_transaction_log_entry *binder_transaction_log_add(
|
static struct binder_transaction_log_entry *binder_transaction_log_add(
|
||||||
struct binder_transaction_log *log)
|
struct binder_transaction_log *log)
|
||||||
@@ -1480,6 +1504,18 @@ static int binder_inc_ref_for_node(struct binder_proc *proc,
|
|||||||
}
|
}
|
||||||
ret = binder_inc_ref_olocked(ref, strong, target_list);
|
ret = binder_inc_ref_olocked(ref, strong, target_list);
|
||||||
*rdata = ref->data;
|
*rdata = ref->data;
|
||||||
|
if (ret && ref == new_ref) {
|
||||||
|
/*
|
||||||
|
* Cleanup the failed reference here as the target
|
||||||
|
* could now be dead and have already released its
|
||||||
|
* references by now. Calling on the new reference
|
||||||
|
* with strong=0 and a tmp_refs will not decrement
|
||||||
|
* the node. The new_ref gets kfree'd below.
|
||||||
|
*/
|
||||||
|
binder_cleanup_ref_olocked(new_ref);
|
||||||
|
ref = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
binder_proc_unlock(proc);
|
binder_proc_unlock(proc);
|
||||||
if (new_ref && ref != new_ref)
|
if (new_ref && ref != new_ref)
|
||||||
/*
|
/*
|
||||||
@@ -2464,6 +2500,56 @@ static int binder_fixup_parent(struct binder_transaction *t,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* binder_can_update_transaction() - Can a txn be superseded by an updated one?
|
||||||
|
* @t1: the pending async txn in the frozen process
|
||||||
|
* @t2: the new async txn to supersede the outdated pending one
|
||||||
|
*
|
||||||
|
* Return: true if t2 can supersede t1
|
||||||
|
* false if t2 can not supersede t1
|
||||||
|
*/
|
||||||
|
static bool binder_can_update_transaction(struct binder_transaction *t1,
|
||||||
|
struct binder_transaction *t2)
|
||||||
|
{
|
||||||
|
if ((t1->flags & t2->flags & (TF_ONE_WAY | TF_UPDATE_TXN)) !=
|
||||||
|
(TF_ONE_WAY | TF_UPDATE_TXN) || !t1->to_proc || !t2->to_proc)
|
||||||
|
return false;
|
||||||
|
if (t1->to_proc->tsk == t2->to_proc->tsk && t1->code == t2->code &&
|
||||||
|
t1->flags == t2->flags && t1->buffer->pid == t2->buffer->pid &&
|
||||||
|
t1->buffer->target_node->ptr == t2->buffer->target_node->ptr &&
|
||||||
|
t1->buffer->target_node->cookie == t2->buffer->target_node->cookie)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* binder_find_outdated_transaction_ilocked() - Find the outdated transaction
|
||||||
|
* @t: new async transaction
|
||||||
|
* @target_list: list to find outdated transaction
|
||||||
|
*
|
||||||
|
* Return: the outdated transaction if found
|
||||||
|
* NULL if no outdated transacton can be found
|
||||||
|
*
|
||||||
|
* Requires the proc->inner_lock to be held.
|
||||||
|
*/
|
||||||
|
static struct binder_transaction *
|
||||||
|
binder_find_outdated_transaction_ilocked(struct binder_transaction *t,
|
||||||
|
struct list_head *target_list)
|
||||||
|
{
|
||||||
|
struct binder_work *w;
|
||||||
|
|
||||||
|
list_for_each_entry(w, target_list, entry) {
|
||||||
|
struct binder_transaction *t_queued;
|
||||||
|
|
||||||
|
if (w->type != BINDER_WORK_TRANSACTION)
|
||||||
|
continue;
|
||||||
|
t_queued = container_of(w, struct binder_transaction, work);
|
||||||
|
if (binder_can_update_transaction(t_queued, t))
|
||||||
|
return t_queued;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* binder_proc_transaction() - sends a transaction to a process and wakes it up
|
* binder_proc_transaction() - sends a transaction to a process and wakes it up
|
||||||
* @t: transaction to send
|
* @t: transaction to send
|
||||||
@@ -2491,6 +2577,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
|||||||
bool oneway = !!(t->flags & TF_ONE_WAY);
|
bool oneway = !!(t->flags & TF_ONE_WAY);
|
||||||
bool pending_async = false;
|
bool pending_async = false;
|
||||||
bool skip = false;
|
bool skip = false;
|
||||||
|
struct binder_transaction *t_outdated = NULL;
|
||||||
|
|
||||||
BUG_ON(!node);
|
BUG_ON(!node);
|
||||||
binder_node_lock(node);
|
binder_node_lock(node);
|
||||||
@@ -2534,6 +2621,17 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
|||||||
} else if (!pending_async) {
|
} else if (!pending_async) {
|
||||||
binder_enqueue_work_ilocked(&t->work, &proc->todo);
|
binder_enqueue_work_ilocked(&t->work, &proc->todo);
|
||||||
} else {
|
} else {
|
||||||
|
if ((t->flags & TF_UPDATE_TXN) && proc->is_frozen) {
|
||||||
|
t_outdated = binder_find_outdated_transaction_ilocked(t,
|
||||||
|
&node->async_todo);
|
||||||
|
if (t_outdated) {
|
||||||
|
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||||
|
"txn %d supersedes %d\n",
|
||||||
|
t->debug_id, t_outdated->debug_id);
|
||||||
|
list_del_init(&t_outdated->work.entry);
|
||||||
|
proc->outstanding_txns--;
|
||||||
|
}
|
||||||
|
}
|
||||||
binder_enqueue_work_ilocked(&t->work, &node->async_todo);
|
binder_enqueue_work_ilocked(&t->work, &node->async_todo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2547,6 +2645,22 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
|||||||
binder_inner_proc_unlock(proc);
|
binder_inner_proc_unlock(proc);
|
||||||
binder_node_unlock(node);
|
binder_node_unlock(node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To reduce potential contention, free the outdated transaction and
|
||||||
|
* buffer after releasing the locks.
|
||||||
|
*/
|
||||||
|
if (t_outdated) {
|
||||||
|
struct binder_buffer *buffer = t_outdated->buffer;
|
||||||
|
|
||||||
|
t_outdated->buffer = NULL;
|
||||||
|
buffer->transaction = NULL;
|
||||||
|
trace_binder_transaction_update_buffer_release(buffer);
|
||||||
|
binder_transaction_buffer_release(proc, NULL, buffer, 0, 0);
|
||||||
|
binder_alloc_free_buf(&proc->alloc, buffer);
|
||||||
|
kfree(t_outdated);
|
||||||
|
binder_stats_deleted(BINDER_STAT_TRANSACTION);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5950,8 +6064,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||||||
print_binder_stats(m, " ", &proc->stats);
|
print_binder_stats(m, " ", &proc->stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int state_show(struct seq_file *m, void *unused)
|
||||||
int binder_state_show(struct seq_file *m, void *unused)
|
|
||||||
{
|
{
|
||||||
struct binder_proc *proc;
|
struct binder_proc *proc;
|
||||||
struct binder_node *node;
|
struct binder_node *node;
|
||||||
@@ -5990,7 +6103,7 @@ int binder_state_show(struct seq_file *m, void *unused)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int binder_stats_show(struct seq_file *m, void *unused)
|
static int stats_show(struct seq_file *m, void *unused)
|
||||||
{
|
{
|
||||||
struct binder_proc *proc;
|
struct binder_proc *proc;
|
||||||
|
|
||||||
@@ -6006,7 +6119,7 @@ int binder_stats_show(struct seq_file *m, void *unused)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int binder_transactions_show(struct seq_file *m, void *unused)
|
static int transactions_show(struct seq_file *m, void *unused)
|
||||||
{
|
{
|
||||||
struct binder_proc *proc;
|
struct binder_proc *proc;
|
||||||
|
|
||||||
@@ -6062,7 +6175,7 @@ static void print_binder_transaction_log_entry(struct seq_file *m,
|
|||||||
"\n" : " (incomplete)\n");
|
"\n" : " (incomplete)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int binder_transaction_log_show(struct seq_file *m, void *unused)
|
static int transaction_log_show(struct seq_file *m, void *unused)
|
||||||
{
|
{
|
||||||
struct binder_transaction_log *log = m->private;
|
struct binder_transaction_log *log = m->private;
|
||||||
unsigned int log_cur = atomic_read(&log->cur);
|
unsigned int log_cur = atomic_read(&log->cur);
|
||||||
@@ -6094,6 +6207,45 @@ const struct file_operations binder_fops = {
|
|||||||
.release = binder_release,
|
.release = binder_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(state);
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(stats);
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(transactions);
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(transaction_log);
|
||||||
|
|
||||||
|
const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
||||||
|
{
|
||||||
|
.name = "state",
|
||||||
|
.mode = 0444,
|
||||||
|
.fops = &state_fops,
|
||||||
|
.data = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "stats",
|
||||||
|
.mode = 0444,
|
||||||
|
.fops = &stats_fops,
|
||||||
|
.data = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "transactions",
|
||||||
|
.mode = 0444,
|
||||||
|
.fops = &transactions_fops,
|
||||||
|
.data = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "transaction_log",
|
||||||
|
.mode = 0444,
|
||||||
|
.fops = &transaction_log_fops,
|
||||||
|
.data = &binder_transaction_log,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "failed_transaction_log",
|
||||||
|
.mode = 0444,
|
||||||
|
.fops = &transaction_log_fops,
|
||||||
|
.data = &binder_transaction_log_failed,
|
||||||
|
},
|
||||||
|
{} /* terminator */
|
||||||
|
};
|
||||||
|
|
||||||
static int __init init_binder_device(const char *name)
|
static int __init init_binder_device(const char *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -6139,36 +6291,18 @@ static int __init binder_init(void)
|
|||||||
atomic_set(&binder_transaction_log_failed.cur, ~0U);
|
atomic_set(&binder_transaction_log_failed.cur, ~0U);
|
||||||
|
|
||||||
binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
|
binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
|
||||||
if (binder_debugfs_dir_entry_root)
|
if (binder_debugfs_dir_entry_root) {
|
||||||
|
const struct binder_debugfs_entry *db_entry;
|
||||||
|
|
||||||
|
binder_for_each_debugfs_entry(db_entry)
|
||||||
|
debugfs_create_file(db_entry->name,
|
||||||
|
db_entry->mode,
|
||||||
|
binder_debugfs_dir_entry_root,
|
||||||
|
db_entry->data,
|
||||||
|
db_entry->fops);
|
||||||
|
|
||||||
binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
|
binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
|
||||||
binder_debugfs_dir_entry_root);
|
binder_debugfs_dir_entry_root);
|
||||||
|
|
||||||
if (binder_debugfs_dir_entry_root) {
|
|
||||||
debugfs_create_file("state",
|
|
||||||
0444,
|
|
||||||
binder_debugfs_dir_entry_root,
|
|
||||||
NULL,
|
|
||||||
&binder_state_fops);
|
|
||||||
debugfs_create_file("stats",
|
|
||||||
0444,
|
|
||||||
binder_debugfs_dir_entry_root,
|
|
||||||
NULL,
|
|
||||||
&binder_stats_fops);
|
|
||||||
debugfs_create_file("transactions",
|
|
||||||
0444,
|
|
||||||
binder_debugfs_dir_entry_root,
|
|
||||||
NULL,
|
|
||||||
&binder_transactions_fops);
|
|
||||||
debugfs_create_file("transaction_log",
|
|
||||||
0444,
|
|
||||||
binder_debugfs_dir_entry_root,
|
|
||||||
&binder_transaction_log,
|
|
||||||
&binder_transaction_log_fops);
|
|
||||||
debugfs_create_file("failed_transaction_log",
|
|
||||||
0444,
|
|
||||||
binder_debugfs_dir_entry_root,
|
|
||||||
&binder_transaction_log_failed,
|
|
||||||
&binder_transaction_log_fops);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) &&
|
if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) &&
|
||||||
|
@@ -107,41 +107,19 @@ static inline int __init init_binderfs(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int binder_stats_show(struct seq_file *m, void *unused);
|
struct binder_debugfs_entry {
|
||||||
DEFINE_SHOW_ATTRIBUTE(binder_stats);
|
const char *name;
|
||||||
|
umode_t mode;
|
||||||
int binder_state_show(struct seq_file *m, void *unused);
|
const struct file_operations *fops;
|
||||||
DEFINE_SHOW_ATTRIBUTE(binder_state);
|
void *data;
|
||||||
|
|
||||||
int binder_transactions_show(struct seq_file *m, void *unused);
|
|
||||||
DEFINE_SHOW_ATTRIBUTE(binder_transactions);
|
|
||||||
|
|
||||||
int binder_transaction_log_show(struct seq_file *m, void *unused);
|
|
||||||
DEFINE_SHOW_ATTRIBUTE(binder_transaction_log);
|
|
||||||
|
|
||||||
struct binder_transaction_log_entry {
|
|
||||||
int debug_id;
|
|
||||||
int debug_id_done;
|
|
||||||
int call_type;
|
|
||||||
int from_proc;
|
|
||||||
int from_thread;
|
|
||||||
int target_handle;
|
|
||||||
int to_proc;
|
|
||||||
int to_thread;
|
|
||||||
int to_node;
|
|
||||||
int data_size;
|
|
||||||
int offsets_size;
|
|
||||||
int return_error_line;
|
|
||||||
uint32_t return_error;
|
|
||||||
uint32_t return_error_param;
|
|
||||||
char context_name[BINDERFS_MAX_NAME + 1];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct binder_transaction_log {
|
extern const struct binder_debugfs_entry binder_debugfs_entries[];
|
||||||
atomic_t cur;
|
|
||||||
bool full;
|
#define binder_for_each_debugfs_entry(entry) \
|
||||||
struct binder_transaction_log_entry entry[32];
|
for ((entry) = binder_debugfs_entries; \
|
||||||
};
|
(entry)->name; \
|
||||||
|
(entry)++)
|
||||||
|
|
||||||
enum binder_stat_types {
|
enum binder_stat_types {
|
||||||
BINDER_STAT_PROC,
|
BINDER_STAT_PROC,
|
||||||
@@ -620,6 +598,4 @@ struct binder_object {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct binder_transaction_log binder_transaction_log;
|
|
||||||
extern struct binder_transaction_log binder_transaction_log_failed;
|
|
||||||
#endif /* _LINUX_BINDER_INTERNAL_H */
|
#endif /* _LINUX_BINDER_INTERNAL_H */
|
||||||
|
@@ -306,6 +306,10 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
|
|||||||
TP_PROTO(struct binder_buffer *buffer),
|
TP_PROTO(struct binder_buffer *buffer),
|
||||||
TP_ARGS(buffer));
|
TP_ARGS(buffer));
|
||||||
|
|
||||||
|
DEFINE_EVENT(binder_buffer_class, binder_transaction_update_buffer_release,
|
||||||
|
TP_PROTO(struct binder_buffer *buffer),
|
||||||
|
TP_ARGS(buffer));
|
||||||
|
|
||||||
TRACE_EVENT(binder_update_page_range,
|
TRACE_EVENT(binder_update_page_range,
|
||||||
TP_PROTO(struct binder_alloc *alloc, bool allocate,
|
TP_PROTO(struct binder_alloc *alloc, bool allocate,
|
||||||
void __user *start, void __user *end),
|
void __user *start, void __user *end),
|
||||||
|
@@ -584,6 +584,7 @@ out:
|
|||||||
static int init_binder_logs(struct super_block *sb)
|
static int init_binder_logs(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
|
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
|
||||||
|
const struct binder_debugfs_entry *db_entry;
|
||||||
struct binderfs_info *info;
|
struct binderfs_info *info;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -594,43 +595,15 @@ static int init_binder_logs(struct super_block *sb)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dentry = binderfs_create_file(binder_logs_root_dir, "stats",
|
binder_for_each_debugfs_entry(db_entry) {
|
||||||
&binder_stats_fops, NULL);
|
|
||||||
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,
|
dentry = binderfs_create_file(binder_logs_root_dir,
|
||||||
"transaction_log",
|
db_entry->name,
|
||||||
&binder_transaction_log_fops,
|
db_entry->fops,
|
||||||
&binder_transaction_log);
|
db_entry->data);
|
||||||
if (IS_ERR(dentry)) {
|
if (IS_ERR(dentry)) {
|
||||||
ret = PTR_ERR(dentry);
|
ret = PTR_ERR(dentry);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dentry = binderfs_create_file(binder_logs_root_dir,
|
|
||||||
"failed_transaction_log",
|
|
||||||
&binder_transaction_log_fops,
|
|
||||||
&binder_transaction_log_failed);
|
|
||||||
if (IS_ERR(dentry)) {
|
|
||||||
ret = PTR_ERR(dentry);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc_log_dir = binderfs_create_dir(binder_logs_root_dir, "proc");
|
proc_log_dir = binderfs_create_dir(binder_logs_root_dir, "proc");
|
||||||
|
@@ -271,7 +271,11 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_exit_mm);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_get_from_fragment_pool);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_get_from_fragment_pool);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_exclude_reserved_zone);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_exclude_reserved_zone);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_include_reserved_zone);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_include_reserved_zone);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_pages_slowpath_begin);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_pages_slowpath_end);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_mem);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_mem);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_mapcount_pages);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_traversal_lruvec);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_typec_tcpci_override_toggling);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_typec_tcpci_override_toggling);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_typec_tcpci_chk_contaminant);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_typec_tcpci_chk_contaminant);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_typec_tcpci_get_vbus);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_typec_tcpci_get_vbus);
|
||||||
@@ -300,6 +304,11 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_logbuf_pr_cont);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_scan_type);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_scan_type);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_swappiness);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_swappiness);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_slab_bypass);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_slab_bypass);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_failed_page_trylock);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_trylock_set);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_trylock_clear);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_trylock_get_result);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_page_trylock);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_referenced_check_bypass);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_referenced_check_bypass);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_drain_all_pages_bypass);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_drain_all_pages_bypass);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cma_drain_all_pages_bypass);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cma_drain_all_pages_bypass);
|
||||||
@@ -336,6 +345,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmc_attach_sd);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sdhci_get_cd);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sdhci_get_cd);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmc_gpio_cd_irqt);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmc_gpio_cd_irqt);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_vmalloc_stack);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_vmalloc_stack);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_remove_vmalloc_stack);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_stack_hash);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_stack_hash);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_track_hash);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_track_hash);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_vmpressure);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_vmpressure);
|
||||||
@@ -390,6 +400,11 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_tcp_recvmsg_stat);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_pci_d3_sleep);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_pci_d3_sleep);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_kmalloc_slab);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_kmalloc_slab);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmap_region);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmap_region);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_update_page_mapcount);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_add_page_to_lrulist);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_del_page_from_lrulist);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_should_be_protected);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mark_page_accessed);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_try_to_unmap_one);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_try_to_unmap_one);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_id_remove);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_id_remove);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_offline);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_offline);
|
||||||
@@ -430,3 +445,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_init_swap_info_struct);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_si_swapinfo);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_si_swapinfo);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_si);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_si);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_shmem_page_flag);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_pidfd_open);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmput);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_pelt_multiplier);
|
||||||
|
@@ -50,6 +50,11 @@ struct iommu_dma_cookie {
|
|||||||
struct iommu_domain *fq_domain;
|
struct iommu_domain *fq_domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct iommu_dma_cookie_ext {
|
||||||
|
struct iommu_dma_cookie cookie;
|
||||||
|
struct mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
|
static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
|
||||||
{
|
{
|
||||||
if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
|
if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
|
||||||
@@ -59,14 +64,15 @@ static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
|
|||||||
|
|
||||||
static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
|
static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
|
||||||
{
|
{
|
||||||
struct iommu_dma_cookie *cookie;
|
struct iommu_dma_cookie_ext *cookie;
|
||||||
|
|
||||||
cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
|
cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
|
||||||
if (cookie) {
|
if (cookie) {
|
||||||
INIT_LIST_HEAD(&cookie->msi_page_list);
|
INIT_LIST_HEAD(&cookie->cookie.msi_page_list);
|
||||||
cookie->type = type;
|
cookie->cookie.type = type;
|
||||||
|
mutex_init(&cookie->mutex);
|
||||||
}
|
}
|
||||||
return cookie;
|
return &cookie->cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -305,9 +311,11 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
|
|||||||
u64 size, struct device *dev)
|
u64 size, struct device *dev)
|
||||||
{
|
{
|
||||||
struct iommu_dma_cookie *cookie = domain->iova_cookie;
|
struct iommu_dma_cookie *cookie = domain->iova_cookie;
|
||||||
|
struct iommu_dma_cookie_ext *cookie_ext;
|
||||||
unsigned long order, base_pfn;
|
unsigned long order, base_pfn;
|
||||||
struct iova_domain *iovad;
|
struct iova_domain *iovad;
|
||||||
int attr;
|
int attr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
|
if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -331,14 +339,18 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* start_pfn is always nonzero for an already-initialised domain */
|
/* start_pfn is always nonzero for an already-initialised domain */
|
||||||
|
cookie_ext = container_of(cookie, struct iommu_dma_cookie_ext, cookie);
|
||||||
|
mutex_lock(&cookie_ext->mutex);
|
||||||
if (iovad->start_pfn) {
|
if (iovad->start_pfn) {
|
||||||
if (1UL << order != iovad->granule ||
|
if (1UL << order != iovad->granule ||
|
||||||
base_pfn != iovad->start_pfn) {
|
base_pfn != iovad->start_pfn) {
|
||||||
pr_warn("Incompatible range for DMA domain\n");
|
pr_warn("Incompatible range for DMA domain\n");
|
||||||
return -EFAULT;
|
ret = -EFAULT;
|
||||||
|
goto done_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto done_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_iova_domain(iovad, 1UL << order, base_pfn);
|
init_iova_domain(iovad, 1UL << order, base_pfn);
|
||||||
@@ -352,10 +364,16 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
|
|||||||
cookie->fq_domain = domain;
|
cookie->fq_domain = domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev)
|
if (!dev) {
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto done_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
return iova_reserve_iommu_regions(dev, domain);
|
ret = iova_reserve_iommu_regions(dev, domain);
|
||||||
|
|
||||||
|
done_unlock:
|
||||||
|
mutex_unlock(&cookie_ext->mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iommu_dma_deferred_attach(struct device *dev,
|
static int iommu_dma_deferred_attach(struct device *dev,
|
||||||
|
@@ -466,9 +466,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
|
|||||||
type = PCIE_ATU_TYPE_CFG1;
|
type = PCIE_ATU_TYPE_CFG1;
|
||||||
|
|
||||||
|
|
||||||
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
|
dw_pcie_prog_outbound_atu(pci, 0, type, pp->cfg0_base, busdev, pp->cfg0_size);
|
||||||
type, pp->cfg0_base,
|
|
||||||
busdev, pp->cfg0_size);
|
|
||||||
|
|
||||||
return pp->va_cfg0_base + where;
|
return pp->va_cfg0_base + where;
|
||||||
}
|
}
|
||||||
@@ -482,9 +480,8 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
|
|||||||
|
|
||||||
ret = pci_generic_config_read(bus, devfn, where, size, val);
|
ret = pci_generic_config_read(bus, devfn, where, size, val);
|
||||||
|
|
||||||
if (!ret && pci->num_viewport <= 2)
|
if (!ret && (pci->iatu_unroll_enabled & DWC_IATU_IOCFG_SHARED))
|
||||||
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
|
dw_pcie_prog_outbound_atu(pci, 0, PCIE_ATU_TYPE_IO, pp->io_base,
|
||||||
PCIE_ATU_TYPE_IO, pp->io_base,
|
|
||||||
pp->io_bus_addr, pp->io_size);
|
pp->io_bus_addr, pp->io_size);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -499,9 +496,8 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
|
|||||||
|
|
||||||
ret = pci_generic_config_write(bus, devfn, where, size, val);
|
ret = pci_generic_config_write(bus, devfn, where, size, val);
|
||||||
|
|
||||||
if (!ret && pci->num_viewport <= 2)
|
if (!ret && (pci->iatu_unroll_enabled & DWC_IATU_IOCFG_SHARED))
|
||||||
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
|
dw_pcie_prog_outbound_atu(pci, 0, PCIE_ATU_TYPE_IO, pp->io_base,
|
||||||
PCIE_ATU_TYPE_IO, pp->io_base,
|
|
||||||
pp->io_bus_addr, pp->io_size);
|
pp->io_bus_addr, pp->io_size);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -588,21 +584,35 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
|||||||
* ATU, so we should not program the ATU here.
|
* ATU, so we should not program the ATU here.
|
||||||
*/
|
*/
|
||||||
if (pp->bridge->child_ops == &dw_child_pcie_ops) {
|
if (pp->bridge->child_ops == &dw_child_pcie_ops) {
|
||||||
struct resource_entry *tmp, *entry = NULL;
|
int atu_idx = 0;
|
||||||
|
struct resource_entry *entry;
|
||||||
|
|
||||||
/* Get last memory resource entry */
|
/* Get last memory resource entry */
|
||||||
resource_list_for_each_entry(tmp, &pp->bridge->windows)
|
resource_list_for_each_entry(entry, &pp->bridge->windows) {
|
||||||
if (resource_type(tmp->res) == IORESOURCE_MEM)
|
if (resource_type(entry->res) != IORESOURCE_MEM)
|
||||||
entry = tmp;
|
continue;
|
||||||
|
|
||||||
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
|
if (pci->num_viewport <= ++atu_idx)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dw_pcie_prog_outbound_atu(pci, atu_idx,
|
||||||
PCIE_ATU_TYPE_MEM, entry->res->start,
|
PCIE_ATU_TYPE_MEM, entry->res->start,
|
||||||
entry->res->start - entry->offset,
|
entry->res->start - entry->offset,
|
||||||
resource_size(entry->res));
|
resource_size(entry->res));
|
||||||
if (pci->num_viewport > 2)
|
}
|
||||||
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2,
|
|
||||||
|
if (pp->io_size) {
|
||||||
|
if (pci->num_viewport > ++atu_idx)
|
||||||
|
dw_pcie_prog_outbound_atu(pci, atu_idx,
|
||||||
PCIE_ATU_TYPE_IO, pp->io_base,
|
PCIE_ATU_TYPE_IO, pp->io_base,
|
||||||
pp->io_bus_addr, pp->io_size);
|
pp->io_bus_addr, pp->io_size);
|
||||||
|
else
|
||||||
|
pci->iatu_unroll_enabled |= DWC_IATU_IOCFG_SHARED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pci->num_viewport <= atu_idx)
|
||||||
|
dev_warn(pci->dev, "Resources exceed number of ATU entries (%d)",
|
||||||
|
pci->num_viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
|
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
|
||||||
|
@@ -274,7 +274,7 @@ static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no,
|
|||||||
if (pci->ops->cpu_addr_fixup)
|
if (pci->ops->cpu_addr_fixup)
|
||||||
cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
|
cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
|
||||||
|
|
||||||
if (pci->iatu_unroll_enabled) {
|
if (pci->iatu_unroll_enabled & DWC_IATU_UNROLL_EN) {
|
||||||
dw_pcie_prog_outbound_atu_unroll(pci, func_no, index, type,
|
dw_pcie_prog_outbound_atu_unroll(pci, func_no, index, type,
|
||||||
cpu_addr, pci_addr, size);
|
cpu_addr, pci_addr, size);
|
||||||
return;
|
return;
|
||||||
@@ -394,7 +394,7 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
|
|||||||
int type;
|
int type;
|
||||||
u32 retries, val;
|
u32 retries, val;
|
||||||
|
|
||||||
if (pci->iatu_unroll_enabled)
|
if (pci->iatu_unroll_enabled & DWC_IATU_UNROLL_EN)
|
||||||
return dw_pcie_prog_inbound_atu_unroll(pci, func_no, index, bar,
|
return dw_pcie_prog_inbound_atu_unroll(pci, func_no, index, bar,
|
||||||
cpu_addr, as_type);
|
cpu_addr, as_type);
|
||||||
|
|
||||||
@@ -554,14 +554,15 @@ void dw_pcie_setup(struct dw_pcie *pci)
|
|||||||
|
|
||||||
if (pci->version >= 0x480A || (!pci->version &&
|
if (pci->version >= 0x480A || (!pci->version &&
|
||||||
dw_pcie_iatu_unroll_enabled(pci))) {
|
dw_pcie_iatu_unroll_enabled(pci))) {
|
||||||
pci->iatu_unroll_enabled = true;
|
pci->iatu_unroll_enabled |= DWC_IATU_UNROLL_EN;
|
||||||
if (!pci->atu_base)
|
if (!pci->atu_base)
|
||||||
pci->atu_base =
|
pci->atu_base =
|
||||||
devm_platform_ioremap_resource_byname(pdev, "atu");
|
devm_platform_ioremap_resource_byname(pdev, "atu");
|
||||||
if (IS_ERR(pci->atu_base))
|
if (IS_ERR(pci->atu_base))
|
||||||
pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
|
pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
|
||||||
}
|
}
|
||||||
dev_dbg(pci->dev, "iATU unroll: %s\n", pci->iatu_unroll_enabled ?
|
dev_dbg(pci->dev, "iATU unroll: %s\n",
|
||||||
|
pci->iatu_unroll_enabled & DWC_IATU_UNROLL_EN ?
|
||||||
"enabled" : "disabled");
|
"enabled" : "disabled");
|
||||||
|
|
||||||
if (pci->link_gen > 0)
|
if (pci->link_gen > 0)
|
||||||
|
@@ -80,9 +80,6 @@
|
|||||||
#define PCIE_ATU_VIEWPORT 0x900
|
#define PCIE_ATU_VIEWPORT 0x900
|
||||||
#define PCIE_ATU_REGION_INBOUND BIT(31)
|
#define PCIE_ATU_REGION_INBOUND BIT(31)
|
||||||
#define PCIE_ATU_REGION_OUTBOUND 0
|
#define PCIE_ATU_REGION_OUTBOUND 0
|
||||||
#define PCIE_ATU_REGION_INDEX2 0x2
|
|
||||||
#define PCIE_ATU_REGION_INDEX1 0x1
|
|
||||||
#define PCIE_ATU_REGION_INDEX0 0x0
|
|
||||||
#define PCIE_ATU_CR1 0x904
|
#define PCIE_ATU_CR1 0x904
|
||||||
#define PCIE_ATU_TYPE_MEM 0x0
|
#define PCIE_ATU_TYPE_MEM 0x0
|
||||||
#define PCIE_ATU_TYPE_IO 0x2
|
#define PCIE_ATU_TYPE_IO 0x2
|
||||||
@@ -259,6 +256,8 @@ struct dw_pcie_ops {
|
|||||||
void (*stop_link)(struct dw_pcie *pcie);
|
void (*stop_link)(struct dw_pcie *pcie);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DWC_IATU_UNROLL_EN BIT(0)
|
||||||
|
#define DWC_IATU_IOCFG_SHARED BIT(1)
|
||||||
struct dw_pcie {
|
struct dw_pcie {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *dbi_base;
|
void __iomem *dbi_base;
|
||||||
|
@@ -156,8 +156,13 @@ static void __dwc3_set_mode(struct work_struct *work)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For DRD host or device mode only */
|
/*
|
||||||
if (dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) {
|
* When current_dr_role is not set, there's no role switching.
|
||||||
|
* Only perform GCTL.CoreSoftReset when there's DRD role switching.
|
||||||
|
*/
|
||||||
|
if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) ||
|
||||||
|
DWC3_VER_IS_PRIOR(DWC31, 190A)) &&
|
||||||
|
dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) {
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
|
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
|
||||||
reg |= DWC3_GCTL_CORESOFTRESET;
|
reg |= DWC3_GCTL_CORESOFTRESET;
|
||||||
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
|
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
|
||||||
|
@@ -2471,6 +2471,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
is_on = !!is_on;
|
is_on = !!is_on;
|
||||||
|
|
||||||
|
if (dwc->pullups_connected == is_on)
|
||||||
|
return 0;
|
||||||
|
|
||||||
vdwc->softconnect = is_on;
|
vdwc->softconnect = is_on;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -12,11 +12,14 @@
|
|||||||
* Jaswinder Singh (jaswinder.singh@linaro.org)
|
* Jaswinder Singh (jaswinder.singh@linaro.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
#include <sound/control.h>
|
#include <sound/control.h>
|
||||||
|
#include <sound/tlv.h>
|
||||||
|
#include <linux/usb/audio.h>
|
||||||
|
|
||||||
#include "u_audio.h"
|
#include "u_audio.h"
|
||||||
|
|
||||||
@@ -24,6 +27,14 @@
|
|||||||
#define PRD_SIZE_MAX PAGE_SIZE
|
#define PRD_SIZE_MAX PAGE_SIZE
|
||||||
#define MIN_PERIODS 4
|
#define MIN_PERIODS 4
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UAC_FBACK_CTRL,
|
||||||
|
UAC_P_PITCH_CTRL,
|
||||||
|
UAC_MUTE_CTRL,
|
||||||
|
UAC_VOLUME_CTRL,
|
||||||
|
UAC_RATE_CTRL,
|
||||||
|
};
|
||||||
|
|
||||||
/* Runtime data params for one stream */
|
/* Runtime data params for one stream */
|
||||||
struct uac_rtd_params {
|
struct uac_rtd_params {
|
||||||
struct snd_uac_chip *uac; /* parent chip */
|
struct snd_uac_chip *uac; /* parent chip */
|
||||||
@@ -43,6 +54,21 @@ struct uac_rtd_params {
|
|||||||
|
|
||||||
struct usb_request *req_fback; /* Feedback endpoint request */
|
struct usb_request *req_fback; /* Feedback endpoint request */
|
||||||
bool fb_ep_enabled; /* if the ep is enabled */
|
bool fb_ep_enabled; /* if the ep is enabled */
|
||||||
|
|
||||||
|
/* Volume/Mute controls and their state */
|
||||||
|
int fu_id; /* Feature Unit ID */
|
||||||
|
struct snd_kcontrol *snd_kctl_volume;
|
||||||
|
struct snd_kcontrol *snd_kctl_mute;
|
||||||
|
s16 volume_min, volume_max, volume_res;
|
||||||
|
s16 volume;
|
||||||
|
int mute;
|
||||||
|
|
||||||
|
struct snd_kcontrol *snd_kctl_rate; /* read-only current rate */
|
||||||
|
int srate; /* selected samplerate */
|
||||||
|
int active; /* playback/capture running */
|
||||||
|
|
||||||
|
spinlock_t lock; /* lock for control transfers */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct snd_uac_chip {
|
struct snd_uac_chip {
|
||||||
@@ -54,13 +80,9 @@ struct snd_uac_chip {
|
|||||||
struct snd_card *card;
|
struct snd_card *card;
|
||||||
struct snd_pcm *pcm;
|
struct snd_pcm *pcm;
|
||||||
|
|
||||||
/* timekeeping for the playback endpoint */
|
|
||||||
unsigned int p_interval;
|
|
||||||
unsigned int p_residue;
|
|
||||||
|
|
||||||
/* pre-calculated values for playback iso completion */
|
/* pre-calculated values for playback iso completion */
|
||||||
unsigned int p_pktsize;
|
unsigned long long p_residue_mil;
|
||||||
unsigned int p_pktsize_residue;
|
unsigned int p_interval;
|
||||||
unsigned int p_framesize;
|
unsigned int p_framesize;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -133,6 +155,9 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
|
|||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
struct uac_rtd_params *prm = req->context;
|
struct uac_rtd_params *prm = req->context;
|
||||||
struct snd_uac_chip *uac = prm->uac;
|
struct snd_uac_chip *uac = prm->uac;
|
||||||
|
unsigned int frames, p_pktsize;
|
||||||
|
unsigned long long pitched_rate_mil, p_pktsize_residue_mil,
|
||||||
|
residue_frames_mil, div_result;
|
||||||
|
|
||||||
/* i/f shutting down */
|
/* i/f shutting down */
|
||||||
if (!prm->ep_enabled) {
|
if (!prm->ep_enabled) {
|
||||||
@@ -172,19 +197,44 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
|
|||||||
* If there is a residue from this division, add it to the
|
* If there is a residue from this division, add it to the
|
||||||
* residue accumulator.
|
* residue accumulator.
|
||||||
*/
|
*/
|
||||||
req->length = uac->p_pktsize;
|
unsigned long long p_interval_mil = uac->p_interval * 1000000ULL;
|
||||||
uac->p_residue += uac->p_pktsize_residue;
|
|
||||||
|
pitched_rate_mil = (unsigned long long) prm->srate * prm->pitch;
|
||||||
|
div_result = pitched_rate_mil;
|
||||||
|
do_div(div_result, uac->p_interval);
|
||||||
|
do_div(div_result, 1000000);
|
||||||
|
frames = (unsigned int) div_result;
|
||||||
|
|
||||||
|
pr_debug("p_srate %d, pitch %d, interval_mil %llu, frames %d\n",
|
||||||
|
prm->srate, prm->pitch, p_interval_mil, frames);
|
||||||
|
|
||||||
|
p_pktsize = min_t(unsigned int,
|
||||||
|
uac->p_framesize * frames,
|
||||||
|
ep->maxpacket);
|
||||||
|
|
||||||
|
if (p_pktsize < ep->maxpacket) {
|
||||||
|
residue_frames_mil = pitched_rate_mil - frames * p_interval_mil;
|
||||||
|
p_pktsize_residue_mil = uac->p_framesize * residue_frames_mil;
|
||||||
|
} else
|
||||||
|
p_pktsize_residue_mil = 0;
|
||||||
|
|
||||||
|
req->length = p_pktsize;
|
||||||
|
uac->p_residue_mil += p_pktsize_residue_mil;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Whenever there are more bytes in the accumulator than we
|
* Whenever there are more bytes in the accumulator p_residue_mil than we
|
||||||
* need to add one more sample frame, increase this packet's
|
* need to add one more sample frame, increase this packet's
|
||||||
* size and decrease the accumulator.
|
* size and decrease the accumulator.
|
||||||
*/
|
*/
|
||||||
if (uac->p_residue / uac->p_interval >= uac->p_framesize) {
|
div_result = uac->p_residue_mil;
|
||||||
|
do_div(div_result, uac->p_interval);
|
||||||
|
do_div(div_result, 1000000);
|
||||||
|
if ((unsigned int) div_result >= uac->p_framesize) {
|
||||||
req->length += uac->p_framesize;
|
req->length += uac->p_framesize;
|
||||||
uac->p_residue -= uac->p_framesize *
|
uac->p_residue_mil -= uac->p_framesize * p_interval_mil;
|
||||||
uac->p_interval;
|
pr_debug("increased req length to %d\n", req->length);
|
||||||
}
|
}
|
||||||
|
pr_debug("remains uac->p_residue_mil %llu\n", uac->p_residue_mil);
|
||||||
|
|
||||||
req->actual = req->length;
|
req->actual = req->length;
|
||||||
}
|
}
|
||||||
@@ -233,7 +283,6 @@ static void u_audio_iso_fback_complete(struct usb_ep *ep,
|
|||||||
struct uac_rtd_params *prm = req->context;
|
struct uac_rtd_params *prm = req->context;
|
||||||
struct snd_uac_chip *uac = prm->uac;
|
struct snd_uac_chip *uac = prm->uac;
|
||||||
struct g_audio *audio_dev = uac->audio_dev;
|
struct g_audio *audio_dev = uac->audio_dev;
|
||||||
struct uac_params *params = &audio_dev->params;
|
|
||||||
int status = req->status;
|
int status = req->status;
|
||||||
|
|
||||||
/* i/f shutting down */
|
/* i/f shutting down */
|
||||||
@@ -255,7 +304,7 @@ static void u_audio_iso_fback_complete(struct usb_ep *ep,
|
|||||||
__func__, status, req->actual, req->length);
|
__func__, status, req->actual, req->length);
|
||||||
|
|
||||||
u_audio_set_fback_frequency(audio_dev->gadget->speed, audio_dev->out_ep,
|
u_audio_set_fback_frequency(audio_dev->gadget->speed, audio_dev->out_ep,
|
||||||
params->c_srate, prm->pitch,
|
prm->srate, prm->pitch,
|
||||||
req->buf);
|
req->buf);
|
||||||
|
|
||||||
if (usb_ep_queue(ep, req, GFP_ATOMIC))
|
if (usb_ep_queue(ep, req, GFP_ATOMIC))
|
||||||
@@ -339,36 +388,33 @@ static int uac_pcm_open(struct snd_pcm_substream *substream)
|
|||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct g_audio *audio_dev;
|
struct g_audio *audio_dev;
|
||||||
struct uac_params *params;
|
struct uac_params *params;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
int p_ssize, c_ssize;
|
int p_ssize, c_ssize;
|
||||||
int p_srate, c_srate;
|
|
||||||
int p_chmask, c_chmask;
|
int p_chmask, c_chmask;
|
||||||
|
|
||||||
audio_dev = uac->audio_dev;
|
audio_dev = uac->audio_dev;
|
||||||
params = &audio_dev->params;
|
params = &audio_dev->params;
|
||||||
p_ssize = params->p_ssize;
|
p_ssize = params->p_ssize;
|
||||||
c_ssize = params->c_ssize;
|
c_ssize = params->c_ssize;
|
||||||
p_srate = params->p_srate;
|
|
||||||
c_srate = params->c_srate;
|
|
||||||
p_chmask = params->p_chmask;
|
p_chmask = params->p_chmask;
|
||||||
c_chmask = params->c_chmask;
|
c_chmask = params->c_chmask;
|
||||||
uac->p_residue = 0;
|
uac->p_residue_mil = 0;
|
||||||
|
|
||||||
runtime->hw = uac_pcm_hardware;
|
runtime->hw = uac_pcm_hardware;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
runtime->hw.rate_min = p_srate;
|
|
||||||
runtime->hw.formats = uac_ssize_to_fmt(p_ssize);
|
runtime->hw.formats = uac_ssize_to_fmt(p_ssize);
|
||||||
runtime->hw.channels_min = num_channels(p_chmask);
|
runtime->hw.channels_min = num_channels(p_chmask);
|
||||||
runtime->hw.period_bytes_min = 2 * uac->p_prm.max_psize
|
prm = &uac->p_prm;
|
||||||
/ runtime->hw.periods_min;
|
|
||||||
} else {
|
} else {
|
||||||
runtime->hw.rate_min = c_srate;
|
|
||||||
runtime->hw.formats = uac_ssize_to_fmt(c_ssize);
|
runtime->hw.formats = uac_ssize_to_fmt(c_ssize);
|
||||||
runtime->hw.channels_min = num_channels(c_chmask);
|
runtime->hw.channels_min = num_channels(c_chmask);
|
||||||
runtime->hw.period_bytes_min = 2 * uac->c_prm.max_psize
|
prm = &uac->c_prm;
|
||||||
/ runtime->hw.periods_min;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runtime->hw.period_bytes_min = 2 * prm->max_psize
|
||||||
|
/ runtime->hw.periods_min;
|
||||||
|
runtime->hw.rate_min = prm->srate;
|
||||||
runtime->hw.rate_max = runtime->hw.rate_min;
|
runtime->hw.rate_max = runtime->hw.rate_min;
|
||||||
runtime->hw.channels_max = runtime->hw.channels_min;
|
runtime->hw.channels_max = runtime->hw.channels_min;
|
||||||
|
|
||||||
@@ -445,6 +491,99 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep)
|
|||||||
dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
|
dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_active(struct uac_rtd_params *prm, bool active)
|
||||||
|
{
|
||||||
|
// notifying through the Rate ctrl
|
||||||
|
struct snd_kcontrol *kctl = prm->snd_kctl_rate;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
if (prm->active != active) {
|
||||||
|
prm->active = active;
|
||||||
|
snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||||
|
&kctl->id);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int u_audio_set_capture_srate(struct g_audio *audio_dev, int srate)
|
||||||
|
{
|
||||||
|
struct uac_params *params = &audio_dev->params;
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
int i;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
dev_dbg(&audio_dev->gadget->dev, "%s: srate %d\n", __func__, srate);
|
||||||
|
prm = &uac->c_prm;
|
||||||
|
for (i = 0; i < UAC_MAX_RATES; i++) {
|
||||||
|
if (params->c_srates[i] == srate) {
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
prm->srate = srate;
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (params->c_srates[i] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_set_capture_srate);
|
||||||
|
|
||||||
|
int u_audio_get_capture_srate(struct g_audio *audio_dev, u32 *val)
|
||||||
|
{
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
prm = &uac->c_prm;
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
*val = prm->srate;
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_get_capture_srate);
|
||||||
|
|
||||||
|
int u_audio_set_playback_srate(struct g_audio *audio_dev, int srate)
|
||||||
|
{
|
||||||
|
struct uac_params *params = &audio_dev->params;
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
int i;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
dev_dbg(&audio_dev->gadget->dev, "%s: srate %d\n", __func__, srate);
|
||||||
|
prm = &uac->p_prm;
|
||||||
|
for (i = 0; i < UAC_MAX_RATES; i++) {
|
||||||
|
if (params->p_srates[i] == srate) {
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
prm->srate = srate;
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (params->p_srates[i] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_set_playback_srate);
|
||||||
|
|
||||||
|
int u_audio_get_playback_srate(struct g_audio *audio_dev, u32 *val)
|
||||||
|
{
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
prm = &uac->p_prm;
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
*val = prm->srate;
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_get_playback_srate);
|
||||||
|
|
||||||
int u_audio_start_capture(struct g_audio *audio_dev)
|
int u_audio_start_capture(struct g_audio *audio_dev)
|
||||||
{
|
{
|
||||||
struct snd_uac_chip *uac = audio_dev->uac;
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
@@ -456,8 +595,9 @@ int u_audio_start_capture(struct g_audio *audio_dev)
|
|||||||
struct uac_params *params = &audio_dev->params;
|
struct uac_params *params = &audio_dev->params;
|
||||||
int req_len, i;
|
int req_len, i;
|
||||||
|
|
||||||
ep = audio_dev->out_ep;
|
|
||||||
prm = &uac->c_prm;
|
prm = &uac->c_prm;
|
||||||
|
dev_dbg(dev, "start capture with rate %d\n", prm->srate);
|
||||||
|
ep = audio_dev->out_ep;
|
||||||
config_ep_by_speed(gadget, &audio_dev->func, ep);
|
config_ep_by_speed(gadget, &audio_dev->func, ep);
|
||||||
req_len = ep->maxpacket;
|
req_len = ep->maxpacket;
|
||||||
|
|
||||||
@@ -483,6 +623,8 @@ int u_audio_start_capture(struct g_audio *audio_dev)
|
|||||||
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_active(&uac->c_prm, true);
|
||||||
|
|
||||||
ep_fback = audio_dev->in_ep_fback;
|
ep_fback = audio_dev->in_ep_fback;
|
||||||
if (!ep_fback)
|
if (!ep_fback)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -514,7 +656,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
|
|||||||
*/
|
*/
|
||||||
prm->pitch = 1000000;
|
prm->pitch = 1000000;
|
||||||
u_audio_set_fback_frequency(audio_dev->gadget->speed, ep,
|
u_audio_set_fback_frequency(audio_dev->gadget->speed, ep,
|
||||||
params->c_srate, prm->pitch,
|
prm->srate, prm->pitch,
|
||||||
req_fback->buf);
|
req_fback->buf);
|
||||||
|
|
||||||
if (usb_ep_queue(ep_fback, req_fback, GFP_ATOMIC))
|
if (usb_ep_queue(ep_fback, req_fback, GFP_ATOMIC))
|
||||||
@@ -528,6 +670,7 @@ void u_audio_stop_capture(struct g_audio *audio_dev)
|
|||||||
{
|
{
|
||||||
struct snd_uac_chip *uac = audio_dev->uac;
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
|
||||||
|
set_active(&uac->c_prm, false);
|
||||||
if (audio_dev->in_ep_fback)
|
if (audio_dev->in_ep_fback)
|
||||||
free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback);
|
free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback);
|
||||||
free_ep(&uac->c_prm, audio_dev->out_ep);
|
free_ep(&uac->c_prm, audio_dev->out_ep);
|
||||||
@@ -546,12 +689,18 @@ int u_audio_start_playback(struct g_audio *audio_dev)
|
|||||||
unsigned int factor;
|
unsigned int factor;
|
||||||
const struct usb_endpoint_descriptor *ep_desc;
|
const struct usb_endpoint_descriptor *ep_desc;
|
||||||
int req_len, i;
|
int req_len, i;
|
||||||
|
unsigned int p_pktsize;
|
||||||
|
|
||||||
ep = audio_dev->in_ep;
|
|
||||||
prm = &uac->p_prm;
|
prm = &uac->p_prm;
|
||||||
|
dev_dbg(dev, "start playback with rate %d\n", prm->srate);
|
||||||
|
ep = audio_dev->in_ep;
|
||||||
config_ep_by_speed(gadget, &audio_dev->func, ep);
|
config_ep_by_speed(gadget, &audio_dev->func, ep);
|
||||||
|
|
||||||
ep_desc = ep->desc;
|
ep_desc = ep->desc;
|
||||||
|
/*
|
||||||
|
* Always start with original frequency
|
||||||
|
*/
|
||||||
|
prm->pitch = 1000000;
|
||||||
|
|
||||||
/* pre-calculate the playback endpoint's interval */
|
/* pre-calculate the playback endpoint's interval */
|
||||||
if (gadget->speed == USB_SPEED_FULL)
|
if (gadget->speed == USB_SPEED_FULL)
|
||||||
@@ -563,19 +712,13 @@ int u_audio_start_playback(struct g_audio *audio_dev)
|
|||||||
uac->p_framesize = params->p_ssize *
|
uac->p_framesize = params->p_ssize *
|
||||||
num_channels(params->p_chmask);
|
num_channels(params->p_chmask);
|
||||||
uac->p_interval = factor / (1 << (ep_desc->bInterval - 1));
|
uac->p_interval = factor / (1 << (ep_desc->bInterval - 1));
|
||||||
uac->p_pktsize = min_t(unsigned int,
|
p_pktsize = min_t(unsigned int,
|
||||||
uac->p_framesize *
|
uac->p_framesize *
|
||||||
(params->p_srate / uac->p_interval),
|
(prm->srate / uac->p_interval),
|
||||||
ep->maxpacket);
|
ep->maxpacket);
|
||||||
|
|
||||||
if (uac->p_pktsize < ep->maxpacket)
|
req_len = p_pktsize;
|
||||||
uac->p_pktsize_residue = uac->p_framesize *
|
uac->p_residue_mil = 0;
|
||||||
(params->p_srate % uac->p_interval);
|
|
||||||
else
|
|
||||||
uac->p_pktsize_residue = 0;
|
|
||||||
|
|
||||||
req_len = uac->p_pktsize;
|
|
||||||
uac->p_residue = 0;
|
|
||||||
|
|
||||||
prm->ep_enabled = true;
|
prm->ep_enabled = true;
|
||||||
usb_ep_enable(ep);
|
usb_ep_enable(ep);
|
||||||
@@ -599,6 +742,8 @@ int u_audio_start_playback(struct g_audio *audio_dev)
|
|||||||
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_active(&uac->p_prm, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(u_audio_start_playback);
|
EXPORT_SYMBOL_GPL(u_audio_start_playback);
|
||||||
@@ -607,10 +752,117 @@ void u_audio_stop_playback(struct g_audio *audio_dev)
|
|||||||
{
|
{
|
||||||
struct snd_uac_chip *uac = audio_dev->uac;
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
|
||||||
|
set_active(&uac->p_prm, false);
|
||||||
free_ep(&uac->p_prm, audio_dev->in_ep);
|
free_ep(&uac->p_prm, audio_dev->in_ep);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(u_audio_stop_playback);
|
EXPORT_SYMBOL_GPL(u_audio_stop_playback);
|
||||||
|
|
||||||
|
void u_audio_suspend(struct g_audio *audio_dev)
|
||||||
|
{
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
|
||||||
|
set_active(&uac->p_prm, false);
|
||||||
|
set_active(&uac->c_prm, false);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_suspend);
|
||||||
|
|
||||||
|
int u_audio_get_volume(struct g_audio *audio_dev, int playback, s16 *val)
|
||||||
|
{
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (playback)
|
||||||
|
prm = &uac->p_prm;
|
||||||
|
else
|
||||||
|
prm = &uac->c_prm;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
*val = prm->volume;
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_get_volume);
|
||||||
|
|
||||||
|
int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
|
||||||
|
{
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
unsigned long flags;
|
||||||
|
int change = 0;
|
||||||
|
|
||||||
|
if (playback)
|
||||||
|
prm = &uac->p_prm;
|
||||||
|
else
|
||||||
|
prm = &uac->c_prm;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
val = clamp(val, prm->volume_min, prm->volume_max);
|
||||||
|
if (prm->volume != val) {
|
||||||
|
prm->volume = val;
|
||||||
|
change = 1;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
|
||||||
|
if (change)
|
||||||
|
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||||
|
&prm->snd_kctl_volume->id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_set_volume);
|
||||||
|
|
||||||
|
int u_audio_get_mute(struct g_audio *audio_dev, int playback, int *val)
|
||||||
|
{
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (playback)
|
||||||
|
prm = &uac->p_prm;
|
||||||
|
else
|
||||||
|
prm = &uac->c_prm;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
*val = prm->mute;
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_get_mute);
|
||||||
|
|
||||||
|
int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
|
||||||
|
{
|
||||||
|
struct snd_uac_chip *uac = audio_dev->uac;
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
unsigned long flags;
|
||||||
|
int change = 0;
|
||||||
|
int mute;
|
||||||
|
|
||||||
|
if (playback)
|
||||||
|
prm = &uac->p_prm;
|
||||||
|
else
|
||||||
|
prm = &uac->c_prm;
|
||||||
|
|
||||||
|
mute = val ? 1 : 0;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
|
if (prm->mute != mute) {
|
||||||
|
prm->mute = mute;
|
||||||
|
change = 1;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
|
|
||||||
|
if (change)
|
||||||
|
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||||
|
&prm->snd_kctl_mute->id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(u_audio_set_mute);
|
||||||
|
|
||||||
|
|
||||||
static int u_audio_pitch_info(struct snd_kcontrol *kcontrol,
|
static int u_audio_pitch_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
@@ -670,14 +922,234 @@ static int u_audio_pitch_put(struct snd_kcontrol *kcontrol,
|
|||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct snd_kcontrol_new u_audio_controls[] = {
|
static int u_audio_mute_info(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
|
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,
|
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||||
.name = "Capture Pitch 1000000",
|
.name = "Capture Pitch 1000000",
|
||||||
.info = u_audio_pitch_info,
|
.info = u_audio_pitch_info,
|
||||||
.get = u_audio_pitch_get,
|
.get = u_audio_pitch_get,
|
||||||
.put = u_audio_pitch_put,
|
.put = u_audio_pitch_put,
|
||||||
},
|
},
|
||||||
|
[UAC_P_PITCH_CTRL] {
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||||
|
.name = "Playback Pitch 1000000",
|
||||||
|
.info = u_audio_pitch_info,
|
||||||
|
.get = u_audio_pitch_get,
|
||||||
|
.put = u_audio_pitch_put,
|
||||||
|
},
|
||||||
|
[UAC_MUTE_CTRL] {
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||||
|
.name = "", /* will be filled later */
|
||||||
|
.info = u_audio_mute_info,
|
||||||
|
.get = u_audio_mute_get,
|
||||||
|
.put = u_audio_mute_put,
|
||||||
|
},
|
||||||
|
[UAC_VOLUME_CTRL] {
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||||
|
.name = "", /* will be filled later */
|
||||||
|
.info = u_audio_volume_info,
|
||||||
|
.get = u_audio_volume_get,
|
||||||
|
.put = u_audio_volume_put,
|
||||||
|
},
|
||||||
|
[UAC_RATE_CTRL] {
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||||
|
.name = "", /* will be filled later */
|
||||||
|
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
|
||||||
|
.info = u_audio_rate_info,
|
||||||
|
.get = u_audio_rate_get,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
||||||
@@ -689,7 +1161,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
|||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
struct uac_params *params;
|
struct uac_params *params;
|
||||||
int p_chmask, c_chmask;
|
int p_chmask, c_chmask;
|
||||||
int err;
|
int i, err;
|
||||||
|
|
||||||
if (!g_audio)
|
if (!g_audio)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -707,8 +1179,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
|||||||
if (c_chmask) {
|
if (c_chmask) {
|
||||||
struct uac_rtd_params *prm = &uac->c_prm;
|
struct uac_rtd_params *prm = &uac->c_prm;
|
||||||
|
|
||||||
|
spin_lock_init(&prm->lock);
|
||||||
uac->c_prm.uac = uac;
|
uac->c_prm.uac = uac;
|
||||||
prm->max_psize = g_audio->out_ep_maxpsize;
|
prm->max_psize = g_audio->out_ep_maxpsize;
|
||||||
|
prm->srate = params->c_srates[0];
|
||||||
|
|
||||||
prm->reqs = kcalloc(params->req_number,
|
prm->reqs = kcalloc(params->req_number,
|
||||||
sizeof(struct usb_request *),
|
sizeof(struct usb_request *),
|
||||||
@@ -730,8 +1204,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
|||||||
if (p_chmask) {
|
if (p_chmask) {
|
||||||
struct uac_rtd_params *prm = &uac->p_prm;
|
struct uac_rtd_params *prm = &uac->p_prm;
|
||||||
|
|
||||||
|
spin_lock_init(&prm->lock);
|
||||||
uac->p_prm.uac = uac;
|
uac->p_prm.uac = uac;
|
||||||
prm->max_psize = g_audio->in_ep_maxpsize;
|
prm->max_psize = g_audio->in_ep_maxpsize;
|
||||||
|
prm->srate = params->p_srates[0];
|
||||||
|
|
||||||
prm->reqs = kcalloc(params->req_number,
|
prm->reqs = kcalloc(params->req_number,
|
||||||
sizeof(struct usb_request *),
|
sizeof(struct usb_request *),
|
||||||
@@ -774,10 +1250,18 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
|||||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops);
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops);
|
||||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops);
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops);
|
||||||
|
|
||||||
if (c_chmask && g_audio->in_ep_fback) {
|
/*
|
||||||
|
* Create mixer and controls
|
||||||
|
* Create only if it's required on USB side
|
||||||
|
*/
|
||||||
|
if ((c_chmask && g_audio->in_ep_fback)
|
||||||
|
|| (p_chmask && params->p_fu.id)
|
||||||
|
|| (c_chmask && params->c_fu.id))
|
||||||
strscpy(card->mixername, card_name, sizeof(card->driver));
|
strscpy(card->mixername, card_name, sizeof(card->driver));
|
||||||
|
|
||||||
kctl = snd_ctl_new1(&u_audio_controls[0], &uac->c_prm);
|
if (c_chmask && g_audio->in_ep_fback) {
|
||||||
|
kctl = snd_ctl_new1(&u_audio_controls[UAC_FBACK_CTRL],
|
||||||
|
&uac->c_prm);
|
||||||
if (!kctl) {
|
if (!kctl) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto snd_fail;
|
goto snd_fail;
|
||||||
@@ -791,6 +1275,117 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
|||||||
goto snd_fail;
|
goto snd_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_chmask) {
|
||||||
|
kctl = snd_ctl_new1(&u_audio_controls[UAC_P_PITCH_CTRL],
|
||||||
|
&uac->p_prm);
|
||||||
|
if (!kctl) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto snd_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
kctl->id.device = pcm->device;
|
||||||
|
kctl->id.subdevice = 0;
|
||||||
|
|
||||||
|
err = snd_ctl_add(card, kctl);
|
||||||
|
if (err < 0)
|
||||||
|
goto snd_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i <= SNDRV_PCM_STREAM_LAST; i++) {
|
||||||
|
struct uac_rtd_params *prm;
|
||||||
|
struct uac_fu_params *fu;
|
||||||
|
char ctrl_name[24];
|
||||||
|
char *direction;
|
||||||
|
|
||||||
|
if (!pcm->streams[i].substream_count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (i == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
prm = &uac->p_prm;
|
||||||
|
fu = ¶ms->p_fu;
|
||||||
|
direction = "Playback";
|
||||||
|
} else {
|
||||||
|
prm = &uac->c_prm;
|
||||||
|
fu = ¶ms->c_fu;
|
||||||
|
direction = "Capture";
|
||||||
|
}
|
||||||
|
|
||||||
|
prm->fu_id = fu->id;
|
||||||
|
|
||||||
|
if (fu->mute_present) {
|
||||||
|
snprintf(ctrl_name, sizeof(ctrl_name),
|
||||||
|
"PCM %s Switch", direction);
|
||||||
|
|
||||||
|
u_audio_controls[UAC_MUTE_CTRL].name = ctrl_name;
|
||||||
|
|
||||||
|
kctl = snd_ctl_new1(&u_audio_controls[UAC_MUTE_CTRL],
|
||||||
|
prm);
|
||||||
|
if (!kctl) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto snd_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
kctl->id.device = pcm->device;
|
||||||
|
kctl->id.subdevice = 0;
|
||||||
|
|
||||||
|
err = snd_ctl_add(card, kctl);
|
||||||
|
if (err < 0)
|
||||||
|
goto snd_fail;
|
||||||
|
prm->snd_kctl_mute = kctl;
|
||||||
|
prm->mute = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fu->volume_present) {
|
||||||
|
snprintf(ctrl_name, sizeof(ctrl_name),
|
||||||
|
"PCM %s Volume", direction);
|
||||||
|
|
||||||
|
u_audio_controls[UAC_VOLUME_CTRL].name = ctrl_name;
|
||||||
|
|
||||||
|
kctl = snd_ctl_new1(&u_audio_controls[UAC_VOLUME_CTRL],
|
||||||
|
prm);
|
||||||
|
if (!kctl) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto snd_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
kctl->id.device = pcm->device;
|
||||||
|
kctl->id.subdevice = 0;
|
||||||
|
|
||||||
|
|
||||||
|
kctl->tlv.c = u_audio_volume_tlv;
|
||||||
|
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ |
|
||||||
|
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
|
||||||
|
|
||||||
|
err = snd_ctl_add(card, kctl);
|
||||||
|
if (err < 0)
|
||||||
|
goto snd_fail;
|
||||||
|
prm->snd_kctl_volume = kctl;
|
||||||
|
prm->volume = fu->volume_max;
|
||||||
|
prm->volume_max = fu->volume_max;
|
||||||
|
prm->volume_min = fu->volume_min;
|
||||||
|
prm->volume_res = fu->volume_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add rate control */
|
||||||
|
snprintf(ctrl_name, sizeof(ctrl_name),
|
||||||
|
"%s Rate", direction);
|
||||||
|
u_audio_controls[UAC_RATE_CTRL].name = ctrl_name;
|
||||||
|
|
||||||
|
kctl = snd_ctl_new1(&u_audio_controls[UAC_RATE_CTRL], prm);
|
||||||
|
if (!kctl) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto snd_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
kctl->id.device = pcm->device;
|
||||||
|
kctl->id.subdevice = 0;
|
||||||
|
|
||||||
|
err = snd_ctl_add(card, kctl);
|
||||||
|
if (err < 0)
|
||||||
|
goto snd_fail;
|
||||||
|
prm->snd_kctl_rate = kctl;
|
||||||
|
}
|
||||||
|
|
||||||
strscpy(card->driver, card_name, sizeof(card->driver));
|
strscpy(card->driver, card_name, sizeof(card->driver));
|
||||||
strscpy(card->shortname, card_name, sizeof(card->shortname));
|
strscpy(card->shortname, card_name, sizeof(card->shortname));
|
||||||
sprintf(card->longname, "%s %i", card_name, card->dev->id);
|
sprintf(card->longname, "%s %i", card_name, card->dev->id);
|
||||||
|
@@ -10,25 +10,48 @@
|
|||||||
#define __U_AUDIO_H
|
#define __U_AUDIO_H
|
||||||
|
|
||||||
#include <linux/usb/composite.h>
|
#include <linux/usb/composite.h>
|
||||||
|
#include "uac_common.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Same maximum frequency deviation on the slower side as in
|
* Same maximum frequency deviation on the slower side as in
|
||||||
* sound/usb/endpoint.c. Value is expressed in per-mil deviation.
|
* sound/usb/endpoint.c. Value is expressed in per-mil deviation.
|
||||||
* The maximum deviation on the faster side will be provided as
|
|
||||||
* parameter, as it impacts the endpoint required bandwidth.
|
|
||||||
*/
|
*/
|
||||||
#define FBACK_SLOW_MAX 250
|
#define FBACK_SLOW_MAX 250
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum frequency deviation on the faster side, default value for UAC1/2.
|
||||||
|
* Value is expressed in per-mil deviation.
|
||||||
|
* UAC2 provides the value as a parameter as it impacts the endpoint required
|
||||||
|
* bandwidth.
|
||||||
|
*/
|
||||||
|
#define FBACK_FAST_MAX 5
|
||||||
|
|
||||||
|
/* Feature Unit parameters */
|
||||||
|
struct uac_fu_params {
|
||||||
|
int id; /* Feature Unit ID */
|
||||||
|
|
||||||
|
bool mute_present; /* mute control enable */
|
||||||
|
|
||||||
|
bool volume_present; /* volume control enable */
|
||||||
|
s16 volume_min; /* min volume in 1/256 dB */
|
||||||
|
s16 volume_max; /* max volume in 1/256 dB */
|
||||||
|
s16 volume_res; /* volume resolution in 1/256 dB */
|
||||||
|
};
|
||||||
|
|
||||||
struct uac_params {
|
struct uac_params {
|
||||||
/* playback */
|
/* playback */
|
||||||
int p_chmask; /* channel mask */
|
int p_chmask; /* channel mask */
|
||||||
int p_srate; /* rate in Hz */
|
int p_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */
|
||||||
int p_ssize; /* sample size */
|
int p_ssize; /* sample size */
|
||||||
|
struct uac_fu_params p_fu; /* Feature Unit parameters */
|
||||||
|
|
||||||
/* capture */
|
/* capture */
|
||||||
int c_chmask; /* channel mask */
|
int c_chmask; /* channel mask */
|
||||||
int c_srate; /* rate in Hz */
|
int c_srates[UAC_MAX_RATES]; /* available rates in Hz (0 terminated list) */
|
||||||
int c_ssize; /* sample size */
|
int c_ssize; /* sample size */
|
||||||
|
struct uac_fu_params c_fu; /* Feature Unit parameters */
|
||||||
|
|
||||||
|
/* rates are dynamic, in uac_rtd_params */
|
||||||
|
|
||||||
int req_number; /* number of preallocated requests */
|
int req_number; /* number of preallocated requests */
|
||||||
int fb_max; /* upper frequency drift feedback limit per-mil */
|
int fb_max; /* upper frequency drift feedback limit per-mil */
|
||||||
@@ -49,6 +72,9 @@ struct g_audio {
|
|||||||
/* Max packet size for all out_ep possible speeds */
|
/* Max packet size for all out_ep possible speeds */
|
||||||
unsigned int out_ep_maxpsize;
|
unsigned int out_ep_maxpsize;
|
||||||
|
|
||||||
|
/* Notify UAC driver about control change */
|
||||||
|
int (*notify)(struct g_audio *g_audio, int unit_id, int cs);
|
||||||
|
|
||||||
/* The ALSA Sound Card it represents on the USB-Client side */
|
/* The ALSA Sound Card it represents on the USB-Client side */
|
||||||
struct snd_uac_chip *uac;
|
struct snd_uac_chip *uac;
|
||||||
|
|
||||||
@@ -94,4 +120,16 @@ void u_audio_stop_capture(struct g_audio *g_audio);
|
|||||||
int u_audio_start_playback(struct g_audio *g_audio);
|
int u_audio_start_playback(struct g_audio *g_audio);
|
||||||
void u_audio_stop_playback(struct g_audio *g_audio);
|
void u_audio_stop_playback(struct g_audio *g_audio);
|
||||||
|
|
||||||
|
int u_audio_get_capture_srate(struct g_audio *audio_dev, u32 *val);
|
||||||
|
int u_audio_set_capture_srate(struct g_audio *audio_dev, int srate);
|
||||||
|
int u_audio_get_playback_srate(struct g_audio *audio_dev, u32 *val);
|
||||||
|
int u_audio_set_playback_srate(struct g_audio *audio_dev, int srate);
|
||||||
|
|
||||||
|
int u_audio_get_volume(struct g_audio *g_audio, int playback, s16 *val);
|
||||||
|
int u_audio_set_volume(struct g_audio *g_audio, int playback, s16 val);
|
||||||
|
int u_audio_get_mute(struct g_audio *g_audio, int playback, int *val);
|
||||||
|
int u_audio_set_mute(struct g_audio *g_audio, int playback, int val);
|
||||||
|
|
||||||
|
void u_audio_suspend(struct g_audio *g_audio);
|
||||||
|
|
||||||
#endif /* __U_AUDIO_H */
|
#endif /* __U_AUDIO_H */
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#define __U_UAC1_H
|
#define __U_UAC1_H
|
||||||
|
|
||||||
#include <linux/usb/composite.h>
|
#include <linux/usb/composite.h>
|
||||||
|
#include "uac_common.h"
|
||||||
|
|
||||||
#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
|
#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
|
||||||
#define UAC1_DEF_CCHMASK 0x3
|
#define UAC1_DEF_CCHMASK 0x3
|
||||||
@@ -18,19 +19,41 @@
|
|||||||
#define UAC1_DEF_PSRATE 48000
|
#define UAC1_DEF_PSRATE 48000
|
||||||
#define UAC1_DEF_PSSIZE 2
|
#define UAC1_DEF_PSSIZE 2
|
||||||
#define UAC1_DEF_REQ_NUM 2
|
#define UAC1_DEF_REQ_NUM 2
|
||||||
|
#define UAC1_DEF_INT_REQ_NUM 10
|
||||||
|
|
||||||
|
#define UAC1_DEF_MUTE_PRESENT 1
|
||||||
|
#define UAC1_DEF_VOLUME_PRESENT 1
|
||||||
|
#define UAC1_DEF_MIN_DB (-100*256) /* -100 dB */
|
||||||
|
#define UAC1_DEF_MAX_DB 0 /* 0 dB */
|
||||||
|
#define UAC1_DEF_RES_DB (1*256) /* 1 dB */
|
||||||
|
|
||||||
|
|
||||||
struct f_uac1_opts {
|
struct f_uac1_opts {
|
||||||
struct usb_function_instance func_inst;
|
struct usb_function_instance func_inst;
|
||||||
int c_chmask;
|
int c_chmask;
|
||||||
int c_srate;
|
int c_srates[UAC_MAX_RATES];
|
||||||
int c_ssize;
|
int c_ssize;
|
||||||
int p_chmask;
|
int p_chmask;
|
||||||
int p_srate;
|
int p_srates[UAC_MAX_RATES];
|
||||||
int p_ssize;
|
int p_ssize;
|
||||||
|
|
||||||
|
bool p_mute_present;
|
||||||
|
bool p_volume_present;
|
||||||
|
s16 p_volume_min;
|
||||||
|
s16 p_volume_max;
|
||||||
|
s16 p_volume_res;
|
||||||
|
|
||||||
|
bool c_mute_present;
|
||||||
|
bool c_volume_present;
|
||||||
|
s16 c_volume_min;
|
||||||
|
s16 c_volume_max;
|
||||||
|
s16 c_volume_res;
|
||||||
|
|
||||||
int req_number;
|
int req_number;
|
||||||
unsigned bound:1;
|
unsigned bound:1;
|
||||||
|
|
||||||
|
char function_name[32];
|
||||||
|
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
int refcnt;
|
int refcnt;
|
||||||
};
|
};
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#define U_UAC2_H
|
#define U_UAC2_H
|
||||||
|
|
||||||
#include <linux/usb/composite.h>
|
#include <linux/usb/composite.h>
|
||||||
|
#include "uac_common.h"
|
||||||
|
|
||||||
#define UAC2_DEF_PCHMASK 0x3
|
#define UAC2_DEF_PCHMASK 0x3
|
||||||
#define UAC2_DEF_PSRATE 48000
|
#define UAC2_DEF_PSRATE 48000
|
||||||
@@ -22,22 +23,44 @@
|
|||||||
#define UAC2_DEF_CSRATE 64000
|
#define UAC2_DEF_CSRATE 64000
|
||||||
#define UAC2_DEF_CSSIZE 2
|
#define UAC2_DEF_CSSIZE 2
|
||||||
#define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC
|
#define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC
|
||||||
|
|
||||||
|
#define UAC2_DEF_MUTE_PRESENT 1
|
||||||
|
#define UAC2_DEF_VOLUME_PRESENT 1
|
||||||
|
#define UAC2_DEF_MIN_DB (-100*256) /* -100 dB */
|
||||||
|
#define UAC2_DEF_MAX_DB 0 /* 0 dB */
|
||||||
|
#define UAC2_DEF_RES_DB (1*256) /* 1 dB */
|
||||||
|
|
||||||
#define UAC2_DEF_REQ_NUM 2
|
#define UAC2_DEF_REQ_NUM 2
|
||||||
#define UAC2_DEF_FB_MAX 5
|
#define UAC2_DEF_INT_REQ_NUM 10
|
||||||
|
|
||||||
struct f_uac2_opts {
|
struct f_uac2_opts {
|
||||||
struct usb_function_instance func_inst;
|
struct usb_function_instance func_inst;
|
||||||
int p_chmask;
|
int p_chmask;
|
||||||
int p_srate;
|
int p_srates[UAC_MAX_RATES];
|
||||||
int p_ssize;
|
int p_ssize;
|
||||||
int c_chmask;
|
int c_chmask;
|
||||||
int c_srate;
|
int c_srates[UAC_MAX_RATES];
|
||||||
int c_ssize;
|
int c_ssize;
|
||||||
int c_sync;
|
int c_sync;
|
||||||
|
|
||||||
|
bool p_mute_present;
|
||||||
|
bool p_volume_present;
|
||||||
|
s16 p_volume_min;
|
||||||
|
s16 p_volume_max;
|
||||||
|
s16 p_volume_res;
|
||||||
|
|
||||||
|
bool c_mute_present;
|
||||||
|
bool c_volume_present;
|
||||||
|
s16 c_volume_min;
|
||||||
|
s16 c_volume_max;
|
||||||
|
s16 c_volume_res;
|
||||||
|
|
||||||
int req_number;
|
int req_number;
|
||||||
int fb_max;
|
int fb_max;
|
||||||
bool bound;
|
bool bound;
|
||||||
|
|
||||||
|
char function_name[32];
|
||||||
|
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
int refcnt;
|
int refcnt;
|
||||||
};
|
};
|
||||||
|
9
drivers/usb/gadget/function/uac_common.h
Normal file
9
drivers/usb/gadget/function/uac_common.h
Normal 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
|
@@ -22,32 +22,34 @@ USB_GADGET_COMPOSITE_OPTIONS();
|
|||||||
|
|
||||||
/* Playback(USB-IN) Default Stereo - Fl/Fr */
|
/* Playback(USB-IN) Default Stereo - Fl/Fr */
|
||||||
static int p_chmask = UAC2_DEF_PCHMASK;
|
static int p_chmask = UAC2_DEF_PCHMASK;
|
||||||
module_param(p_chmask, uint, S_IRUGO);
|
module_param(p_chmask, uint, 0444);
|
||||||
MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
|
MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
|
||||||
|
|
||||||
/* Playback Default 48 KHz */
|
/* Playback Default 48 KHz */
|
||||||
static int p_srate = UAC2_DEF_PSRATE;
|
static int p_srates[UAC_MAX_RATES] = {UAC2_DEF_PSRATE};
|
||||||
module_param(p_srate, uint, S_IRUGO);
|
static int p_srates_cnt = 1;
|
||||||
MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
|
module_param_array_named(p_srate, p_srates, uint, &p_srates_cnt, 0444);
|
||||||
|
MODULE_PARM_DESC(p_srate, "Playback Sampling Rates (array)");
|
||||||
|
|
||||||
/* Playback Default 16bits/sample */
|
/* Playback Default 16bits/sample */
|
||||||
static int p_ssize = UAC2_DEF_PSSIZE;
|
static int p_ssize = UAC2_DEF_PSSIZE;
|
||||||
module_param(p_ssize, uint, S_IRUGO);
|
module_param(p_ssize, uint, 0444);
|
||||||
MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
|
MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
|
||||||
|
|
||||||
/* Capture(USB-OUT) Default Stereo - Fl/Fr */
|
/* Capture(USB-OUT) Default Stereo - Fl/Fr */
|
||||||
static int c_chmask = UAC2_DEF_CCHMASK;
|
static int c_chmask = UAC2_DEF_CCHMASK;
|
||||||
module_param(c_chmask, uint, S_IRUGO);
|
module_param(c_chmask, uint, 0444);
|
||||||
MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
|
MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
|
||||||
|
|
||||||
/* Capture Default 64 KHz */
|
/* Capture Default 64 KHz */
|
||||||
static int c_srate = UAC2_DEF_CSRATE;
|
static int c_srates[UAC_MAX_RATES] = {UAC2_DEF_CSRATE};
|
||||||
module_param(c_srate, uint, S_IRUGO);
|
static int c_srates_cnt = 1;
|
||||||
MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
|
module_param_array_named(c_srate, c_srates, uint, &c_srates_cnt, 0444);
|
||||||
|
MODULE_PARM_DESC(c_srate, "Capture Sampling Rates (array)");
|
||||||
|
|
||||||
/* Capture Default 16bits/sample */
|
/* Capture Default 16bits/sample */
|
||||||
static int c_ssize = UAC2_DEF_CSSIZE;
|
static int c_ssize = UAC2_DEF_CSSIZE;
|
||||||
module_param(c_ssize, uint, S_IRUGO);
|
module_param(c_ssize, uint, 0444);
|
||||||
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
|
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
|
||||||
#else
|
#else
|
||||||
#ifndef CONFIG_GADGET_UAC1_LEGACY
|
#ifndef CONFIG_GADGET_UAC1_LEGACY
|
||||||
@@ -55,58 +57,60 @@ MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
|
|||||||
|
|
||||||
/* Playback(USB-IN) Default Stereo - Fl/Fr */
|
/* Playback(USB-IN) Default Stereo - Fl/Fr */
|
||||||
static int p_chmask = UAC1_DEF_PCHMASK;
|
static int p_chmask = UAC1_DEF_PCHMASK;
|
||||||
module_param(p_chmask, uint, S_IRUGO);
|
module_param(p_chmask, uint, 0444);
|
||||||
MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
|
MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
|
||||||
|
|
||||||
/* Playback Default 48 KHz */
|
/* Playback Default 48 KHz */
|
||||||
static int p_srate = UAC1_DEF_PSRATE;
|
static int p_srates[UAC_MAX_RATES] = {UAC1_DEF_PSRATE};
|
||||||
module_param(p_srate, uint, S_IRUGO);
|
static int p_srates_cnt = 1;
|
||||||
MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
|
module_param_array_named(p_srate, p_srates, uint, &p_srates_cnt, 0444);
|
||||||
|
MODULE_PARM_DESC(p_srate, "Playback Sampling Rates (array)");
|
||||||
|
|
||||||
/* Playback Default 16bits/sample */
|
/* Playback Default 16bits/sample */
|
||||||
static int p_ssize = UAC1_DEF_PSSIZE;
|
static int p_ssize = UAC1_DEF_PSSIZE;
|
||||||
module_param(p_ssize, uint, S_IRUGO);
|
module_param(p_ssize, uint, 0444);
|
||||||
MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
|
MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
|
||||||
|
|
||||||
/* Capture(USB-OUT) Default Stereo - Fl/Fr */
|
/* Capture(USB-OUT) Default Stereo - Fl/Fr */
|
||||||
static int c_chmask = UAC1_DEF_CCHMASK;
|
static int c_chmask = UAC1_DEF_CCHMASK;
|
||||||
module_param(c_chmask, uint, S_IRUGO);
|
module_param(c_chmask, uint, 0444);
|
||||||
MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
|
MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
|
||||||
|
|
||||||
/* Capture Default 48 KHz */
|
/* Capture Default 48 KHz */
|
||||||
static int c_srate = UAC1_DEF_CSRATE;
|
static int c_srates[UAC_MAX_RATES] = {UAC1_DEF_CSRATE};
|
||||||
module_param(c_srate, uint, S_IRUGO);
|
static int c_srates_cnt = 1;
|
||||||
MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
|
module_param_array_named(c_srate, c_srates, uint, &c_srates_cnt, 0444);
|
||||||
|
MODULE_PARM_DESC(c_srate, "Capture Sampling Rates (array)");
|
||||||
|
|
||||||
/* Capture Default 16bits/sample */
|
/* Capture Default 16bits/sample */
|
||||||
static int c_ssize = UAC1_DEF_CSSIZE;
|
static int c_ssize = UAC1_DEF_CSSIZE;
|
||||||
module_param(c_ssize, uint, S_IRUGO);
|
module_param(c_ssize, uint, 0444);
|
||||||
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
|
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
|
||||||
#else /* CONFIG_GADGET_UAC1_LEGACY */
|
#else /* CONFIG_GADGET_UAC1_LEGACY */
|
||||||
#include "u_uac1_legacy.h"
|
#include "u_uac1_legacy.h"
|
||||||
|
|
||||||
static char *fn_play = FILE_PCM_PLAYBACK;
|
static char *fn_play = FILE_PCM_PLAYBACK;
|
||||||
module_param(fn_play, charp, S_IRUGO);
|
module_param(fn_play, charp, 0444);
|
||||||
MODULE_PARM_DESC(fn_play, "Playback PCM device file name");
|
MODULE_PARM_DESC(fn_play, "Playback PCM device file name");
|
||||||
|
|
||||||
static char *fn_cap = FILE_PCM_CAPTURE;
|
static char *fn_cap = FILE_PCM_CAPTURE;
|
||||||
module_param(fn_cap, charp, S_IRUGO);
|
module_param(fn_cap, charp, 0444);
|
||||||
MODULE_PARM_DESC(fn_cap, "Capture PCM device file name");
|
MODULE_PARM_DESC(fn_cap, "Capture PCM device file name");
|
||||||
|
|
||||||
static char *fn_cntl = FILE_CONTROL;
|
static char *fn_cntl = FILE_CONTROL;
|
||||||
module_param(fn_cntl, charp, S_IRUGO);
|
module_param(fn_cntl, charp, 0444);
|
||||||
MODULE_PARM_DESC(fn_cntl, "Control device file name");
|
MODULE_PARM_DESC(fn_cntl, "Control device file name");
|
||||||
|
|
||||||
static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE;
|
static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE;
|
||||||
module_param(req_buf_size, int, S_IRUGO);
|
module_param(req_buf_size, int, 0444);
|
||||||
MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size");
|
MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size");
|
||||||
|
|
||||||
static int req_count = UAC1_REQ_COUNT;
|
static int req_count = UAC1_REQ_COUNT;
|
||||||
module_param(req_count, int, S_IRUGO);
|
module_param(req_count, int, 0444);
|
||||||
MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count");
|
MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count");
|
||||||
|
|
||||||
static int audio_buf_size = UAC1_AUDIO_BUF_SIZE;
|
static int audio_buf_size = UAC1_AUDIO_BUF_SIZE;
|
||||||
module_param(audio_buf_size, int, S_IRUGO);
|
module_param(audio_buf_size, int, 0444);
|
||||||
MODULE_PARM_DESC(audio_buf_size, "Audio buffer size");
|
MODULE_PARM_DESC(audio_buf_size, "Audio buffer size");
|
||||||
#endif /* CONFIG_GADGET_UAC1_LEGACY */
|
#endif /* CONFIG_GADGET_UAC1_LEGACY */
|
||||||
#endif
|
#endif
|
||||||
@@ -237,9 +241,11 @@ static int audio_bind(struct usb_composite_dev *cdev)
|
|||||||
{
|
{
|
||||||
#ifndef CONFIG_GADGET_UAC1
|
#ifndef CONFIG_GADGET_UAC1
|
||||||
struct f_uac2_opts *uac2_opts;
|
struct f_uac2_opts *uac2_opts;
|
||||||
|
int i;
|
||||||
#else
|
#else
|
||||||
#ifndef CONFIG_GADGET_UAC1_LEGACY
|
#ifndef CONFIG_GADGET_UAC1_LEGACY
|
||||||
struct f_uac1_opts *uac1_opts;
|
struct f_uac1_opts *uac1_opts;
|
||||||
|
int i;
|
||||||
#else
|
#else
|
||||||
struct f_uac1_legacy_opts *uac1_opts;
|
struct f_uac1_legacy_opts *uac1_opts;
|
||||||
#endif
|
#endif
|
||||||
@@ -263,20 +269,32 @@ static int audio_bind(struct usb_composite_dev *cdev)
|
|||||||
#ifndef CONFIG_GADGET_UAC1
|
#ifndef CONFIG_GADGET_UAC1
|
||||||
uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst);
|
uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst);
|
||||||
uac2_opts->p_chmask = p_chmask;
|
uac2_opts->p_chmask = p_chmask;
|
||||||
uac2_opts->p_srate = p_srate;
|
|
||||||
|
for (i = 0; i < p_srates_cnt; ++i)
|
||||||
|
uac2_opts->p_srates[i] = p_srates[i];
|
||||||
|
|
||||||
uac2_opts->p_ssize = p_ssize;
|
uac2_opts->p_ssize = p_ssize;
|
||||||
uac2_opts->c_chmask = c_chmask;
|
uac2_opts->c_chmask = c_chmask;
|
||||||
uac2_opts->c_srate = c_srate;
|
|
||||||
|
for (i = 0; i < c_srates_cnt; ++i)
|
||||||
|
uac2_opts->c_srates[i] = c_srates[i];
|
||||||
|
|
||||||
uac2_opts->c_ssize = c_ssize;
|
uac2_opts->c_ssize = c_ssize;
|
||||||
uac2_opts->req_number = UAC2_DEF_REQ_NUM;
|
uac2_opts->req_number = UAC2_DEF_REQ_NUM;
|
||||||
#else
|
#else
|
||||||
#ifndef CONFIG_GADGET_UAC1_LEGACY
|
#ifndef CONFIG_GADGET_UAC1_LEGACY
|
||||||
uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
|
uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
|
||||||
uac1_opts->p_chmask = p_chmask;
|
uac1_opts->p_chmask = p_chmask;
|
||||||
uac1_opts->p_srate = p_srate;
|
|
||||||
|
for (i = 0; i < p_srates_cnt; ++i)
|
||||||
|
uac1_opts->p_srates[i] = p_srates[i];
|
||||||
|
|
||||||
uac1_opts->p_ssize = p_ssize;
|
uac1_opts->p_ssize = p_ssize;
|
||||||
uac1_opts->c_chmask = c_chmask;
|
uac1_opts->c_chmask = c_chmask;
|
||||||
uac1_opts->c_srate = c_srate;
|
|
||||||
|
for (i = 0; i < c_srates_cnt; ++i)
|
||||||
|
uac1_opts->c_srates[i] = c_srates[i];
|
||||||
|
|
||||||
uac1_opts->c_ssize = c_ssize;
|
uac1_opts->c_ssize = c_ssize;
|
||||||
uac1_opts->req_number = UAC1_DEF_REQ_NUM;
|
uac1_opts->req_number = UAC1_DEF_REQ_NUM;
|
||||||
#else /* CONFIG_GADGET_UAC1_LEGACY */
|
#else /* CONFIG_GADGET_UAC1_LEGACY */
|
||||||
|
@@ -160,7 +160,7 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
|
void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
|
||||||
{
|
{
|
||||||
int i, b;
|
int i, b;
|
||||||
unsigned int ent_idx;
|
unsigned int ent_idx;
|
||||||
@@ -176,7 +176,7 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
|
|||||||
b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
|
b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
|
||||||
|
|
||||||
clear_bit_le(b, sbi->vol_amap[i]->b_data);
|
clear_bit_le(b, sbi->vol_amap[i]->b_data);
|
||||||
exfat_update_bh(sbi->vol_amap[i], IS_DIRSYNC(inode));
|
exfat_update_bh(sbi->vol_amap[i], sync);
|
||||||
|
|
||||||
if (opts->discard) {
|
if (opts->discard) {
|
||||||
int ret_discard;
|
int ret_discard;
|
||||||
|
@@ -416,7 +416,7 @@ int exfat_count_num_clusters(struct super_block *sb,
|
|||||||
int exfat_load_bitmap(struct super_block *sb);
|
int exfat_load_bitmap(struct super_block *sb);
|
||||||
void exfat_free_bitmap(struct exfat_sb_info *sbi);
|
void exfat_free_bitmap(struct exfat_sb_info *sbi);
|
||||||
int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync);
|
int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync);
|
||||||
void exfat_clear_bitmap(struct inode *inode, unsigned int clu);
|
void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync);
|
||||||
unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
|
unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
|
||||||
int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
|
int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
|
||||||
|
|
||||||
|
@@ -149,6 +149,7 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
|
|||||||
unsigned int clu;
|
unsigned int clu;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
int cur_cmap_i, next_cmap_i;
|
||||||
|
|
||||||
/* invalid cluster number */
|
/* invalid cluster number */
|
||||||
if (p_chain->dir == EXFAT_FREE_CLUSTER ||
|
if (p_chain->dir == EXFAT_FREE_CLUSTER ||
|
||||||
@@ -168,21 +169,53 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
|
|||||||
|
|
||||||
clu = p_chain->dir;
|
clu = p_chain->dir;
|
||||||
|
|
||||||
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
cur_cmap_i = next_cmap_i =
|
||||||
do {
|
BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu));
|
||||||
exfat_clear_bitmap(inode, clu);
|
|
||||||
clu++;
|
|
||||||
|
|
||||||
|
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||||
|
unsigned int last_cluster = p_chain->dir + p_chain->size - 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bool sync = false;
|
||||||
|
|
||||||
|
if (clu < last_cluster)
|
||||||
|
next_cmap_i =
|
||||||
|
BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu+1));
|
||||||
|
|
||||||
|
/* flush bitmap only if index would be changed or for last cluster */
|
||||||
|
if (clu == last_cluster || cur_cmap_i != next_cmap_i) {
|
||||||
|
sync = true;
|
||||||
|
cur_cmap_i = next_cmap_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
|
||||||
|
clu++;
|
||||||
num_clusters++;
|
num_clusters++;
|
||||||
} while (num_clusters < p_chain->size);
|
} while (num_clusters < p_chain->size);
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
exfat_clear_bitmap(inode, clu);
|
bool sync = false;
|
||||||
|
unsigned int n_clu = clu;
|
||||||
|
int err = exfat_get_next_cluster(sb, &n_clu);
|
||||||
|
|
||||||
if (exfat_get_next_cluster(sb, &clu))
|
if (err || n_clu == EXFAT_EOF_CLUSTER)
|
||||||
goto dec_used_clus;
|
sync = true;
|
||||||
|
else
|
||||||
|
next_cmap_i =
|
||||||
|
BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(n_clu));
|
||||||
|
|
||||||
|
if (cur_cmap_i != next_cmap_i) {
|
||||||
|
sync = true;
|
||||||
|
cur_cmap_i = next_cmap_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
|
||||||
|
clu = n_clu;
|
||||||
|
|
||||||
num_clusters++;
|
num_clusters++;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto dec_used_clus;
|
||||||
} while (clu != EXFAT_EOF_CLUSTER);
|
} while (clu != EXFAT_EOF_CLUSTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4217,8 +4217,9 @@ static inline void f2fs_invalidate_compress_pages(struct f2fs_sb_info *sbi,
|
|||||||
#define inc_compr_inode_stat(inode) do { } while (0)
|
#define inc_compr_inode_stat(inode) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void set_compress_context(struct inode *inode)
|
static inline int set_compress_context(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_F2FS_FS_COMPRESSION
|
||||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||||
|
|
||||||
F2FS_I(inode)->i_compress_algorithm =
|
F2FS_I(inode)->i_compress_algorithm =
|
||||||
@@ -4240,6 +4241,10 @@ static inline void set_compress_context(struct inode *inode)
|
|||||||
stat_inc_compr_inode(inode);
|
stat_inc_compr_inode(inode);
|
||||||
inc_compr_inode_stat(inode);
|
inc_compr_inode_stat(inode);
|
||||||
f2fs_mark_inode_dirty_sync(inode, true);
|
f2fs_mark_inode_dirty_sync(inode, true);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool f2fs_disable_compressed_file(struct inode *inode)
|
static inline bool f2fs_disable_compressed_file(struct inode *inode)
|
||||||
|
@@ -1855,8 +1855,8 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (S_ISREG(inode->i_mode) && inode->i_size)
|
if (S_ISREG(inode->i_mode) && inode->i_size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (set_compress_context(inode))
|
||||||
set_compress_context(inode);
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((iflags ^ masked_flags) & F2FS_NOCOMP_FL) {
|
if ((iflags ^ masked_flags) & F2FS_NOCOMP_FL) {
|
||||||
|
@@ -282,6 +282,13 @@ struct css_set {
|
|||||||
struct rcu_head rcu_head;
|
struct rcu_head rcu_head;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ext_css_set {
|
||||||
|
struct css_set cset;
|
||||||
|
|
||||||
|
struct list_head mg_src_preload_node;
|
||||||
|
struct list_head mg_dst_preload_node;
|
||||||
|
};
|
||||||
|
|
||||||
struct cgroup_base_stat {
|
struct cgroup_base_stat {
|
||||||
struct task_cputime cputime;
|
struct task_cputime cputime;
|
||||||
};
|
};
|
||||||
|
@@ -72,7 +72,8 @@ struct css_task_iter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern struct cgroup_root cgrp_dfl_root;
|
extern struct cgroup_root cgrp_dfl_root;
|
||||||
extern struct css_set init_css_set;
|
extern struct ext_css_set init_ext_css_set;
|
||||||
|
#define init_css_set init_ext_css_set.cset
|
||||||
|
|
||||||
#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
|
#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
|
||||||
#include <linux/cgroup_subsys.h>
|
#include <linux/cgroup_subsys.h>
|
||||||
|
@@ -345,6 +345,9 @@ struct mem_cgroup {
|
|||||||
|
|
||||||
extern struct mem_cgroup *root_mem_cgroup;
|
extern struct mem_cgroup *root_mem_cgroup;
|
||||||
|
|
||||||
|
struct lruvec *page_to_lruvec(struct page *page, pg_data_t *pgdat);
|
||||||
|
void do_traversal_all_lruvec(void);
|
||||||
|
|
||||||
static __always_inline bool memcg_stat_item_in_bytes(int idx)
|
static __always_inline bool memcg_stat_item_in_bytes(int idx)
|
||||||
{
|
{
|
||||||
if (idx == MEMCG_PERCPU_B)
|
if (idx == MEMCG_PERCPU_B)
|
||||||
@@ -969,6 +972,15 @@ void split_page_memcg(struct page *head, unsigned int nr);
|
|||||||
|
|
||||||
struct mem_cgroup;
|
struct mem_cgroup;
|
||||||
|
|
||||||
|
static inline struct lruvec *page_to_lruvec(struct page *page, pg_data_t *pgdat)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void do_traversal_all_lruvec(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
|
static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@@ -3363,7 +3363,6 @@ unsigned long wp_shared_mapping_range(struct address_space *mapping,
|
|||||||
extern int sysctl_nr_trim_pages;
|
extern int sysctl_nr_trim_pages;
|
||||||
extern bool pte_map_lock_addr(struct vm_fault *vmf, unsigned long addr);
|
extern bool pte_map_lock_addr(struct vm_fault *vmf, unsigned long addr);
|
||||||
extern int reclaim_shmem_address_space(struct address_space *mapping);
|
extern int reclaim_shmem_address_space(struct address_space *mapping);
|
||||||
extern int reclaim_pages_from_list(struct list_head *page_list);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it
|
* seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it
|
||||||
|
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
#include <linux/huge_mm.h>
|
#include <linux/huge_mm.h>
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
|
#ifndef __GENKSYMS__
|
||||||
|
#define PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
#include <trace/hooks/mm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* page_is_file_lru - should the page be on a file LRU or anon LRU?
|
* page_is_file_lru - should the page be on a file LRU or anon LRU?
|
||||||
@@ -48,6 +52,7 @@ static __always_inline void update_lru_size(struct lruvec *lruvec,
|
|||||||
static __always_inline void add_page_to_lru_list(struct page *page,
|
static __always_inline void add_page_to_lru_list(struct page *page,
|
||||||
struct lruvec *lruvec, enum lru_list lru)
|
struct lruvec *lruvec, enum lru_list lru)
|
||||||
{
|
{
|
||||||
|
trace_android_vh_add_page_to_lrulist(page, false, lru);
|
||||||
update_lru_size(lruvec, lru, page_zonenum(page), thp_nr_pages(page));
|
update_lru_size(lruvec, lru, page_zonenum(page), thp_nr_pages(page));
|
||||||
list_add(&page->lru, &lruvec->lists[lru]);
|
list_add(&page->lru, &lruvec->lists[lru]);
|
||||||
}
|
}
|
||||||
@@ -55,6 +60,7 @@ static __always_inline void add_page_to_lru_list(struct page *page,
|
|||||||
static __always_inline void add_page_to_lru_list_tail(struct page *page,
|
static __always_inline void add_page_to_lru_list_tail(struct page *page,
|
||||||
struct lruvec *lruvec, enum lru_list lru)
|
struct lruvec *lruvec, enum lru_list lru)
|
||||||
{
|
{
|
||||||
|
trace_android_vh_add_page_to_lrulist(page, false, lru);
|
||||||
update_lru_size(lruvec, lru, page_zonenum(page), thp_nr_pages(page));
|
update_lru_size(lruvec, lru, page_zonenum(page), thp_nr_pages(page));
|
||||||
list_add_tail(&page->lru, &lruvec->lists[lru]);
|
list_add_tail(&page->lru, &lruvec->lists[lru]);
|
||||||
}
|
}
|
||||||
@@ -62,6 +68,7 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page,
|
|||||||
static __always_inline void del_page_from_lru_list(struct page *page,
|
static __always_inline void del_page_from_lru_list(struct page *page,
|
||||||
struct lruvec *lruvec, enum lru_list lru)
|
struct lruvec *lruvec, enum lru_list lru)
|
||||||
{
|
{
|
||||||
|
trace_android_vh_del_page_from_lrulist(page, false, lru);
|
||||||
list_del(&page->lru);
|
list_del(&page->lru);
|
||||||
update_lru_size(lruvec, lru, page_zonenum(page), -thp_nr_pages(page));
|
update_lru_size(lruvec, lru, page_zonenum(page), -thp_nr_pages(page));
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,10 @@
|
|||||||
#include <linux/rwsem.h>
|
#include <linux/rwsem.h>
|
||||||
#include <linux/memcontrol.h>
|
#include <linux/memcontrol.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
|
#ifndef __GENKSYMS__
|
||||||
|
#define PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
#include <trace/hooks/mm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The anon_vma heads a list of private "related" vmas, to scan if
|
* The anon_vma heads a list of private "related" vmas, to scan if
|
||||||
@@ -194,6 +198,11 @@ void hugepage_add_new_anon_rmap(struct page *, struct vm_area_struct *,
|
|||||||
|
|
||||||
static inline void page_dup_rmap(struct page *page, bool compound)
|
static inline void page_dup_rmap(struct page *page, bool compound)
|
||||||
{
|
{
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
if (!compound)
|
||||||
|
trace_android_vh_update_page_mapcount(page, true, compound, NULL, &success);
|
||||||
|
if (!success)
|
||||||
atomic_inc(compound ? compound_mapcount_ptr(page) : &page->_mapcount);
|
atomic_inc(compound ? compound_mapcount_ptr(page) : &page->_mapcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -92,6 +92,13 @@ int sysctl_numa_balancing(struct ctl_table *table, int write, void *buffer,
|
|||||||
int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
|
int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
|
||||||
size_t *lenp, loff_t *ppos);
|
size_t *lenp, loff_t *ppos);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
extern unsigned int sysctl_sched_pelt_multiplier;
|
||||||
|
|
||||||
|
int sched_pelt_multiplier(struct ctl_table *table, int write, void *buffer,
|
||||||
|
size_t *lenp, loff_t *ppos);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
|
#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
|
||||||
extern unsigned int sysctl_sched_energy_aware;
|
extern unsigned int sysctl_sched_energy_aware;
|
||||||
int sched_energy_aware_handler(struct ctl_table *table, int write,
|
int sched_energy_aware_handler(struct ctl_table *table, int write,
|
||||||
|
@@ -156,6 +156,20 @@ struct uac2_feature_unit_descriptor {
|
|||||||
__u8 bmaControls[]; /* variable length */
|
__u8 bmaControls[]; /* variable length */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define UAC2_DT_FEATURE_UNIT_SIZE(ch) (6 + ((ch) + 1) * 4)
|
||||||
|
|
||||||
|
/* As above, but more useful for defining your own descriptors: */
|
||||||
|
#define DECLARE_UAC2_FEATURE_UNIT_DESCRIPTOR(ch) \
|
||||||
|
struct uac2_feature_unit_descriptor_##ch { \
|
||||||
|
__u8 bLength; \
|
||||||
|
__u8 bDescriptorType; \
|
||||||
|
__u8 bDescriptorSubtype; \
|
||||||
|
__u8 bUnitID; \
|
||||||
|
__u8 bSourceID; \
|
||||||
|
__le32 bmaControls[ch + 1]; \
|
||||||
|
__u8 iFeature; \
|
||||||
|
} __packed
|
||||||
|
|
||||||
/* 4.7.2.10 Effect Unit Descriptor */
|
/* 4.7.2.10 Effect Unit Descriptor */
|
||||||
|
|
||||||
struct uac2_effect_unit_descriptor {
|
struct uac2_effect_unit_descriptor {
|
||||||
|
@@ -34,6 +34,11 @@ struct hdmi_codec_daifmt {
|
|||||||
unsigned int frame_clk_inv:1;
|
unsigned int frame_clk_inv:1;
|
||||||
unsigned int bit_clk_master:1;
|
unsigned int bit_clk_master:1;
|
||||||
unsigned int frame_clk_master:1;
|
unsigned int frame_clk_master:1;
|
||||||
|
/* bit_fmt could be standard PCM format or
|
||||||
|
* IEC958 encoded format. ALSA IEC958 plugin will pass
|
||||||
|
* IEC958_SUBFRAME format to the underneath driver.
|
||||||
|
*/
|
||||||
|
snd_pcm_format_t bit_fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -60,12 +65,22 @@ struct hdmi_codec_ops {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Configures HDMI-encoder for audio stream.
|
* Configures HDMI-encoder for audio stream.
|
||||||
* Mandatory
|
* Having either prepare or hw_params is mandatory.
|
||||||
*/
|
*/
|
||||||
int (*hw_params)(struct device *dev, void *data,
|
int (*hw_params)(struct device *dev, void *data,
|
||||||
struct hdmi_codec_daifmt *fmt,
|
struct hdmi_codec_daifmt *fmt,
|
||||||
struct hdmi_codec_params *hparms);
|
struct hdmi_codec_params *hparms);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configures HDMI-encoder for audio stream. Can be called
|
||||||
|
* multiple times for each setup.
|
||||||
|
*
|
||||||
|
* Having either prepare or hw_params is mandatory.
|
||||||
|
*/
|
||||||
|
int (*prepare)(struct device *dev, void *data,
|
||||||
|
struct hdmi_codec_daifmt *fmt,
|
||||||
|
struct hdmi_codec_params *hparms);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shuts down the audio stream.
|
* Shuts down the audio stream.
|
||||||
* Mandatory
|
* Mandatory
|
||||||
|
@@ -4,6 +4,14 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len);
|
||||||
|
|
||||||
|
int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
|
||||||
|
u8 *cs, size_t len);
|
||||||
|
|
||||||
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
|
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
|
@@ -11,19 +11,23 @@
|
|||||||
* Following tracepoints are not exported in tracefs and provide a
|
* Following tracepoints are not exported in tracefs and provide a
|
||||||
* mechanism for vendor modules to hook and extend functionality
|
* mechanism for vendor modules to hook and extend functionality
|
||||||
*/
|
*/
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_ANDROID_BINDER_IPC)
|
||||||
struct binder_alloc;
|
struct binder_alloc;
|
||||||
struct binder_proc;
|
struct binder_proc;
|
||||||
struct binder_thread;
|
struct binder_thread;
|
||||||
struct binder_transaction;
|
struct binder_transaction;
|
||||||
struct task_struct;
|
|
||||||
struct seq_file;
|
|
||||||
struct binder_transaction_data;
|
struct binder_transaction_data;
|
||||||
#else
|
#else
|
||||||
/* struct binder_alloc */
|
/* struct binder_alloc */
|
||||||
#include <../drivers/android/binder_alloc.h>
|
#include <../drivers/android/binder_alloc.h>
|
||||||
/* struct binder_proc, struct binder_thread, struct binder_transaction */
|
/* struct binder_proc, struct binder_thread, struct binder_transaction */
|
||||||
#include <../drivers/android/binder_internal.h>
|
#include <../drivers/android/binder_internal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GENKSYMS__
|
||||||
|
struct task_struct;
|
||||||
|
struct seq_file;
|
||||||
|
#else
|
||||||
/* struct task_struct */
|
/* struct task_struct */
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
/* struct seq_file */
|
/* struct seq_file */
|
||||||
@@ -31,6 +35,7 @@ struct binder_transaction_data;
|
|||||||
/* struct binder_transaction_data */
|
/* struct binder_transaction_data */
|
||||||
#include <uapi/linux/android/binder.h>
|
#include <uapi/linux/android/binder.h>
|
||||||
#endif /* __GENKSYMS__ */
|
#endif /* __GENKSYMS__ */
|
||||||
|
|
||||||
DECLARE_HOOK(android_vh_binder_transaction_init,
|
DECLARE_HOOK(android_vh_binder_transaction_init,
|
||||||
TP_PROTO(struct binder_transaction *t),
|
TP_PROTO(struct binder_transaction *t),
|
||||||
TP_ARGS(t));
|
TP_ARGS(t));
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
#include <trace/hooks/vendor_hooks.h>
|
#include <trace/hooks/vendor_hooks.h>
|
||||||
|
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !defined(CONFIG_BLOCK)
|
||||||
struct blk_mq_tags;
|
struct blk_mq_tags;
|
||||||
struct blk_mq_alloc_data;
|
struct blk_mq_alloc_data;
|
||||||
struct blk_mq_tag_set;
|
struct blk_mq_tag_set;
|
||||||
|
@@ -9,12 +9,16 @@
|
|||||||
#include <trace/hooks/vendor_hooks.h>
|
#include <trace/hooks/vendor_hooks.h>
|
||||||
|
|
||||||
struct cgroup_taskset;
|
struct cgroup_taskset;
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_CGROUPS)
|
||||||
struct cgroup_subsys;
|
struct cgroup_subsys;
|
||||||
struct task_struct;
|
|
||||||
#else
|
#else
|
||||||
/* struct cgroup_subsys */
|
/* struct cgroup_subsys */
|
||||||
#include <linux/cgroup-defs.h>
|
#include <linux/cgroup-defs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GENKSYMS__
|
||||||
|
struct task_struct;
|
||||||
|
#else
|
||||||
/* struct task_struct */
|
/* struct task_struct */
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#endif /* __GENKSYMS__ */
|
#endif /* __GENKSYMS__ */
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
#include <trace/hooks/vendor_hooks.h>
|
#include <trace/hooks/vendor_hooks.h>
|
||||||
|
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_PRINTK)
|
||||||
struct printk_record;
|
struct printk_record;
|
||||||
struct printk_ringbuffer;
|
struct printk_ringbuffer;
|
||||||
#else
|
#else
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifdef PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
#undef PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
|
||||||
|
#include <trace/hooks/save_incpath.h>
|
||||||
|
#include <trace/hooks/mm.h>
|
||||||
|
#include <trace/hooks/restore_incpath.h>
|
||||||
|
|
||||||
|
#else /* PROTECT_TRACE_INCLUDE_PATH */
|
||||||
|
|
||||||
#undef TRACE_SYSTEM
|
#undef TRACE_SYSTEM
|
||||||
#define TRACE_SYSTEM mm
|
#define TRACE_SYSTEM mm
|
||||||
|
|
||||||
@@ -13,6 +22,7 @@
|
|||||||
#include <linux/oom.h>
|
#include <linux/oom.h>
|
||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
#include <trace/hooks/vendor_hooks.h>
|
#include <trace/hooks/vendor_hooks.h>
|
||||||
|
#include <linux/rwsem.h>
|
||||||
|
|
||||||
#ifdef __GENKSYMS__
|
#ifdef __GENKSYMS__
|
||||||
struct slabinfo;
|
struct slabinfo;
|
||||||
@@ -87,6 +97,12 @@ DECLARE_HOOK(android_vh_include_reserved_zone,
|
|||||||
DECLARE_HOOK(android_vh_show_mem,
|
DECLARE_HOOK(android_vh_show_mem,
|
||||||
TP_PROTO(unsigned int filter, nodemask_t *nodemask),
|
TP_PROTO(unsigned int filter, nodemask_t *nodemask),
|
||||||
TP_ARGS(filter, nodemask));
|
TP_ARGS(filter, nodemask));
|
||||||
|
DECLARE_HOOK(android_vh_alloc_pages_slowpath_begin,
|
||||||
|
TP_PROTO(gfp_t gfp_mask, unsigned int order, unsigned long *pdata),
|
||||||
|
TP_ARGS(gfp_mask, order, pdata));
|
||||||
|
DECLARE_HOOK(android_vh_alloc_pages_slowpath_end,
|
||||||
|
TP_PROTO(gfp_t gfp_mask, unsigned int order, unsigned long data),
|
||||||
|
TP_ARGS(gfp_mask, order, data));
|
||||||
struct dirty_throttle_control;
|
struct dirty_throttle_control;
|
||||||
DECLARE_HOOK(android_vh_mm_dirty_limits,
|
DECLARE_HOOK(android_vh_mm_dirty_limits,
|
||||||
TP_PROTO(struct dirty_throttle_control *const gdtc, bool strictlimit,
|
TP_PROTO(struct dirty_throttle_control *const gdtc, bool strictlimit,
|
||||||
@@ -133,11 +149,37 @@ DECLARE_HOOK(android_vh_mmap_region,
|
|||||||
DECLARE_HOOK(android_vh_try_to_unmap_one,
|
DECLARE_HOOK(android_vh_try_to_unmap_one,
|
||||||
TP_PROTO(struct vm_area_struct *vma, struct page *page, unsigned long addr, bool ret),
|
TP_PROTO(struct vm_area_struct *vma, struct page *page, unsigned long addr, bool ret),
|
||||||
TP_ARGS(vma, page, addr, ret));
|
TP_ARGS(vma, page, addr, ret));
|
||||||
|
DECLARE_HOOK(android_vh_do_page_trylock,
|
||||||
|
TP_PROTO(struct page *page, struct rw_semaphore *sem,
|
||||||
|
bool *got_lock, bool *success),
|
||||||
|
TP_ARGS(page, sem, got_lock, success));
|
||||||
DECLARE_HOOK(android_vh_drain_all_pages_bypass,
|
DECLARE_HOOK(android_vh_drain_all_pages_bypass,
|
||||||
TP_PROTO(gfp_t gfp_mask, unsigned int order, unsigned long alloc_flags,
|
TP_PROTO(gfp_t gfp_mask, unsigned int order, unsigned long alloc_flags,
|
||||||
int migratetype, unsigned long did_some_progress,
|
int migratetype, unsigned long did_some_progress,
|
||||||
bool *bypass),
|
bool *bypass),
|
||||||
TP_ARGS(gfp_mask, order, alloc_flags, migratetype, did_some_progress, bypass));
|
TP_ARGS(gfp_mask, order, alloc_flags, migratetype, did_some_progress, bypass));
|
||||||
|
DECLARE_HOOK(android_vh_update_page_mapcount,
|
||||||
|
TP_PROTO(struct page *page, bool inc_size, bool compound,
|
||||||
|
bool *first_mapping, bool *success),
|
||||||
|
TP_ARGS(page, inc_size, compound, first_mapping, success));
|
||||||
|
DECLARE_HOOK(android_vh_add_page_to_lrulist,
|
||||||
|
TP_PROTO(struct page *page, bool compound, enum lru_list lru),
|
||||||
|
TP_ARGS(page, compound, lru));
|
||||||
|
DECLARE_HOOK(android_vh_del_page_from_lrulist,
|
||||||
|
TP_PROTO(struct page *page, bool compound, enum lru_list lru),
|
||||||
|
TP_ARGS(page, compound, lru));
|
||||||
|
DECLARE_HOOK(android_vh_show_mapcount_pages,
|
||||||
|
TP_PROTO(void *unused),
|
||||||
|
TP_ARGS(unused));
|
||||||
|
DECLARE_HOOK(android_vh_do_traversal_lruvec,
|
||||||
|
TP_PROTO(struct lruvec *lruvec),
|
||||||
|
TP_ARGS(lruvec));
|
||||||
|
DECLARE_HOOK(android_vh_page_should_be_protected,
|
||||||
|
TP_PROTO(struct page *page, bool *should_protect),
|
||||||
|
TP_ARGS(page, should_protect));
|
||||||
|
DECLARE_HOOK(android_vh_mark_page_accessed,
|
||||||
|
TP_PROTO(struct page *page),
|
||||||
|
TP_ARGS(page));
|
||||||
DECLARE_HOOK(android_vh_cma_drain_all_pages_bypass,
|
DECLARE_HOOK(android_vh_cma_drain_all_pages_bypass,
|
||||||
TP_PROTO(unsigned int migratetype, bool *bypass),
|
TP_PROTO(unsigned int migratetype, bool *bypass),
|
||||||
TP_ARGS(migratetype, bypass));
|
TP_ARGS(migratetype, bypass));
|
||||||
@@ -215,9 +257,17 @@ DECLARE_HOOK(android_vh_alloc_si,
|
|||||||
DECLARE_HOOK(android_vh_free_pages,
|
DECLARE_HOOK(android_vh_free_pages,
|
||||||
TP_PROTO(struct page *page, unsigned int order),
|
TP_PROTO(struct page *page, unsigned int order),
|
||||||
TP_ARGS(page, order));
|
TP_ARGS(page, order));
|
||||||
|
DECLARE_HOOK(android_vh_set_shmem_page_flag,
|
||||||
|
TP_PROTO(struct page *page),
|
||||||
|
TP_ARGS(page));
|
||||||
|
DECLARE_HOOK(android_vh_remove_vmalloc_stack,
|
||||||
|
TP_PROTO(struct vm_struct *vm),
|
||||||
|
TP_ARGS(vm));
|
||||||
/* macro versions of hooks are no longer required */
|
/* macro versions of hooks are no longer required */
|
||||||
|
|
||||||
#endif /* _TRACE_HOOK_MM_H */
|
#endif /* _TRACE_HOOK_MM_H */
|
||||||
|
|
||||||
/* This part must be outside protection */
|
/* This part must be outside protection */
|
||||||
#include <trace/define_trace.h>
|
#include <trace/define_trace.h>
|
||||||
|
|
||||||
|
#endif /* PROTECT_TRACE_INCLUDE_PATH */
|
||||||
|
@@ -10,13 +10,17 @@
|
|||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
#include <trace/hooks/vendor_hooks.h>
|
#include <trace/hooks/vendor_hooks.h>
|
||||||
|
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_MMC_SDHCI)
|
||||||
struct sdhci_host;
|
struct sdhci_host;
|
||||||
struct mmc_card;
|
|
||||||
struct mmc_host;
|
|
||||||
#else
|
#else
|
||||||
/* struct sdhci_host */
|
/* struct sdhci_host */
|
||||||
#include <../drivers/mmc/host/sdhci.h>
|
#include <../drivers/mmc/host/sdhci.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GENKSYMS__
|
||||||
|
struct mmc_card;
|
||||||
|
struct mmc_host;
|
||||||
|
#else
|
||||||
/* struct mmc_card */
|
/* struct mmc_card */
|
||||||
#include <linux/mmc/card.h>
|
#include <linux/mmc/card.h>
|
||||||
/* struct mmc_host */
|
/* struct mmc_host */
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS)
|
#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS)
|
||||||
|
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !defined(CONFIG_PSI)
|
||||||
struct psi_group;
|
struct psi_group;
|
||||||
struct psi_trigger;
|
struct psi_trigger;
|
||||||
#else
|
#else
|
||||||
|
32
include/trace/hooks/restore_incpath.h
Normal file
32
include/trace/hooks/restore_incpath.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Include this file from a header declaring vendor hooks to preserve and later
|
||||||
|
* restore TRACE_INCLUDE_PATH value. Typical usage:
|
||||||
|
*
|
||||||
|
* #ifdef PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
* #undef PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
*
|
||||||
|
* #include <trace/hooks/save_incpath.h>
|
||||||
|
* #include <vendor hooks header>
|
||||||
|
* #include <trace/hooks/restore_incpath.h>
|
||||||
|
*
|
||||||
|
* #else
|
||||||
|
*
|
||||||
|
* <vendor hook definitions>
|
||||||
|
*
|
||||||
|
* #endif
|
||||||
|
*
|
||||||
|
* The header that includes vendor hooks header file should define
|
||||||
|
* PROTECT_TRACE_INCLUDE_PATH before including the vendor hook file like this:
|
||||||
|
*
|
||||||
|
* #define PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
* #include <vendor hooks header>
|
||||||
|
*/
|
||||||
|
#ifdef STORED_TRACE_INCLUDE_PATH
|
||||||
|
# undef TRACE_INCLUDE_PATH
|
||||||
|
# define TRACE_INCLUDE_PATH STORED_TRACE_INCLUDE_PATH
|
||||||
|
# undef STORED_TRACE_INCLUDE_PATH
|
||||||
|
#else
|
||||||
|
# undef TRACE_INCLUDE_PATH
|
||||||
|
#endif
|
||||||
|
|
29
include/trace/hooks/save_incpath.h
Normal file
29
include/trace/hooks/save_incpath.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Include this file from a header declaring vendor hooks to preserve and later
|
||||||
|
* restore TRACE_INCLUDE_PATH value. Typical usage:
|
||||||
|
*
|
||||||
|
* #ifdef PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
* #undef PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
*
|
||||||
|
* #include <trace/hooks/save_incpath.h>
|
||||||
|
* #include <vendor hooks header>
|
||||||
|
* #include <trace/hooks/restore_incpath.h>
|
||||||
|
*
|
||||||
|
* #else
|
||||||
|
*
|
||||||
|
* <vendor hook definitions>
|
||||||
|
*
|
||||||
|
* #endif
|
||||||
|
*
|
||||||
|
* The header that includes vendor hooks header file should define
|
||||||
|
* PROTECT_TRACE_INCLUDE_PATH before including the vendor hook file like this:
|
||||||
|
*
|
||||||
|
* #define PROTECT_TRACE_INCLUDE_PATH
|
||||||
|
* #include <vendor hooks header>
|
||||||
|
*/
|
||||||
|
#ifdef TRACE_INCLUDE_PATH
|
||||||
|
#define STORED_TRACE_INCLUDE_PATH TRACE_INCLUDE_PATH
|
||||||
|
#undef TRACE_INCLUDE_PATH
|
||||||
|
#endif
|
||||||
|
|
@@ -391,6 +391,17 @@ DECLARE_HOOK(android_vh_setscheduler_uclamp,
|
|||||||
TP_PROTO(struct task_struct *tsk, int clamp_id, unsigned int value),
|
TP_PROTO(struct task_struct *tsk, int clamp_id, unsigned int value),
|
||||||
TP_ARGS(tsk, clamp_id, value));
|
TP_ARGS(tsk, clamp_id, value));
|
||||||
|
|
||||||
|
DECLARE_HOOK(android_vh_pidfd_open,
|
||||||
|
TP_PROTO(struct pid *p),
|
||||||
|
TP_ARGS(p));
|
||||||
|
|
||||||
|
DECLARE_HOOK(android_vh_mmput,
|
||||||
|
TP_PROTO(void *unused),
|
||||||
|
TP_ARGS(unused));
|
||||||
|
|
||||||
|
DECLARE_HOOK(android_vh_sched_pelt_multiplier,
|
||||||
|
TP_PROTO(unsigned int old, unsigned int cur, int *ret),
|
||||||
|
TP_ARGS(old, cur, ret));
|
||||||
/* macro versions of hooks are no longer required */
|
/* macro versions of hooks are no longer required */
|
||||||
|
|
||||||
#endif /* _TRACE_HOOK_SCHED_H */
|
#endif /* _TRACE_HOOK_SCHED_H */
|
||||||
|
@@ -6,12 +6,13 @@
|
|||||||
#define _TRACE_HOOK_TYPEC_H
|
#define _TRACE_HOOK_TYPEC_H
|
||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
#include <linux/usb/pd.h>
|
#include <linux/usb/pd.h>
|
||||||
|
#include <linux/usb/tcpm.h>
|
||||||
#include <trace/hooks/vendor_hooks.h>
|
#include <trace/hooks/vendor_hooks.h>
|
||||||
/*
|
/*
|
||||||
* Following tracepoints are not exported in tracefs and provide a
|
* Following tracepoints are not exported in tracefs and provide a
|
||||||
* mechanism for vendor modules to hook and extend functionality
|
* mechanism for vendor modules to hook and extend functionality
|
||||||
*/
|
*/
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_TYPEC_TCPCI)
|
||||||
struct tcpci_data;
|
struct tcpci_data;
|
||||||
#else
|
#else
|
||||||
/* struct tcpci_data */
|
/* struct tcpci_data */
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
* Following tracepoints are not exported in tracefs and provide a
|
* Following tracepoints are not exported in tracefs and provide a
|
||||||
* mechanism for vendor modules to hook and extend functionality
|
* mechanism for vendor modules to hook and extend functionality
|
||||||
*/
|
*/
|
||||||
#ifdef __GENKSYMS__
|
#if defined(__GENKSYMS__) || !IS_ENABLED(CONFIG_SCSI_UFSHCD)
|
||||||
struct ufs_hba;
|
struct ufs_hba;
|
||||||
struct ufshcd_lrb;
|
struct ufshcd_lrb;
|
||||||
struct uic_command;
|
struct uic_command;
|
||||||
|
@@ -28,6 +28,18 @@ DECLARE_RESTRICTED_HOOK(android_rvh_set_balance_anon_file_reclaim,
|
|||||||
DECLARE_HOOK(android_vh_page_referenced_check_bypass,
|
DECLARE_HOOK(android_vh_page_referenced_check_bypass,
|
||||||
TP_PROTO(struct page *page, unsigned long nr_to_scan, int lru, bool *bypass),
|
TP_PROTO(struct page *page, unsigned long nr_to_scan, int lru, bool *bypass),
|
||||||
TP_ARGS(page, nr_to_scan, lru, bypass));
|
TP_ARGS(page, nr_to_scan, lru, bypass));
|
||||||
|
DECLARE_HOOK(android_vh_page_trylock_get_result,
|
||||||
|
TP_PROTO(struct page *page, bool *trylock_fail),
|
||||||
|
TP_ARGS(page, trylock_fail));
|
||||||
|
DECLARE_HOOK(android_vh_handle_failed_page_trylock,
|
||||||
|
TP_PROTO(struct list_head *page_list),
|
||||||
|
TP_ARGS(page_list));
|
||||||
|
DECLARE_HOOK(android_vh_page_trylock_set,
|
||||||
|
TP_PROTO(struct page *page),
|
||||||
|
TP_ARGS(page));
|
||||||
|
DECLARE_HOOK(android_vh_page_trylock_clear,
|
||||||
|
TP_PROTO(struct page *page),
|
||||||
|
TP_ARGS(page));
|
||||||
DECLARE_HOOK(android_vh_shrink_node_memcgs,
|
DECLARE_HOOK(android_vh_shrink_node_memcgs,
|
||||||
TP_PROTO(struct mem_cgroup *memcg, bool *skip),
|
TP_PROTO(struct mem_cgroup *memcg, bool *skip),
|
||||||
TP_ARGS(memcg, skip));
|
TP_ARGS(memcg, skip));
|
||||||
|
@@ -319,6 +319,7 @@ enum transaction_flags {
|
|||||||
TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
|
TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
|
||||||
TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
|
TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
|
||||||
TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
|
TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
|
||||||
|
TF_UPDATE_TXN = 0x40, /* update the outdated pending async txn */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct binder_transaction_data {
|
struct binder_transaction_data {
|
||||||
|
@@ -746,7 +746,8 @@ EXPORT_SYMBOL_GPL(of_css);
|
|||||||
* reference-counted, to improve performance when child cgroups
|
* reference-counted, to improve performance when child cgroups
|
||||||
* haven't been created.
|
* haven't been created.
|
||||||
*/
|
*/
|
||||||
struct css_set init_css_set = {
|
struct ext_css_set init_ext_css_set = {
|
||||||
|
.cset = {
|
||||||
.refcount = REFCOUNT_INIT(1),
|
.refcount = REFCOUNT_INIT(1),
|
||||||
.dom_cset = &init_css_set,
|
.dom_cset = &init_css_set,
|
||||||
.tasks = LIST_HEAD_INIT(init_css_set.tasks),
|
.tasks = LIST_HEAD_INIT(init_css_set.tasks),
|
||||||
@@ -757,7 +758,6 @@ struct css_set init_css_set = {
|
|||||||
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
|
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
|
||||||
.mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node),
|
.mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node),
|
||||||
.mg_node = LIST_HEAD_INIT(init_css_set.mg_node),
|
.mg_node = LIST_HEAD_INIT(init_css_set.mg_node),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following field is re-initialized when this cset gets linked
|
* The following field is re-initialized when this cset gets linked
|
||||||
* in cgroup_init(). However, let's initialize the field
|
* in cgroup_init(). However, let's initialize the field
|
||||||
@@ -765,6 +765,9 @@ struct css_set init_css_set = {
|
|||||||
* early during boot.
|
* early during boot.
|
||||||
*/
|
*/
|
||||||
.dfl_cgrp = &cgrp_dfl_root.cgrp,
|
.dfl_cgrp = &cgrp_dfl_root.cgrp,
|
||||||
|
},
|
||||||
|
.mg_src_preload_node = LIST_HEAD_INIT(init_ext_css_set.mg_src_preload_node),
|
||||||
|
.mg_dst_preload_node = LIST_HEAD_INIT(init_ext_css_set.mg_dst_preload_node),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int css_set_count = 1; /* 1 for init_css_set */
|
static int css_set_count = 1; /* 1 for init_css_set */
|
||||||
@@ -1191,6 +1194,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
|
|||||||
struct cgroup *cgrp)
|
struct cgroup *cgrp)
|
||||||
{
|
{
|
||||||
struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT] = { };
|
struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT] = { };
|
||||||
|
struct ext_css_set *ext_cset;
|
||||||
struct css_set *cset;
|
struct css_set *cset;
|
||||||
struct list_head tmp_links;
|
struct list_head tmp_links;
|
||||||
struct cgrp_cset_link *link;
|
struct cgrp_cset_link *link;
|
||||||
@@ -1211,9 +1215,10 @@ static struct css_set *find_css_set(struct css_set *old_cset,
|
|||||||
if (cset)
|
if (cset)
|
||||||
return cset;
|
return cset;
|
||||||
|
|
||||||
cset = kzalloc(sizeof(*cset), GFP_KERNEL);
|
ext_cset = kzalloc(sizeof(*ext_cset), GFP_KERNEL);
|
||||||
if (!cset)
|
if (!ext_cset)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
cset = &ext_cset->cset;
|
||||||
|
|
||||||
/* Allocate all the cgrp_cset_link objects that we'll need */
|
/* Allocate all the cgrp_cset_link objects that we'll need */
|
||||||
if (allocate_cgrp_cset_links(cgroup_root_count, &tmp_links) < 0) {
|
if (allocate_cgrp_cset_links(cgroup_root_count, &tmp_links) < 0) {
|
||||||
@@ -1231,6 +1236,8 @@ static struct css_set *find_css_set(struct css_set *old_cset,
|
|||||||
INIT_HLIST_NODE(&cset->hlist);
|
INIT_HLIST_NODE(&cset->hlist);
|
||||||
INIT_LIST_HEAD(&cset->cgrp_links);
|
INIT_LIST_HEAD(&cset->cgrp_links);
|
||||||
INIT_LIST_HEAD(&cset->mg_preload_node);
|
INIT_LIST_HEAD(&cset->mg_preload_node);
|
||||||
|
INIT_LIST_HEAD(&ext_cset->mg_src_preload_node);
|
||||||
|
INIT_LIST_HEAD(&ext_cset->mg_dst_preload_node);
|
||||||
INIT_LIST_HEAD(&cset->mg_node);
|
INIT_LIST_HEAD(&cset->mg_node);
|
||||||
|
|
||||||
/* Copy the set of subsystem state objects generated in
|
/* Copy the set of subsystem state objects generated in
|
||||||
@@ -2578,22 +2585,28 @@ int cgroup_migrate_vet_dst(struct cgroup *dst_cgrp)
|
|||||||
*/
|
*/
|
||||||
void cgroup_migrate_finish(struct cgroup_mgctx *mgctx)
|
void cgroup_migrate_finish(struct cgroup_mgctx *mgctx)
|
||||||
{
|
{
|
||||||
LIST_HEAD(preloaded);
|
struct ext_css_set *cset, *tmp_cset;
|
||||||
struct css_set *cset, *tmp_cset;
|
|
||||||
|
|
||||||
lockdep_assert_held(&cgroup_mutex);
|
lockdep_assert_held(&cgroup_mutex);
|
||||||
|
|
||||||
spin_lock_irq(&css_set_lock);
|
spin_lock_irq(&css_set_lock);
|
||||||
|
|
||||||
list_splice_tail_init(&mgctx->preloaded_src_csets, &preloaded);
|
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_src_csets,
|
||||||
list_splice_tail_init(&mgctx->preloaded_dst_csets, &preloaded);
|
mg_src_preload_node) {
|
||||||
|
cset->cset.mg_src_cgrp = NULL;
|
||||||
|
cset->cset.mg_dst_cgrp = NULL;
|
||||||
|
cset->cset.mg_dst_cset = NULL;
|
||||||
|
list_del_init(&cset->mg_src_preload_node);
|
||||||
|
put_css_set_locked(&cset->cset);
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(cset, tmp_cset, &preloaded, mg_preload_node) {
|
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_dst_csets,
|
||||||
cset->mg_src_cgrp = NULL;
|
mg_dst_preload_node) {
|
||||||
cset->mg_dst_cgrp = NULL;
|
cset->cset.mg_src_cgrp = NULL;
|
||||||
cset->mg_dst_cset = NULL;
|
cset->cset.mg_dst_cgrp = NULL;
|
||||||
list_del_init(&cset->mg_preload_node);
|
cset->cset.mg_dst_cset = NULL;
|
||||||
put_css_set_locked(cset);
|
list_del_init(&cset->mg_dst_preload_node);
|
||||||
|
put_css_set_locked(&cset->cset);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irq(&css_set_lock);
|
spin_unlock_irq(&css_set_lock);
|
||||||
@@ -2620,6 +2633,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||||||
struct cgroup_mgctx *mgctx)
|
struct cgroup_mgctx *mgctx)
|
||||||
{
|
{
|
||||||
struct cgroup *src_cgrp;
|
struct cgroup *src_cgrp;
|
||||||
|
struct ext_css_set *ext_src_cset;
|
||||||
|
|
||||||
lockdep_assert_held(&cgroup_mutex);
|
lockdep_assert_held(&cgroup_mutex);
|
||||||
lockdep_assert_held(&css_set_lock);
|
lockdep_assert_held(&css_set_lock);
|
||||||
@@ -2633,8 +2647,9 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
|
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
|
||||||
|
ext_src_cset = container_of(src_cset, struct ext_css_set, cset);
|
||||||
|
|
||||||
if (!list_empty(&src_cset->mg_preload_node))
|
if (!list_empty(&ext_src_cset->mg_src_preload_node))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
WARN_ON(src_cset->mg_src_cgrp);
|
WARN_ON(src_cset->mg_src_cgrp);
|
||||||
@@ -2645,7 +2660,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||||||
src_cset->mg_src_cgrp = src_cgrp;
|
src_cset->mg_src_cgrp = src_cgrp;
|
||||||
src_cset->mg_dst_cgrp = dst_cgrp;
|
src_cset->mg_dst_cgrp = dst_cgrp;
|
||||||
get_css_set(src_cset);
|
get_css_set(src_cset);
|
||||||
list_add_tail(&src_cset->mg_preload_node, &mgctx->preloaded_src_csets);
|
list_add_tail(&ext_src_cset->mg_src_preload_node, &mgctx->preloaded_src_csets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2664,20 +2679,23 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||||||
*/
|
*/
|
||||||
int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
|
int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
|
||||||
{
|
{
|
||||||
struct css_set *src_cset, *tmp_cset;
|
struct ext_css_set *ext_src_set, *tmp_cset;
|
||||||
|
|
||||||
lockdep_assert_held(&cgroup_mutex);
|
lockdep_assert_held(&cgroup_mutex);
|
||||||
|
|
||||||
/* look up the dst cset for each src cset and link it to src */
|
/* look up the dst cset for each src cset and link it to src */
|
||||||
list_for_each_entry_safe(src_cset, tmp_cset, &mgctx->preloaded_src_csets,
|
list_for_each_entry_safe(ext_src_set, tmp_cset, &mgctx->preloaded_src_csets,
|
||||||
mg_preload_node) {
|
mg_src_preload_node) {
|
||||||
|
struct css_set *src_cset = &ext_src_set->cset;
|
||||||
struct css_set *dst_cset;
|
struct css_set *dst_cset;
|
||||||
|
struct ext_css_set *ext_dst_cset;
|
||||||
struct cgroup_subsys *ss;
|
struct cgroup_subsys *ss;
|
||||||
int ssid;
|
int ssid;
|
||||||
|
|
||||||
dst_cset = find_css_set(src_cset, src_cset->mg_dst_cgrp);
|
dst_cset = find_css_set(src_cset, src_cset->mg_dst_cgrp);
|
||||||
if (!dst_cset)
|
if (!dst_cset)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
ext_dst_cset = container_of(dst_cset, struct ext_css_set, cset);
|
||||||
|
|
||||||
WARN_ON_ONCE(src_cset->mg_dst_cset || dst_cset->mg_dst_cset);
|
WARN_ON_ONCE(src_cset->mg_dst_cset || dst_cset->mg_dst_cset);
|
||||||
|
|
||||||
@@ -2689,7 +2707,7 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
|
|||||||
if (src_cset == dst_cset) {
|
if (src_cset == dst_cset) {
|
||||||
src_cset->mg_src_cgrp = NULL;
|
src_cset->mg_src_cgrp = NULL;
|
||||||
src_cset->mg_dst_cgrp = NULL;
|
src_cset->mg_dst_cgrp = NULL;
|
||||||
list_del_init(&src_cset->mg_preload_node);
|
list_del_init(&ext_src_set->mg_src_preload_node);
|
||||||
put_css_set(src_cset);
|
put_css_set(src_cset);
|
||||||
put_css_set(dst_cset);
|
put_css_set(dst_cset);
|
||||||
continue;
|
continue;
|
||||||
@@ -2697,8 +2715,8 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
|
|||||||
|
|
||||||
src_cset->mg_dst_cset = dst_cset;
|
src_cset->mg_dst_cset = dst_cset;
|
||||||
|
|
||||||
if (list_empty(&dst_cset->mg_preload_node))
|
if (list_empty(&ext_dst_cset->mg_dst_preload_node))
|
||||||
list_add_tail(&dst_cset->mg_preload_node,
|
list_add_tail(&ext_dst_cset->mg_dst_preload_node,
|
||||||
&mgctx->preloaded_dst_csets);
|
&mgctx->preloaded_dst_csets);
|
||||||
else
|
else
|
||||||
put_css_set(dst_cset);
|
put_css_set(dst_cset);
|
||||||
@@ -2926,7 +2944,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
|
|||||||
DEFINE_CGROUP_MGCTX(mgctx);
|
DEFINE_CGROUP_MGCTX(mgctx);
|
||||||
struct cgroup_subsys_state *d_css;
|
struct cgroup_subsys_state *d_css;
|
||||||
struct cgroup *dsct;
|
struct cgroup *dsct;
|
||||||
struct css_set *src_cset;
|
struct ext_css_set *ext_src_set;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lockdep_assert_held(&cgroup_mutex);
|
lockdep_assert_held(&cgroup_mutex);
|
||||||
@@ -2949,11 +2967,12 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
|
|||||||
goto out_finish;
|
goto out_finish;
|
||||||
|
|
||||||
spin_lock_irq(&css_set_lock);
|
spin_lock_irq(&css_set_lock);
|
||||||
list_for_each_entry(src_cset, &mgctx.preloaded_src_csets, mg_preload_node) {
|
list_for_each_entry(ext_src_set, &mgctx.preloaded_src_csets,
|
||||||
|
mg_src_preload_node) {
|
||||||
struct task_struct *task, *ntask;
|
struct task_struct *task, *ntask;
|
||||||
|
|
||||||
/* all tasks in src_csets need to be migrated */
|
/* all tasks in src_csets need to be migrated */
|
||||||
list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list)
|
list_for_each_entry_safe(task, ntask, &ext_src_set->cset.tasks, cg_list)
|
||||||
cgroup_migrate_add_task(task, &mgctx);
|
cgroup_migrate_add_task(task, &mgctx);
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&css_set_lock);
|
spin_unlock_irq(&css_set_lock);
|
||||||
|
@@ -1150,9 +1150,11 @@ void mmput(struct mm_struct *mm)
|
|||||||
{
|
{
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
if (atomic_dec_and_test(&mm->mm_users))
|
if (atomic_dec_and_test(&mm->mm_users)) {
|
||||||
|
trace_android_vh_mmput(NULL);
|
||||||
__mmput(mm);
|
__mmput(mm);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(mmput);
|
EXPORT_SYMBOL_GPL(mmput);
|
||||||
|
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
|
@@ -45,6 +45,9 @@
|
|||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
#include <uapi/linux/pidfd.h>
|
#include <uapi/linux/pidfd.h>
|
||||||
|
|
||||||
|
#undef CREATE_TRACE_POINTS
|
||||||
|
#include <trace/hooks/sched.h>
|
||||||
|
|
||||||
struct pid init_struct_pid = {
|
struct pid init_struct_pid = {
|
||||||
.count = REFCOUNT_INIT(1),
|
.count = REFCOUNT_INIT(1),
|
||||||
.tasks = {
|
.tasks = {
|
||||||
@@ -602,6 +605,7 @@ SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags)
|
|||||||
else
|
else
|
||||||
fd = -EINVAL;
|
fd = -EINVAL;
|
||||||
|
|
||||||
|
trace_android_vh_pidfd_open(p);
|
||||||
put_pid(p);
|
put_pid(p);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@@ -4788,7 +4788,7 @@ static int tg_unthrottle_up(struct task_group *tg, void *data)
|
|||||||
|
|
||||||
cfs_rq->throttle_count--;
|
cfs_rq->throttle_count--;
|
||||||
if (!cfs_rq->throttle_count) {
|
if (!cfs_rq->throttle_count) {
|
||||||
cfs_rq->throttled_clock_pelt_time += rq_clock_pelt(rq) -
|
cfs_rq->throttled_clock_pelt_time += rq_clock_task_mult(rq) -
|
||||||
cfs_rq->throttled_clock_pelt;
|
cfs_rq->throttled_clock_pelt;
|
||||||
|
|
||||||
/* Add cfs_rq with already running entity in the list */
|
/* Add cfs_rq with already running entity in the list */
|
||||||
@@ -4806,7 +4806,7 @@ static int tg_throttle_down(struct task_group *tg, void *data)
|
|||||||
|
|
||||||
/* group is entering throttled state, stop time */
|
/* group is entering throttled state, stop time */
|
||||||
if (!cfs_rq->throttle_count) {
|
if (!cfs_rq->throttle_count) {
|
||||||
cfs_rq->throttled_clock_pelt = rq_clock_pelt(rq);
|
cfs_rq->throttled_clock_pelt = rq_clock_task_mult(rq);
|
||||||
list_del_leaf_cfs_rq(cfs_rq);
|
list_del_leaf_cfs_rq(cfs_rq);
|
||||||
}
|
}
|
||||||
cfs_rq->throttle_count++;
|
cfs_rq->throttle_count++;
|
||||||
@@ -5224,7 +5224,7 @@ static void sync_throttle(struct task_group *tg, int cpu)
|
|||||||
pcfs_rq = tg->parent->cfs_rq[cpu];
|
pcfs_rq = tg->parent->cfs_rq[cpu];
|
||||||
|
|
||||||
cfs_rq->throttle_count = pcfs_rq->throttle_count;
|
cfs_rq->throttle_count = pcfs_rq->throttle_count;
|
||||||
cfs_rq->throttled_clock_pelt = rq_clock_pelt(cpu_rq(cpu));
|
cfs_rq->throttled_clock_pelt = rq_clock_task_mult(cpu_rq(cpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* conditionally throttle active cfs_rq's from put_prev_entity() */
|
/* conditionally throttle active cfs_rq's from put_prev_entity() */
|
||||||
|
@@ -531,3 +531,50 @@ int update_irq_load_avg(struct rq *rq, u64 running)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <trace/hooks/sched.h>
|
||||||
|
DEFINE_PER_CPU(u64, clock_task_mult);
|
||||||
|
|
||||||
|
unsigned int sysctl_sched_pelt_multiplier = 1;
|
||||||
|
__read_mostly unsigned int sched_pelt_lshift;
|
||||||
|
|
||||||
|
int sched_pelt_multiplier(struct ctl_table *table, int write, void *buffer,
|
||||||
|
size_t *lenp, loff_t *ppos)
|
||||||
|
{
|
||||||
|
static DEFINE_MUTEX(mutex);
|
||||||
|
unsigned int old;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&mutex);
|
||||||
|
|
||||||
|
old = sysctl_sched_pelt_multiplier;
|
||||||
|
ret = proc_dointvec(table, write, buffer, lenp, ppos);
|
||||||
|
if (ret)
|
||||||
|
goto undo;
|
||||||
|
if (!write)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
trace_android_vh_sched_pelt_multiplier(old, sysctl_sched_pelt_multiplier, &ret);
|
||||||
|
if (ret)
|
||||||
|
goto undo;
|
||||||
|
|
||||||
|
switch (sysctl_sched_pelt_multiplier) {
|
||||||
|
case 1:
|
||||||
|
fallthrough;
|
||||||
|
case 2:
|
||||||
|
fallthrough;
|
||||||
|
case 4:
|
||||||
|
WRITE_ONCE(sched_pelt_lshift,
|
||||||
|
sysctl_sched_pelt_multiplier >> 1);
|
||||||
|
goto done;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
undo:
|
||||||
|
sysctl_sched_pelt_multiplier = old;
|
||||||
|
done:
|
||||||
|
mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -61,6 +61,8 @@ static inline void cfs_se_util_change(struct sched_avg *avg)
|
|||||||
WRITE_ONCE(avg->util_est.enqueued, enqueued);
|
WRITE_ONCE(avg->util_est.enqueued, enqueued);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern unsigned int sched_pelt_lshift;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The clock_pelt scales the time to reflect the effective amount of
|
* The clock_pelt scales the time to reflect the effective amount of
|
||||||
* computation done during the running delta time but then sync back to
|
* computation done during the running delta time but then sync back to
|
||||||
@@ -75,9 +77,13 @@ static inline void cfs_se_util_change(struct sched_avg *avg)
|
|||||||
*/
|
*/
|
||||||
static inline void update_rq_clock_pelt(struct rq *rq, s64 delta)
|
static inline void update_rq_clock_pelt(struct rq *rq, s64 delta)
|
||||||
{
|
{
|
||||||
|
delta <<= READ_ONCE(sched_pelt_lshift);
|
||||||
|
|
||||||
|
per_cpu(clock_task_mult, rq->cpu) += delta;
|
||||||
|
|
||||||
if (unlikely(is_idle_task(rq->curr))) {
|
if (unlikely(is_idle_task(rq->curr))) {
|
||||||
/* The rq is idle, we can sync to clock_task */
|
/* The rq is idle, we can sync to clock_task */
|
||||||
rq->clock_pelt = rq_clock_task(rq);
|
rq->clock_pelt = rq_clock_task_mult(rq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +135,8 @@ static inline void update_idle_rq_clock_pelt(struct rq *rq)
|
|||||||
* rq's clock_task.
|
* rq's clock_task.
|
||||||
*/
|
*/
|
||||||
if (util_sum >= divider)
|
if (util_sum >= divider)
|
||||||
rq->lost_idle_time += rq_clock_task(rq) - rq->clock_pelt;
|
rq->lost_idle_time += rq_clock_task_mult(rq) -
|
||||||
|
rq->clock_pelt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u64 rq_clock_pelt(struct rq *rq)
|
static inline u64 rq_clock_pelt(struct rq *rq)
|
||||||
|
@@ -1193,6 +1193,16 @@ static inline u64 rq_clock_task(struct rq *rq)
|
|||||||
return rq->clock_task;
|
return rq->clock_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE_PER_CPU(u64, clock_task_mult);
|
||||||
|
|
||||||
|
static inline u64 rq_clock_task_mult(struct rq *rq)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&rq->lock);
|
||||||
|
assert_clock_updated(rq);
|
||||||
|
|
||||||
|
return per_cpu(clock_task_mult, cpu_of(rq));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By default the decay is the default pelt decay period.
|
* By default the decay is the default pelt decay period.
|
||||||
* The decay shift can change the decay period in
|
* The decay shift can change the decay period in
|
||||||
|
@@ -1832,6 +1832,15 @@ static struct ctl_table kern_table[] = {
|
|||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = sched_rr_handler,
|
.proc_handler = sched_rr_handler,
|
||||||
},
|
},
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
{
|
||||||
|
.procname = "sched_pelt_multiplier",
|
||||||
|
.data = &sysctl_sched_pelt_multiplier,
|
||||||
|
.maxlen = sizeof(unsigned int),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = sched_pelt_multiplier,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_UCLAMP_TASK
|
#ifdef CONFIG_UCLAMP_TASK
|
||||||
{
|
{
|
||||||
.procname = "sched_util_clamp_min",
|
.procname = "sched_util_clamp_min",
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
#include <linux/oom.h>
|
#include <linux/oom.h>
|
||||||
#include <linux/numa.h>
|
#include <linux/numa.h>
|
||||||
#include <linux/page_owner.h>
|
#include <linux/page_owner.h>
|
||||||
|
#include <trace/hooks/mm.h>
|
||||||
#include <asm/tlb.h>
|
#include <asm/tlb.h>
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@@ -2033,6 +2033,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
|||||||
bool young, write, soft_dirty, pmd_migration = false, uffd_wp = false;
|
bool young, write, soft_dirty, pmd_migration = false, uffd_wp = false;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
int i;
|
int i;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
VM_BUG_ON(haddr & ~HPAGE_PMD_MASK);
|
VM_BUG_ON(haddr & ~HPAGE_PMD_MASK);
|
||||||
VM_BUG_ON_VMA(vma->vm_start > haddr, vma);
|
VM_BUG_ON_VMA(vma->vm_start > haddr, vma);
|
||||||
@@ -2164,8 +2165,12 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
|||||||
pte = pte_offset_map(&_pmd, addr);
|
pte = pte_offset_map(&_pmd, addr);
|
||||||
BUG_ON(!pte_none(*pte));
|
BUG_ON(!pte_none(*pte));
|
||||||
set_pte_at(mm, addr, pte, entry);
|
set_pte_at(mm, addr, pte, entry);
|
||||||
if (!pmd_migration)
|
if (!pmd_migration) {
|
||||||
|
trace_android_vh_update_page_mapcount(&page[i], true,
|
||||||
|
false, NULL, &success);
|
||||||
|
if (!success)
|
||||||
atomic_inc(&page[i]._mapcount);
|
atomic_inc(&page[i]._mapcount);
|
||||||
|
}
|
||||||
pte_unmap(pte);
|
pte_unmap(pte);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2176,9 +2181,13 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
|||||||
*/
|
*/
|
||||||
if (compound_mapcount(page) > 1 &&
|
if (compound_mapcount(page) > 1 &&
|
||||||
!TestSetPageDoubleMap(page)) {
|
!TestSetPageDoubleMap(page)) {
|
||||||
for (i = 0; i < HPAGE_PMD_NR; i++)
|
for (i = 0; i < HPAGE_PMD_NR; i++) {
|
||||||
|
trace_android_vh_update_page_mapcount(&page[i], true,
|
||||||
|
false, NULL, &success);
|
||||||
|
if (!success)
|
||||||
atomic_inc(&page[i]._mapcount);
|
atomic_inc(&page[i]._mapcount);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lock_page_memcg(page);
|
lock_page_memcg(page);
|
||||||
if (atomic_add_negative(-1, compound_mapcount_ptr(page))) {
|
if (atomic_add_negative(-1, compound_mapcount_ptr(page))) {
|
||||||
@@ -2186,10 +2195,14 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
|||||||
__dec_lruvec_page_state(page, NR_ANON_THPS);
|
__dec_lruvec_page_state(page, NR_ANON_THPS);
|
||||||
if (TestClearPageDoubleMap(page)) {
|
if (TestClearPageDoubleMap(page)) {
|
||||||
/* No need in mapcount reference anymore */
|
/* No need in mapcount reference anymore */
|
||||||
for (i = 0; i < HPAGE_PMD_NR; i++)
|
for (i = 0; i < HPAGE_PMD_NR; i++) {
|
||||||
|
trace_android_vh_update_page_mapcount(&page[i],
|
||||||
|
false, false, NULL, &success);
|
||||||
|
if (!success)
|
||||||
atomic_dec(&page[i]._mapcount);
|
atomic_dec(&page[i]._mapcount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
unlock_page_memcg(page);
|
unlock_page_memcg(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1372,6 +1372,38 @@ out:
|
|||||||
return lruvec;
|
return lruvec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct lruvec *page_to_lruvec(struct page *page, pg_data_t *pgdat)
|
||||||
|
{
|
||||||
|
struct lruvec *lruvec;
|
||||||
|
|
||||||
|
lruvec = mem_cgroup_page_lruvec(page, pgdat);
|
||||||
|
|
||||||
|
return lruvec;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(page_to_lruvec);
|
||||||
|
|
||||||
|
void do_traversal_all_lruvec(void)
|
||||||
|
{
|
||||||
|
pg_data_t *pgdat;
|
||||||
|
|
||||||
|
for_each_online_pgdat(pgdat) {
|
||||||
|
struct mem_cgroup *memcg = NULL;
|
||||||
|
|
||||||
|
spin_lock_irq(&pgdat->lru_lock);
|
||||||
|
memcg = mem_cgroup_iter(NULL, NULL, NULL);
|
||||||
|
do {
|
||||||
|
struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat);
|
||||||
|
|
||||||
|
trace_android_vh_do_traversal_lruvec(lruvec);
|
||||||
|
|
||||||
|
memcg = mem_cgroup_iter(NULL, memcg, NULL);
|
||||||
|
} while (memcg);
|
||||||
|
|
||||||
|
spin_unlock_irq(&pgdat->lru_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(do_traversal_all_lruvec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mem_cgroup_update_lru_size - account for adding or removing an lru page
|
* mem_cgroup_update_lru_size - account for adding or removing an lru page
|
||||||
* @lruvec: mem_cgroup per zone lru vector
|
* @lruvec: mem_cgroup per zone lru vector
|
||||||
|
@@ -4794,7 +4794,9 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
|
|||||||
int no_progress_loops;
|
int no_progress_loops;
|
||||||
unsigned int cpuset_mems_cookie;
|
unsigned int cpuset_mems_cookie;
|
||||||
int reserve_flags;
|
int reserve_flags;
|
||||||
|
unsigned long vh_record;
|
||||||
|
|
||||||
|
trace_android_vh_alloc_pages_slowpath_begin(gfp_mask, order, &vh_record);
|
||||||
/*
|
/*
|
||||||
* We also sanity check to catch abuse of atomic reserves being used by
|
* We also sanity check to catch abuse of atomic reserves being used by
|
||||||
* callers that are not in atomic context.
|
* callers that are not in atomic context.
|
||||||
@@ -5036,6 +5038,7 @@ fail:
|
|||||||
warn_alloc(gfp_mask, ac->nodemask,
|
warn_alloc(gfp_mask, ac->nodemask,
|
||||||
"page allocation failure: order:%u", order);
|
"page allocation failure: order:%u", order);
|
||||||
got_pg:
|
got_pg:
|
||||||
|
trace_android_vh_alloc_pages_slowpath_end(gfp_mask, order, vh_record);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5647,6 +5650,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
|
|||||||
free_pcp,
|
free_pcp,
|
||||||
global_zone_page_state(NR_FREE_CMA_PAGES));
|
global_zone_page_state(NR_FREE_CMA_PAGES));
|
||||||
|
|
||||||
|
trace_android_vh_show_mapcount_pages(NULL);
|
||||||
for_each_online_pgdat(pgdat) {
|
for_each_online_pgdat(pgdat) {
|
||||||
if (show_mem_node_skip(filter, pgdat->node_id, nodemask))
|
if (show_mem_node_skip(filter, pgdat->node_id, nodemask))
|
||||||
continue;
|
continue;
|
||||||
|
73
mm/rmap.c
73
mm/rmap.c
@@ -525,6 +525,7 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
|
|||||||
struct anon_vma *anon_vma = NULL;
|
struct anon_vma *anon_vma = NULL;
|
||||||
struct anon_vma *root_anon_vma;
|
struct anon_vma *root_anon_vma;
|
||||||
unsigned long anon_mapping;
|
unsigned long anon_mapping;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
anon_mapping = (unsigned long)READ_ONCE(page->mapping);
|
anon_mapping = (unsigned long)READ_ONCE(page->mapping);
|
||||||
@@ -547,7 +548,11 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
|
|||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
trace_android_vh_do_page_trylock(page, NULL, NULL, &success);
|
||||||
|
if (success) {
|
||||||
|
anon_vma = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/* trylock failed, we got to sleep */
|
/* trylock failed, we got to sleep */
|
||||||
if (!atomic_inc_not_zero(&anon_vma->refcount)) {
|
if (!atomic_inc_not_zero(&anon_vma->refcount)) {
|
||||||
anon_vma = NULL;
|
anon_vma = NULL;
|
||||||
@@ -1113,6 +1118,7 @@ void do_page_add_anon_rmap(struct page *page,
|
|||||||
{
|
{
|
||||||
bool compound = flags & RMAP_COMPOUND;
|
bool compound = flags & RMAP_COMPOUND;
|
||||||
bool first;
|
bool first;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
if (unlikely(PageKsm(page)))
|
if (unlikely(PageKsm(page)))
|
||||||
lock_page_memcg(page);
|
lock_page_memcg(page);
|
||||||
@@ -1126,6 +1132,9 @@ void do_page_add_anon_rmap(struct page *page,
|
|||||||
mapcount = compound_mapcount_ptr(page);
|
mapcount = compound_mapcount_ptr(page);
|
||||||
first = atomic_inc_and_test(mapcount);
|
first = atomic_inc_and_test(mapcount);
|
||||||
} else {
|
} else {
|
||||||
|
trace_android_vh_update_page_mapcount(page, true, compound,
|
||||||
|
&first, &success);
|
||||||
|
if (!success)
|
||||||
first = atomic_inc_and_test(&page->_mapcount);
|
first = atomic_inc_and_test(&page->_mapcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1200,14 +1209,23 @@ void __page_add_new_anon_rmap(struct page *page,
|
|||||||
void page_add_file_rmap(struct page *page, bool compound)
|
void page_add_file_rmap(struct page *page, bool compound)
|
||||||
{
|
{
|
||||||
int i, nr = 1;
|
int i, nr = 1;
|
||||||
|
bool first_mapping;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
VM_BUG_ON_PAGE(compound && !PageTransHuge(page), page);
|
VM_BUG_ON_PAGE(compound && !PageTransHuge(page), page);
|
||||||
lock_page_memcg(page);
|
lock_page_memcg(page);
|
||||||
if (compound && PageTransHuge(page)) {
|
if (compound && PageTransHuge(page)) {
|
||||||
for (i = 0, nr = 0; i < thp_nr_pages(page); i++) {
|
for (i = 0, nr = 0; i < thp_nr_pages(page); i++) {
|
||||||
|
trace_android_vh_update_page_mapcount(&page[i], true,
|
||||||
|
compound, &first_mapping, &success);
|
||||||
|
if ((success)) {
|
||||||
|
if (first_mapping)
|
||||||
|
nr++;
|
||||||
|
} else {
|
||||||
if (atomic_inc_and_test(&page[i]._mapcount))
|
if (atomic_inc_and_test(&page[i]._mapcount))
|
||||||
nr++;
|
nr++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!atomic_inc_and_test(compound_mapcount_ptr(page)))
|
if (!atomic_inc_and_test(compound_mapcount_ptr(page)))
|
||||||
goto out;
|
goto out;
|
||||||
if (PageSwapBacked(page))
|
if (PageSwapBacked(page))
|
||||||
@@ -1222,9 +1240,16 @@ void page_add_file_rmap(struct page *page, bool compound)
|
|||||||
if (PageMlocked(page))
|
if (PageMlocked(page))
|
||||||
clear_page_mlock(compound_head(page));
|
clear_page_mlock(compound_head(page));
|
||||||
}
|
}
|
||||||
|
trace_android_vh_update_page_mapcount(page, true,
|
||||||
|
compound, &first_mapping, &success);
|
||||||
|
if (success) {
|
||||||
|
if (!first_mapping)
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
if (!atomic_inc_and_test(&page->_mapcount))
|
if (!atomic_inc_and_test(&page->_mapcount))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
__mod_lruvec_page_state(page, NR_FILE_MAPPED, nr);
|
__mod_lruvec_page_state(page, NR_FILE_MAPPED, nr);
|
||||||
out:
|
out:
|
||||||
unlock_page_memcg(page);
|
unlock_page_memcg(page);
|
||||||
@@ -1233,6 +1258,8 @@ out:
|
|||||||
static void page_remove_file_rmap(struct page *page, bool compound)
|
static void page_remove_file_rmap(struct page *page, bool compound)
|
||||||
{
|
{
|
||||||
int i, nr = 1;
|
int i, nr = 1;
|
||||||
|
bool first_mapping;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
VM_BUG_ON_PAGE(compound && !PageHead(page), page);
|
VM_BUG_ON_PAGE(compound && !PageHead(page), page);
|
||||||
|
|
||||||
@@ -1246,19 +1273,33 @@ static void page_remove_file_rmap(struct page *page, bool compound)
|
|||||||
/* page still mapped by someone else? */
|
/* page still mapped by someone else? */
|
||||||
if (compound && PageTransHuge(page)) {
|
if (compound && PageTransHuge(page)) {
|
||||||
for (i = 0, nr = 0; i < thp_nr_pages(page); i++) {
|
for (i = 0, nr = 0; i < thp_nr_pages(page); i++) {
|
||||||
|
trace_android_vh_update_page_mapcount(&page[i], false,
|
||||||
|
compound, &first_mapping, &success);
|
||||||
|
if (success) {
|
||||||
|
if (first_mapping)
|
||||||
|
nr++;
|
||||||
|
} else {
|
||||||
if (atomic_add_negative(-1, &page[i]._mapcount))
|
if (atomic_add_negative(-1, &page[i]._mapcount))
|
||||||
nr++;
|
nr++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!atomic_add_negative(-1, compound_mapcount_ptr(page)))
|
if (!atomic_add_negative(-1, compound_mapcount_ptr(page)))
|
||||||
return;
|
return;
|
||||||
if (PageSwapBacked(page))
|
if (PageSwapBacked(page))
|
||||||
__dec_node_page_state(page, NR_SHMEM_PMDMAPPED);
|
__dec_node_page_state(page, NR_SHMEM_PMDMAPPED);
|
||||||
else
|
else
|
||||||
__dec_node_page_state(page, NR_FILE_PMDMAPPED);
|
__dec_node_page_state(page, NR_FILE_PMDMAPPED);
|
||||||
|
} else {
|
||||||
|
trace_android_vh_update_page_mapcount(page, false,
|
||||||
|
compound, &first_mapping, &success);
|
||||||
|
if (success) {
|
||||||
|
if (!first_mapping)
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!atomic_add_negative(-1, &page->_mapcount))
|
if (!atomic_add_negative(-1, &page->_mapcount))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use the irq-unsafe __{inc|mod}_lruvec_page_state because
|
* We use the irq-unsafe __{inc|mod}_lruvec_page_state because
|
||||||
@@ -1274,6 +1315,8 @@ static void page_remove_file_rmap(struct page *page, bool compound)
|
|||||||
static void page_remove_anon_compound_rmap(struct page *page)
|
static void page_remove_anon_compound_rmap(struct page *page)
|
||||||
{
|
{
|
||||||
int i, nr;
|
int i, nr;
|
||||||
|
bool first_mapping;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
if (!atomic_add_negative(-1, compound_mapcount_ptr(page)))
|
if (!atomic_add_negative(-1, compound_mapcount_ptr(page)))
|
||||||
return;
|
return;
|
||||||
@@ -1293,9 +1336,16 @@ static void page_remove_anon_compound_rmap(struct page *page)
|
|||||||
* them are still mapped.
|
* them are still mapped.
|
||||||
*/
|
*/
|
||||||
for (i = 0, nr = 0; i < thp_nr_pages(page); i++) {
|
for (i = 0, nr = 0; i < thp_nr_pages(page); i++) {
|
||||||
|
trace_android_vh_update_page_mapcount(&page[i], false,
|
||||||
|
false, &first_mapping, &success);
|
||||||
|
if (success) {
|
||||||
|
if (first_mapping)
|
||||||
|
nr++;
|
||||||
|
} else {
|
||||||
if (atomic_add_negative(-1, &page[i]._mapcount))
|
if (atomic_add_negative(-1, &page[i]._mapcount))
|
||||||
nr++;
|
nr++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queue the page for deferred split if at least one small
|
* Queue the page for deferred split if at least one small
|
||||||
@@ -1324,6 +1374,8 @@ static void page_remove_anon_compound_rmap(struct page *page)
|
|||||||
*/
|
*/
|
||||||
void page_remove_rmap(struct page *page, bool compound)
|
void page_remove_rmap(struct page *page, bool compound)
|
||||||
{
|
{
|
||||||
|
bool first_mapping;
|
||||||
|
bool success = false;
|
||||||
lock_page_memcg(page);
|
lock_page_memcg(page);
|
||||||
|
|
||||||
if (!PageAnon(page)) {
|
if (!PageAnon(page)) {
|
||||||
@@ -1336,10 +1388,16 @@ void page_remove_rmap(struct page *page, bool compound)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace_android_vh_update_page_mapcount(page, false,
|
||||||
|
compound, &first_mapping, &success);
|
||||||
|
if (success) {
|
||||||
|
if (!first_mapping)
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
/* page still mapped by someone else? */
|
/* page still mapped by someone else? */
|
||||||
if (!atomic_add_negative(-1, &page->_mapcount))
|
if (!atomic_add_negative(-1, &page->_mapcount))
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* We use the irq-unsafe __{inc|mod}_zone_page_stat because
|
* We use the irq-unsafe __{inc|mod}_zone_page_stat because
|
||||||
* these counters are not modified in interrupt context, and
|
* these counters are not modified in interrupt context, and
|
||||||
@@ -1928,6 +1986,7 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc,
|
|||||||
struct address_space *mapping = page_mapping(page);
|
struct address_space *mapping = page_mapping(page);
|
||||||
pgoff_t pgoff_start, pgoff_end;
|
pgoff_t pgoff_start, pgoff_end;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
|
bool got_lock = false, success = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The page lock not only makes sure that page->mapping cannot
|
* The page lock not only makes sure that page->mapping cannot
|
||||||
@@ -1942,8 +2001,16 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc,
|
|||||||
|
|
||||||
pgoff_start = page_to_pgoff(page);
|
pgoff_start = page_to_pgoff(page);
|
||||||
pgoff_end = pgoff_start + thp_nr_pages(page) - 1;
|
pgoff_end = pgoff_start + thp_nr_pages(page) - 1;
|
||||||
if (!locked)
|
if (!locked) {
|
||||||
|
trace_android_vh_do_page_trylock(page,
|
||||||
|
&mapping->i_mmap_rwsem, &got_lock, &success);
|
||||||
|
if (success) {
|
||||||
|
if (!got_lock)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
i_mmap_lock_read(mapping);
|
i_mmap_lock_read(mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
vma_interval_tree_foreach(vma, &mapping->i_mmap,
|
vma_interval_tree_foreach(vma, &mapping->i_mmap,
|
||||||
pgoff_start, pgoff_end) {
|
pgoff_start, pgoff_end) {
|
||||||
unsigned long address = vma_address(page, vma);
|
unsigned long address = vma_address(page, vma);
|
||||||
|
@@ -46,6 +46,7 @@
|
|||||||
|
|
||||||
#undef CREATE_TRACE_POINTS
|
#undef CREATE_TRACE_POINTS
|
||||||
#include <trace/hooks/shmem_fs.h>
|
#include <trace/hooks/shmem_fs.h>
|
||||||
|
#include <trace/hooks/mm.h>
|
||||||
|
|
||||||
static struct vfsmount *shm_mnt;
|
static struct vfsmount *shm_mnt;
|
||||||
|
|
||||||
@@ -1430,6 +1431,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
|
|||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace_android_vh_set_shmem_page_flag(page);
|
||||||
swap = get_swap_page(page);
|
swap = get_swap_page(page);
|
||||||
if (!swap.val)
|
if (!swap.val)
|
||||||
goto redirty;
|
goto redirty;
|
||||||
@@ -4311,7 +4313,6 @@ int reclaim_shmem_address_space(struct address_space *mapping)
|
|||||||
pgoff_t start = 0;
|
pgoff_t start = 0;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
LIST_HEAD(page_list);
|
LIST_HEAD(page_list);
|
||||||
int reclaimed;
|
|
||||||
XA_STATE(xas, &mapping->i_pages, start);
|
XA_STATE(xas, &mapping->i_pages, start);
|
||||||
|
|
||||||
if (!shmem_mapping(mapping))
|
if (!shmem_mapping(mapping))
|
||||||
@@ -4329,8 +4330,6 @@ int reclaim_shmem_address_space(struct address_space *mapping)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
list_add(&page->lru, &page_list);
|
list_add(&page->lru, &page_list);
|
||||||
inc_node_page_state(page, NR_ISOLATED_ANON +
|
|
||||||
page_is_file_lru(page));
|
|
||||||
|
|
||||||
if (need_resched()) {
|
if (need_resched()) {
|
||||||
xas_pause(&xas);
|
xas_pause(&xas);
|
||||||
@@ -4338,9 +4337,8 @@ int reclaim_shmem_address_space(struct address_space *mapping)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
reclaimed = reclaim_pages_from_list(&page_list);
|
|
||||||
|
|
||||||
return reclaimed;
|
return reclaim_pages(&page_list);
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -437,6 +437,7 @@ void mark_page_accessed(struct page *page)
|
|||||||
{
|
{
|
||||||
page = compound_head(page);
|
page = compound_head(page);
|
||||||
|
|
||||||
|
trace_android_vh_mark_page_accessed(page);
|
||||||
if (!PageReferenced(page)) {
|
if (!PageReferenced(page)) {
|
||||||
SetPageReferenced(page);
|
SetPageReferenced(page);
|
||||||
} else if (PageUnevictable(page)) {
|
} else if (PageUnevictable(page)) {
|
||||||
|
@@ -2170,6 +2170,7 @@ struct vm_struct *remove_vm_area(const void *addr)
|
|||||||
if (va && va->vm) {
|
if (va && va->vm) {
|
||||||
struct vm_struct *vm = va->vm;
|
struct vm_struct *vm = va->vm;
|
||||||
|
|
||||||
|
trace_android_vh_remove_vmalloc_stack(vm);
|
||||||
va->vm = NULL;
|
va->vm = NULL;
|
||||||
spin_unlock(&vmap_area_lock);
|
spin_unlock(&vmap_area_lock);
|
||||||
|
|
||||||
|
64
mm/vmscan.c
64
mm/vmscan.c
@@ -1020,11 +1020,20 @@ static enum page_references page_check_references(struct page *page,
|
|||||||
{
|
{
|
||||||
int referenced_ptes, referenced_page;
|
int referenced_ptes, referenced_page;
|
||||||
unsigned long vm_flags;
|
unsigned long vm_flags;
|
||||||
|
bool should_protect = false;
|
||||||
|
bool trylock_fail = false;
|
||||||
|
|
||||||
|
trace_android_vh_page_should_be_protected(page, &should_protect);
|
||||||
|
if (unlikely(should_protect))
|
||||||
|
return PAGEREF_ACTIVATE;
|
||||||
|
|
||||||
|
trace_android_vh_page_trylock_set(page);
|
||||||
referenced_ptes = page_referenced(page, 1, sc->target_mem_cgroup,
|
referenced_ptes = page_referenced(page, 1, sc->target_mem_cgroup,
|
||||||
&vm_flags);
|
&vm_flags);
|
||||||
referenced_page = TestClearPageReferenced(page);
|
referenced_page = TestClearPageReferenced(page);
|
||||||
|
trace_android_vh_page_trylock_get_result(page, &trylock_fail);
|
||||||
|
if (trylock_fail)
|
||||||
|
return PAGEREF_KEEP;
|
||||||
/*
|
/*
|
||||||
* Mlock lost the isolation race with us. Let try_to_unmap()
|
* Mlock lost the isolation race with us. Let try_to_unmap()
|
||||||
* move the page to the unevictable list.
|
* move the page to the unevictable list.
|
||||||
@@ -1336,6 +1345,7 @@ static unsigned int shrink_page_list(struct list_head *page_list,
|
|||||||
if (unlikely(PageTransHuge(page)))
|
if (unlikely(PageTransHuge(page)))
|
||||||
flags |= TTU_SPLIT_HUGE_PMD;
|
flags |= TTU_SPLIT_HUGE_PMD;
|
||||||
|
|
||||||
|
trace_android_vh_page_trylock_set(page);
|
||||||
if (!try_to_unmap(page, flags)) {
|
if (!try_to_unmap(page, flags)) {
|
||||||
stat->nr_unmap_fail += nr_pages;
|
stat->nr_unmap_fail += nr_pages;
|
||||||
if (!was_swapbacked && PageSwapBacked(page))
|
if (!was_swapbacked && PageSwapBacked(page))
|
||||||
@@ -1446,6 +1456,7 @@ static unsigned int shrink_page_list(struct list_head *page_list,
|
|||||||
* increment nr_reclaimed here (and
|
* increment nr_reclaimed here (and
|
||||||
* leave it off the LRU).
|
* leave it off the LRU).
|
||||||
*/
|
*/
|
||||||
|
trace_android_vh_page_trylock_clear(page);
|
||||||
nr_reclaimed++;
|
nr_reclaimed++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1481,8 +1492,10 @@ free_it:
|
|||||||
*/
|
*/
|
||||||
if (unlikely(PageTransHuge(page)))
|
if (unlikely(PageTransHuge(page)))
|
||||||
destroy_compound_page(page);
|
destroy_compound_page(page);
|
||||||
else
|
else {
|
||||||
|
trace_android_vh_page_trylock_clear(page);
|
||||||
list_add(&page->lru, &free_pages);
|
list_add(&page->lru, &free_pages);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
activate_locked_split:
|
activate_locked_split:
|
||||||
@@ -1564,36 +1577,6 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
|
|||||||
return nr_reclaimed;
|
return nr_reclaimed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int reclaim_pages_from_list(struct list_head *page_list)
|
|
||||||
{
|
|
||||||
struct scan_control sc = {
|
|
||||||
.gfp_mask = GFP_KERNEL,
|
|
||||||
.priority = DEF_PRIORITY,
|
|
||||||
.may_writepage = 1,
|
|
||||||
.may_unmap = 1,
|
|
||||||
.may_swap = 1,
|
|
||||||
};
|
|
||||||
unsigned long nr_reclaimed;
|
|
||||||
struct reclaim_stat dummy_stat;
|
|
||||||
struct page *page;
|
|
||||||
|
|
||||||
list_for_each_entry(page, page_list, lru)
|
|
||||||
ClearPageActive(page);
|
|
||||||
|
|
||||||
nr_reclaimed = shrink_page_list(page_list, NULL, &sc,
|
|
||||||
&dummy_stat, false);
|
|
||||||
while (!list_empty(page_list)) {
|
|
||||||
|
|
||||||
page = lru_to_page(page_list);
|
|
||||||
list_del(&page->lru);
|
|
||||||
dec_node_page_state(page, NR_ISOLATED_ANON +
|
|
||||||
page_is_file_lru(page));
|
|
||||||
putback_lru_page(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nr_reclaimed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to remove the specified page from its LRU. Only take this page
|
* Attempt to remove the specified page from its LRU. Only take this page
|
||||||
* if it is of the appropriate PageActive status. Pages which are being
|
* if it is of the appropriate PageActive status. Pages which are being
|
||||||
@@ -1757,6 +1740,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
|
|||||||
case 0:
|
case 0:
|
||||||
nr_taken += nr_pages;
|
nr_taken += nr_pages;
|
||||||
nr_zone_taken[page_zonenum(page)] += nr_pages;
|
nr_zone_taken[page_zonenum(page)] += nr_pages;
|
||||||
|
trace_android_vh_del_page_from_lrulist(page, false, lru);
|
||||||
list_move(&page->lru, dst);
|
list_move(&page->lru, dst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1931,6 +1915,7 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec,
|
|||||||
nr_pages = thp_nr_pages(page);
|
nr_pages = thp_nr_pages(page);
|
||||||
update_lru_size(lruvec, lru, page_zonenum(page), nr_pages);
|
update_lru_size(lruvec, lru, page_zonenum(page), nr_pages);
|
||||||
list_move(&page->lru, &lruvec->lists[lru]);
|
list_move(&page->lru, &lruvec->lists[lru]);
|
||||||
|
trace_android_vh_add_page_to_lrulist(page, false, lru);
|
||||||
|
|
||||||
if (put_page_testzero(page)) {
|
if (put_page_testzero(page)) {
|
||||||
__ClearPageLRU(page);
|
__ClearPageLRU(page);
|
||||||
@@ -2022,6 +2007,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nr_reclaimed = shrink_page_list(&page_list, pgdat, sc, &stat, false);
|
nr_reclaimed = shrink_page_list(&page_list, pgdat, sc, &stat, false);
|
||||||
|
trace_android_vh_handle_failed_page_trylock(&page_list);
|
||||||
|
|
||||||
spin_lock_irq(&pgdat->lru_lock);
|
spin_lock_irq(&pgdat->lru_lock);
|
||||||
|
|
||||||
@@ -2034,7 +2020,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
|
|||||||
__count_vm_events(item, nr_reclaimed);
|
__count_vm_events(item, nr_reclaimed);
|
||||||
__count_memcg_events(lruvec_memcg(lruvec), item, nr_reclaimed);
|
__count_memcg_events(lruvec_memcg(lruvec), item, nr_reclaimed);
|
||||||
__count_vm_events(PGSTEAL_ANON + file, nr_reclaimed);
|
__count_vm_events(PGSTEAL_ANON + file, nr_reclaimed);
|
||||||
|
|
||||||
spin_unlock_irq(&pgdat->lru_lock);
|
spin_unlock_irq(&pgdat->lru_lock);
|
||||||
|
|
||||||
mem_cgroup_uncharge_list(&page_list);
|
mem_cgroup_uncharge_list(&page_list);
|
||||||
@@ -2085,6 +2070,7 @@ static void shrink_active_list(unsigned long nr_to_scan,
|
|||||||
int file = is_file_lru(lru);
|
int file = is_file_lru(lru);
|
||||||
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
||||||
bool bypass = false;
|
bool bypass = false;
|
||||||
|
bool should_protect = false;
|
||||||
|
|
||||||
lru_add_drain();
|
lru_add_drain();
|
||||||
|
|
||||||
@@ -2119,10 +2105,17 @@ static void shrink_active_list(unsigned long nr_to_scan,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace_android_vh_page_should_be_protected(page, &should_protect);
|
||||||
|
if (unlikely(should_protect)) {
|
||||||
|
nr_rotated += thp_nr_pages(page);
|
||||||
|
list_add(&page->lru, &l_active);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
trace_android_vh_page_referenced_check_bypass(page, nr_to_scan, lru, &bypass);
|
trace_android_vh_page_referenced_check_bypass(page, nr_to_scan, lru, &bypass);
|
||||||
if (bypass)
|
if (bypass)
|
||||||
goto skip_page_referenced;
|
goto skip_page_referenced;
|
||||||
|
trace_android_vh_page_trylock_set(page);
|
||||||
if (page_referenced(page, 0, sc->target_mem_cgroup,
|
if (page_referenced(page, 0, sc->target_mem_cgroup,
|
||||||
&vm_flags)) {
|
&vm_flags)) {
|
||||||
/*
|
/*
|
||||||
@@ -2135,11 +2128,13 @@ static void shrink_active_list(unsigned long nr_to_scan,
|
|||||||
* so we ignore them here.
|
* so we ignore them here.
|
||||||
*/
|
*/
|
||||||
if ((vm_flags & VM_EXEC) && page_is_file_lru(page)) {
|
if ((vm_flags & VM_EXEC) && page_is_file_lru(page)) {
|
||||||
|
trace_android_vh_page_trylock_clear(page);
|
||||||
nr_rotated += thp_nr_pages(page);
|
nr_rotated += thp_nr_pages(page);
|
||||||
list_add(&page->lru, &l_active);
|
list_add(&page->lru, &l_active);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
trace_android_vh_page_trylock_clear(page);
|
||||||
skip_page_referenced:
|
skip_page_referenced:
|
||||||
ClearPageActive(page); /* we are de-activating */
|
ClearPageActive(page); /* we are de-activating */
|
||||||
SetPageWorkingset(page);
|
SetPageWorkingset(page);
|
||||||
@@ -2221,6 +2216,7 @@ unsigned long reclaim_pages(struct list_head *page_list)
|
|||||||
|
|
||||||
return nr_reclaimed;
|
return nr_reclaimed;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(reclaim_pages);
|
||||||
|
|
||||||
static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
|
static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
|
||||||
struct lruvec *lruvec, struct scan_control *sc)
|
struct lruvec *lruvec, struct scan_control *sc)
|
||||||
|
@@ -9,14 +9,51 @@
|
|||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
#include <sound/pcm_iec958.h>
|
#include <sound/pcm_iec958.h>
|
||||||
|
|
||||||
static int create_iec958_consumer(uint rate, uint sample_width,
|
/**
|
||||||
u8 *cs, size_t len)
|
* snd_pcm_create_iec958_consumer_default - create default consumer format IEC958 channel status
|
||||||
|
* @cs: channel status buffer, at least four bytes
|
||||||
|
* @len: length of channel status buffer
|
||||||
|
*
|
||||||
|
* Create the consumer format channel status data in @cs of maximum size
|
||||||
|
* @len. When relevant, the configuration-dependant bits will be set as
|
||||||
|
* unspecified.
|
||||||
|
*
|
||||||
|
* Drivers should then call einter snd_pcm_fill_iec958_consumer() or
|
||||||
|
* snd_pcm_fill_iec958_consumer_hw_params() to replace these unspecified
|
||||||
|
* bits by their actual values.
|
||||||
|
*
|
||||||
|
* Drivers may wish to tweak the contents of the buffer after creation.
|
||||||
|
*
|
||||||
|
* Returns: length of buffer, or negative error code if something failed.
|
||||||
|
*/
|
||||||
|
int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len)
|
||||||
{
|
{
|
||||||
unsigned int fs, ws;
|
|
||||||
|
|
||||||
if (len < 4)
|
if (len < 4)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(cs, 0, len);
|
||||||
|
|
||||||
|
cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
|
||||||
|
cs[1] = IEC958_AES1_CON_GENERAL;
|
||||||
|
cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
|
||||||
|
cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID;
|
||||||
|
|
||||||
|
if (len > 4)
|
||||||
|
cs[4] = IEC958_AES4_CON_WORDLEN_NOTID;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_pcm_create_iec958_consumer_default);
|
||||||
|
|
||||||
|
static int fill_iec958_consumer(uint rate, uint sample_width,
|
||||||
|
u8 *cs, size_t len)
|
||||||
|
{
|
||||||
|
if (len < 4)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((cs[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) {
|
||||||
|
unsigned int fs;
|
||||||
|
|
||||||
switch (rate) {
|
switch (rate) {
|
||||||
case 32000:
|
case 32000:
|
||||||
fs = IEC958_AES3_CON_FS_32000;
|
fs = IEC958_AES3_CON_FS_32000;
|
||||||
@@ -43,7 +80,14 @@ static int create_iec958_consumer(uint rate, uint sample_width,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > 4) {
|
cs[3] &= ~IEC958_AES3_CON_FS;
|
||||||
|
cs[3] |= fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 4 &&
|
||||||
|
(cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
|
||||||
|
unsigned int ws;
|
||||||
|
|
||||||
switch (sample_width) {
|
switch (sample_width) {
|
||||||
case 16:
|
case 16:
|
||||||
ws = IEC958_AES4_CON_WORDLEN_20_16;
|
ws = IEC958_AES4_CON_WORDLEN_20_16;
|
||||||
@@ -64,21 +108,58 @@ static int create_iec958_consumer(uint rate, uint sample_width,
|
|||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cs[4] &= ~IEC958_AES4_CON_WORDLEN;
|
||||||
|
cs[4] |= ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(cs, 0, len);
|
|
||||||
|
|
||||||
cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
|
|
||||||
cs[1] = IEC958_AES1_CON_GENERAL;
|
|
||||||
cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
|
|
||||||
cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
|
|
||||||
|
|
||||||
if (len > 4)
|
|
||||||
cs[4] = ws;
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_pcm_fill_iec958_consumer - Fill consumer format IEC958 channel status
|
||||||
|
* @runtime: pcm runtime structure with ->rate filled in
|
||||||
|
* @cs: channel status buffer, at least four bytes
|
||||||
|
* @len: length of channel status buffer
|
||||||
|
*
|
||||||
|
* Fill the unspecified bits in an IEC958 status bits array using the
|
||||||
|
* parameters of the PCM runtime @runtime.
|
||||||
|
*
|
||||||
|
* Drivers may wish to tweak the contents of the buffer after its been
|
||||||
|
* filled.
|
||||||
|
*
|
||||||
|
* Returns: length of buffer, or negative error code if something failed.
|
||||||
|
*/
|
||||||
|
int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime,
|
||||||
|
u8 *cs, size_t len)
|
||||||
|
{
|
||||||
|
return fill_iec958_consumer(runtime->rate,
|
||||||
|
snd_pcm_format_width(runtime->format),
|
||||||
|
cs, len);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_pcm_fill_iec958_consumer_hw_params - Fill consumer format IEC958 channel status
|
||||||
|
* @params: the hw_params instance for extracting rate and sample format
|
||||||
|
* @cs: channel status buffer, at least four bytes
|
||||||
|
* @len: length of channel status buffer
|
||||||
|
*
|
||||||
|
* Fill the unspecified bits in an IEC958 status bits array using the
|
||||||
|
* parameters of the PCM hardware parameters @params.
|
||||||
|
*
|
||||||
|
* Drivers may wish to tweak the contents of the buffer after its been
|
||||||
|
* filled..
|
||||||
|
*
|
||||||
|
* Returns: length of buffer, or negative error code if something failed.
|
||||||
|
*/
|
||||||
|
int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
|
||||||
|
u8 *cs, size_t len)
|
||||||
|
{
|
||||||
|
return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer_hw_params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
|
* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
|
||||||
* @runtime: pcm runtime structure with ->rate filled in
|
* @runtime: pcm runtime structure with ->rate filled in
|
||||||
@@ -95,9 +176,13 @@ static int create_iec958_consumer(uint rate, uint sample_width,
|
|||||||
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
|
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
return create_iec958_consumer(runtime->rate,
|
int ret;
|
||||||
snd_pcm_format_width(runtime->format),
|
|
||||||
cs, len);
|
ret = snd_pcm_create_iec958_consumer_default(cs, len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return snd_pcm_fill_iec958_consumer(runtime, cs, len);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
|
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
|
||||||
|
|
||||||
@@ -117,7 +202,12 @@ EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
|
|||||||
int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
|
int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
|
||||||
u8 *cs, size_t len)
|
u8 *cs, size_t len)
|
||||||
{
|
{
|
||||||
return create_iec958_consumer(params_rate(params), params_width(params),
|
int ret;
|
||||||
cs, len);
|
|
||||||
|
ret = snd_pcm_create_iec958_consumer_default(cs, len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
|
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
|
||||||
|
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
struct hdmi_codec_channel_map_table {
|
struct hdmi_codec_channel_map_table {
|
||||||
unsigned char map; /* ALSA API channel map position */
|
unsigned char map; /* ALSA API channel map position */
|
||||||
unsigned long spk_mask; /* speaker position bit mask */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -278,10 +277,12 @@ struct hdmi_codec_priv {
|
|||||||
bool busy;
|
bool busy;
|
||||||
struct snd_soc_jack *jack;
|
struct snd_soc_jack *jack;
|
||||||
unsigned int jack_status;
|
unsigned int jack_status;
|
||||||
|
u8 iec_status[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
|
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
|
||||||
SND_SOC_DAPM_OUTPUT("TX"),
|
SND_SOC_DAPM_OUTPUT("TX"),
|
||||||
|
SND_SOC_DAPM_OUTPUT("RX"),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -385,10 +386,52 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hdmi_codec_iec958_info(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
|
{
|
||||||
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
|
||||||
|
uinfo->count = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdmi_codec_iec958_default_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
|
||||||
|
|
||||||
|
memcpy(ucontrol->value.iec958.status, hcp->iec_status,
|
||||||
|
sizeof(hcp->iec_status));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdmi_codec_iec958_default_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
|
||||||
|
|
||||||
|
memcpy(hcp->iec_status, ucontrol->value.iec958.status,
|
||||||
|
sizeof(hcp->iec_status));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdmi_codec_iec958_mask_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
memset(ucontrol->value.iec958.status, 0xff,
|
||||||
|
sizeof_field(struct hdmi_codec_priv, iec_status));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int hdmi_codec_startup(struct snd_pcm_substream *substream,
|
static int hdmi_codec_startup(struct snd_pcm_substream *substream,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
||||||
|
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&hcp->lock);
|
mutex_lock(&hcp->lock);
|
||||||
@@ -404,7 +447,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hcp->hcd.ops->get_eld) {
|
if (tx && hcp->hcd.ops->get_eld) {
|
||||||
ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data,
|
ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data,
|
||||||
hcp->eld, sizeof(hcp->eld));
|
hcp->eld, sizeof(hcp->eld));
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -438,6 +481,42 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
|
|||||||
mutex_unlock(&hcp->lock);
|
mutex_unlock(&hcp->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hdmi_codec_fill_codec_params(struct snd_soc_dai *dai,
|
||||||
|
unsigned int sample_width,
|
||||||
|
unsigned int sample_rate,
|
||||||
|
unsigned int channels,
|
||||||
|
struct hdmi_codec_params *hp)
|
||||||
|
{
|
||||||
|
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
/* Select a channel allocation that matches with ELD and pcm channels */
|
||||||
|
idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
|
||||||
|
if (idx < 0) {
|
||||||
|
dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
|
||||||
|
idx);
|
||||||
|
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(hp, 0, sizeof(*hp));
|
||||||
|
|
||||||
|
hdmi_audio_infoframe_init(&hp->cea);
|
||||||
|
hp->cea.channels = channels;
|
||||||
|
hp->cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
|
||||||
|
hp->cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
|
||||||
|
hp->cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
|
||||||
|
hp->cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
|
||||||
|
|
||||||
|
hp->sample_width = sample_width;
|
||||||
|
hp->sample_rate = sample_rate;
|
||||||
|
hp->channels = channels;
|
||||||
|
|
||||||
|
hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
|
static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_hw_params *params,
|
struct snd_pcm_hw_params *params,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
@@ -452,13 +531,25 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
|
|||||||
.dig_subframe = { 0 },
|
.dig_subframe = { 0 },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
int ret, idx;
|
int ret;
|
||||||
|
|
||||||
|
if (!hcp->hcd.ops->hw_params)
|
||||||
|
return 0;
|
||||||
|
|
||||||
dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
|
dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
|
||||||
params_width(params), params_rate(params),
|
params_width(params), params_rate(params),
|
||||||
params_channels(params));
|
params_channels(params));
|
||||||
|
|
||||||
ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status,
|
ret = hdmi_codec_fill_codec_params(dai,
|
||||||
|
params_width(params),
|
||||||
|
params_rate(params),
|
||||||
|
params_channels(params),
|
||||||
|
&hp);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
memcpy(hp.iec.status, hcp->iec_status, sizeof(hp.iec.status));
|
||||||
|
ret = snd_pcm_fill_iec958_consumer_hw_params(params, hp.iec.status,
|
||||||
sizeof(hp.iec.status));
|
sizeof(hp.iec.status));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
|
dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
|
||||||
@@ -466,31 +557,47 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdmi_audio_infoframe_init(&hp.cea);
|
cf->bit_fmt = params_format(params);
|
||||||
hp.cea.channels = params_channels(params);
|
|
||||||
hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
|
|
||||||
hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
|
|
||||||
hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
|
|
||||||
|
|
||||||
/* Select a channel allocation that matches with ELD and pcm channels */
|
|
||||||
idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels);
|
|
||||||
if (idx < 0) {
|
|
||||||
dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
|
|
||||||
idx);
|
|
||||||
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
|
|
||||||
hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
|
|
||||||
|
|
||||||
hp.sample_width = params_width(params);
|
|
||||||
hp.sample_rate = params_rate(params);
|
|
||||||
hp.channels = params_channels(params);
|
|
||||||
|
|
||||||
return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
|
return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
|
||||||
cf, &hp);
|
cf, &hp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hdmi_codec_prepare(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
||||||
|
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
|
||||||
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
unsigned int channels = runtime->channels;
|
||||||
|
unsigned int width = snd_pcm_format_width(runtime->format);
|
||||||
|
unsigned int rate = runtime->rate;
|
||||||
|
struct hdmi_codec_params hp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!hcp->hcd.ops->prepare)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
|
||||||
|
width, rate, channels);
|
||||||
|
|
||||||
|
ret = hdmi_codec_fill_codec_params(dai, width, rate, channels, &hp);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
memcpy(hp.iec.status, hcp->iec_status, sizeof(hp.iec.status));
|
||||||
|
ret = snd_pcm_fill_iec958_consumer(runtime, hp.iec.status,
|
||||||
|
sizeof(hp.iec.status));
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cf->bit_fmt = runtime->format;
|
||||||
|
return hcp->hcd.ops->prepare(dai->dev->parent, hcp->hcd.data,
|
||||||
|
cf, &hp);
|
||||||
|
}
|
||||||
|
|
||||||
static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai,
|
static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
unsigned int fmt)
|
unsigned int fmt)
|
||||||
{
|
{
|
||||||
@@ -582,6 +689,7 @@ static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = {
|
|||||||
.startup = hdmi_codec_startup,
|
.startup = hdmi_codec_startup,
|
||||||
.shutdown = hdmi_codec_shutdown,
|
.shutdown = hdmi_codec_shutdown,
|
||||||
.hw_params = hdmi_codec_hw_params,
|
.hw_params = hdmi_codec_hw_params,
|
||||||
|
.prepare = hdmi_codec_prepare,
|
||||||
.set_fmt = hdmi_codec_i2s_set_fmt,
|
.set_fmt = hdmi_codec_i2s_set_fmt,
|
||||||
.mute_stream = hdmi_codec_mute,
|
.mute_stream = hdmi_codec_mute,
|
||||||
};
|
};
|
||||||
@@ -615,23 +723,40 @@ static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
|
|||||||
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
|
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
|
||||||
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
|
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
|
||||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
|
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
|
||||||
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
|
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\
|
||||||
|
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
|
||||||
|
|
||||||
|
static struct snd_kcontrol_new hdmi_codec_controls[] = {
|
||||||
|
{
|
||||||
|
.access = SNDRV_CTL_ELEM_ACCESS_READ,
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||||
|
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
|
||||||
|
.info = hdmi_codec_iec958_info,
|
||||||
|
.get = hdmi_codec_iec958_mask_get,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||||
|
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
|
||||||
|
.info = hdmi_codec_iec958_info,
|
||||||
|
.get = hdmi_codec_iec958_default_get,
|
||||||
|
.put = hdmi_codec_iec958_default_put,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.access = (SNDRV_CTL_ELEM_ACCESS_READ |
|
||||||
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE),
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||||
|
.name = "ELD",
|
||||||
|
.info = hdmi_eld_ctl_info,
|
||||||
|
.get = hdmi_eld_ctl_get,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct snd_soc_dai_driver *drv = dai->driver;
|
struct snd_soc_dai_driver *drv = dai->driver;
|
||||||
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
||||||
struct snd_kcontrol *kctl;
|
unsigned int i;
|
||||||
struct snd_kcontrol_new hdmi_eld_ctl = {
|
|
||||||
.access = SNDRV_CTL_ELEM_ACCESS_READ |
|
|
||||||
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
|
|
||||||
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
|
||||||
.name = "ELD",
|
|
||||||
.info = hdmi_eld_ctl_info,
|
|
||||||
.get = hdmi_eld_ctl_get,
|
|
||||||
.device = rtd->pcm->device,
|
|
||||||
};
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
||||||
@@ -648,26 +773,41 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
|||||||
hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
|
hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
|
||||||
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(hdmi_codec_controls); i++) {
|
||||||
|
struct snd_kcontrol *kctl;
|
||||||
|
|
||||||
/* add ELD ctl with the device number corresponding to the PCM stream */
|
/* add ELD ctl with the device number corresponding to the PCM stream */
|
||||||
kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component);
|
kctl = snd_ctl_new1(&hdmi_codec_controls[i], dai->component);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return snd_ctl_add(rtd->card->snd_card, kctl);
|
kctl->id.device = rtd->pcm->device;
|
||||||
|
ret = snd_ctl_add(rtd->card->snd_card, kctl);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hdmi_dai_probe(struct snd_soc_dai *dai)
|
static int hdmi_dai_probe(struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct snd_soc_dapm_context *dapm;
|
struct snd_soc_dapm_context *dapm;
|
||||||
struct hdmi_codec_daifmt *daifmt;
|
struct hdmi_codec_daifmt *daifmt;
|
||||||
struct snd_soc_dapm_route route = {
|
struct snd_soc_dapm_route route[] = {
|
||||||
|
{
|
||||||
.sink = "TX",
|
.sink = "TX",
|
||||||
.source = dai->driver->playback.stream_name,
|
.source = dai->driver->playback.stream_name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.sink = dai->driver->capture.stream_name,
|
||||||
|
.source = "RX",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dapm = snd_soc_component_get_dapm(dai->component);
|
dapm = snd_soc_component_get_dapm(dai->component);
|
||||||
ret = snd_soc_dapm_add_routes(dapm, &route, 1);
|
ret = snd_soc_dapm_add_routes(dapm, route, 2);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -692,10 +832,16 @@ static void plugged_cb(struct device *dev, bool plugged)
|
|||||||
{
|
{
|
||||||
struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
|
struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (plugged)
|
if (plugged) {
|
||||||
|
if (hcp->hcd.ops->get_eld) {
|
||||||
|
hcp->hcd.ops->get_eld(dev->parent, hcp->hcd.data,
|
||||||
|
hcp->eld, sizeof(hcp->eld));
|
||||||
|
}
|
||||||
hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
|
hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
|
||||||
else
|
} else {
|
||||||
hdmi_codec_jack_report(hcp, 0);
|
hdmi_codec_jack_report(hcp, 0);
|
||||||
|
memset(hcp->eld, 0, sizeof(hcp->eld));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hdmi_codec_set_jack(struct snd_soc_component *component,
|
static int hdmi_codec_set_jack(struct snd_soc_component *component,
|
||||||
@@ -703,7 +849,7 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component,
|
|||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
|
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
|
||||||
int ret = -EOPNOTSUPP;
|
int ret = -ENOTSUPP;
|
||||||
|
|
||||||
if (hcp->hcd.ops->hook_plugged_cb) {
|
if (hcp->hcd.ops->hook_plugged_cb) {
|
||||||
hcp->jack = jack;
|
hcp->jack = jack;
|
||||||
@@ -719,7 +865,7 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component,
|
|||||||
|
|
||||||
static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
|
static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
|
struct hdmi_codec_daifmt *cf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = hdmi_dai_probe(dai);
|
ret = hdmi_dai_probe(dai);
|
||||||
@@ -751,6 +897,14 @@ static const struct snd_soc_dai_driver hdmi_i2s_dai = {
|
|||||||
.formats = I2S_FORMATS,
|
.formats = I2S_FORMATS,
|
||||||
.sig_bits = 24,
|
.sig_bits = 24,
|
||||||
},
|
},
|
||||||
|
.capture = {
|
||||||
|
.stream_name = "Capture",
|
||||||
|
.channels_min = 2,
|
||||||
|
.channels_max = 8,
|
||||||
|
.rates = HDMI_RATES,
|
||||||
|
.formats = I2S_FORMATS,
|
||||||
|
.sig_bits = 24,
|
||||||
|
},
|
||||||
.ops = &hdmi_codec_i2s_dai_ops,
|
.ops = &hdmi_codec_i2s_dai_ops,
|
||||||
.pcm_new = hdmi_codec_pcm_new,
|
.pcm_new = hdmi_codec_pcm_new,
|
||||||
};
|
};
|
||||||
@@ -767,6 +921,13 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = {
|
|||||||
.rates = HDMI_RATES,
|
.rates = HDMI_RATES,
|
||||||
.formats = SPDIF_FORMATS,
|
.formats = SPDIF_FORMATS,
|
||||||
},
|
},
|
||||||
|
.capture = {
|
||||||
|
.stream_name = "Capture",
|
||||||
|
.channels_min = 2,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = HDMI_RATES,
|
||||||
|
.formats = SPDIF_FORMATS,
|
||||||
|
},
|
||||||
.ops = &hdmi_codec_spdif_dai_ops,
|
.ops = &hdmi_codec_spdif_dai_ops,
|
||||||
.pcm_new = hdmi_codec_pcm_new,
|
.pcm_new = hdmi_codec_pcm_new,
|
||||||
};
|
};
|
||||||
@@ -819,7 +980,8 @@ static int hdmi_codec_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dai_count = hcd->i2s + hcd->spdif;
|
dai_count = hcd->i2s + hcd->spdif;
|
||||||
if (dai_count < 1 || !hcd->ops || !hcd->ops->hw_params ||
|
if (dai_count < 1 || !hcd->ops ||
|
||||||
|
(!hcd->ops->hw_params && !hcd->ops->prepare) ||
|
||||||
!hcd->ops->audio_shutdown) {
|
!hcd->ops->audio_shutdown) {
|
||||||
dev_err(dev, "%s: Invalid parameters\n", __func__);
|
dev_err(dev, "%s: Invalid parameters\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -832,6 +994,11 @@ static int hdmi_codec_probe(struct platform_device *pdev)
|
|||||||
hcp->hcd = *hcd;
|
hcp->hcd = *hcd;
|
||||||
mutex_init(&hcp->lock);
|
mutex_init(&hcp->lock);
|
||||||
|
|
||||||
|
ret = snd_pcm_create_iec958_consumer_default(hcp->iec_status,
|
||||||
|
sizeof(hcp->iec_status));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);
|
daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);
|
||||||
if (!daidrv)
|
if (!daidrv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
Reference in New Issue
Block a user