summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurora zuma automerger <aurora-zuma-automerger@google.com>2023-04-11 07:52:58 +0000
committerCopybara-Service <copybara-worker@google.com>2023-04-17 11:07:31 -0700
commitd055791577688a8357ebecbff9abc74fe0426470 (patch)
tree41491e1f286eafacf1037b1ad03955d2fc68f79c
parent6bac35c4ca96b3ac798d00ac3c0c154e80752981 (diff)
downloadzuma-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-format246
-rw-r--r--Makefile3
-rw-r--r--callisto-pm.c52
-rw-r--r--gcip-kernel-driver/drivers/gcip/gcip-iommu.c18
-rw-r--r--gcip-kernel-driver/drivers/gcip/gcip-kci.c6
-rw-r--r--gcip-kernel-driver/drivers/gcip/gcip-mailbox.c25
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-mailbox.h21
-rw-r--r--gxp-common-platform.c118
-rw-r--r--gxp-core-telemetry.c73
-rw-r--r--gxp-debug-dump.c44
-rw-r--r--gxp-debugfs.c545
-rw-r--r--gxp-debugfs.h20
-rw-r--r--gxp-dma-iommu.c6
-rw-r--r--gxp-dma.h3
-rw-r--r--gxp-dmabuf.c2
-rw-r--r--gxp-firmware.c138
-rw-r--r--gxp-mailbox-driver.c4
-rw-r--r--gxp-mailbox-driver.h4
-rw-r--r--gxp-mailbox-manager.c107
-rw-r--r--gxp-mailbox-manager.h9
-rw-r--r--gxp-mcu-firmware.c89
-rw-r--r--gxp-pm.c131
-rw-r--r--gxp-pm.h44
-rw-r--r--gxp-trace.c9
-rw-r--r--gxp-uci.c2
-rw-r--r--gxp.h2
-rw-r--r--include/linux/gsa/gsa_dsp.h2
-rw-r--r--include/trace/events/gxp.h3
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
diff --git a/Makefile b/Makefile
index 37b6e30..4a24099 100644
--- a/Makefile
+++ b/Makefile
@@ -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;
diff --git a/gxp-dma.h b/gxp-dma.h
index 4dbc719..a489ef1 100644
--- a/gxp-dma.h
+++ b/gxp-dma.h
@@ -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 */
diff --git a/gxp-pm.c b/gxp-pm.c
index 1cf0782..4bb8072 100644
--- a/gxp-pm.c
+++ b/gxp-pm.c
@@ -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);
diff --git a/gxp-pm.h b/gxp-pm.h
index 217c3df..884f2b5 100644
--- a/gxp-pm.h
+++ b/gxp-pm.h
@@ -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>
diff --git a/gxp-uci.c b/gxp-uci.c
index 430422b..cc1fd3b 100644
--- a/gxp-uci.c
+++ b/gxp-uci.c
@@ -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
diff --git a/gxp.h b/gxp.h
index 44ce609..e4db89e 100644
--- a/gxp.h
+++ b/gxp.h
@@ -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),