diff options
author | Aurora zuma automerger <aurora-zuma-automerger@google.com> | 2023-04-11 07:52:58 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-04-17 11:07:31 -0700 |
commit | d055791577688a8357ebecbff9abc74fe0426470 (patch) | |
tree | 41491e1f286eafacf1037b1ad03955d2fc68f79c | |
parent | 6bac35c4ca96b3ac798d00ac3c0c154e80752981 (diff) | |
download | zuma-d055791577688a8357ebecbff9abc74fe0426470.tar.gz |
gxp: [Copybara Auto Merge] Merge branch 'zuma' into 'android14-gs-pixel-5.15'
gxp: callisto add BCL support
Bug: 270997009
gxp: add gxp_pm_chip_init
Bug: 277302257
gxp: call PM powering ops
Bug: 277302257 (repeat)
gcip: Fix version check for best-fit IOVA allocate
GCIP_MAIN_REV_ID: dba9b3e554230a8bf037d949a4a60bfcf68b9c15
gcip: Disable best-fit algo on kernel > 5.15
Bug: 277649169
GCIP_MAIN_REV_ID: 59ee39cabcc120581efc4c594424e537594385aa
gxp: Handle missing scmversion
Bug: 277787303
gcip: check acquired lock is atomic
Bug: 275652066
GCIP_HEADERS_REV_ID: 814e10b2d2d80cb3c45c0d5ea190282fe9e1b835
gcip: check acquired lock is atomic
Bug: 275652066 (repeat)
gcip: Conditionally use alloc_iova_fast workaround
GCIP_MAIN_REV_ID: 7962e3b9000d59e530d9633ab37656f0d8ac693a
gxp: remove redundant PM ops and add comments
Bug: 277302257 (repeat)
gxp: clang-format set column limit to 100
gxp: update clang-format to Linux 6.2.10
gxp: Add unique identifier to crash reason
Bug: 249103167
gxp: Remove debugfs.{c,h}
Bug: 27266337
gxp: Move cmumux{1,2} debugfs to gxp-common-platform
Bug: 27266337 (repeat)
gxp: Move blk_powerstate and wakelock debugfs to gxp-pm
Bug: 272663376
gxp: Move mailbox debugfs to gxp-mailbox-manager
Bug: 272663376 (repeat)
gxp: Move coredump debugfs to gxp-debug-dump
Bug: 272663376 (repeat)
gxp: Move firmware_run debugfs to gxp-firmware
Bug: 272663376 (repeat)
gxp: Move log and log_eventfd debugfs to telemetry
Bug: 272663376 (repeat)
gxp: Remove unused lpm_test
Bug: 272663376 (repeat)
gxp: Move debugfs initialization earlier
Bug: 272663376 (repeat)
gxp: rename gxp PM ops
Bug: 277302257 (repeat)
gxp: add gxp_pm_chip_set_ops
Bug: 277302257 (repeat)
gxp: add format string for commit hash
Bug: 270589821
gxp: unittests: enable ftrace events to increase the code coverage
Bug: 273847390
gxp: put CREATE_TRACE_POINTS to a separate file
gxp: Enable core debug dump support for dogfood
Bug: 274956438
gxp: remove support for unsigned MCU FW
Bug: 277191960
gxp: modify GSA behavior in fallback GSA header
Bug: 277191960 (repeat)
gxp: refuse running MCU in TZ with no gsa_dev
gxp: fix error handling while running MCU by GSA
gxp: bump version to 1.14
gxp: support coherency on imported dma-bufs
Bug: 276866171
gxp: adopt updated acquire_lock interface of GCIP
Bug: 275652066 (repeat)
GitOrigin-RevId: 938e4b82a5fc20d56e28cd75b6aaddb39548ba28
Change-Id: If888871701ab5d2aab17b168e0cdf85498a336b9
-rw-r--r-- | .clang-format | 246 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | callisto-pm.c | 52 | ||||
-rw-r--r-- | gcip-kernel-driver/drivers/gcip/gcip-iommu.c | 18 | ||||
-rw-r--r-- | gcip-kernel-driver/drivers/gcip/gcip-kci.c | 6 | ||||
-rw-r--r-- | gcip-kernel-driver/drivers/gcip/gcip-mailbox.c | 25 | ||||
-rw-r--r-- | gcip-kernel-driver/include/gcip/gcip-mailbox.h | 21 | ||||
-rw-r--r-- | gxp-common-platform.c | 118 | ||||
-rw-r--r-- | gxp-core-telemetry.c | 73 | ||||
-rw-r--r-- | gxp-debug-dump.c | 44 | ||||
-rw-r--r-- | gxp-debugfs.c | 545 | ||||
-rw-r--r-- | gxp-debugfs.h | 20 | ||||
-rw-r--r-- | gxp-dma-iommu.c | 6 | ||||
-rw-r--r-- | gxp-dma.h | 3 | ||||
-rw-r--r-- | gxp-dmabuf.c | 2 | ||||
-rw-r--r-- | gxp-firmware.c | 138 | ||||
-rw-r--r-- | gxp-mailbox-driver.c | 4 | ||||
-rw-r--r-- | gxp-mailbox-driver.h | 4 | ||||
-rw-r--r-- | gxp-mailbox-manager.c | 107 | ||||
-rw-r--r-- | gxp-mailbox-manager.h | 9 | ||||
-rw-r--r-- | gxp-mcu-firmware.c | 89 | ||||
-rw-r--r-- | gxp-pm.c | 131 | ||||
-rw-r--r-- | gxp-pm.h | 44 | ||||
-rw-r--r-- | gxp-trace.c | 9 | ||||
-rw-r--r-- | gxp-uci.c | 2 | ||||
-rw-r--r-- | gxp.h | 2 | ||||
-rw-r--r-- | include/linux/gsa/gsa_dsp.h | 2 | ||||
-rw-r--r-- | include/trace/events/gxp.h | 3 |
28 files changed, 984 insertions, 742 deletions
diff --git a/.clang-format b/.clang-format index 10dc5a9..d116625 100644 --- a/.clang-format +++ b/.clang-format @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # -# clang-format configuration file. Intended for clang-format >= 4. +# clang-format configuration file. Intended for clang-format >= 11. # # For more information, see: # @@ -13,7 +13,7 @@ AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false -#AlignEscapedNewlines: Left # Unknown to clang-format-4.0 +AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: false @@ -37,24 +37,24 @@ BraceWrapping: AfterObjCDeclaration: false AfterStruct: false AfterUnion: false - #AfterExternBlock: false # Unknown to clang-format-5.0 + AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false - #SplitEmptyFunction: true # Unknown to clang-format-4.0 - #SplitEmptyRecord: true # Unknown to clang-format-4.0 - #SplitEmptyNamespace: true # Unknown to clang-format-4.0 + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom -#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0 +BreakBeforeInheritanceComma: false BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false -#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0 +BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: false -ColumnLimit: 80 +ColumnLimit: 100 CommentPragmas: '^ IWYU pragma:' -#CompactNamespaces: false # Unknown to clang-format-4.0 +CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 @@ -62,39 +62,56 @@ Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false -#FixNamespaceComments: false # Unknown to clang-format-4.0 +FixNamespaceComments: false # Taken from: -# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \ +# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \ # | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ -# | sort | uniq +# | LC_ALL=C sort -u ForEachMacros: + - '__ata_qc_for_each' + - '__bio_for_each_bvec' + - '__bio_for_each_segment' + - '__evlist__for_each_entry' + - '__evlist__for_each_entry_continue' + - '__evlist__for_each_entry_from' + - '__evlist__for_each_entry_reverse' + - '__evlist__for_each_entry_safe' + - '__for_each_mem_range' + - '__for_each_mem_range_rev' + - '__for_each_thread' + - '__hlist_for_each_rcu' + - '__map__for_each_symbol_by_name' + - '__perf_evlist__for_each_entry' + - '__perf_evlist__for_each_entry_reverse' + - '__perf_evlist__for_each_entry_safe' + - '__rq_for_each_bio' + - '__shost_for_each_device' - 'apei_estatus_for_each_section' - 'ata_for_each_dev' - 'ata_for_each_link' - - '__ata_qc_for_each' - 'ata_qc_for_each' - 'ata_qc_for_each_raw' - 'ata_qc_for_each_with_internal' - 'ax25_for_each' - 'ax25_uid_for_each' - - '__bio_for_each_bvec' - 'bio_for_each_bvec' - 'bio_for_each_bvec_all' + - 'bio_for_each_folio_all' - 'bio_for_each_integrity_vec' - - '__bio_for_each_segment' - 'bio_for_each_segment' - 'bio_for_each_segment_all' - 'bio_list_for_each' - 'bip_for_each_vec' - - 'bitmap_for_each_clear_region' - - 'bitmap_for_each_set_region' - - 'blkg_for_each_descendant_post' - - 'blkg_for_each_descendant_pre' - - 'blk_queue_for_each_rl' - 'bond_for_each_slave' - 'bond_for_each_slave_rcu' + - 'bpf__perf_for_each_map' + - 'bpf__perf_for_each_map_named' - 'bpf_for_each_spilled_reg' + - 'bpf_object__for_each_map' + - 'bpf_object__for_each_program' + - 'bpf_object__for_each_safe' + - 'bpf_perf_object__for_each' - 'btree_for_each_safe128' - 'btree_for_each_safe32' - 'btree_for_each_safe64' @@ -102,6 +119,7 @@ ForEachMacros: - 'card_for_each_dev' - 'cgroup_taskset_for_each' - 'cgroup_taskset_for_each_leader' + - 'cpufreq_for_each_efficient_entry_idx' - 'cpufreq_for_each_entry' - 'cpufreq_for_each_entry_idx' - 'cpufreq_for_each_valid_entry' @@ -109,8 +127,22 @@ ForEachMacros: - 'css_for_each_child' - 'css_for_each_descendant_post' - 'css_for_each_descendant_pre' + - 'damon_for_each_region' + - 'damon_for_each_region_safe' + - 'damon_for_each_scheme' + - 'damon_for_each_scheme_safe' + - 'damon_for_each_target' + - 'damon_for_each_target_safe' + - 'data__for_each_file' + - 'data__for_each_file_new' + - 'data__for_each_file_start' - 'device_for_each_child_node' + - 'displayid_iter_for_each' + - 'dma_fence_array_for_each' - 'dma_fence_chain_for_each' + - 'dma_fence_unwrap_for_each' + - 'dma_resv_for_each_fence' + - 'dma_resv_for_each_fence_unlocked' - 'do_for_each_ftrace_op' - 'drm_atomic_crtc_for_each_plane' - 'drm_atomic_crtc_state_for_each_plane' @@ -122,6 +154,7 @@ ForEachMacros: - 'drm_for_each_bridge_in_chain' - 'drm_for_each_connector_iter' - 'drm_for_each_crtc' + - 'drm_for_each_crtc_reverse' - 'drm_for_each_encoder' - 'drm_for_each_encoder_mask' - 'drm_for_each_fb' @@ -133,14 +166,37 @@ ForEachMacros: - 'drm_mm_for_each_node' - 'drm_mm_for_each_node_in_range' - 'drm_mm_for_each_node_safe' + - 'dsa_switch_for_each_available_port' + - 'dsa_switch_for_each_cpu_port' + - 'dsa_switch_for_each_port' + - 'dsa_switch_for_each_port_continue_reverse' + - 'dsa_switch_for_each_port_safe' + - 'dsa_switch_for_each_user_port' + - 'dsa_tree_for_each_user_port' + - 'dso__for_each_symbol' + - 'dsos__for_each_with_build_id' + - 'elf_hash_for_each_possible' + - 'elf_section__for_each_rel' + - 'elf_section__for_each_rela' + - 'elf_symtab__for_each_symbol' + - 'evlist__for_each_cpu' + - 'evlist__for_each_entry' + - 'evlist__for_each_entry_continue' + - 'evlist__for_each_entry_from' + - 'evlist__for_each_entry_reverse' + - 'evlist__for_each_entry_safe' - 'flow_action_for_each' + - 'for_each_acpi_dev_match' - 'for_each_active_dev_scope' - 'for_each_active_drhd_unit' - 'for_each_active_iommu' - 'for_each_aggr_pgid' - 'for_each_available_child_of_node' + - 'for_each_bench' - 'for_each_bio' - 'for_each_board_func_rsrc' + - 'for_each_btf_ext_rec' + - 'for_each_btf_ext_sec' - 'for_each_bvec' - 'for_each_card_auxs' - 'for_each_card_auxs_safe' @@ -156,20 +212,25 @@ ForEachMacros: - 'for_each_child_of_node' - 'for_each_clear_bit' - 'for_each_clear_bit_from' + - 'for_each_clear_bitrange' + - 'for_each_clear_bitrange_from' + - 'for_each_cmd' - 'for_each_cmsghdr' + - 'for_each_collection' + - 'for_each_comp_order' - 'for_each_compatible_node' - 'for_each_component_dais' - 'for_each_component_dais_safe' - - 'for_each_comp_order' - 'for_each_console' + - 'for_each_console_srcu' - 'for_each_cpu' - 'for_each_cpu_and' - 'for_each_cpu_not' - 'for_each_cpu_wrap' - 'for_each_dapm_widgets' + - 'for_each_dedup_cand' - 'for_each_dev_addr' - 'for_each_dev_scope' - - 'for_each_displayid_db' - 'for_each_dma_cap_mask' - 'for_each_dpcm_be' - 'for_each_dpcm_be_rollback' @@ -183,6 +244,8 @@ ForEachMacros: - 'for_each_element_extid' - 'for_each_element_id' - 'for_each_endpoint_of_node' + - 'for_each_event' + - 'for_each_event_tps' - 'for_each_evictable_lru' - 'for_each_fib6_node_rt_rcu' - 'for_each_fib6_walker_rt' @@ -191,31 +254,35 @@ ForEachMacros: - 'for_each_free_mem_range' - 'for_each_free_mem_range_reverse' - 'for_each_func_rsrc' + - 'for_each_group_evsel' + - 'for_each_group_member' - 'for_each_hstate' - 'for_each_if' + - 'for_each_inject_fn' + - 'for_each_insn' + - 'for_each_insn_prefix' + - 'for_each_intid' - 'for_each_iommu' - 'for_each_ip_tunnel_rcu' - 'for_each_irq_nr' + - 'for_each_lang' - 'for_each_link_codecs' - 'for_each_link_cpus' - 'for_each_link_platforms' - 'for_each_lru' - 'for_each_matching_node' - 'for_each_matching_node_and_match' - - 'for_each_member' - - 'for_each_mem_region' - - 'for_each_memblock_type' - - 'for_each_memcg_cache_index' - 'for_each_mem_pfn_range' - - '__for_each_mem_range' - 'for_each_mem_range' - - '__for_each_mem_range_rev' - 'for_each_mem_range_rev' + - 'for_each_mem_region' + - 'for_each_member' + - 'for_each_memory' - 'for_each_migratetype_order' - - 'for_each_msi_entry' - - 'for_each_msi_entry_safe' + - 'for_each_missing_reg' - 'for_each_net' - 'for_each_net_continue_reverse' + - 'for_each_net_rcu' - 'for_each_netdev' - 'for_each_netdev_continue' - 'for_each_netdev_continue_rcu' @@ -225,12 +292,13 @@ ForEachMacros: - 'for_each_netdev_rcu' - 'for_each_netdev_reverse' - 'for_each_netdev_safe' - - 'for_each_net_rcu' - 'for_each_new_connector_in_state' - 'for_each_new_crtc_in_state' - 'for_each_new_mst_mgr_in_state' - 'for_each_new_plane_in_state' + - 'for_each_new_plane_in_state_reverse' - 'for_each_new_private_obj_in_state' + - 'for_each_new_reg' - 'for_each_node' - 'for_each_node_by_name' - 'for_each_node_by_type' @@ -246,20 +314,20 @@ ForEachMacros: - 'for_each_old_connector_in_state' - 'for_each_old_crtc_in_state' - 'for_each_old_mst_mgr_in_state' + - 'for_each_old_plane_in_state' + - 'for_each_old_private_obj_in_state' - 'for_each_oldnew_connector_in_state' - 'for_each_oldnew_crtc_in_state' - 'for_each_oldnew_mst_mgr_in_state' - 'for_each_oldnew_plane_in_state' - 'for_each_oldnew_plane_in_state_reverse' - 'for_each_oldnew_private_obj_in_state' - - 'for_each_old_plane_in_state' - - 'for_each_old_private_obj_in_state' - 'for_each_online_cpu' - 'for_each_online_node' - 'for_each_online_pgdat' + - 'for_each_path' - 'for_each_pci_bridge' - 'for_each_pci_dev' - - 'for_each_pci_msi_entry' - 'for_each_pcm_streams' - 'for_each_physmem_range' - 'for_each_populated_zone' @@ -267,22 +335,33 @@ ForEachMacros: - 'for_each_present_cpu' - 'for_each_prime_number' - 'for_each_prime_number_from' + - 'for_each_probe_cache_entry' - 'for_each_process' - 'for_each_process_thread' + - 'for_each_prop_codec_conf' + - 'for_each_prop_dai_codec' + - 'for_each_prop_dai_cpu' + - 'for_each_prop_dlc_codecs' + - 'for_each_prop_dlc_cpus' + - 'for_each_prop_dlc_platforms' - 'for_each_property_of_node' + - 'for_each_reg' + - 'for_each_reg_filtered' - 'for_each_registered_fb' - 'for_each_requested_gpio' - 'for_each_requested_gpio_in_range' - 'for_each_reserved_mem_range' - 'for_each_reserved_mem_region' - 'for_each_rtd_codec_dais' - - 'for_each_rtd_codec_dais_rollback' - 'for_each_rtd_components' - 'for_each_rtd_cpu_dais' - - 'for_each_rtd_cpu_dais_rollback' - 'for_each_rtd_dais' + - 'for_each_script' + - 'for_each_sec' - 'for_each_set_bit' - 'for_each_set_bit_from' + - 'for_each_set_bitrange' + - 'for_each_set_bitrange_from' - 'for_each_set_clump8' - 'for_each_sg' - 'for_each_sg_dma_page' @@ -291,17 +370,25 @@ ForEachMacros: - 'for_each_sgtable_dma_sg' - 'for_each_sgtable_page' - 'for_each_sgtable_sg' + - 'for_each_shell_test' - 'for_each_sibling_event' - 'for_each_subelement' - 'for_each_subelement_extid' - 'for_each_subelement_id' - - '__for_each_thread' + - 'for_each_sublist' + - 'for_each_subsystem' + - 'for_each_supported_activate_fn' + - 'for_each_supported_inject_fn' + - 'for_each_test' - 'for_each_thread' + - 'for_each_token' - 'for_each_unicast_dest_pgid' + - 'for_each_vsi' - 'for_each_wakeup_source' - 'for_each_zone' - 'for_each_zone_zonelist' - 'for_each_zone_zonelist_nodemask' + - 'func_for_each_insn' - 'fwnode_for_each_available_child_node' - 'fwnode_for_each_child_node' - 'fwnode_graph_for_each_endpoint' @@ -315,7 +402,13 @@ ForEachMacros: - 'hash_for_each_possible_safe' - 'hash_for_each_rcu' - 'hash_for_each_safe' + - 'hashmap__for_each_entry' + - 'hashmap__for_each_entry_safe' + - 'hashmap__for_each_key_entry' + - 'hashmap__for_each_key_entry_safe' - 'hctx_for_each_ctx' + - 'hists__for_each_format' + - 'hists__for_each_sort_list' - 'hlist_bl_for_each_entry' - 'hlist_bl_for_each_entry_rcu' - 'hlist_bl_for_each_entry_safe' @@ -330,7 +423,7 @@ ForEachMacros: - 'hlist_for_each_entry_rcu_bh' - 'hlist_for_each_entry_rcu_notrace' - 'hlist_for_each_entry_safe' - - '__hlist_for_each_rcu' + - 'hlist_for_each_entry_srcu' - 'hlist_for_each_safe' - 'hlist_nulls_for_each_entry' - 'hlist_nulls_for_each_entry_from' @@ -338,9 +431,6 @@ ForEachMacros: - 'hlist_nulls_for_each_entry_safe' - 'i3c_bus_for_each_i2cdev' - 'i3c_bus_for_each_i3cdev' - - 'ide_host_for_each_port' - - 'ide_port_for_each_dev' - - 'ide_port_for_each_present_dev' - 'idr_for_each_entry' - 'idr_for_each_entry_continue' - 'idr_for_each_entry_continue_ul' @@ -348,7 +438,15 @@ ForEachMacros: - 'in_dev_for_each_ifa_rcu' - 'in_dev_for_each_ifa_rtnl' - 'inet_bind_bucket_for_each' + - 'inet_lhash2_for_each_icsk' + - 'inet_lhash2_for_each_icsk_continue' - 'inet_lhash2_for_each_icsk_rcu' + - 'interval_tree_for_each_double_span' + - 'interval_tree_for_each_span' + - 'intlist__for_each_entry' + - 'intlist__for_each_entry_safe' + - 'iopt_for_each_contig_area' + - 'kcore_copy__for_each_phdr' - 'key_for_each' - 'key_for_each_safe' - 'klp_for_each_func' @@ -359,7 +457,9 @@ ForEachMacros: - 'klp_for_each_object_static' - 'kunit_suite_for_each_test_case' - 'kvm_for_each_memslot' + - 'kvm_for_each_memslot_in_gfn_range' - 'kvm_for_each_vcpu' + - 'libbpf_nla_for_each_attr' - 'list_for_each' - 'list_for_each_codec' - 'list_for_each_codec_safe' @@ -378,6 +478,8 @@ ForEachMacros: - 'list_for_each_entry_safe_continue' - 'list_for_each_entry_safe_from' - 'list_for_each_entry_safe_reverse' + - 'list_for_each_entry_srcu' + - 'list_for_each_from' - 'list_for_each_prev' - 'list_for_each_prev_safe' - 'list_for_each_safe' @@ -385,11 +487,18 @@ ForEachMacros: - 'llist_for_each_entry' - 'llist_for_each_entry_safe' - 'llist_for_each_safe' + - 'map__for_each_symbol' + - 'map__for_each_symbol_by_name' + - 'map_for_each_event' + - 'map_for_each_metric' + - 'maps__for_each_entry' + - 'maps__for_each_entry_safe' - 'mci_for_each_dimm' - 'media_device_for_each_entity' - 'media_device_for_each_intf' - 'media_device_for_each_link' - 'media_device_for_each_pad' + - 'msi_for_each_desc' - 'nanddev_io_for_each_page' - 'netdev_for_each_lower_dev' - 'netdev_for_each_lower_private' @@ -411,8 +520,26 @@ ForEachMacros: - 'of_property_for_each_string' - 'of_property_for_each_u32' - 'pci_bus_for_each_resource' + - 'pci_doe_for_each_off' + - 'pcl_for_each_chunk' + - 'pcl_for_each_segment' - 'pcm_for_each_format' + - 'perf_config_items__for_each_entry' + - 'perf_config_sections__for_each_entry' + - 'perf_config_set__for_each_entry' + - 'perf_cpu_map__for_each_cpu' + - 'perf_evlist__for_each_entry' + - 'perf_evlist__for_each_entry_reverse' + - 'perf_evlist__for_each_entry_safe' + - 'perf_evlist__for_each_evsel' + - 'perf_evlist__for_each_mmap' + - 'perf_hpp_list__for_each_format' + - 'perf_hpp_list__for_each_format_safe' + - 'perf_hpp_list__for_each_sort_list' + - 'perf_hpp_list__for_each_sort_list_safe' + - 'perf_pmu__for_each_hybrid_pmu' - 'ping_portaddr_for_each_entry' + - 'ping_portaddr_for_each_entry_rcu' - 'plist_for_each' - 'plist_for_each_continue' - 'plist_for_each_entry' @@ -426,10 +553,12 @@ ForEachMacros: - 'queue_for_each_hw_ctx' - 'radix_tree_for_each_slot' - 'radix_tree_for_each_tagged' + - 'rb_for_each' - 'rbtree_postorder_for_each_entry_safe' - 'rdma_for_each_block' - 'rdma_for_each_port' - 'rdma_umem_for_each_dma_block' + - 'resort_rb__for_each_entry' - 'resource_list_for_each_entry' - 'resource_list_for_each_entry_safe' - 'rhl_for_each_entry_rcu' @@ -443,15 +572,18 @@ ForEachMacros: - 'rht_for_each_from' - 'rht_for_each_rcu' - 'rht_for_each_rcu_from' - - '__rq_for_each_bio' - 'rq_for_each_bvec' - 'rq_for_each_segment' + - 'rq_list_for_each' + - 'rq_list_for_each_safe' - 'scsi_for_each_prot_sg' - 'scsi_for_each_sg' - 'sctp_for_each_hentry' - 'sctp_skb_for_each' + - 'sec_for_each_insn' + - 'sec_for_each_insn_continue' + - 'sec_for_each_insn_from' - 'shdma_for_each_chan' - - '__shost_for_each_device' - 'shost_for_each_device' - 'sk_for_each' - 'sk_for_each_bound' @@ -468,7 +600,13 @@ ForEachMacros: - 'snd_soc_dapm_widget_for_each_path_safe' - 'snd_soc_dapm_widget_for_each_sink_path' - 'snd_soc_dapm_widget_for_each_source_path' + - 'strlist__for_each_entry' + - 'strlist__for_each_entry_safe' + - 'sym_for_each_insn' + - 'sym_for_each_insn_continue_reverse' + - 'symbols__for_each_entry' - 'tb_property_for_each' + - 'tcf_act_for_each_action' - 'tcf_exts_for_each_action' - 'udp_portaddr_for_each_entry' - 'udp_portaddr_for_each_entry_rcu' @@ -492,15 +630,17 @@ ForEachMacros: - 'xbc_node_for_each_array_value' - 'xbc_node_for_each_child' - 'xbc_node_for_each_key_value' + - 'xbc_node_for_each_subkey' - 'zorro_for_each_dev' -#IncludeBlocks: Preserve # Unknown to clang-format-5.0 +IncludeBlocks: Preserve IncludeCategories: - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: false -#IndentPPDirectives: None # Unknown to clang-format-5.0 +IndentGotoLabels: false +IndentPPDirectives: None IndentWidth: 8 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave @@ -510,13 +650,13 @@ MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None -#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0 +ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 8 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true # Taken from git's rules -#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0 +PenaltyBreakAssignment: 10 PenaltyBreakBeforeFirstCallParameter: 30 PenaltyBreakComment: 10 PenaltyBreakFirstLessLess: 0 @@ -527,14 +667,14 @@ PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right ReflowComments: false SortIncludes: false -#SortUsingDeclarations: false # Unknown to clang-format-4.0 +SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0 -#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0 -SpaceBeforeParens: ControlStatements -#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0 +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false @@ -14,7 +14,6 @@ gxp-objs += \ gxp-client.o \ gxp-core-telemetry.o \ gxp-debug-dump.o \ - gxp-debugfs.o \ gxp-dma-fence.o \ gxp-dma-iommu.o \ gxp-dmabuf.o \ @@ -32,6 +31,7 @@ gxp-objs += \ gxp-pm.o \ gxp-ssmt.o \ gxp-thermal.o \ + gxp-trace.o \ gxp-vd.o @@ -39,6 +39,7 @@ ifeq ($(GXP_CHIP),CALLISTO) gxp-objs += \ callisto-platform.o \ + callisto-pm.o \ gsx01-mailbox-driver.o \ gxp-dci.o \ gxp-kci.o \ diff --git a/callisto-pm.c b/callisto-pm.c new file mode 100644 index 0000000..055a678 --- /dev/null +++ b/callisto-pm.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Callisto power management implementations. + * + * Copyright (C) 2023 Google LLC + */ + +#include <linux/thermal.h> /* for fixing bug in gs_tmu_v3 */ +#include <linux/types.h> +#include <soc/google/bcl.h> +#include <soc/google/gs_tmu_v3.h> + +#include "gxp-internal.h" +#include "gxp-pm.h" + +static int callisto_after_blk_power_up(struct gxp_dev *gxp) +{ + int ret; + + if (gxp->power_mgr->bcl_dev) { + ret = google_init_aur_ratio(gxp->power_mgr->bcl_dev); + if (ret) + dev_warn(gxp->dev, "init BCL ratio failed: %d", ret); + } + /* Inform TMU the block is up. */ + return set_acpm_tj_power_status(TZ_AUR, true); +} + +static void callisto_before_blk_power_down(struct gxp_dev *gxp) +{ + int ret; + + ret = set_acpm_tj_power_status(TZ_AUR, false); + if (ret) + dev_err(gxp->dev, + "set Tj power status on blk down failed: %d\n", ret); +} + +static const struct gxp_pm_ops gxp_pm_ops = { + .after_blk_power_up = callisto_after_blk_power_up, + .before_blk_power_down = callisto_before_blk_power_down, +}; + +void gxp_pm_chip_set_ops(struct gxp_power_manager *mgr) +{ + mgr->ops = &gxp_pm_ops; +} + +void gxp_pm_chip_init(struct gxp_dev *gxp) +{ + gxp->power_mgr->bcl_dev = google_retrieve_bcl_handle(); +} diff --git a/gcip-kernel-driver/drivers/gcip/gcip-iommu.c b/gcip-kernel-driver/drivers/gcip/gcip-iommu.c index 979eb86..ab0ef51 100644 --- a/gcip-kernel-driver/drivers/gcip/gcip-iommu.c +++ b/gcip-kernel-driver/drivers/gcip/gcip-iommu.c @@ -16,12 +16,19 @@ #include <linux/of.h> #include <linux/scatterlist.h> #include <linux/slab.h> +#include <linux/version.h> #include <gcip/gcip-domain-pool.h> #include <gcip/gcip-iommu.h> #include <gcip/gcip-mem-pool.h> -#define HAS_IOVAD_BEST_FIT_ALGO (IS_ENABLED(CONFIG_GCIP_TEST) || IS_ENABLED(CONFIG_ANDROID)) +/* + * TODO(b/277649169) Best fit IOVA allocator was removed in 6.1 GKI + * The API needs to either be upstreamed, integrated into this driver, or disabled for 6.1 + * compatibility. For now, disable best-fit on all non-Android kernels and any GKI > 5.15. + */ +#define HAS_IOVAD_BEST_FIT_ALGO (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) && \ + (IS_ENABLED(CONFIG_GCIP_TEST) || IS_ENABLED(CONFIG_ANDROID))) /* Macros for manipulating @gcip_map_flags parameter. */ #define GCIP_MAP_FLAGS_GET_VALUE(ATTR, flags) \ @@ -104,8 +111,17 @@ static dma_addr_t iovad_alloc_iova_space(struct gcip_iommu_domain *domain, size_ size = size >> shift; +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0) + /* + * alloc_iova_fast() makes use of a cache of recently freed IOVA pages which does not + * behave correctly for non-power-of-two amounts of pages. Round up the number of + * pages being allocated to ensure it's a safe number of pages. + * + * This rounding is done automatically as of 5.17 + */ if (size < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1))) size = roundup_pow_of_two(size); +#endif iova = alloc_iova_fast(&domain->iova_space.iovad, size, domain->domain_pool->last_daddr >> shift, true); diff --git a/gcip-kernel-driver/drivers/gcip/gcip-kci.c b/gcip-kernel-driver/drivers/gcip/gcip-kci.c index 58852d5..33f8021 100644 --- a/gcip-kernel-driver/drivers/gcip/gcip-kci.c +++ b/gcip-kernel-driver/drivers/gcip/gcip-kci.c @@ -36,7 +36,7 @@ static void gcip_kci_inc_cmd_queue_tail(struct gcip_mailbox *mailbox, u32 inc) kci->ops->inc_cmd_queue_tail(kci, inc); } -static int gcip_kci_acquire_cmd_queue_lock(struct gcip_mailbox *mailbox, bool try) +static int gcip_kci_acquire_cmd_queue_lock(struct gcip_mailbox *mailbox, bool try, bool *atomic) { struct gcip_kci *kci = gcip_mailbox_get_data(mailbox); @@ -102,10 +102,12 @@ static void gcip_kci_inc_resp_queue_head(struct gcip_mailbox *mailbox, u32 inc) kci->ops->inc_resp_queue_head(kci, inc); } -static int gcip_kci_acquire_resp_queue_lock(struct gcip_mailbox *mailbox, bool try) +static int gcip_kci_acquire_resp_queue_lock(struct gcip_mailbox *mailbox, bool try, bool *atomic) { struct gcip_kci *kci = gcip_mailbox_get_data(mailbox); + *atomic = true; + if (try) return spin_trylock(&kci->resp_queue_lock); diff --git a/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c b/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c index 6d20771..c7aa921 100644 --- a/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c +++ b/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c @@ -24,7 +24,8 @@ #define GET_CMD_QUEUE_HEAD() mailbox->ops->get_cmd_queue_head(mailbox) #define GET_CMD_QUEUE_TAIL() mailbox->ops->get_cmd_queue_tail(mailbox) #define INC_CMD_QUEUE_TAIL(inc) mailbox->ops->inc_cmd_queue_tail(mailbox, inc) -#define ACQUIRE_CMD_QUEUE_LOCK(try) mailbox->ops->acquire_cmd_queue_lock(mailbox, try) +#define ACQUIRE_CMD_QUEUE_LOCK(try, atomic) \ + mailbox->ops->acquire_cmd_queue_lock(mailbox, try, atomic) #define RELEASE_CMD_QUEUE_LOCK() mailbox->ops->release_cmd_queue_lock(mailbox) #define GET_CMD_ELEM_SEQ(cmd) mailbox->ops->get_cmd_elem_seq(mailbox, cmd) @@ -35,7 +36,8 @@ #define GET_RESP_QUEUE_HEAD() mailbox->ops->get_resp_queue_head(mailbox) #define INC_RESP_QUEUE_HEAD(inc) mailbox->ops->inc_resp_queue_head(mailbox, inc) #define GET_RESP_QUEUE_TAIL() mailbox->ops->get_resp_queue_tail(mailbox) -#define ACQUIRE_RESP_QUEUE_LOCK(try) mailbox->ops->acquire_resp_queue_lock(mailbox, try) +#define ACQUIRE_RESP_QUEUE_LOCK(try, atomic) \ + mailbox->ops->acquire_resp_queue_lock(mailbox, try, atomic) #define RELEASE_RESP_QUEUE_LOCK() mailbox->ops->release_resp_queue_lock(mailbox) #define GET_RESP_ELEM_SEQ(resp) mailbox->ops->get_resp_elem_seq(mailbox, resp) @@ -107,12 +109,13 @@ static void gcip_mailbox_del_wait_resp(struct gcip_mailbox *mailbox, void *resp) * Returns 0 on success, or -ENOMEM if failed on allocation. */ static int gcip_mailbox_push_wait_resp(struct gcip_mailbox *mailbox, void *resp, - struct gcip_mailbox_resp_awaiter *awaiter) + struct gcip_mailbox_resp_awaiter *awaiter, bool atomic) { - struct gcip_mailbox_wait_list_elem *entry = kzalloc(sizeof(*entry), GFP_KERNEL); + struct gcip_mailbox_wait_list_elem *entry; unsigned long flags; int ret; + entry = kzalloc(sizeof(*entry), atomic ? GFP_ATOMIC : GFP_KERNEL); if (!entry) return -ENOMEM; @@ -148,8 +151,9 @@ static int gcip_mailbox_enqueue_cmd(struct gcip_mailbox *mailbox, void *cmd, voi { int ret = 0; u32 tail; + bool atomic = false; - ACQUIRE_CMD_QUEUE_LOCK(false); + ACQUIRE_CMD_QUEUE_LOCK(false, &atomic); SET_CMD_ELEM_SEQ(cmd, mailbox->cur_seq); /* @@ -177,7 +181,7 @@ static int gcip_mailbox_enqueue_cmd(struct gcip_mailbox *mailbox, void *cmd, voi /* Adds @resp to the wait_list only if the cmd can be pushed successfully. */ SET_RESP_ELEM_SEQ(resp, GET_CMD_ELEM_SEQ(cmd)); SET_RESP_ELEM_STATUS(resp, GCIP_MAILBOX_STATUS_WAITING_RESPONSE); - ret = gcip_mailbox_push_wait_resp(mailbox, resp, awaiter); + ret = gcip_mailbox_push_wait_resp(mailbox, resp, awaiter, atomic); if (ret) goto out; } @@ -324,9 +328,10 @@ static void *gcip_mailbox_fetch_responses(struct gcip_mailbox *mailbox, u32 *tot const u32 elem_size = mailbox->resp_elem_size; void *ret = NULL; /* Array of responses. */ void *prev_ptr = NULL; /* Temporary pointer to realloc ret. */ + bool atomic = false; /* Someone is working on consuming - we can leave early. */ - if (!ACQUIRE_RESP_QUEUE_LOCK(true)) + if (!ACQUIRE_RESP_QUEUE_LOCK(true, &atomic)) goto out; head = GET_RESP_QUEUE_HEAD(); @@ -349,7 +354,8 @@ static void *gcip_mailbox_fetch_responses(struct gcip_mailbox *mailbox, u32 *tot break; prev_ptr = ret; - ret = krealloc(prev_ptr, (total + count) * elem_size, GFP_KERNEL); + ret = krealloc(prev_ptr, (total + count) * elem_size, + atomic ? GFP_ATOMIC : GFP_KERNEL); /* * Out-of-memory, we can return the previously fetched responses if any, or ENOMEM * otherwise. @@ -387,8 +393,9 @@ static int gcip_mailbox_fetch_one_response(struct gcip_mailbox *mailbox, void *r { u32 head; u32 tail; + bool atomic; - if (!ACQUIRE_RESP_QUEUE_LOCK(true)) + if (!ACQUIRE_RESP_QUEUE_LOCK(true, &atomic)) return 0; head = GET_RESP_QUEUE_HEAD(); diff --git a/gcip-kernel-driver/include/gcip/gcip-mailbox.h b/gcip-kernel-driver/include/gcip/gcip-mailbox.h index c88d2d7..835503f 100644 --- a/gcip-kernel-driver/include/gcip/gcip-mailbox.h +++ b/gcip-kernel-driver/include/gcip/gcip-mailbox.h @@ -133,14 +133,18 @@ struct gcip_mailbox_ops { void (*inc_cmd_queue_tail)(struct gcip_mailbox *mailbox, u32 inc); /* * Acquires the lock of cmd_queue. If @try is true, "_trylock" functions can be used, but - * also it can be ignored. Returns 1 if succeed, 0 if failed. This callback will be called - * in the following situations. + * also it can be ignored. If the lock will make the context atomic, @atomic must be set + * to true. Returns 1 if succeed, 0 if failed. + * + * This callback will be called in the following situations. * - Enqueue a command to the cmd_queue. + * * The lock can be mutex lock or spin lock and it will be released by calling * `release_cmd_queue_lock` callback. + * * Context: normal. */ - int (*acquire_cmd_queue_lock)(struct gcip_mailbox *mailbox, bool try); + int (*acquire_cmd_queue_lock)(struct gcip_mailbox *mailbox, bool try, bool *atomic); /* * Releases the lock of cmd_queue which is acquired by calling `acquire_cmd_queue_lock`. * Context: normal. @@ -184,15 +188,20 @@ struct gcip_mailbox_ops { void (*inc_resp_queue_head)(struct gcip_mailbox *mailbox, u32 inc); /* * Acquires the lock of resp_queue. If @try is true, "_trylock" functions can be used, but - * also it can be ignored. Returns 1 if succeed, 0 if failed. This callback will be called - * in the following situations. + * also it can be ignored. If the lock will make the context atomic, @atomic must be set + * to true. Returns 1 if succeed, 0 if failed. + * + * This callback will be called in the following situations: * - Fetch response(s) from the resp_queue. + * * The lock can be a mutex lock or a spin lock. However, if @try is considered and the * "_trylock" is used, it must be a spin lock only. + * * The lock will be released by calling `release_resp_queue_lock` callback. + * * Context: normal and in_interrupt(). */ - int (*acquire_resp_queue_lock)(struct gcip_mailbox *mailbox, bool try); + int (*acquire_resp_queue_lock)(struct gcip_mailbox *mailbox, bool try, bool *atomic); /* * Releases the lock of resp_queue which is acquired by calling `acquire_resp_queue_lock`. * Context: normal and in_interrupt(). diff --git a/gxp-common-platform.c b/gxp-common-platform.c index 205e7f0..c9fa143 100644 --- a/gxp-common-platform.c +++ b/gxp-common-platform.c @@ -30,7 +30,6 @@ #include "gxp-config.h" #include "gxp-core-telemetry.h" #include "gxp-debug-dump.h" -#include "gxp-debugfs.h" #include "gxp-dma-fence.h" #include "gxp-dma.h" #include "gxp-dmabuf.h" @@ -1249,7 +1248,7 @@ static int gxp_map_dmabuf(struct gxp_client *client, } mapping = gxp_dmabuf_map(gxp, client->vd->domain, ibuf.dmabuf_fd, - /*gxp_dma_flags=*/0, + ibuf.flags, mapping_flags_to_dma_dir(ibuf.flags)); if (IS_ERR(mapping)) { ret = PTR_ERR(mapping); @@ -1422,7 +1421,7 @@ out: static inline const char *get_driver_commit(void) { #if IS_ENABLED(CONFIG_MODULE_SCMVERSION) - return THIS_MODULE->scmversion; + return THIS_MODULE->scmversion ?: "scmversion missing"; #elif defined(GIT_REPO_TAG) return GIT_REPO_TAG; #else @@ -1764,6 +1763,72 @@ static const struct file_operations gxp_fops = { .unlocked_ioctl = gxp_ioctl, }; +static int debugfs_cmu_mux1_set(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + + if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { + dev_err(gxp->dev, "CMU registers are not mapped"); + return -ENODEV; + } + if (val > 1) { + dev_err(gxp->dev, + "Incorrect val for cmu_mux1, only 0 and 1 allowed\n"); + return -EINVAL; + } + + writel(val << 4, gxp->cmu.vaddr + PLL_CON0_PLL_AUR); + return 0; +} + +static int debugfs_cmu_mux1_get(void *data, u64 *val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + + if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { + dev_err(gxp->dev, "CMU registers are not mapped"); + return -ENODEV; + } + *val = readl(gxp->cmu.vaddr + PLL_CON0_PLL_AUR); + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_cmu_mux1_fops, debugfs_cmu_mux1_get, + debugfs_cmu_mux1_set, "%llu\n"); + +static int debugfs_cmu_mux2_set(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + + if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { + dev_err(gxp->dev, "CMU registers are not mapped"); + return -ENODEV; + } + if (val > 1) { + dev_err(gxp->dev, + "Incorrect val for cmu_mux2, only 0 and 1 allowed\n"); + return -EINVAL; + } + + writel(val << 4, gxp->cmu.vaddr + PLL_CON0_NOC_USER); + return 0; +} + +static int debugfs_cmu_mux2_get(void *data, u64 *val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + + if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { + dev_err(gxp->dev, "CMU registers are not mapped"); + return -ENODEV; + } + *val = readl(gxp->cmu.vaddr + PLL_CON0_NOC_USER); + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_cmu_mux2_fops, debugfs_cmu_mux2_get, + debugfs_cmu_mux2_set, "%llu\n"); + static int gxp_set_reg_resources(struct platform_device *pdev, struct gxp_dev *gxp) { struct device *dev = gxp->dev; @@ -1842,6 +1907,12 @@ static int gxp_set_reg_resources(struct platform_device *pdev, struct gxp_dev *g } } + /* Will be removed by gxp_remove_debugdir. */ + debugfs_create_file("cmumux1", 0600, gxp->d_entry, gxp, + &debugfs_cmu_mux1_fops); + debugfs_create_file("cmumux2", 0600, gxp->d_entry, gxp, + &debugfs_cmu_mux2_fops); + return 0; } @@ -1993,6 +2064,31 @@ static __exit void gxp_fs_exit(void) class_destroy(gxp_class); } +static void gxp_remove_debugdir(struct gxp_dev *gxp) +{ + if (!gxp->d_entry) + return; + + debugfs_remove_recursive(gxp->d_entry); +} + +/* + * Creates the GXP debug FS directory and assigns to @gxp->d_entry. + * On failure a warning is logged and @gxp->d_entry is NULL. + */ +static void gxp_create_debugdir(struct gxp_dev *gxp) +{ + gxp->d_entry = debugfs_create_dir(GXP_NAME, NULL); + if (IS_ERR_OR_NULL(gxp->d_entry)) { + dev_warn(gxp->dev, "Create debugfs dir failed: %d", + PTR_ERR_OR_ZERO(gxp->d_entry)); + gxp->d_entry = NULL; + } + + mutex_init(&gxp->debugfs_client_lock); + gxp->debugfs_wakelock_held = false; +} + static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_dev *gxp) { struct device *dev = &pdev->dev; @@ -2001,6 +2097,8 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de dev_notice(dev, "Probing gxp driver with commit %s\n", get_driver_commit()); + gxp_create_debugdir(gxp); + platform_set_drvdata(pdev, gxp); gxp->dev = dev; if (gxp->parse_dt) { @@ -2013,8 +2111,6 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de if (ret) return ret; - gxp_create_debugdir(gxp); - ret = gxp_pm_init(gxp); if (ret) { dev_err(dev, "Failed to init power management (ret=%d)\n", ret); @@ -2140,7 +2236,6 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de if (ret) goto err_before_remove; - gxp_create_debugfs(gxp); gxp_debug_pointer = gxp; dev_info(dev, "Probe finished"); @@ -2167,7 +2262,7 @@ err_free_domain_pool: kfree(gxp->domain_pool); err_debug_dump_exit: gxp_debug_dump_exit(gxp); - /* mailbox manager init doesn't need revert */ + gxp_mailbox_destroy_manager(gxp, gxp->mailbox_mgr); err_dma_exit: gxp_dma_exit(gxp); err_put_tpu_dev: @@ -2183,15 +2278,10 @@ static int gxp_common_platform_remove(struct platform_device *pdev) { struct gxp_dev *gxp = platform_get_drvdata(pdev); - /* - * Call gxp_thermal_exit before gxp_remove_debugdir since it will - * remove its own debugfs. - */ - gxp_thermal_exit(gxp); - gxp_remove_debugdir(gxp); gxp_device_remove(gxp); if (gxp->before_remove) gxp->before_remove(gxp); + gxp_thermal_exit(gxp); gxp_core_telemetry_exit(gxp); gxp_fw_data_destroy(gxp); gxp_vd_destroy(gxp); @@ -2200,10 +2290,12 @@ static int gxp_common_platform_remove(struct platform_device *pdev) gxp_domain_pool_destroy(gxp->domain_pool); kfree(gxp->domain_pool); gxp_debug_dump_exit(gxp); + gxp_mailbox_destroy_manager(gxp, gxp->mailbox_mgr); gxp_dma_exit(gxp); gxp_put_tpu_dev(gxp); gxp_put_gsa_dev(gxp); gxp_pm_destroy(gxp); + gxp_remove_debugdir(gxp); gxp_debug_pointer = NULL; diff --git a/gxp-core-telemetry.c b/gxp-core-telemetry.c index f3a2424..eaf8b09 100644 --- a/gxp-core-telemetry.c +++ b/gxp-core-telemetry.c @@ -18,6 +18,9 @@ #include "gxp-notification.h" #include "gxp-vd.h" +#define DEBUGFS_LOG_BUFF "log" +#define DEBUGFS_LOG_EVENTFD "log_eventfd" + static uint gxp_core_telemetry_buffer_size = CORE_TELEMETRY_DEFAULT_BUFFER_SIZE; module_param_named(core_telemetry_buffer_size, gxp_core_telemetry_buffer_size, uint, 0660); @@ -130,6 +133,67 @@ int gxp_secure_core_telemetry_init(struct gxp_dev *gxp, phys_addr_t phys) return 0; } +static int debugfs_log_buff_set(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + int i; + struct gxp_coherent_buf *buffers; + u64 *ptr; + + mutex_lock(&gxp->core_telemetry_mgr->lock); + + buffers = gxp->core_telemetry_mgr->logging_buff_data->buffers; + for (i = 0; i < GXP_NUM_CORES; i++) { + ptr = buffers[i].vaddr; + *ptr = val; + } + + mutex_unlock(&gxp->core_telemetry_mgr->lock); + + return 0; +} + +static int debugfs_log_buff_get(void *data, u64 *val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + struct gxp_coherent_buf *buffers; + + mutex_lock(&gxp->core_telemetry_mgr->lock); + + buffers = gxp->core_telemetry_mgr->logging_buff_data->buffers; + *val = *(u64 *)(buffers[0].vaddr); + + mutex_unlock(&gxp->core_telemetry_mgr->lock); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_log_buff_fops, debugfs_log_buff_get, + debugfs_log_buff_set, "%llu\n"); + +static int debugfs_log_eventfd_signal_set(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + int ret = 0; + + mutex_lock(&gxp->core_telemetry_mgr->lock); + + if (!gxp->core_telemetry_mgr->logging_efd) { + ret = -ENODEV; + goto out; + } + + ret = eventfd_signal(gxp->core_telemetry_mgr->logging_efd, 1); + +out: + mutex_unlock(&gxp->core_telemetry_mgr->lock); + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_log_eventfd_signal_fops, NULL, + debugfs_log_eventfd_signal_set, "%llu\n"); + int gxp_core_telemetry_init(struct gxp_dev *gxp) { struct gxp_core_telemetry_manager *mgr; @@ -197,6 +261,12 @@ int gxp_core_telemetry_init(struct gxp_dev *gxp) gxp->core_telemetry_mgr->logging_buff_data = log_buff_data; gxp->core_telemetry_mgr->tracing_buff_data = trace_buff_data; + + debugfs_create_file(DEBUGFS_LOG_BUFF, 0600, gxp->d_entry, gxp, + &debugfs_log_buff_fops); + debugfs_create_file(DEBUGFS_LOG_EVENTFD, 0200, gxp->d_entry, gxp, + &debugfs_log_eventfd_signal_fops); + return 0; err_free: @@ -515,6 +585,9 @@ void gxp_core_telemetry_exit(struct gxp_dev *gxp) return; } + debugfs_remove(debugfs_lookup(DEBUGFS_LOG_BUFF, gxp->d_entry)); + debugfs_remove(debugfs_lookup(DEBUGFS_LOG_EVENTFD, gxp->d_entry)); + log_buff_data = mgr->logging_buff_data; trace_buff_data = mgr->tracing_buff_data; diff --git a/gxp-debug-dump.c b/gxp-debug-dump.c index ad9b49c..e0947c1 100644 --- a/gxp-debug-dump.c +++ b/gxp-debug-dump.c @@ -28,6 +28,7 @@ #include "gxp-internal.h" #include "gxp-lpm.h" #include "gxp-mapping.h" +#include "gxp-notification.h" #include "gxp-pm.h" #include "gxp-vd.h" @@ -49,6 +50,8 @@ #define CORE_FIRMWARE_RW_STRIDE 0x200000 /* 2 MB */ #define CORE_FIRMWARE_RW_ADDR(x) (0xFA400000 + CORE_FIRMWARE_RW_STRIDE * x) +#define DEBUGFS_COREDUMP "coredump" + /* Enum indicating the debug dump request reason. */ enum gxp_debug_dump_init_type { DEBUG_DUMP_FW_INIT, DEBUG_DUMP_KERNEL_INIT }; @@ -61,8 +64,16 @@ enum gxp_common_segments_idx { #if IS_ENABLED(CONFIG_GXP_TEST) static int gxp_debug_dump_enable = 1; #else +#if IS_ENABLED(CONFIG_CALLISTO) +/* + * TODO(b/277094681): Revert setting gxp_debug_dump_enable to 1 + * around device beta milestone. + */ +static int gxp_debug_dump_enable = 1; +#else static int gxp_debug_dump_enable; #endif +#endif module_param_named(debug_dump_enable, gxp_debug_dump_enable, int, 0660); static void gxp_debug_dump_cache_invalidate(struct gxp_dev *gxp) @@ -683,7 +694,7 @@ out_efault: } else { dev_dbg(gxp->dev, "Passing dump data to SSCD daemon\n"); snprintf(sscd_msg, SSCD_MSG_LENGTH - 1, - "gxp debug dump (core %0x)", core_id); + "gxp debug dump (vdid %d)(core %0x)", vd->vdid, core_id); gxp_send_to_sscd(gxp, mgr->segs[core_id], seg_idx + user_buf_cnt, sscd_msg); @@ -847,6 +858,32 @@ struct work_struct *gxp_debug_dump_get_notification_handler(struct gxp_dev *gxp, return &mgr->debug_dump_works[core].work; } +static int debugfs_coredump(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + int core; + + if (!gxp_debug_dump_is_enabled()) { + dev_err(gxp->dev, "Debug dump functionality is disabled\n"); + return -EINVAL; + } + + down_read(&gxp->vd_semaphore); + + for (core = 0; core < GXP_NUM_CORES; core++) { + if (gxp_is_fw_running(gxp, core)) + gxp_notification_send(gxp, core, + CORE_NOTIF_GENERATE_DEBUG_DUMP); + } + + up_read(&gxp->vd_semaphore); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_coredump_fops, NULL, debugfs_coredump, + "%llu\n"); + int gxp_debug_dump_init(struct gxp_dev *gxp, void *sscd_dev, void *sscd_pdata) { struct gxp_debug_dump_manager *mgr; @@ -888,6 +925,9 @@ int gxp_debug_dump_init(struct gxp_dev *gxp, void *sscd_dev, void *sscd_pdata) mgr->sscd_pdata = sscd_pdata; mutex_init(&mgr->debug_dump_lock); + debugfs_create_file(DEBUGFS_COREDUMP, 0200, gxp->d_entry, gxp, + &debugfs_coredump_fops); + return 0; } @@ -900,6 +940,8 @@ void gxp_debug_dump_exit(struct gxp_dev *gxp) return; } + debugfs_remove(debugfs_lookup(DEBUGFS_COREDUMP, gxp->d_entry)); + kfree(gxp->debug_dump_mgr->common_dump); gxp_dma_free_coherent_buf(gxp, NULL, &mgr->buf); diff --git a/gxp-debugfs.c b/gxp-debugfs.c deleted file mode 100644 index 76ef4f0..0000000 --- a/gxp-debugfs.c +++ /dev/null @@ -1,545 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * GXP debugfs support. - * - * Copyright (C) 2021 Google LLC - */ - -#include <linux/acpm_dvfs.h> - -#include <gcip/gcip-pm.h> - -#include "gxp-client.h" -#include "gxp-core-telemetry.h" -#include "gxp-debug-dump.h" -#include "gxp-debugfs.h" -#include "gxp-dma.h" -#include "gxp-firmware-data.h" -#include "gxp-firmware-loader.h" -#include "gxp-firmware.h" -#include "gxp-internal.h" -#include "gxp-notification.h" -#include "gxp-lpm.h" -#include "gxp-mailbox.h" -#include "gxp-pm.h" -#include "gxp-vd.h" -#include "gxp.h" - -#if GXP_HAS_MCU -#include "gxp-mcu-platform.h" -#endif - -static int gxp_debugfs_lpm_test(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - - dev_info(gxp->dev, "%llu\n", val); - - return 0; -} -DEFINE_DEBUGFS_ATTRIBUTE(gxp_lpm_test_fops, NULL, gxp_debugfs_lpm_test, - "%llu\n"); - -static int gxp_debugfs_mailbox(void *data, u64 val) -{ - int core = 0, retval; - u16 status; - struct gxp_dev *gxp = (struct gxp_dev *)data; - struct gxp_mailbox *mbx; - struct gxp_client *client; - struct gxp_power_states power_states = { - .power = GXP_POWER_STATE_NOM, - .memory = MEMORY_POWER_STATE_UNDEFINED, - }; - u16 cmd_code; - int ret; - - mutex_lock(&gxp->debugfs_client_lock); - client = gxp->debugfs_client; - -#if GXP_HAS_MCU - if (gxp_is_direct_mode(gxp)) { -#endif - core = val / 1000; - if (core >= GXP_NUM_CORES) { - dev_notice(gxp->dev, - "Mailbox for core %d doesn't exist.\n", - core); - ret = -EINVAL; - goto out; - } - - if (gxp->mailbox_mgr->mailboxes[core] == NULL) { - dev_notice( - gxp->dev, - "Unable to send mailbox command -- mailbox %d not ready\n", - core); - ret = -EINVAL; - goto out; - } - - /* Create a dummy client to access @client->gxp from the `execute_cmd` callback. */ - if (!client) - client = gxp_client_create(gxp); - mbx = gxp->mailbox_mgr->mailboxes[core]; - cmd_code = GXP_MBOX_CODE_DISPATCH; -#if GXP_HAS_MCU - } else { - if (!client) { - dev_err(gxp->dev, - "You should load firmwares via gxp/firmware_run first\n"); - ret = -EIO; - goto out; - } - - down_read(&gxp->debugfs_client->semaphore); - if (!gxp_client_has_available_vd(gxp->debugfs_client, - "GXP_MAILBOX_COMMAND")) { - ret = -ENODEV; - up_read(&gxp->debugfs_client->semaphore); - goto out; - } - up_read(&gxp->debugfs_client->semaphore); - - mbx = to_mcu_dev(gxp)->mcu.uci.mbx; - if (!mbx) { - dev_err(gxp->dev, "UCI is not initialized.\n"); - ret = -EIO; - goto out; - } - - cmd_code = CORE_COMMAND; - } -#endif - - retval = gxp->mailbox_mgr->execute_cmd(client, mbx, core, cmd_code, 0, - 0, 0, 0, 1, power_states, NULL, - &status); - - dev_info( - gxp->dev, - "Mailbox Command Sent: core=%d, resp.status=%d, resp.retval=%d\n", - core, status, retval); - ret = 0; -out: - if (client && client != gxp->debugfs_client) - gxp_client_destroy(client); - mutex_unlock(&gxp->debugfs_client_lock); - return ret; -} -DEFINE_DEBUGFS_ATTRIBUTE(gxp_mailbox_fops, NULL, gxp_debugfs_mailbox, "%llu\n"); - -static int gxp_firmware_run_set(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - struct gxp_client *client; - int ret = 0; - uint core; - bool acquired_block_wakelock; - - ret = gxp_firmware_loader_load_if_needed(gxp); - if (ret) { - dev_err(gxp->dev, "Unable to load firmware files\n"); - return ret; - } - - mutex_lock(&gxp->debugfs_client_lock); - - if (val) { - if (gxp->debugfs_client) { - dev_err(gxp->dev, "Firmware is already running!\n"); - ret = -EIO; - goto out; - } - - /* - * Since this debugfs node destroys, then creates new fw_data, - * and runs firmware on every DSP core, it cannot be run if - * any of the cores already has a VD running on it. - */ - down_write(&gxp->vd_semaphore); - for (core = 0; core < GXP_NUM_CORES; core++) { - if (gxp->core_to_vd[core]) { - dev_err(gxp->dev, - "Unable to run firmware with debugfs while other clients are running\n"); - ret = -EBUSY; - up_write(&gxp->vd_semaphore); - goto out; - } - } - up_write(&gxp->vd_semaphore); - - client = gxp_client_create(gxp); - if (IS_ERR(client)) { - dev_err(gxp->dev, "Failed to create client\n"); - goto out; - } - gxp->debugfs_client = client; - - mutex_lock(&gxp->client_list_lock); - list_add(&client->list_entry, &gxp->client_list); - mutex_unlock(&gxp->client_list_lock); - - down_write(&client->semaphore); - - ret = gxp_client_allocate_virtual_device(client, GXP_NUM_CORES, - 0); - if (ret) { - dev_err(gxp->dev, "Failed to allocate VD\n"); - goto err_destroy_client; - } - - ret = gxp_client_acquire_block_wakelock( - client, &acquired_block_wakelock); - if (ret) { - dev_err(gxp->dev, "Failed to acquire BLOCK wakelock\n"); - goto err_destroy_client; - } - - ret = gxp_client_acquire_vd_wakelock(client, uud_states); - if (ret) { - dev_err(gxp->dev, "Failed to acquire VD wakelock\n"); - goto err_release_block_wakelock; - } - - up_write(&client->semaphore); - } else { - if (!gxp->debugfs_client) { - dev_err(gxp->dev, "Firmware is not running!\n"); - ret = -EIO; - goto out; - } - - /* - * Cleaning up the client will stop the VD it owns and release - * the BLOCK wakelock it is holding. - */ - goto out_destroy_client; - } - -out: - mutex_unlock(&gxp->debugfs_client_lock); - - return ret; - -err_release_block_wakelock: - gxp_client_release_block_wakelock(client); -err_destroy_client: - up_write(&client->semaphore); -out_destroy_client: - mutex_lock(&gxp->client_list_lock); - list_del(&gxp->debugfs_client->list_entry); - mutex_unlock(&gxp->client_list_lock); - - /* Destroying a client cleans up any VDss or wakelocks it held. */ - gxp_client_destroy(gxp->debugfs_client); - gxp->debugfs_client = NULL; - mutex_unlock(&gxp->debugfs_client_lock); - return ret; -} - -static int gxp_firmware_run_get(void *data, u64 *val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - - down_read(&gxp->vd_semaphore); - *val = gxp->firmware_mgr->firmware_running; - up_read(&gxp->vd_semaphore); - - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_firmware_run_fops, gxp_firmware_run_get, - gxp_firmware_run_set, "%llx\n"); - -static int gxp_wakelock_set(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - int ret = 0; - - mutex_lock(&gxp->debugfs_client_lock); - - if (val > 0) { - /* Wakelock Acquire */ - if (gxp->debugfs_wakelock_held) { - dev_warn(gxp->dev, - "Debugfs wakelock is already held.\n"); - ret = -EBUSY; - goto out; - } - - ret = gcip_pm_get(gxp->power_mgr->pm); - if (ret) { - dev_err(gxp->dev, "gcip_pm_get failed ret=%d\n", ret); - goto out; - } - gxp->debugfs_wakelock_held = true; - gxp_pm_update_requested_power_states(gxp, off_states, - uud_states); - } else { - /* Wakelock Release */ - if (!gxp->debugfs_wakelock_held) { - dev_warn(gxp->dev, "Debugfs wakelock not held.\n"); - ret = -EIO; - goto out; - } - - gcip_pm_put(gxp->power_mgr->pm); - gxp->debugfs_wakelock_held = false; - gxp_pm_update_requested_power_states(gxp, uud_states, - off_states); - } - -out: - mutex_unlock(&gxp->debugfs_client_lock); - - return ret; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_wakelock_fops, NULL, gxp_wakelock_set, "%llx\n"); - -static int gxp_blk_powerstate_set(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - int ret = 0; - - if (gxp_pm_get_blk_state(gxp) == AUR_OFF) { - dev_warn( - gxp->dev, - "Cannot set block power state when the block is off. Obtain a wakelock to power it on.\n"); - return -ENODEV; - } - - if (val >= AUR_DVFS_MIN_RATE) { - ret = gxp_pm_blk_set_rate_acpm(gxp, val); - } else { - ret = -EINVAL; - dev_err(gxp->dev, "Incorrect state %llu\n", val); - } - return ret; -} - -static int gxp_blk_powerstate_get(void *data, u64 *val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - - if (gxp_pm_get_blk_state(gxp) == AUR_OFF) { - dev_warn( - gxp->dev, - "Cannot get block power state when the block is off.\n"); - return -ENODEV; - } - - *val = gxp_pm_blk_get_state_acpm(gxp); - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_blk_powerstate_fops, gxp_blk_powerstate_get, - gxp_blk_powerstate_set, "%llx\n"); - -static int gxp_debugfs_coredump(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - int core; - - if (!gxp_debug_dump_is_enabled()) { - dev_err(gxp->dev, "Debug dump functionality is disabled\n"); - return -EINVAL; - } - - down_read(&gxp->vd_semaphore); - - for (core = 0; core < GXP_NUM_CORES; core++) { - if (gxp_is_fw_running(gxp, core)) - gxp_notification_send(gxp, core, - CORE_NOTIF_GENERATE_DEBUG_DUMP); - } - - up_read(&gxp->vd_semaphore); - - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_coredump_fops, NULL, gxp_debugfs_coredump, - "%llu\n"); - -static int gxp_log_buff_set(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - int i; - struct gxp_coherent_buf *buffers; - u64 *ptr; - - mutex_lock(&gxp->core_telemetry_mgr->lock); - - buffers = gxp->core_telemetry_mgr->logging_buff_data->buffers; - for (i = 0; i < GXP_NUM_CORES; i++) { - ptr = buffers[i].vaddr; - *ptr = val; - } - - mutex_unlock(&gxp->core_telemetry_mgr->lock); - - return 0; -} - -static int gxp_log_buff_get(void *data, u64 *val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - struct gxp_coherent_buf *buffers; - - mutex_lock(&gxp->core_telemetry_mgr->lock); - - buffers = gxp->core_telemetry_mgr->logging_buff_data->buffers; - *val = *(u64 *)(buffers[0].vaddr); - - mutex_unlock(&gxp->core_telemetry_mgr->lock); - - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_log_buff_fops, gxp_log_buff_get, gxp_log_buff_set, - "%llu\n"); - -static int gxp_log_eventfd_signal_set(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - int ret = 0; - - mutex_lock(&gxp->core_telemetry_mgr->lock); - - if (!gxp->core_telemetry_mgr->logging_efd) { - ret = -ENODEV; - goto out; - } - - ret = eventfd_signal(gxp->core_telemetry_mgr->logging_efd, 1); - -out: - mutex_unlock(&gxp->core_telemetry_mgr->lock); - - return ret; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_log_eventfd_signal_fops, NULL, - gxp_log_eventfd_signal_set, "%llu\n"); - -static int gxp_cmu_mux1_set(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - - if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { - dev_err(gxp->dev, "CMU registers are not mapped"); - return -ENODEV; - } - if (val > 1) { - dev_err(gxp->dev, - "Incorrect val for cmu_mux1, only 0 and 1 allowed\n"); - return -EINVAL; - } - - writel(val << 4, gxp->cmu.vaddr + PLL_CON0_PLL_AUR); - return 0; -} - -static int gxp_cmu_mux1_get(void *data, u64 *val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - - if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { - dev_err(gxp->dev, "CMU registers are not mapped"); - return -ENODEV; - } - *val = readl(gxp->cmu.vaddr + PLL_CON0_PLL_AUR); - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_cmu_mux1_fops, gxp_cmu_mux1_get, gxp_cmu_mux1_set, - "%llu\n"); - -static int gxp_cmu_mux2_set(void *data, u64 val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - - if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { - dev_err(gxp->dev, "CMU registers are not mapped"); - return -ENODEV; - } - if (val > 1) { - dev_err(gxp->dev, - "Incorrect val for cmu_mux2, only 0 and 1 allowed\n"); - return -EINVAL; - } - - writel(val << 4, gxp->cmu.vaddr + PLL_CON0_NOC_USER); - return 0; -} - -static int gxp_cmu_mux2_get(void *data, u64 *val) -{ - struct gxp_dev *gxp = (struct gxp_dev *)data; - - if (IS_ERR_OR_NULL(gxp->cmu.vaddr)) { - dev_err(gxp->dev, "CMU registers are not mapped"); - return -ENODEV; - } - *val = readl(gxp->cmu.vaddr + PLL_CON0_NOC_USER); - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(gxp_cmu_mux2_fops, gxp_cmu_mux2_get, gxp_cmu_mux2_set, - "%llu\n"); - -void gxp_create_debugdir(struct gxp_dev *gxp) -{ - gxp->d_entry = debugfs_create_dir(GXP_NAME, NULL); - if (IS_ERR_OR_NULL(gxp->d_entry)) { - dev_warn(gxp->dev, "Create debugfs dir failed: %d", - PTR_ERR_OR_ZERO(gxp->d_entry)); - gxp->d_entry = NULL; - } -} - -void gxp_create_debugfs(struct gxp_dev *gxp) -{ - if (!gxp->d_entry) - return; - - mutex_init(&gxp->debugfs_client_lock); - gxp->debugfs_wakelock_held = false; - - debugfs_create_file("lpm_test", 0200, gxp->d_entry, gxp, - &gxp_lpm_test_fops); - debugfs_create_file("mailbox", 0200, gxp->d_entry, gxp, - &gxp_mailbox_fops); - debugfs_create_file("firmware_run", 0600, gxp->d_entry, gxp, - &gxp_firmware_run_fops); - debugfs_create_file("wakelock", 0200, gxp->d_entry, gxp, - &gxp_wakelock_fops); - debugfs_create_file("blk_powerstate", 0600, gxp->d_entry, gxp, - &gxp_blk_powerstate_fops); - debugfs_create_file("coredump", 0200, gxp->d_entry, gxp, - &gxp_coredump_fops); - debugfs_create_file("log", 0600, gxp->d_entry, gxp, &gxp_log_buff_fops); - debugfs_create_file("log_eventfd", 0200, gxp->d_entry, gxp, - &gxp_log_eventfd_signal_fops); - debugfs_create_file("cmumux1", 0600, gxp->d_entry, gxp, - &gxp_cmu_mux1_fops); - debugfs_create_file("cmumux2", 0600, gxp->d_entry, gxp, - &gxp_cmu_mux2_fops); -} - -void gxp_remove_debugdir(struct gxp_dev *gxp) -{ - if (!gxp->d_entry) - return; - debugfs_remove_recursive(gxp->d_entry); - - /* - * Now that debugfs is torn down, and no other calls to - * `gxp_firmware_run_set()` can occur, destroy any client that may have - * been left running. - */ - if (gxp->debugfs_client) - gxp_client_destroy(gxp->debugfs_client); -} diff --git a/gxp-debugfs.h b/gxp-debugfs.h deleted file mode 100644 index 6ea8688..0000000 --- a/gxp-debugfs.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * GXP debugfs support. - * - * Copyright (C) 2020 Google LLC - */ -#ifndef __GXP_DEBUGFS_H__ -#define __GXP_DEBUGFS_H__ - -#include "gxp-internal.h" - -/* - * Creates the GXP debug FS directory and assigns to @gxp->d_entry. - * On failure a warning is logged and @gxp->d_entry is NULL. - */ -void gxp_create_debugdir(struct gxp_dev *gxp); -void gxp_create_debugfs(struct gxp_dev *gxp); -void gxp_remove_debugdir(struct gxp_dev *gxp); - -#endif /* __GXP_DEBUGFS_H__ */ diff --git a/gxp-dma-iommu.c b/gxp-dma-iommu.c index 0cedfb8..665a8d1 100644 --- a/gxp-dma-iommu.c +++ b/gxp-dma-iommu.c @@ -24,7 +24,6 @@ #include "gxp-ssmt.h" #include "gxp.h" -#define CREATE_TRACE_POINTS #include <trace/events/gxp.h> struct gxp_dma_iommu_manager { @@ -727,11 +726,12 @@ void gxp_dma_sync_sg_for_device(struct gxp_dev *gxp, struct scatterlist *sg, struct sg_table * gxp_dma_map_dmabuf_attachment(struct gxp_dev *gxp, struct gcip_iommu_domain *gdomain, - struct dma_buf_attachment *attachment, + struct dma_buf_attachment *attachment, u32 flags, enum dma_data_direction direction) { struct sg_table *sgt; - int prot = dma_info_to_prot(direction, /*coherent=*/0, /*attrs=*/0); + bool coherent = flags & GXP_MAP_COHERENT ? true : false; + int prot = dma_info_to_prot(direction, coherent, /*attrs=*/0); ssize_t size_mapped; int ret; @@ -321,6 +321,7 @@ void gxp_dma_sync_sg_for_device(struct gxp_dev *gxp, struct scatterlist *sg, * @gdomain: The IOMMU domain the dma-buf to be mapped on * @attachment: An attachment, representing the dma-buf, obtained from * `dma_buf_attach()` + * @flags: flag indicating mapping attributes * @direction: DMA direction * * Return: A scatter-gather table describing the mapping of the dma-buf @@ -329,7 +330,7 @@ void gxp_dma_sync_sg_for_device(struct gxp_dev *gxp, struct scatterlist *sg, struct sg_table * gxp_dma_map_dmabuf_attachment(struct gxp_dev *gxp, struct gcip_iommu_domain *gdomain, - struct dma_buf_attachment *attachment, + struct dma_buf_attachment *attachment, u32 flags, enum dma_data_direction direction); /** diff --git a/gxp-dmabuf.c b/gxp-dmabuf.c index a152e67..d0dcf54 100644 --- a/gxp-dmabuf.c +++ b/gxp-dmabuf.c @@ -78,7 +78,7 @@ struct gxp_mapping *gxp_dmabuf_map(struct gxp_dev *gxp, goto err_attach; } - sgt = gxp_dma_map_dmabuf_attachment(gxp, domain, attachment, dir); + sgt = gxp_dma_map_dmabuf_attachment(gxp, domain, attachment, flags, dir); if (IS_ERR(sgt)) { dev_err(gxp->dev, "Failed to map dma-buf attachment (ret=%ld)\n", diff --git a/gxp-firmware.c b/gxp-firmware.c index 0255994..ecb1f80 100644 --- a/gxp-firmware.c +++ b/gxp-firmware.c @@ -21,6 +21,7 @@ #include <gcip/gcip-image-config.h> #include "gxp-bpm.h" +#include "gxp-client.h" #include "gxp-config.h" #include "gxp-core-telemetry.h" #include "gxp-debug-dump.h" @@ -41,6 +42,7 @@ #endif #define FW_HEADER_SIZE GCIP_FW_HEADER_SIZE +#define DEBUGFS_FIRMWARE_RUN "firmware_run" static int gxp_dsp_fw_auth_disable; module_param_named(dsp_fw_auth_disable, gxp_dsp_fw_auth_disable, int, 0660); @@ -573,6 +575,129 @@ static const struct attribute_group gxp_firmware_attr_group = { .attrs = dev_attrs, }; +static int debugfs_firmware_run_set(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + struct gxp_client *client; + int ret = 0; + uint core; + bool acquired_block_wakelock; + + ret = gxp_firmware_loader_load_if_needed(gxp); + if (ret) { + dev_err(gxp->dev, "Unable to load firmware files\n"); + return ret; + } + + mutex_lock(&gxp->debugfs_client_lock); + + if (val) { + if (gxp->debugfs_client) { + dev_err(gxp->dev, "Firmware is already running!\n"); + ret = -EIO; + goto out; + } + + /* + * Since this debugfs node destroys, then creates new fw_data, + * and runs firmware on every DSP core, it cannot be run if + * any of the cores already has a VD running on it. + */ + down_write(&gxp->vd_semaphore); + for (core = 0; core < GXP_NUM_CORES; core++) { + if (gxp->core_to_vd[core]) { + dev_err(gxp->dev, + "Unable to run firmware with debugfs while other clients are running\n"); + ret = -EBUSY; + up_write(&gxp->vd_semaphore); + goto out; + } + } + up_write(&gxp->vd_semaphore); + + client = gxp_client_create(gxp); + if (IS_ERR(client)) { + dev_err(gxp->dev, "Failed to create client\n"); + goto out; + } + gxp->debugfs_client = client; + + mutex_lock(&gxp->client_list_lock); + list_add(&client->list_entry, &gxp->client_list); + mutex_unlock(&gxp->client_list_lock); + + down_write(&client->semaphore); + + ret = gxp_client_allocate_virtual_device(client, GXP_NUM_CORES, + 0); + if (ret) { + dev_err(gxp->dev, "Failed to allocate VD\n"); + goto err_destroy_client; + } + + ret = gxp_client_acquire_block_wakelock( + client, &acquired_block_wakelock); + if (ret) { + dev_err(gxp->dev, "Failed to acquire BLOCK wakelock\n"); + goto err_destroy_client; + } + + ret = gxp_client_acquire_vd_wakelock(client, uud_states); + if (ret) { + dev_err(gxp->dev, "Failed to acquire VD wakelock\n"); + goto err_release_block_wakelock; + } + + up_write(&client->semaphore); + } else { + if (!gxp->debugfs_client) { + dev_err(gxp->dev, "Firmware is not running!\n"); + ret = -EIO; + goto out; + } + + /* + * Cleaning up the client will stop the VD it owns and release + * the BLOCK wakelock it is holding. + */ + goto out_destroy_client; + } + +out: + mutex_unlock(&gxp->debugfs_client_lock); + + return ret; + +err_release_block_wakelock: + gxp_client_release_block_wakelock(client); +err_destroy_client: + up_write(&client->semaphore); +out_destroy_client: + mutex_lock(&gxp->client_list_lock); + list_del(&gxp->debugfs_client->list_entry); + mutex_unlock(&gxp->client_list_lock); + + /* Destroying a client cleans up any VDss or wakelocks it held. */ + gxp_client_destroy(gxp->debugfs_client); + gxp->debugfs_client = NULL; + mutex_unlock(&gxp->debugfs_client_lock); + return ret; +} + +static int debugfs_firmware_run_get(void *data, u64 *val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + + down_read(&gxp->vd_semaphore); + *val = gxp->firmware_mgr->firmware_running; + up_read(&gxp->vd_semaphore); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_firmware_run_fops, debugfs_firmware_run_get, + debugfs_firmware_run_set, "%llx\n"); + int gxp_fw_init(struct gxp_dev *gxp) { u32 ver, proc_id; @@ -658,6 +783,10 @@ int gxp_fw_init(struct gxp_dev *gxp) goto out_fw_destroy; mgr->firmware_running = 0; + + debugfs_create_file(DEBUGFS_FIRMWARE_RUN, 0600, gxp->d_entry, gxp, + &debugfs_firmware_run_fops); + return 0; out_fw_destroy: @@ -673,6 +802,15 @@ void gxp_fw_destroy(struct gxp_dev *gxp) if (IS_GXP_TEST && !mgr) return; + debugfs_remove(debugfs_lookup(DEBUGFS_FIRMWARE_RUN, gxp->d_entry)); + /* + * Now that debugfs is torn down, and no other calls to + * `debugfs_firmware_run_set()` can occur, destroy any client that may + * have been left running. + */ + if (gxp->debugfs_client) + gxp_client_destroy(gxp->debugfs_client); + device_remove_group(gxp->dev, &gxp_firmware_attr_group); for (core = 0; core < GXP_NUM_CORES; core++) { diff --git a/gxp-mailbox-driver.c b/gxp-mailbox-driver.c index 8d610c3..59f8aea 100644 --- a/gxp-mailbox-driver.c +++ b/gxp-mailbox-driver.c @@ -392,7 +392,7 @@ void gxp_mailbox_gcip_ops_inc_cmd_queue_tail(struct gcip_mailbox *mailbox, } int gxp_mailbox_gcip_ops_acquire_cmd_queue_lock(struct gcip_mailbox *mailbox, - bool try) + bool try, bool *atomic) { struct gxp_mailbox *gxp_mbx = mailbox->data; @@ -439,7 +439,7 @@ void gxp_mailbox_gcip_ops_inc_resp_queue_head(struct gcip_mailbox *mailbox, } int gxp_mailbox_gcip_ops_acquire_resp_queue_lock(struct gcip_mailbox *mailbox, - bool try) + bool try, bool *atomic) { struct gxp_mailbox *gxp_mbx = mailbox->data; diff --git a/gxp-mailbox-driver.h b/gxp-mailbox-driver.h index 4eaf36b..7ed6cfc 100644 --- a/gxp-mailbox-driver.h +++ b/gxp-mailbox-driver.h @@ -145,7 +145,7 @@ u32 gxp_mailbox_gcip_ops_get_cmd_queue_tail(struct gcip_mailbox *mailbox); void gxp_mailbox_gcip_ops_inc_cmd_queue_tail(struct gcip_mailbox *mailbox, u32 inc); int gxp_mailbox_gcip_ops_acquire_cmd_queue_lock(struct gcip_mailbox *mailbox, - bool try); + bool try, bool *atomic); void gxp_mailbox_gcip_ops_release_cmd_queue_lock(struct gcip_mailbox *mailbox); u32 gxp_mailbox_gcip_ops_get_resp_queue_size(struct gcip_mailbox *mailbox); @@ -154,7 +154,7 @@ u32 gxp_mailbox_gcip_ops_get_resp_queue_tail(struct gcip_mailbox *mailbox); void gxp_mailbox_gcip_ops_inc_resp_queue_head(struct gcip_mailbox *mailbox, u32 inc); int gxp_mailbox_gcip_ops_acquire_resp_queue_lock(struct gcip_mailbox *mailbox, - bool try); + bool try, bool *atomic); void gxp_mailbox_gcip_ops_release_resp_queue_lock(struct gcip_mailbox *mailbox); void gxp_mailbox_gcip_ops_acquire_wait_list_lock(struct gcip_mailbox *mailbox, diff --git a/gxp-mailbox-manager.c b/gxp-mailbox-manager.c index 1085a51..5d5a276 100644 --- a/gxp-mailbox-manager.c +++ b/gxp-mailbox-manager.c @@ -8,6 +8,102 @@ #include "gxp-mailbox-driver.h" #include "gxp-mailbox-manager.h" #include "gxp-mailbox.h" +#include "gxp.h" +#if GXP_HAS_MCU +#include "gxp-mcu-platform.h" +#endif + +#define DEBUGFS_MAILBOX "mailbox" + +static int debugfs_mailbox_execute_cmd(void *data, u64 val) +{ + int core = 0, retval; + u16 status; + struct gxp_dev *gxp = (struct gxp_dev *)data; + struct gxp_mailbox *mbx; + struct gxp_client *client; + struct gxp_power_states power_states = { + .power = GXP_POWER_STATE_NOM, + .memory = MEMORY_POWER_STATE_UNDEFINED, + }; + u16 cmd_code; + int ret; + + mutex_lock(&gxp->debugfs_client_lock); + client = gxp->debugfs_client; + +#if GXP_HAS_MCU + if (gxp_is_direct_mode(gxp)) { +#endif + core = val / 1000; + if (core >= GXP_NUM_CORES) { + dev_notice(gxp->dev, + "Mailbox for core %d doesn't exist.\n", + core); + ret = -EINVAL; + goto out; + } + + if (gxp->mailbox_mgr->mailboxes[core] == NULL) { + dev_notice( + gxp->dev, + "Unable to send mailbox command -- mailbox %d not ready\n", + core); + ret = -EINVAL; + goto out; + } + + /* Create a dummy client to access @client->gxp from the `execute_cmd` callback. */ + if (!client) + client = gxp_client_create(gxp); + mbx = gxp->mailbox_mgr->mailboxes[core]; + cmd_code = GXP_MBOX_CODE_DISPATCH; +#if GXP_HAS_MCU + } else { + if (!client) { + dev_err(gxp->dev, + "You should load firmwares via gxp/firmware_run first\n"); + ret = -EIO; + goto out; + } + + down_read(&gxp->debugfs_client->semaphore); + if (!gxp_client_has_available_vd(gxp->debugfs_client, + "GXP_MAILBOX_COMMAND")) { + ret = -ENODEV; + up_read(&gxp->debugfs_client->semaphore); + goto out; + } + up_read(&gxp->debugfs_client->semaphore); + + mbx = to_mcu_dev(gxp)->mcu.uci.mbx; + if (!mbx) { + dev_err(gxp->dev, "UCI is not initialized.\n"); + ret = -EIO; + goto out; + } + + cmd_code = CORE_COMMAND; + } +#endif + + retval = gxp->mailbox_mgr->execute_cmd(client, mbx, core, cmd_code, 0, + 0, 0, 0, 1, power_states, NULL, + &status); + + dev_info( + gxp->dev, + "Mailbox Command Sent: core=%d, resp.status=%d, resp.retval=%d\n", + core, status, retval); + ret = 0; +out: + if (client && client != gxp->debugfs_client) + gxp_client_destroy(client); + mutex_unlock(&gxp->debugfs_client_lock); + return ret; +} +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_mailbox_fops, NULL, + debugfs_mailbox_execute_cmd, "%llu\n"); struct gxp_mailbox_manager *gxp_mailbox_create_manager(struct gxp_dev *gxp, uint num_cores) @@ -28,5 +124,16 @@ struct gxp_mailbox_manager *gxp_mailbox_create_manager(struct gxp_dev *gxp, if (!mgr->mailboxes) return ERR_PTR(-ENOMEM); + debugfs_create_file(DEBUGFS_MAILBOX, 0200, gxp->d_entry, gxp, + &debugfs_mailbox_fops); + return mgr; } + +void gxp_mailbox_destroy_manager(struct gxp_dev *gxp, + struct gxp_mailbox_manager *mgr) +{ + debugfs_remove(debugfs_lookup(DEBUGFS_MAILBOX, gxp->d_entry)); + devm_kfree(gxp->dev, mgr->mailboxes); + devm_kfree(gxp->dev, mgr); +} diff --git a/gxp-mailbox-manager.h b/gxp-mailbox-manager.h index 24cd16b..18658da 100644 --- a/gxp-mailbox-manager.h +++ b/gxp-mailbox-manager.h @@ -46,8 +46,9 @@ typedef void (*reset_mailbox_t)(struct gxp_mailbox *mailbox); /* * Called when requests synchronous commands. This callback will be called from the - * `gxp_debugfs_mailbox` function. The response will be returned to the @resp_seq, @resp_status - * and `retval` of `struct gxp_response` will be returned as the return value of this function. + * `debugfs_mailbox_execute_cmd` function. The response will be returned to the @resp_seq, + * @resp_status and `retval` of `struct gxp_response` will be returned as the return value of this + * function. * You can pass NULL to @resp_seq and @resp_status if you don't need the result. See the * `struct gxp_response` for the details. * @@ -134,4 +135,8 @@ struct gxp_mailbox_manager { struct gxp_mailbox_manager *gxp_mailbox_create_manager(struct gxp_dev *gxp, uint num_cores); +/* Destroy and free the mailbox manager. */ +void gxp_mailbox_destroy_manager(struct gxp_dev *gxp, + struct gxp_mailbox_manager *mgr); + #endif /* __GXP_MAILBOX_MANAGER_H__ */ diff --git a/gxp-mcu-firmware.c b/gxp-mcu-firmware.c index 3c85d5e..7c97481 100644 --- a/gxp-mcu-firmware.c +++ b/gxp-mcu-firmware.c @@ -76,8 +76,7 @@ int gxp_mcu_firmware_load(struct gxp_dev *gxp, char *fw_name, struct device *dev = gxp->dev; struct gcip_image_config *imgcfg; struct gcip_common_image_header *hdr; - size_t offset, size; - bool is_signed; + size_t size; mutex_lock(&mcu_fw->lock); if (mcu_fw->status == GCIP_FW_LOADING || @@ -99,16 +98,14 @@ int gxp_mcu_firmware_load(struct gxp_dev *gxp, char *fw_name, hdr = (struct gcip_common_image_header *)(*fw)->data; - is_signed = is_signed_firmware(*fw, hdr); - - if (is_signed) { - offset = GCIP_FW_HEADER_SIZE; - size = (*fw)->size - GCIP_FW_HEADER_SIZE; - } else { - offset = 0; - size = (*fw)->size; + if (!is_signed_firmware(*fw, hdr)) { + dev_err(dev, "Invalid firmware format %s", fw_name); + ret = -EINVAL; + goto err_release_firmware; } + size = (*fw)->size - GCIP_FW_HEADER_SIZE; + if (size > mcu_fw->image_buf.size) { dev_err(dev, "firmware %s size %#zx exceeds buffer size %#llx", fw_name, size, mcu_fw->image_buf.size); @@ -116,43 +113,41 @@ int gxp_mcu_firmware_load(struct gxp_dev *gxp, char *fw_name, goto err_release_firmware; } - if (is_signed) { - imgcfg = get_image_config_from_hdr(hdr); - if (!imgcfg) { - dev_err(dev, "Unsupported image header generation"); - ret = -EINVAL; - goto err_release_firmware; - } - /* Initialize the secure telemetry buffers if available */ - if (imgcfg->secure_telemetry_region_start) { - ret = gxp_secure_core_telemetry_init( - gxp, imgcfg->secure_telemetry_region_start); - if (ret) - dev_warn( - dev, - "Secure telemetry initialization failed."); - } - ret = gcip_image_config_parse(&mcu_fw->cfg_parser, imgcfg); + imgcfg = get_image_config_from_hdr(hdr); + if (!imgcfg) { + dev_err(dev, "Unsupported image header generation"); + ret = -EINVAL; + goto err_release_firmware; + } + /* Initialize the secure telemetry buffers if available. */ + if (imgcfg->secure_telemetry_region_start) { + ret = gxp_secure_core_telemetry_init( + gxp, imgcfg->secure_telemetry_region_start); if (ret) - dev_err(dev, "image config parsing failed: %d", ret); - mcu_fw->is_secure = !gcip_image_config_is_ns(imgcfg); - } else { - ret = gxp_iommu_map(gxp, gxp_iommu_get_domain_for_dev(gxp), - mcu_fw->image_buf.daddr, - mcu_fw->image_buf.paddr, - mcu_fw->image_buf.size, - IOMMU_READ | IOMMU_WRITE); - mcu_fw->is_secure = false; + dev_warn(dev, + "Secure telemetry initialization failed."); } - - if (ret) + ret = gcip_image_config_parse(&mcu_fw->cfg_parser, imgcfg); + if (ret) { + dev_err(dev, "image config parsing failed: %d", ret); goto err_release_firmware; + } + if (!gcip_image_config_is_ns(imgcfg) && !gxp->gsa_dev) { + dev_err(dev, + "Can't run MCU in secure mode without the GSA device"); + ret = -EINVAL; + goto err_clear_config; + } + mcu_fw->is_secure = !gcip_image_config_is_ns(imgcfg); - memcpy(mcu_fw->image_buf.vaddr, (*fw)->data + offset, size); + memcpy(mcu_fw->image_buf.vaddr, (*fw)->data + GCIP_FW_HEADER_SIZE, + size); out: mutex_unlock(&mcu_fw->lock); return 0; +err_clear_config: + gcip_image_config_clear(&mcu_fw->cfg_parser); err_release_firmware: release_firmware(*fw); err_out: @@ -163,9 +158,7 @@ err_out: void gxp_mcu_firmware_unload(struct gxp_dev *gxp, const struct firmware *fw) { - struct gcip_common_image_header *hdr; struct gxp_mcu_firmware *mcu_fw = gxp_mcu_firmware_of(gxp); - bool is_signed; mutex_lock(&mcu_fw->lock); if (mcu_fw->status == GCIP_FW_INVALID) { @@ -173,15 +166,7 @@ void gxp_mcu_firmware_unload(struct gxp_dev *gxp, const struct firmware *fw) mutex_unlock(&mcu_fw->lock); return; } - hdr = (struct gcip_common_image_header *)fw->data; - is_signed = is_signed_firmware(fw, hdr); - if (is_signed) - gcip_image_config_clear(&mcu_fw->cfg_parser); - else - gxp_iommu_unmap(mcu_fw->gxp, - gxp_iommu_get_domain_for_dev(mcu_fw->gxp), - mcu_fw->image_buf.daddr, - mcu_fw->image_buf.size); + gcip_image_config_clear(&mcu_fw->cfg_parser); mcu_fw->status = GCIP_FW_INVALID; mutex_unlock(&mcu_fw->lock); } @@ -266,8 +251,10 @@ static int gxp_mcu_firmware_power_up(struct gxp_mcu_firmware *mcu_fw) if (mcu_fw->is_secure) { state = gsa_send_dsp_cmd(gxp->gsa_dev, GSA_DSP_START); - if (state != GSA_DSP_STATE_RUNNING) + if (state != GSA_DSP_STATE_RUNNING) { + ret = -EIO; goto err_lpm_down; + } } else { program_iremap_csr(gxp, &mcu_fw->image_buf); /* Raise wakeup doorbell */ @@ -9,11 +9,9 @@ #include <linux/bits.h> #include <linux/io.h> #include <linux/pm_runtime.h> -#include <linux/thermal.h> /* for fixing bug in gs_tmu_v3 */ #include <linux/types.h> #include <linux/workqueue.h> #include <soc/google/exynos_pm_qos.h> -#include <soc/google/gs_tmu_v3.h> #include <gcip/gcip-pm.h> @@ -26,6 +24,9 @@ #include "gxp-lpm.h" #include "gxp-pm.h" +#define DEBUGFS_BLK_POWERSTATE "blk_powerstate" +#define DEBUGFS_WAKELOCK "wakelock" + #define SHUTDOWN_DELAY_US_MIN 200 #define SHUTDOWN_DELAY_US_MAX 400 @@ -57,13 +58,6 @@ static const s32 aur_memory_state2mif_table[] = { 0, AUR_MEM_MIF_VERY_HIGH, AUR_MEM_MIF_MAX }; -static struct gxp_pm_device_ops gxp_aur_ops = { - .pre_blk_powerup = NULL, - .post_blk_powerup = NULL, - .pre_blk_poweroff = NULL, - .post_blk_poweroff = NULL, -}; - static int gxp_pm_blkpwr_up(struct gxp_dev *gxp) { int ret; @@ -80,13 +74,13 @@ static int gxp_pm_blkpwr_up(struct gxp_dev *gxp) ret); return ret; } - /* Inform TMU the block is up. */ - ret = set_acpm_tj_power_status(TZ_AUR, true); - if (ret) { - pm_runtime_put_sync(gxp->dev); - dev_err(gxp->dev, - "set Tj power status on blk up failed: %d\n", ret); - return ret; + if (gxp->power_mgr->ops->after_blk_power_up) { + ret = gxp->power_mgr->ops->after_blk_power_up(gxp); + if (ret) { + pm_runtime_put_sync(gxp->dev); + dev_err(gxp->dev, "after blk power up failed: %d", ret); + return ret; + } } return 0; } @@ -102,10 +96,8 @@ static int gxp_pm_blkpwr_down(struct gxp_dev *gxp) return -EAGAIN; } - ret = set_acpm_tj_power_status(TZ_AUR, false); - if (ret) - dev_err(gxp->dev, - "set Tj power status on blk down failed: %d\n", ret); + if (gxp->power_mgr->ops->before_blk_power_down) + gxp->power_mgr->ops->before_blk_power_down(gxp); ret = pm_runtime_put_sync(gxp->dev); if (ret) /* @@ -770,6 +762,93 @@ static int gxp_pm_power_down(void *data) return gxp_pm_blk_off(gxp); } +static int debugfs_wakelock_set(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + int ret = 0; + + mutex_lock(&gxp->debugfs_client_lock); + + if (val > 0) { + /* Wakelock Acquire */ + if (gxp->debugfs_wakelock_held) { + dev_warn(gxp->dev, + "Debugfs wakelock is already held.\n"); + ret = -EBUSY; + goto out; + } + + ret = gcip_pm_get(gxp->power_mgr->pm); + if (ret) { + dev_err(gxp->dev, "gcip_pm_get failed ret=%d\n", ret); + goto out; + } + gxp->debugfs_wakelock_held = true; + gxp_pm_update_requested_power_states(gxp, off_states, + uud_states); + } else { + /* Wakelock Release */ + if (!gxp->debugfs_wakelock_held) { + dev_warn(gxp->dev, "Debugfs wakelock not held.\n"); + ret = -EIO; + goto out; + } + + gcip_pm_put(gxp->power_mgr->pm); + gxp->debugfs_wakelock_held = false; + gxp_pm_update_requested_power_states(gxp, uud_states, + off_states); + } + +out: + mutex_unlock(&gxp->debugfs_client_lock); + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_wakelock_fops, NULL, debugfs_wakelock_set, + "%llx\n"); + +static int debugfs_blk_powerstate_set(void *data, u64 val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + int ret = 0; + + if (gxp_pm_get_blk_state(gxp) == AUR_OFF) { + dev_warn( + gxp->dev, + "Cannot set block power state when the block is off. Obtain a wakelock to power it on.\n"); + return -ENODEV; + } + + if (val >= AUR_DVFS_MIN_RATE) { + ret = gxp_pm_blk_set_rate_acpm(gxp, val); + } else { + ret = -EINVAL; + dev_err(gxp->dev, "Incorrect state %llu\n", val); + } + return ret; +} + +static int debugfs_blk_powerstate_get(void *data, u64 *val) +{ + struct gxp_dev *gxp = (struct gxp_dev *)data; + + if (gxp_pm_get_blk_state(gxp) == AUR_OFF) { + dev_warn( + gxp->dev, + "Cannot get block power state when the block is off.\n"); + return -ENODEV; + } + + *val = gxp_pm_blk_get_state_acpm(gxp); + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_blk_powerstate_fops, + debugfs_blk_powerstate_get, debugfs_blk_powerstate_set, + "%llx\n"); + int gxp_pm_init(struct gxp_dev *gxp) { struct gxp_power_manager *mgr; @@ -800,7 +879,7 @@ int gxp_pm_init(struct gxp_dev *gxp) mgr->curr_memory_state = AUR_MEM_UNDEFINED; mgr->curr_low_clkmux = false; mgr->last_scheduled_low_clkmux = false; - mgr->ops = &gxp_aur_ops; + gxp_pm_chip_set_ops(mgr); gxp->power_mgr = mgr; for (i = 0; i < AUR_NUM_POWER_STATE_WORKER; i++) { mgr->set_acpm_state_work[i].gxp = gxp; @@ -836,6 +915,13 @@ int gxp_pm_init(struct gxp_dev *gxp) pm_runtime_enable(gxp->dev); exynos_pm_qos_add_request(&mgr->int_min, PM_QOS_DEVICE_THROUGHPUT, 0); exynos_pm_qos_add_request(&mgr->mif_min, PM_QOS_BUS_THROUGHPUT, 0); + gxp_pm_chip_init(gxp); + + gxp->debugfs_wakelock_held = false; + debugfs_create_file(DEBUGFS_WAKELOCK, 0200, gxp->d_entry, gxp, + &debugfs_wakelock_fops); + debugfs_create_file(DEBUGFS_BLK_POWERSTATE, 0600, gxp->d_entry, gxp, + &debugfs_blk_powerstate_fops); return 0; } @@ -847,6 +933,9 @@ int gxp_pm_destroy(struct gxp_dev *gxp) if (IS_GXP_TEST && !mgr) return 0; + debugfs_remove(debugfs_lookup(DEBUGFS_BLK_POWERSTATE, gxp->d_entry)); + debugfs_remove(debugfs_lookup(DEBUGFS_WAKELOCK, gxp->d_entry)); + gcip_pm_destroy(mgr->pm); exynos_pm_qos_remove_request(&mgr->mif_min); @@ -7,6 +7,7 @@ #ifndef __GXP_PM_H__ #define __GXP_PM_H__ +#include <soc/google/bcl.h> #include <soc/google/exynos_pm_qos.h> #include <gcip/gcip-pm.h> @@ -69,11 +70,20 @@ enum aur_power_cmu_mux_state { #define AUR_NUM_POWER_STATE_WORKER 4 -struct gxp_pm_device_ops { - int (*pre_blk_powerup)(struct gxp_dev *gxp); - int (*post_blk_powerup)(struct gxp_dev *gxp); - int (*pre_blk_poweroff)(struct gxp_dev *gxp); - int (*post_blk_poweroff)(struct gxp_dev *gxp); +struct gxp_pm_ops { + /* + * This callback is called after pm_runtime_get*(). + * A non-zero return value could fail the block power up process. + * + * This callback is optional. + */ + int (*after_blk_power_up)(struct gxp_dev *gxp); + /* + * This callback is called before pm_runtime_put*(). + * + * This callback is optional. + */ + void (*before_blk_power_down)(struct gxp_dev *gxp); }; struct gxp_set_acpm_state_work { @@ -123,7 +133,7 @@ struct gxp_power_manager { bool last_scheduled_low_clkmux; int curr_state; int curr_memory_state; /* Note: this state will not be maintained in the MCU mode. */ - struct gxp_pm_device_ops *ops; + const struct gxp_pm_ops *ops; struct gxp_set_acpm_state_work set_acpm_state_work[AUR_NUM_POWER_STATE_WORKER]; /* Serializes searching for an open worker in set_acpm_state_work[] */ @@ -137,6 +147,8 @@ struct gxp_power_manager { /* INT/MIF requests for memory bandwidth */ struct exynos_pm_qos_request int_min; struct exynos_pm_qos_request mif_min; + /* BCL device handler. */ + struct bcl_device *bcl_dev; int force_mux_normal_count; /* Max frequency that the thermal driver/ACPM will allow in Hz */ unsigned long thermal_limit; @@ -328,4 +340,24 @@ void gxp_pm_resume_clkmux(struct gxp_dev *gxp); */ void gxp_pm_set_thermal_limit(struct gxp_dev *gxp, unsigned long thermal_limit); +/** + * gxp_pm_chip_set_ops() - Set the operations to the power manager, i.e. + * @mgr->ops. + * @mgr: The power manager to be set operations to + * + * This function is expected to be implemented by chip-dependent power + * management files but not by gxp-pm.c. + */ +void gxp_pm_chip_set_ops(struct gxp_power_manager *mgr); + +/** + * gxp_pm_chip_init() - Do chip-dependent power management initialization. + * @gxp: The GXP device + * + * This function is called as the last step of gxp_pm_init(). + * This function is expected to be implemented by chip-dependent power + * management files but not by gxp-pm.c. + */ +void gxp_pm_chip_init(struct gxp_dev *gxp); + #endif /* __GXP_PM_H__ */ diff --git a/gxp-trace.c b/gxp-trace.c new file mode 100644 index 0000000..4d0202d --- /dev/null +++ b/gxp-trace.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * GXP ftrace support. + * + * Copyright (C) 2023 Google LLC + */ + +#define CREATE_TRACE_POINTS +#include <trace/events/gxp.h> @@ -162,7 +162,7 @@ static void gxp_uci_mailbox_manager_release_unconsumed_async_resps( static void gxp_uci_mailbox_manager_set_ops(struct gxp_mailbox_manager *mgr) { - /* This operator will be used only from the gxp-debugfs.c. */ + /* This operator will be used only from the debugfs. */ mgr->execute_cmd = gxp_uci_mailbox_manager_execute_cmd; /* * Most mailbox manager operators are used by the `gxp-common-platform.c` when the device @@ -13,7 +13,7 @@ /* Interface Version */ #define GXP_INTERFACE_VERSION_MAJOR 1 -#define GXP_INTERFACE_VERSION_MINOR 13 +#define GXP_INTERFACE_VERSION_MINOR 14 #define GXP_INTERFACE_VERSION_BUILD 0 /* diff --git a/include/linux/gsa/gsa_dsp.h b/include/linux/gsa/gsa_dsp.h index 288adaf..7a77875 100644 --- a/include/linux/gsa/gsa_dsp.h +++ b/include/linux/gsa/gsa_dsp.h @@ -65,6 +65,8 @@ enum gsa_dsp_cmd { */ static inline int gsa_send_dsp_cmd(struct device *gsa, enum gsa_dsp_cmd cmd) { + if (cmd == GSA_DSP_START) + return GSA_DSP_STATE_RUNNING; return GSA_DSP_STATE_INACTIVE; } diff --git a/include/trace/events/gxp.h b/include/trace/events/gxp.h index 1e4257b..53e7a9d 100644 --- a/include/trace/events/gxp.h +++ b/include/trace/events/gxp.h @@ -11,8 +11,11 @@ #if !defined(_TRACE_GXP_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_GXP_H +#include <linux/stringify.h> #include <linux/tracepoint.h> +#define GXP_TRACE_SYSTEM __stringify(TRACE_SYSTEM) + TRACE_EVENT(gxp_dma_map_sg_start, TP_PROTO(int nents), |