diff options
author | Nrithya Kanakasabapathy <nrithya@google.com> | 2021-05-05 17:27:38 +0000 |
---|---|---|
committer | Nrithya Kanakasabapathy <nrithya@google.com> | 2021-05-05 17:27:38 +0000 |
commit | c2a5f1fcc8911d94858bb48492a1b529f9a8e80e (patch) | |
tree | f6e4acf179bfed2d3fb08ba3e64e7b51c6e5bef9 | |
parent | f9b2ca71995a76c1b892d07b920b68cad2547a03 (diff) | |
download | abrolhos-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-format | 552 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos-device.c | 76 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos-platform.c | 2 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos-platform.h | 4 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos-pm.c | 8 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos/config-mailbox.h | 2 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-device-group.c | 22 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-dmabuf.c | 10 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-dram.h | 8 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-firmware.c | 117 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-firmware.h | 3 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-fs.c | 47 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-internal.h | 16 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-kci.c | 17 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-mailbox.c | 51 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-mailbox.h | 21 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-wakelock.c | 34 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-wakelock.h | 17 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu.h | 52 |
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 +... @@ -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__ */ |