summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNrithya Kanakasabapathy <nrithya@google.com>2021-05-05 17:27:38 +0000
committerNrithya Kanakasabapathy <nrithya@google.com>2021-05-05 17:27:38 +0000
commitc2a5f1fcc8911d94858bb48492a1b529f9a8e80e (patch)
treef6e4acf179bfed2d3fb08ba3e64e7b51c6e5bef9
parentf9b2ca71995a76c1b892d07b920b68cad2547a03 (diff)
downloadabrolhos-c2a5f1fcc8911d94858bb48492a1b529f9a8e80e.tar.gz
Merge branch 'whitechapel' into android-gs-pixel-5.10
* whitechapel: edgetpu: pin pages without FOLL_WRITE if the first try failed with EFAULT. clang-format: add .clang-format edgetpu: validate the circular_queue_count result edgetpu: validate the value of tail before using it edgetpu: add ioctl for external mailbox handshake edgetpu: add firmware state change lockout API edgetpu: fix group leave for dies that failed to load firmware edgetpu: fix overflow on number of pages edgetpu: KCI print return status code on error response edgetpu: check edgetpu_sync_fence_signal errno Change-Id: If418b09faaf3439b4b4a61b0adf648536f20e52e
-rw-r--r--.clang-format552
-rw-r--r--.gitignore1
-rw-r--r--drivers/edgetpu/abrolhos-device.c76
-rw-r--r--drivers/edgetpu/abrolhos-platform.c2
-rw-r--r--drivers/edgetpu/abrolhos-platform.h4
-rw-r--r--drivers/edgetpu/abrolhos-pm.c8
-rw-r--r--drivers/edgetpu/abrolhos/config-mailbox.h2
-rw-r--r--drivers/edgetpu/edgetpu-device-group.c22
-rw-r--r--drivers/edgetpu/edgetpu-dmabuf.c10
-rw-r--r--drivers/edgetpu/edgetpu-dram.h8
-rw-r--r--drivers/edgetpu/edgetpu-firmware.c117
-rw-r--r--drivers/edgetpu/edgetpu-firmware.h3
-rw-r--r--drivers/edgetpu/edgetpu-fs.c47
-rw-r--r--drivers/edgetpu/edgetpu-internal.h16
-rw-r--r--drivers/edgetpu/edgetpu-kci.c17
-rw-r--r--drivers/edgetpu/edgetpu-mailbox.c51
-rw-r--r--drivers/edgetpu/edgetpu-mailbox.h21
-rw-r--r--drivers/edgetpu/edgetpu-wakelock.c34
-rw-r--r--drivers/edgetpu/edgetpu-wakelock.h17
-rw-r--r--drivers/edgetpu/edgetpu.h52
20 files changed, 995 insertions, 65 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..c24b147
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,552 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# clang-format configuration file. Intended for clang-format >= 4.
+#
+# For more information, see:
+#
+# Documentation/process/clang-format.rst
+# https://clang.llvm.org/docs/ClangFormat.html
+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+#
+---
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
+AlignOperands: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ #AfterExternBlock: false # Unknown to clang-format-5.0
+ 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
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+#CompactNamespaces: false # Unknown to clang-format-4.0
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+#FixNamespaceComments: false # Unknown to clang-format-4.0
+
+# Taken from:
+# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
+# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
+# | sort | uniq
+ForEachMacros:
+ - '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_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_for_each_spilled_reg'
+ - 'btree_for_each_safe128'
+ - 'btree_for_each_safe32'
+ - 'btree_for_each_safe64'
+ - 'btree_for_each_safel'
+ - 'card_for_each_dev'
+ - 'cgroup_taskset_for_each'
+ - 'cgroup_taskset_for_each_leader'
+ - 'cpufreq_for_each_entry'
+ - 'cpufreq_for_each_entry_idx'
+ - 'cpufreq_for_each_valid_entry'
+ - 'cpufreq_for_each_valid_entry_idx'
+ - 'css_for_each_child'
+ - 'css_for_each_descendant_post'
+ - 'css_for_each_descendant_pre'
+ - 'cxl_for_each_cmd'
+ - 'device_for_each_child_node'
+ - 'dma_fence_chain_for_each'
+ - 'do_for_each_ftrace_op'
+ - 'drm_atomic_crtc_for_each_plane'
+ - 'drm_atomic_crtc_state_for_each_plane'
+ - 'drm_atomic_crtc_state_for_each_plane_state'
+ - 'drm_atomic_for_each_plane_damage'
+ - 'drm_client_for_each_connector_iter'
+ - 'drm_client_for_each_modeset'
+ - 'drm_connector_for_each_possible_encoder'
+ - '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'
+ - 'drm_for_each_legacy_plane'
+ - 'drm_for_each_plane'
+ - 'drm_for_each_plane_mask'
+ - 'drm_for_each_privobj'
+ - 'drm_mm_for_each_hole'
+ - 'drm_mm_for_each_node'
+ - 'drm_mm_for_each_node_in_range'
+ - 'drm_mm_for_each_node_safe'
+ - 'flow_action_for_each'
+ - '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_bio'
+ - 'for_each_board_func_rsrc'
+ - 'for_each_bvec'
+ - 'for_each_card_auxs'
+ - 'for_each_card_auxs_safe'
+ - 'for_each_card_components'
+ - 'for_each_card_dapms'
+ - 'for_each_card_pre_auxs'
+ - 'for_each_card_prelinks'
+ - 'for_each_card_rtds'
+ - 'for_each_card_rtds_safe'
+ - 'for_each_card_widgets'
+ - 'for_each_card_widgets_safe'
+ - 'for_each_cgroup_storage_type'
+ - 'for_each_child_of_node'
+ - 'for_each_clear_bit'
+ - 'for_each_clear_bit_from'
+ - 'for_each_cmsghdr'
+ - 'for_each_compatible_node'
+ - 'for_each_component_dais'
+ - 'for_each_component_dais_safe'
+ - 'for_each_comp_order'
+ - 'for_each_console'
+ - 'for_each_cpu'
+ - 'for_each_cpu_and'
+ - 'for_each_cpu_not'
+ - 'for_each_cpu_wrap'
+ - 'for_each_dapm_widgets'
+ - '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'
+ - 'for_each_dpcm_be_safe'
+ - 'for_each_dpcm_fe'
+ - 'for_each_drhd_unit'
+ - 'for_each_dss_dev'
+ - 'for_each_efi_memory_desc'
+ - 'for_each_efi_memory_desc_in_map'
+ - 'for_each_element'
+ - 'for_each_element_extid'
+ - 'for_each_element_id'
+ - 'for_each_endpoint_of_node'
+ - 'for_each_evictable_lru'
+ - 'for_each_fib6_node_rt_rcu'
+ - 'for_each_fib6_walker_rt'
+ - 'for_each_free_mem_pfn_range_in_zone'
+ - 'for_each_free_mem_pfn_range_in_zone_from'
+ - 'for_each_free_mem_range'
+ - 'for_each_free_mem_range_reverse'
+ - 'for_each_func_rsrc'
+ - 'for_each_hstate'
+ - 'for_each_if'
+ - 'for_each_iommu'
+ - 'for_each_ip_tunnel_rcu'
+ - 'for_each_irq_nr'
+ - '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_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_migratetype_order'
+ - 'for_each_msi_entry'
+ - 'for_each_msi_entry_safe'
+ - 'for_each_net'
+ - 'for_each_net_continue_reverse'
+ - 'for_each_netdev'
+ - 'for_each_netdev_continue'
+ - 'for_each_netdev_continue_rcu'
+ - 'for_each_netdev_continue_reverse'
+ - 'for_each_netdev_feature'
+ - 'for_each_netdev_in_bond_rcu'
+ - '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_private_obj_in_state'
+ - 'for_each_node'
+ - 'for_each_node_by_name'
+ - 'for_each_node_by_type'
+ - 'for_each_node_mask'
+ - 'for_each_node_state'
+ - 'for_each_node_with_cpus'
+ - 'for_each_node_with_property'
+ - 'for_each_nonreserved_multicast_dest_pgid'
+ - 'for_each_of_allnodes'
+ - 'for_each_of_allnodes_from'
+ - 'for_each_of_cpu_node'
+ - 'for_each_of_pci_range'
+ - 'for_each_old_connector_in_state'
+ - 'for_each_old_crtc_in_state'
+ - 'for_each_old_mst_mgr_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_pci_bridge'
+ - 'for_each_pci_dev'
+ - 'for_each_pci_msi_entry'
+ - 'for_each_pcm_streams'
+ - 'for_each_physmem_range'
+ - 'for_each_populated_zone'
+ - 'for_each_possible_cpu'
+ - 'for_each_present_cpu'
+ - 'for_each_prime_number'
+ - 'for_each_prime_number_from'
+ - 'for_each_process'
+ - 'for_each_process_thread'
+ - 'for_each_property_of_node'
+ - '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_components'
+ - 'for_each_rtd_cpu_dais'
+ - 'for_each_rtd_dais'
+ - 'for_each_set_bit'
+ - 'for_each_set_bit_from'
+ - 'for_each_set_clump8'
+ - 'for_each_sg'
+ - 'for_each_sg_dma_page'
+ - 'for_each_sg_page'
+ - 'for_each_sgtable_dma_page'
+ - 'for_each_sgtable_dma_sg'
+ - 'for_each_sgtable_page'
+ - 'for_each_sgtable_sg'
+ - 'for_each_sibling_event'
+ - 'for_each_subelement'
+ - 'for_each_subelement_extid'
+ - 'for_each_subelement_id'
+ - '__for_each_thread'
+ - 'for_each_thread'
+ - 'for_each_unicast_dest_pgid'
+ - 'for_each_vsi'
+ - 'for_each_wakeup_source'
+ - 'for_each_zone'
+ - 'for_each_zone_zonelist'
+ - 'for_each_zone_zonelist_nodemask'
+ - 'fwnode_for_each_available_child_node'
+ - 'fwnode_for_each_child_node'
+ - 'fwnode_graph_for_each_endpoint'
+ - 'gadget_for_each_ep'
+ - 'genradix_for_each'
+ - 'genradix_for_each_from'
+ - 'hash_for_each'
+ - 'hash_for_each_possible'
+ - 'hash_for_each_possible_rcu'
+ - 'hash_for_each_possible_rcu_notrace'
+ - 'hash_for_each_possible_safe'
+ - 'hash_for_each_rcu'
+ - 'hash_for_each_safe'
+ - 'hctx_for_each_ctx'
+ - 'hlist_bl_for_each_entry'
+ - 'hlist_bl_for_each_entry_rcu'
+ - 'hlist_bl_for_each_entry_safe'
+ - 'hlist_for_each'
+ - 'hlist_for_each_entry'
+ - 'hlist_for_each_entry_continue'
+ - 'hlist_for_each_entry_continue_rcu'
+ - 'hlist_for_each_entry_continue_rcu_bh'
+ - 'hlist_for_each_entry_from'
+ - 'hlist_for_each_entry_from_rcu'
+ - 'hlist_for_each_entry_rcu'
+ - 'hlist_for_each_entry_rcu_bh'
+ - 'hlist_for_each_entry_rcu_notrace'
+ - 'hlist_for_each_entry_safe'
+ - 'hlist_for_each_entry_srcu'
+ - '__hlist_for_each_rcu'
+ - 'hlist_for_each_safe'
+ - 'hlist_nulls_for_each_entry'
+ - 'hlist_nulls_for_each_entry_from'
+ - 'hlist_nulls_for_each_entry_rcu'
+ - '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'
+ - 'idr_for_each_entry_ul'
+ - 'in_dev_for_each_ifa_rcu'
+ - 'in_dev_for_each_ifa_rtnl'
+ - 'inet_bind_bucket_for_each'
+ - 'inet_lhash2_for_each_icsk_rcu'
+ - 'key_for_each'
+ - 'key_for_each_safe'
+ - 'klp_for_each_func'
+ - 'klp_for_each_func_safe'
+ - 'klp_for_each_func_static'
+ - 'klp_for_each_object'
+ - 'klp_for_each_object_safe'
+ - 'klp_for_each_object_static'
+ - 'kunit_suite_for_each_test_case'
+ - 'kvm_for_each_memslot'
+ - 'kvm_for_each_vcpu'
+ - 'list_for_each'
+ - 'list_for_each_codec'
+ - 'list_for_each_codec_safe'
+ - 'list_for_each_continue'
+ - 'list_for_each_entry'
+ - 'list_for_each_entry_continue'
+ - 'list_for_each_entry_continue_rcu'
+ - 'list_for_each_entry_continue_reverse'
+ - 'list_for_each_entry_from'
+ - 'list_for_each_entry_from_rcu'
+ - 'list_for_each_entry_from_reverse'
+ - 'list_for_each_entry_lockless'
+ - 'list_for_each_entry_rcu'
+ - 'list_for_each_entry_reverse'
+ - 'list_for_each_entry_safe'
+ - '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_prev'
+ - 'list_for_each_prev_safe'
+ - 'list_for_each_safe'
+ - 'llist_for_each'
+ - 'llist_for_each_entry'
+ - 'llist_for_each_entry_safe'
+ - 'llist_for_each_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'
+ - 'nanddev_io_for_each_page'
+ - 'netdev_for_each_lower_dev'
+ - 'netdev_for_each_lower_private'
+ - 'netdev_for_each_lower_private_rcu'
+ - 'netdev_for_each_mc_addr'
+ - 'netdev_for_each_uc_addr'
+ - 'netdev_for_each_upper_dev_rcu'
+ - 'netdev_hw_addr_list_for_each'
+ - 'nft_rule_for_each_expr'
+ - 'nla_for_each_attr'
+ - 'nla_for_each_nested'
+ - 'nlmsg_for_each_attr'
+ - 'nlmsg_for_each_msg'
+ - 'nr_neigh_for_each'
+ - 'nr_neigh_for_each_safe'
+ - 'nr_node_for_each'
+ - 'nr_node_for_each_safe'
+ - 'of_for_each_phandle'
+ - 'of_property_for_each_string'
+ - 'of_property_for_each_u32'
+ - 'pci_bus_for_each_resource'
+ - 'pcl_for_each_chunk'
+ - 'pcl_for_each_segment'
+ - 'pcm_for_each_format'
+ - 'ping_portaddr_for_each_entry'
+ - 'plist_for_each'
+ - 'plist_for_each_continue'
+ - 'plist_for_each_entry'
+ - 'plist_for_each_entry_continue'
+ - 'plist_for_each_entry_safe'
+ - 'plist_for_each_safe'
+ - 'pnp_for_each_card'
+ - 'pnp_for_each_dev'
+ - 'protocol_for_each_card'
+ - 'protocol_for_each_dev'
+ - 'queue_for_each_hw_ctx'
+ - 'radix_tree_for_each_slot'
+ - 'radix_tree_for_each_tagged'
+ - 'rbtree_postorder_for_each_entry_safe'
+ - 'rdma_for_each_block'
+ - 'rdma_for_each_port'
+ - 'rdma_umem_for_each_dma_block'
+ - 'resource_list_for_each_entry'
+ - 'resource_list_for_each_entry_safe'
+ - 'rhl_for_each_entry_rcu'
+ - 'rhl_for_each_rcu'
+ - 'rht_for_each'
+ - 'rht_for_each_entry'
+ - 'rht_for_each_entry_from'
+ - 'rht_for_each_entry_rcu'
+ - 'rht_for_each_entry_rcu_from'
+ - 'rht_for_each_entry_safe'
+ - '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'
+ - 'scsi_for_each_prot_sg'
+ - 'scsi_for_each_sg'
+ - 'sctp_for_each_hentry'
+ - 'sctp_skb_for_each'
+ - 'shdma_for_each_chan'
+ - '__shost_for_each_device'
+ - 'shost_for_each_device'
+ - 'sk_for_each'
+ - 'sk_for_each_bound'
+ - 'sk_for_each_entry_offset_rcu'
+ - 'sk_for_each_from'
+ - 'sk_for_each_rcu'
+ - 'sk_for_each_safe'
+ - 'sk_nulls_for_each'
+ - 'sk_nulls_for_each_from'
+ - 'sk_nulls_for_each_rcu'
+ - 'snd_array_for_each'
+ - 'snd_pcm_group_for_each_entry'
+ - 'snd_soc_dapm_widget_for_each_path'
+ - 'snd_soc_dapm_widget_for_each_path_safe'
+ - 'snd_soc_dapm_widget_for_each_sink_path'
+ - 'snd_soc_dapm_widget_for_each_source_path'
+ - 'tb_property_for_each'
+ - 'tcf_exts_for_each_action'
+ - 'udp_portaddr_for_each_entry'
+ - 'udp_portaddr_for_each_entry_rcu'
+ - 'usb_hub_for_each_child'
+ - 'v4l2_device_for_each_subdev'
+ - 'v4l2_m2m_for_each_dst_buf'
+ - 'v4l2_m2m_for_each_dst_buf_safe'
+ - 'v4l2_m2m_for_each_src_buf'
+ - 'v4l2_m2m_for_each_src_buf_safe'
+ - 'virtio_device_for_each_vq'
+ - 'while_for_each_ftrace_op'
+ - 'xa_for_each'
+ - 'xa_for_each_marked'
+ - 'xa_for_each_range'
+ - 'xa_for_each_start'
+ - 'xas_for_each'
+ - 'xas_for_each_conflict'
+ - 'xas_for_each_marked'
+ - 'xbc_array_for_each_value'
+ - 'xbc_for_each_key_value'
+ - 'xbc_node_for_each_array_value'
+ - 'xbc_node_for_each_child'
+ - 'xbc_node_for_each_key_value'
+ - 'zorro_for_each_dev'
+
+#IncludeBlocks: Preserve # Unknown to clang-format-5.0
+IncludeCategories:
+ - Regex: '.*'
+ Priority: 1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+#IndentPPDirectives: None # Unknown to clang-format-5.0
+IndentWidth: 8
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
+ObjCBlockIndentWidth: 8
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: true
+
+# Taken from git's rules
+#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakString: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 60
+
+PointerAlignment: Right
+ReflowComments: false
+SortIncludes: false
+#SortUsingDeclarations: false # Unknown to clang-format-4.0
+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
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp03
+TabWidth: 8
+UseTab: Always
+...
diff --git a/.gitignore b/.gitignore
index 0c39aa2..778e659 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,7 @@ Module.symvers
#
!.gitignore
!.mailmap
+!.clang-format
!.cocciconfig
#
diff --git a/drivers/edgetpu/abrolhos-device.c b/drivers/edgetpu/abrolhos-device.c
index 8d08e33..1f7bdc3 100644
--- a/drivers/edgetpu/abrolhos-device.c
+++ b/drivers/edgetpu/abrolhos-device.c
@@ -7,13 +7,14 @@
#include <linux/irqreturn.h>
+#include "abrolhos-platform.h"
+#include "abrolhos-pm.h"
#include "edgetpu-config.h"
#include "edgetpu-debug-dump.h"
#include "edgetpu-internal.h"
#include "edgetpu-mailbox.h"
-#include "abrolhos-platform.h"
-#include "abrolhos-pm.h"
#include "edgetpu-telemetry.h"
+#include "edgetpu-wakelock.h"
#define HOST_NONSECURE_INTRSRCMASKREG 0x000f0004
@@ -168,3 +169,74 @@ void edgetpu_chip_handle_reverse_kci(struct edgetpu_dev *etdev,
break;
}
}
+
+static int abrolhos_check_ext_mailbox_args(const char *func,
+ struct edgetpu_dev *etdev,
+ struct edgetpu_ext_mailbox *ext_mbox)
+{
+ if (ext_mbox->type != EDGETPU_EXT_MAILBOX_TYPE_TZ) {
+ etdev_err(etdev, "%s: Invalid type %d != %d\n", func,
+ ext_mbox->type, EDGETPU_EXT_MAILBOX_TYPE_TZ);
+ return -EINVAL;
+ }
+ if (ext_mbox->count != 1) {
+ etdev_err(etdev, "%s: Invalid mailbox count: %d != 1\n", func,
+ ext_mbox->count);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int edgetpu_chip_acquire_ext_mailbox(struct edgetpu_client *client,
+ struct edgetpu_ext_mailbox *ext_mbox)
+{
+ struct abrolhos_platform_dev *apdev = to_abrolhos_dev(client->etdev);
+ int ret;
+
+ ret = abrolhos_check_ext_mailbox_args(__func__, client->etdev,
+ ext_mbox);
+ if (ret)
+ return ret;
+
+ mutex_lock(&apdev->tz_mailbox_lock);
+ if (apdev->secure_client) {
+ etdev_err(client->etdev,
+ "TZ mailbox already in use by PID %d\n",
+ apdev->secure_client->pid);
+ mutex_unlock(&apdev->tz_mailbox_lock);
+ return -EBUSY;
+ }
+ apdev->secure_client = client;
+ ret = edgetpu_mailbox_enable_ext(client, ABROLHOS_TZ_MAILBOX_ID);
+ mutex_unlock(&apdev->tz_mailbox_lock);
+ return ret;
+}
+
+int edgetpu_chip_release_ext_mailbox(struct edgetpu_client *client,
+ struct edgetpu_ext_mailbox *ext_mbox)
+{
+ struct abrolhos_platform_dev *apdev = to_abrolhos_dev(client->etdev);
+ int ret = 0;
+
+ ret = abrolhos_check_ext_mailbox_args(__func__, client->etdev,
+ ext_mbox);
+ if (ret)
+ return ret;
+
+ mutex_lock(&apdev->tz_mailbox_lock);
+ if (!apdev->secure_client) {
+ etdev_err(client->etdev, "TZ mailbox already released\n");
+ mutex_unlock(&apdev->tz_mailbox_lock);
+ return -ENODEV;
+ }
+ if (apdev->secure_client != client) {
+ etdev_err(client->etdev,
+ "TZ mailbox owned by different client\n");
+ mutex_unlock(&apdev->tz_mailbox_lock);
+ return -EBUSY;
+ }
+ apdev->secure_client = NULL;
+ ret = edgetpu_mailbox_disable_ext(client, ABROLHOS_TZ_MAILBOX_ID);
+ mutex_unlock(&apdev->tz_mailbox_lock);
+ return ret;
+}
diff --git a/drivers/edgetpu/abrolhos-platform.c b/drivers/edgetpu/abrolhos-platform.c
index 2661853..a613b63 100644
--- a/drivers/edgetpu/abrolhos-platform.c
+++ b/drivers/edgetpu/abrolhos-platform.c
@@ -218,6 +218,8 @@ static int edgetpu_platform_probe(struct platform_device *pdev)
if (!abpdev)
return -ENOMEM;
+ mutex_init(&abpdev->tz_mailbox_lock);
+
platform_set_drvdata(pdev, &abpdev->edgetpu_dev);
abpdev->edgetpu_dev.dev = dev;
diff --git a/drivers/edgetpu/abrolhos-platform.h b/drivers/edgetpu/abrolhos-platform.h
index 84e155e..039a44d 100644
--- a/drivers/edgetpu/abrolhos-platform.h
+++ b/drivers/edgetpu/abrolhos-platform.h
@@ -56,6 +56,10 @@ struct abrolhos_platform_dev {
struct edgetpu_coherent_mem trace_mem;
struct abrolhos_sscd_info sscd_info;
struct gs101_bcl_dev *bcl_dev;
+ /* Protects TZ Mailbox client pointer */
+ struct mutex tz_mailbox_lock;
+ /* TZ mailbox client */
+ struct edgetpu_client *secure_client;
};
#endif /* __ABROLHOS_PLATFORM_H__ */
diff --git a/drivers/edgetpu/abrolhos-pm.c b/drivers/edgetpu/abrolhos-pm.c
index 0562f30..e9b3458 100644
--- a/drivers/edgetpu/abrolhos-pm.c
+++ b/drivers/edgetpu/abrolhos-pm.c
@@ -611,6 +611,14 @@ static void abrolhos_power_down(struct edgetpu_pm *etpm)
exynos_pm_qos_update_request(&platform_pwr->mif_min, 0);
abrolhos_pm_cleanup_bts_scenario(etdev);
+
+ /*
+ * A client closing the edgetpu device or crashing can leave the
+ * TZ mailbox in acquired state, but firmware loses state on power down.
+ * Clear the state here just in case.
+ */
+ abpdev->secure_client = NULL;
+
}
static int abrolhos_pm_after_create(struct edgetpu_pm *etpm)
diff --git a/drivers/edgetpu/abrolhos/config-mailbox.h b/drivers/edgetpu/abrolhos/config-mailbox.h
index 7ec0ee6..b19cf46 100644
--- a/drivers/edgetpu/abrolhos/config-mailbox.h
+++ b/drivers/edgetpu/abrolhos/config-mailbox.h
@@ -14,6 +14,8 @@
#define EDGETPU_NUM_VII_MAILBOXES (EDGETPU_NUM_MAILBOXES - 1)
#define EDGETPU_NUM_P2P_MAILBOXES 0
+#define ABROLHOS_TZ_MAILBOX_ID (1 << 8)
+
#define ABROLHOS_CSR_MBOX2_CONTEXT_ENABLE 0xe0000
#define ABROLHOS_CSR_MBOX2_CMD_QUEUE_DOORBELL_SET 0xe1000
#define ABROLHOS_CSR_MBOX2_RESP_QUEUE_DOORBELL_SET 0xe1800
diff --git a/drivers/edgetpu/edgetpu-device-group.c b/drivers/edgetpu/edgetpu-device-group.c
index ba13c85..9c93c0b 100644
--- a/drivers/edgetpu/edgetpu-device-group.c
+++ b/drivers/edgetpu/edgetpu-device-group.c
@@ -613,10 +613,14 @@ void edgetpu_device_group_leave(struct edgetpu_client *client)
{
mutex_lock(&client->etdev->state_lock);
/*
- * The only chance that the state is not GOOD here is the wdt timeout
- * action is working. Let that worker perform the group leaving.
+ * State might not be GOOD here if the wdt timeout
+ * action is working or initial fw load failed. If wdt worker
+ * is running let it perform the group leaving.
*/
- if (client->etdev->state == ETDEV_STATE_GOOD)
+ etdev_dbg(client->etdev, "%s: state=%u\n",
+ __func__, client->etdev->state);
+ if (client->etdev->state == ETDEV_STATE_GOOD ||
+ client->etdev->state == ETDEV_STATE_NOFW)
edgetpu_device_group_leave_locked(client);
mutex_unlock(&client->etdev->state_lock);
}
@@ -1102,7 +1106,7 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
return ERR_PTR(-EINVAL);
offset = host_addr & (PAGE_SIZE - 1);
/* overflow check */
- if (unlikely(size + offset < size))
+ if (unlikely(size / PAGE_SIZE >= UINT_MAX || size + offset < size))
return ERR_PTR(-ENOMEM);
num_pages = (size + offset) / PAGE_SIZE;
if ((size + offset) % PAGE_SIZE)
@@ -1123,6 +1127,16 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
*/
ret = pin_user_pages_fast(host_addr & PAGE_MASK, num_pages,
FOLL_WRITE | FOLL_LONGTERM, pages);
+
+ /*
+ * TODO(b/186876297): finds a way to detect the read / write permission.
+ * The host pages might be read-only and could fail if we attempt to pin
+ * it with FOLL_WRITE. Removes it and tries again.
+ */
+ if (ret == -EFAULT)
+ ret = pin_user_pages_fast(host_addr & PAGE_MASK, num_pages,
+ FOLL_LONGTERM, pages);
+
if (ret < 0) {
etdev_dbg(etdev, "get user pages failed %u:%pK-%u: %d",
group->workload_id, (void *)host_addr, num_pages,
diff --git a/drivers/edgetpu/edgetpu-dmabuf.c b/drivers/edgetpu/edgetpu-dmabuf.c
index f5c5a62..c2bf3ae 100644
--- a/drivers/edgetpu/edgetpu-dmabuf.c
+++ b/drivers/edgetpu/edgetpu-dmabuf.c
@@ -955,13 +955,15 @@ int edgetpu_sync_fence_signal(struct edgetpu_signal_sync_fence_data *datap)
int errno;
int ret;
- fence = sync_file_get_fence(datap->fence);
- if (!fence)
- return -EINVAL;
-
errno = datap->error;
if (errno > 0)
errno = -errno;
+ if (errno < -MAX_ERRNO)
+ return -EINVAL;
+
+ fence = sync_file_get_fence(datap->fence);
+ if (!fence)
+ return -EINVAL;
spin_lock_irq(fence->lock);
pr_debug("%s: %s-%s%llu-" SEQ_FMT " errno=%d\n", __func__,
diff --git a/drivers/edgetpu/edgetpu-dram.h b/drivers/edgetpu/edgetpu-dram.h
index 8df49e8..9e944c7 100644
--- a/drivers/edgetpu/edgetpu-dram.h
+++ b/drivers/edgetpu/edgetpu-dram.h
@@ -70,6 +70,9 @@ void edgetpu_device_dram_dmabuf_info_show(struct dma_buf *dmabuf,
/* Return amount of on-device DRAM currently used in bytes. */
size_t edgetpu_device_dram_used(struct edgetpu_dev *etdev);
+/* Return the amount of free device dram in bytes */
+size_t edgetpu_device_dram_available(struct edgetpu_dev *etdev);
+
#else /* !CONFIG_EDGETPU_DEVICE_DRAM */
static inline int edgetpu_device_dram_init(struct edgetpu_dev *etdev)
@@ -127,6 +130,11 @@ static inline size_t edgetpu_device_dram_used(struct edgetpu_dev *etdev)
{
return 0;
}
+
+static inline size_t edgetpu_device_dram_available(struct edgetpu_dev *etdev)
+{
+ return 0;
+}
#endif /* CONFIG_EDGETPU_DEVICE_DRAM */
#endif /* __EDGETPU_DRAM_H__ */
diff --git a/drivers/edgetpu/edgetpu-firmware.c b/drivers/edgetpu/edgetpu-firmware.c
index ded7cc7..3b1c874 100644
--- a/drivers/edgetpu/edgetpu-firmware.c
+++ b/drivers/edgetpu/edgetpu-firmware.c
@@ -312,6 +312,73 @@ edgetpu_firmware_get_build_time(struct edgetpu_firmware *et_fw)
return et_fw->p->fw_info.fw_build_time;
}
+/*
+ * Grab firmware lock to protect against firmware state changes.
+ * Locks out firmware loading / unloading while caller performs ops that are
+ * incompatible with a change in firmware status. Does not care whether or not
+ * the device is joined to a group.
+ */
+int edgetpu_firmware_lock(struct edgetpu_dev *etdev)
+{
+ struct edgetpu_firmware *et_fw = etdev->firmware;
+
+ if (!et_fw)
+ return -EINVAL;
+ mutex_lock(&et_fw->p->fw_desc_lock);
+ return 0;
+}
+
+/* Drop f/w lock, let any pending firmware load proceed. */
+void edgetpu_firmware_unlock(struct edgetpu_dev *etdev)
+{
+ struct edgetpu_firmware *et_fw = etdev->firmware;
+
+ if (!et_fw)
+ return;
+ mutex_unlock(&et_fw->p->fw_desc_lock);
+}
+
+/*
+ * Lock firmware for loading. Disallow group join for device during load.
+ * Failed if device is already joined to a group and is in use.
+ */
+static int edgetpu_firmware_load_lock(struct edgetpu_dev *etdev)
+{
+ struct edgetpu_firmware *et_fw = etdev->firmware;
+
+ if (!et_fw) {
+ etdev_err(
+ etdev,
+ "Cannot load firmware when no loader is available\n");
+ return -EINVAL;
+ }
+ mutex_lock(&et_fw->p->fw_desc_lock);
+
+ /* Disallow group join while loading, fail if already joined */
+ if (!edgetpu_set_group_join_lockout(etdev, true)) {
+ etdev_err(
+ etdev,
+ "Cannot load firmware because device is in use");
+ mutex_unlock(&et_fw->p->fw_desc_lock);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+/* Unlock firmware after lock held for loading, re-allow group join. */
+static void edgetpu_firmware_load_unlock(struct edgetpu_dev *etdev)
+{
+ struct edgetpu_firmware *et_fw = etdev->firmware;
+
+ if (!et_fw) {
+ etdev_dbg(etdev,
+ "Unlock firmware when no loader available\n");
+ return;
+ }
+ edgetpu_set_group_join_lockout(etdev, false);
+ mutex_unlock(&et_fw->p->fw_desc_lock);
+}
+
int edgetpu_firmware_run_locked(struct edgetpu_firmware *et_fw,
const char *name,
enum edgetpu_firmware_flags flags)
@@ -387,7 +454,7 @@ int edgetpu_firmware_run(struct edgetpu_dev *etdev, const char *name,
prev_state = etdev->state;
etdev->state = ETDEV_STATE_FWLOADING;
mutex_unlock(&etdev->state_lock);
- ret = edgetpu_firmware_lock(etdev);
+ ret = edgetpu_firmware_load_lock(etdev);
if (ret) {
etdev_err(etdev, "%s: lock failed (%d)\n", __func__, ret);
mutex_lock(&etdev->state_lock);
@@ -408,7 +475,7 @@ int edgetpu_firmware_run(struct edgetpu_dev *etdev, const char *name,
ret = edgetpu_firmware_run_locked(et_fw, name, flags);
etdev->firmware = et_fw;
edgetpu_pm_put(etdev->pm);
- edgetpu_firmware_unlock(etdev);
+ edgetpu_firmware_load_unlock(etdev);
mutex_lock(&etdev->state_lock);
if (ret == -EIO)
@@ -422,42 +489,7 @@ int edgetpu_firmware_run(struct edgetpu_dev *etdev, const char *name,
return ret;
}
-int edgetpu_firmware_lock(struct edgetpu_dev *etdev)
-{
- struct edgetpu_firmware *et_fw = etdev->firmware;
-
- if (!et_fw) {
- etdev_err(
- etdev,
- "Cannot load firmware when no loader is available\n");
- return -EINVAL;
- }
- mutex_lock(&et_fw->p->fw_desc_lock);
-
- /* Disallow group join while loading, fail if already joined */
- if (!edgetpu_set_group_join_lockout(etdev, true)) {
- etdev_err(
- etdev,
- "Cannot load firmware because device is in use");
- mutex_unlock(&et_fw->p->fw_desc_lock);
- return -EBUSY;
- }
- return 0;
-}
-
-void edgetpu_firmware_unlock(struct edgetpu_dev *etdev)
-{
- struct edgetpu_firmware *et_fw = etdev->firmware;
-
- if (!et_fw) {
- etdev_dbg(etdev,
- "Unlock firmware when no loader available\n");
- return;
- }
- edgetpu_set_group_join_lockout(etdev, false);
- mutex_unlock(&et_fw->p->fw_desc_lock);
-}
-
+/* Caller must hold firmware lock. */
enum edgetpu_firmware_status
edgetpu_firmware_status_locked(struct edgetpu_dev *etdev)
{
@@ -468,6 +500,7 @@ edgetpu_firmware_status_locked(struct edgetpu_dev *etdev)
return et_fw->p->status;
}
+/* Caller must hold firmware lock for loading. */
int edgetpu_firmware_restart_locked(struct edgetpu_dev *etdev)
{
struct edgetpu_firmware *et_fw = etdev->firmware;
@@ -680,10 +713,10 @@ static void edgetpu_firmware_wdt_timeout_action(void *data)
edgetpu_abort_clients(etdev);
- ret = edgetpu_firmware_lock(etdev);
+ ret = edgetpu_firmware_load_lock(etdev);
/*
- * edgetpu_firmware_lock() should always return success here as etdev
- * is already removed from all groups and fw loader exists.
+ * edgetpu_firmware_load_lock() should always return success here as
+ * etdev is already removed from all groups and fw loader exists.
*/
if (ret) {
etdev_err(etdev, "%s: lock failed (%d)\n", __func__, ret);
@@ -694,7 +727,7 @@ static void edgetpu_firmware_wdt_timeout_action(void *data)
if (!ret)
ret = edgetpu_firmware_restart_locked(etdev);
edgetpu_pm_put(etdev->pm);
- edgetpu_firmware_unlock(etdev);
+ edgetpu_firmware_load_unlock(etdev);
mutex_lock(&etdev->state_lock);
if (ret == -EIO)
diff --git a/drivers/edgetpu/edgetpu-firmware.h b/drivers/edgetpu/edgetpu-firmware.h
index 477d1a5..d068d29 100644
--- a/drivers/edgetpu/edgetpu-firmware.h
+++ b/drivers/edgetpu/edgetpu-firmware.h
@@ -205,7 +205,8 @@ void edgetpu_firmware_unlock(struct edgetpu_dev *etdev);
/*
- * Returns the state of the firmware image currently loaded for this device
+ * Returns the state of the firmware image currently loaded for this device.
+ * Caller must hold firmware lock.
*/
enum edgetpu_firmware_status
edgetpu_firmware_status_locked(struct edgetpu_dev *etdev);
diff --git a/drivers/edgetpu/edgetpu-fs.c b/drivers/edgetpu/edgetpu-fs.c
index 3966226..265d5b2 100644
--- a/drivers/edgetpu/edgetpu-fs.c
+++ b/drivers/edgetpu/edgetpu-fs.c
@@ -620,6 +620,43 @@ error_release:
return ret;
}
+static int
+edgetpu_ioctl_dram_usage(struct edgetpu_dev *etdev,
+ struct edgetpu_device_dram_usage __user *argp)
+{
+ struct edgetpu_device_dram_usage dram;
+
+ dram.allocated = edgetpu_device_dram_used(etdev);
+ dram.available = edgetpu_device_dram_available(etdev);
+ if (copy_to_user(argp, &dram, sizeof(*argp)))
+ return -EFAULT;
+ return 0;
+}
+
+static int
+edgetpu_ioctl_acquire_ext_mailbox(struct edgetpu_client *client,
+ struct edgetpu_ext_mailbox __user *argp)
+{
+ struct edgetpu_ext_mailbox ext_mailbox;
+
+ if (copy_from_user(&ext_mailbox, argp, sizeof(ext_mailbox)))
+ return -EFAULT;
+
+ return edgetpu_chip_acquire_ext_mailbox(client, &ext_mailbox);
+}
+
+static int
+edgetpu_ioctl_release_ext_mailbox(struct edgetpu_client *client,
+ struct edgetpu_ext_mailbox __user *argp)
+{
+ struct edgetpu_ext_mailbox ext_mailbox;
+
+ if (copy_from_user(&ext_mailbox, argp, sizeof(ext_mailbox)))
+ return -EFAULT;
+
+ return edgetpu_chip_release_ext_mailbox(client, &ext_mailbox);
+}
+
long edgetpu_ioctl(struct file *file, uint cmd, ulong arg)
{
struct edgetpu_client *client = file->private_data;
@@ -699,6 +736,16 @@ long edgetpu_ioctl(struct file *file, uint cmd, ulong arg)
case EDGETPU_GET_TPU_TIMESTAMP:
ret = edgetpu_ioctl_tpu_timestamp(client, argp);
break;
+ case EDGETPU_GET_DRAM_USAGE:
+ ret = edgetpu_ioctl_dram_usage(client->etdev, argp);
+ break;
+ case EDGETPU_ACQUIRE_EXT_MAILBOX:
+ ret = edgetpu_ioctl_acquire_ext_mailbox(client, argp);
+ break;
+ case EDGETPU_RELEASE_EXT_MAILBOX:
+ ret = edgetpu_ioctl_release_ext_mailbox(client, argp);
+ break;
+
default:
return -ENOTTY; /* unknown command */
}
diff --git a/drivers/edgetpu/edgetpu-internal.h b/drivers/edgetpu/edgetpu-internal.h
index 1a8cc35..dc83dd4 100644
--- a/drivers/edgetpu/edgetpu-internal.h
+++ b/drivers/edgetpu/edgetpu-internal.h
@@ -416,4 +416,20 @@ void edgetpu_mark_probe_fail(struct edgetpu_dev *etdev);
*/
int edgetpu_get_state_errno_locked(struct edgetpu_dev *etdev);
+/*
+ * "External mailboxes" below refers to mailboxes that are not handled
+ * directly by the DarwiNN runtime, such as secure or device-to-device.
+ *
+ * Chip specific code will typically keep track of state and inform the firmware
+ * that a mailbox has become active/inactive.
+ */
+
+/* Chip-specific code to acquire external mailboxes */
+int edgetpu_chip_acquire_ext_mailbox(struct edgetpu_client *client,
+ struct edgetpu_ext_mailbox *ext_mbox);
+
+/* Chip-specific code to release external mailboxes */
+int edgetpu_chip_release_ext_mailbox(struct edgetpu_client *client,
+ struct edgetpu_ext_mailbox *ext_mbox);
+
#endif /* __EDGETPU_INTERNAL_H__ */
diff --git a/drivers/edgetpu/edgetpu-kci.c b/drivers/edgetpu/edgetpu-kci.c
index c8b5d86..f506a04 100644
--- a/drivers/edgetpu/edgetpu-kci.c
+++ b/drivers/edgetpu/edgetpu-kci.c
@@ -274,6 +274,19 @@ static struct edgetpu_kci_response_element *edgetpu_kci_fetch_responses(
/* loop until our head equals to CSR tail */
while (1) {
tail = EDGETPU_MAILBOX_RESP_QUEUE_READ_SYNC(kci->mailbox, tail);
+ /*
+ * Make sure the CSR is read and reported properly by checking
+ * if any bit higher than CIRCULAR_QUEUE_WRAP_BIT is set and if
+ * the tail exceeds kci->mailbox->resp_queue_size.
+ */
+ if (unlikely(tail & ~CIRCULAR_QUEUE_VALID_MASK ||
+ CIRCULAR_QUEUE_REAL_INDEX(tail) >= size)) {
+ etdev_err_ratelimited(
+ kci->mailbox->etdev,
+ "Invalid response queue tail: 0x%x\n", tail);
+ break;
+ }
+
count = circular_queue_count(head, tail, size);
if (count == 0)
break;
@@ -662,8 +675,8 @@ static int edgetpu_kci_send_cmd_return_resp(
return -ETIMEDOUT;
}
if (resp->status != KCI_STATUS_OK) {
- etdev_dbg(kci->mailbox->etdev, "%s: resp status=%u", __func__,
- resp->status);
+ etdev_err(kci->mailbox->etdev, "KCI cmd %u response status %u",
+ cmd->code, resp->status);
return -ENOMSG;
}
diff --git a/drivers/edgetpu/edgetpu-mailbox.c b/drivers/edgetpu/edgetpu-mailbox.c
index 6ffc141..8ce6ace 100644
--- a/drivers/edgetpu/edgetpu-mailbox.c
+++ b/drivers/edgetpu/edgetpu-mailbox.c
@@ -18,6 +18,7 @@
#include "edgetpu-kci.h"
#include "edgetpu-mailbox.h"
#include "edgetpu-mmu.h"
+#include "edgetpu-wakelock.h"
#include "edgetpu.h"
/*
@@ -717,3 +718,53 @@ void edgetpu_mailbox_restore_active_vii_queues(struct edgetpu_dev *etdev)
}
mutex_unlock(&etdev->groups_lock);
}
+
+int edgetpu_mailbox_enable_ext(struct edgetpu_client *client, u32 mailbox_ids)
+{
+ int ret;
+
+ if (!edgetpu_wakelock_lock(client->wakelock)) {
+ etdev_err(client->etdev,
+ "Enabling mailboxes %08x needs wakelock acquired\n",
+ mailbox_ids);
+ edgetpu_wakelock_unlock(client->wakelock);
+ return -EAGAIN;
+ }
+
+ edgetpu_wakelock_inc_event_locked(client->wakelock,
+ EDGETPU_WAKELOCK_EVENT_EXT_MAILBOX);
+
+ etdev_dbg(client->etdev, "Opening mailboxes: %08X\n", mailbox_ids);
+
+ ret = edgetpu_kci_open_device(client->etdev->kci, mailbox_ids);
+ if (ret)
+ etdev_err(client->etdev, "Open mailboxes %08x failed (%d)\n",
+ mailbox_ids, ret);
+ edgetpu_wakelock_unlock(client->wakelock);
+ return ret;
+}
+
+int edgetpu_mailbox_disable_ext(struct edgetpu_client *client, u32 mailbox_ids)
+{
+ int ret;
+
+ if (!edgetpu_wakelock_lock(client->wakelock)) {
+ etdev_err(client->etdev,
+ "Disabling mailboxes %08x needs wakelock acquired\n",
+ mailbox_ids);
+ edgetpu_wakelock_unlock(client->wakelock);
+ return -EAGAIN;
+ }
+
+ edgetpu_wakelock_dec_event_locked(client->wakelock,
+ EDGETPU_WAKELOCK_EVENT_EXT_MAILBOX);
+
+ etdev_dbg(client->etdev, "Closing mailbox: %08X\n", mailbox_ids);
+ ret = edgetpu_kci_close_device(client->etdev->kci, mailbox_ids);
+
+ if (ret)
+ etdev_err(client->etdev, "Close mailboxes %08x failed (%d)\n",
+ mailbox_ids, ret);
+ edgetpu_wakelock_unlock(client->wakelock);
+ return ret;
+}
diff --git a/drivers/edgetpu/edgetpu-mailbox.h b/drivers/edgetpu/edgetpu-mailbox.h
index ddae12a..cdab5aa 100644
--- a/drivers/edgetpu/edgetpu-mailbox.h
+++ b/drivers/edgetpu/edgetpu-mailbox.h
@@ -17,6 +17,8 @@
#define CIRCULAR_QUEUE_WRAP_BIT (1 << 10)
#define CIRCULAR_QUEUE_INDEX_MASK (CIRCULAR_QUEUE_WRAP_BIT - 1)
+#define CIRCULAR_QUEUE_VALID_MASK \
+ (CIRCULAR_QUEUE_INDEX_MASK | CIRCULAR_QUEUE_WRAP_BIT)
#define CIRCULAR_QUEUE_WRAPPED(idx) ((idx) & CIRCULAR_QUEUE_WRAP_BIT)
#define CIRCULAR_QUEUE_REAL_INDEX(idx) ((idx) & CIRCULAR_QUEUE_INDEX_MASK)
@@ -274,6 +276,12 @@ void edgetpu_mailbox_restore_active_vii_queues(struct edgetpu_dev *etdev);
int edgetpu_mailbox_p2p_batch(struct edgetpu_mailbox_manager *mgr, uint n,
uint skip_i, struct edgetpu_mailbox **mailboxes);
+/* Notify firmware of external mailboxes becoming active */
+int edgetpu_mailbox_enable_ext(struct edgetpu_client *client, u32 mailbox_ids);
+
+/* Notify firmware of external mailboxes becoming inactive */
+int edgetpu_mailbox_disable_ext(struct edgetpu_client *client, u32 mailbox_ids);
+
/* Utilities of circular queue operations */
/*
@@ -282,11 +290,18 @@ int edgetpu_mailbox_p2p_batch(struct edgetpu_mailbox_manager *mgr, uint n,
*/
static inline u32 circular_queue_count(u32 head, u32 tail, u32 queue_size)
{
+ u32 ret;
+
if (CIRCULAR_QUEUE_WRAPPED(tail) != CIRCULAR_QUEUE_WRAPPED(head))
- return queue_size - CIRCULAR_QUEUE_REAL_INDEX(head) +
- CIRCULAR_QUEUE_REAL_INDEX(tail);
+ ret = queue_size - CIRCULAR_QUEUE_REAL_INDEX(head) +
+ CIRCULAR_QUEUE_REAL_INDEX(tail);
else
- return tail - head;
+ ret = tail - head;
+
+ if (unlikely(ret > queue_size))
+ return 0;
+
+ return ret;
}
/* Increases @index of a circular queue by @inc. */
diff --git a/drivers/edgetpu/edgetpu-wakelock.c b/drivers/edgetpu/edgetpu-wakelock.c
index f308d3a..e217ace 100644
--- a/drivers/edgetpu/edgetpu-wakelock.c
+++ b/drivers/edgetpu/edgetpu-wakelock.c
@@ -68,14 +68,13 @@ void edgetpu_wakelock_free(struct edgetpu_wakelock *wakelock)
kfree(wakelock);
}
-bool edgetpu_wakelock_inc_event(struct edgetpu_wakelock *wakelock,
- enum edgetpu_wakelock_event evt)
+bool edgetpu_wakelock_inc_event_locked(struct edgetpu_wakelock *wakelock,
+ enum edgetpu_wakelock_event evt)
{
bool ret = true;
if (NO_WAKELOCK(wakelock))
return true;
- mutex_lock(&wakelock->lock);
if (!wakelock->req_count) {
ret = false;
etdev_warn(
@@ -93,18 +92,29 @@ bool edgetpu_wakelock_inc_event(struct edgetpu_wakelock *wakelock,
evt);
}
}
- mutex_unlock(&wakelock->lock);
return ret;
}
-bool edgetpu_wakelock_dec_event(struct edgetpu_wakelock *wakelock,
+bool edgetpu_wakelock_inc_event(struct edgetpu_wakelock *wakelock,
enum edgetpu_wakelock_event evt)
{
- bool ret = true;
+ bool ret;
if (NO_WAKELOCK(wakelock))
return true;
mutex_lock(&wakelock->lock);
+ ret = edgetpu_wakelock_inc_event_locked(wakelock, evt);
+ mutex_unlock(&wakelock->lock);
+ return ret;
+}
+
+bool edgetpu_wakelock_dec_event_locked(struct edgetpu_wakelock *wakelock,
+ enum edgetpu_wakelock_event evt)
+{
+ bool ret = true;
+
+ if (NO_WAKELOCK(wakelock))
+ return true;
if (!wakelock->event_count[evt]) {
ret = false;
etdev_warn(wakelock->etdev, "event %d unbalanced decreasing",
@@ -112,6 +122,18 @@ bool edgetpu_wakelock_dec_event(struct edgetpu_wakelock *wakelock,
} else {
--wakelock->event_count[evt];
}
+ return ret;
+}
+
+bool edgetpu_wakelock_dec_event(struct edgetpu_wakelock *wakelock,
+ enum edgetpu_wakelock_event evt)
+{
+ bool ret;
+
+ if (NO_WAKELOCK(wakelock))
+ return true;
+ mutex_lock(&wakelock->lock);
+ ret = edgetpu_wakelock_dec_event_locked(wakelock, evt);
mutex_unlock(&wakelock->lock);
return ret;
}
diff --git a/drivers/edgetpu/edgetpu-wakelock.h b/drivers/edgetpu/edgetpu-wakelock.h
index 69e0fa7..a353284 100644
--- a/drivers/edgetpu/edgetpu-wakelock.h
+++ b/drivers/edgetpu/edgetpu-wakelock.h
@@ -33,7 +33,8 @@
X(EDGETPU_WAKELOCK_EVENT_MBOX_CSR, 1), \
X(EDGETPU_WAKELOCK_EVENT_CMD_QUEUE, 2), \
X(EDGETPU_WAKELOCK_EVENT_RESP_QUEUE, 3), \
- X(EDGETPU_WAKELOCK_EVENT_END, 4)
+ X(EDGETPU_WAKELOCK_EVENT_EXT_MAILBOX, 4), \
+ X(EDGETPU_WAKELOCK_EVENT_END, 5)
enum edgetpu_wakelock_event {
#define X(name, val) name = val
@@ -82,6 +83,13 @@ void edgetpu_wakelock_free(struct edgetpu_wakelock *wakelock);
*/
bool edgetpu_wakelock_inc_event(struct edgetpu_wakelock *wakelock,
enum edgetpu_wakelock_event evt);
+
+/*
+ * A version of the above where the caller holds the wakelock internal lock
+ * by calling edgetpu_wakelock_lock.
+ */
+bool edgetpu_wakelock_inc_event_locked(struct edgetpu_wakelock *wakelock,
+ enum edgetpu_wakelock_event evt);
/*
* Decreases the event counter of @evt by one.
*
@@ -96,6 +104,13 @@ bool edgetpu_wakelock_dec_event(struct edgetpu_wakelock *wakelock,
enum edgetpu_wakelock_event evt);
/*
+ * A version of the above where the caller holds the wakelock internal lock
+ * by calling edgetpu_wakelock_lock.
+ */
+bool edgetpu_wakelock_dec_event_locked(struct edgetpu_wakelock *wakelock,
+ enum edgetpu_wakelock_event evt);
+
+/*
* Holds the internal lock of @wakelock. Fields in @wakelock are protected when
* this lock is holding.
*
diff --git a/drivers/edgetpu/edgetpu.h b/drivers/edgetpu/edgetpu.h
index c382581..85532b1 100644
--- a/drivers/edgetpu/edgetpu.h
+++ b/drivers/edgetpu/edgetpu.h
@@ -41,6 +41,11 @@ typedef __u32 edgetpu_map_flag_t;
#define EDGETPU_MAP_ATTR_PBHA_SHIFT 5
#define EDGETPU_MAP_ATTR_PBHA_MASK 0xf
+/* External mailbox types */
+#define EDGETPU_EXT_MAILBOX_TYPE_TZ 1
+#define EDGETPU_EXT_MAILBOX_TYPE_GSA 2
+#define EDGETPU_EXT_MAILBOX_TYPE_DSP 3
+
struct edgetpu_map_ioctl {
__u64 host_address;
__u64 size; /* size of mapping in bytes */
@@ -458,4 +463,51 @@ struct edgetpu_fw_version {
#define EDGETPU_GET_TPU_TIMESTAMP \
_IOR(EDGETPU_IOCTL_BASE, 28, __u64)
+/*
+ * struct edgetpu_device_dram_usage
+ * @allocated: size of allocated dram in bytes
+ * @available: size of free device dram in bytes
+ */
+struct edgetpu_device_dram_usage {
+ __u64 allocated;
+ __u64 available;
+};
+
+/*
+ * Query the allocated and free device DRAM.
+ *
+ * @available and @allocated are set to 0 for chips without a device DRAM.
+ */
+#define EDGETPU_GET_DRAM_USAGE \
+ _IOR(EDGETPU_IOCTL_BASE, 29, struct edgetpu_device_dram_usage)
+
+/*
+ * struct edgetpu_ext_mailbox
+ * @client_id: Client identifier (may not be needed depending on type)
+ * @attrs: Array of mailbox attributes (pointer to
+ * edgetpu_mailbox_attr, may be NULL depending on type)
+ * @type: One of the EDGETPU_EXT_MAILBOX_xxx values
+ * @count: Number of mailboxes to acquire
+ */
+struct edgetpu_ext_mailbox {
+ __u64 client_id;
+ __u64 attrs;
+ __u32 type;
+ __u32 count;
+};
+
+/*
+ * Acquire a chip-specific mailbox that is not directly managed by the TPU
+ * runtime. This can be a secure mailbox or a device-to-device mailbox.
+ */
+#define EDGETPU_ACQUIRE_EXT_MAILBOX \
+ _IOW(EDGETPU_IOCTL_BASE, 30, struct edgetpu_ext_mailbox)
+
+/*
+ * Release a chip-specific mailbox that is not directly managed by the TPU
+ * runtime. This can be a secure mailbox or a device-to-device mailbox.
+ */
+#define EDGETPU_RELEASE_EXT_MAILBOX \
+ _IOW(EDGETPU_IOCTL_BASE, 31, struct edgetpu_ext_mailbox)
+
#endif /* __EDGETPU_H__ */