Loading arch/arm64/boot/dts/qcom/sm6150-camera-sensor-idp.dtsi +6 −6 Original line number Diff line number Diff line Loading @@ -17,9 +17,9 @@ cell-index = <0>; reg = <0x00 0x00>; compatible = "qcom,camera-flash"; flash-source = <&pm6150l_flash0>; torch-source = <&pm6150l_torch1>; switch-source = <&pm6150l_switch0>; flash-source = <&pm6150l_flash0 &pm6150l_flash1>; torch-source = <&pm6150l_torch0 &pm6150l_torch1>; switch-source = <&pm6150l_switch2 &pm6150l_switch2>; status = "ok"; }; Loading @@ -27,9 +27,9 @@ cell-index = <1>; reg = <0x01 0x00>; compatible = "qcom,camera-flash"; flash-source = <&pm6150l_flash1>; torch-source = <&pm6150l_torch1>; switch-source = <&pm6150l_switch1>; flash-source = <&pm6150l_flash0 &pm6150l_flash1>; torch-source = <&pm6150l_torch0 &pm6150l_torch1>; switch-source = <&pm6150l_switch2 &pm6150l_switch2>; status = "ok"; }; Loading arch/arm64/boot/dts/qcom/sm6150-camera.dtsi +6 −6 Original line number Diff line number Diff line Loading @@ -625,9 +625,9 @@ <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; clock-rates = <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; clock-cntl-level = "svs", "turbo"; clock-cntl-level = "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; status = "ok"; }; Loading Loading @@ -712,9 +712,9 @@ <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; clock-rates = <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; clock-cntl-level = "svs", "turbo"; clock-cntl-level = "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; status = "ok"; }; Loading Loading @@ -796,9 +796,9 @@ <&clock_camcc CAM_CC_IFE_LITE_CLK_SRC>, <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>; clock-rates = <0 0 0 0 0 0 200000000 0 0 0 360000000 0>, <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, <0 0 0 0 0 0 540000000 0 0 0 600000000 0>; clock-cntl-level = "svs", "turbo"; clock-cntl-level = "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; status = "ok"; }; Loading drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c +6 −5 Original line number Diff line number Diff line Loading @@ -624,7 +624,8 @@ static void cam_hw_cdm_work(struct work_struct *work) } static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *token) struct device *dev, unsigned long iova, int flags, void *token, uint32_t buf_info) { struct cam_hw_info *cdm_hw = NULL; struct cam_cdm *core = NULL; Loading Loading @@ -910,7 +911,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) CAM_ERR(CAM_CDM, "cpas-cdm get iommu handle failed"); goto unlock_release_mem; } cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_hw_cdm_iommu_fault_handler, cdm_hw); rc = cam_smmu_ops(cdm_core->iommu_hdl.non_secure, CAM_SMMU_ATTACH); Loading Loading @@ -1034,7 +1035,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) flush_workqueue(cdm_core->work_queue); destroy_workqueue(cdm_core->work_queue); destroy_non_secure_hdl: cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, NULL, cdm_hw); if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); Loading Loading @@ -1106,8 +1107,8 @@ int cam_hw_cdm_remove(struct platform_device *pdev) if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, NULL, cdm_hw); cam_smmu_unset_client_page_fault_handler( cdm_core->iommu_hdl.non_secure, cdm_hw); mutex_destroy(&cdm_hw->hw_mutex); kfree(cdm_hw->soc_info.soc_private); Loading drivers/media/platform/msm/camera/cam_core/cam_context.c +82 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ int cam_context_shutdown(struct cam_context *ctx) int rc = 0; int32_t ctx_hdl = ctx->dev_hdl; mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev) { rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev( ctx, NULL); Loading @@ -56,6 +57,7 @@ int cam_context_shutdown(struct cam_context *ctx) if (rc < 0) CAM_ERR(CAM_CORE, "Error while dev release %d", rc); } mutex_unlock(&ctx->ctx_mutex); if (!rc) rc = cam_destroy_device_hdl(ctx_hdl); Loading Loading @@ -223,6 +225,27 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, return rc; } int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, uint32_t buf_info) { int rc = 0; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (ctx->state_machine[ctx->state].pagefault_ops) { rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova, buf_info); } else { CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", ctx->dev_hdl, ctx->state); } return rc; } int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { Loading Loading @@ -264,6 +287,36 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, return rc; } int cam_context_handle_acquire_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid acquire device hw command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.acquire_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No acquire hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd) { Loading Loading @@ -293,6 +346,35 @@ int cam_context_handle_release_dev(struct cam_context *ctx, return rc; } int cam_context_handle_release_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid release HW command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.release_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.release_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No release hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_flush_dev(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { Loading drivers/media/platform/msm/camera/cam_core/cam_context.h +58 −13 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ enum cam_context_state { * @num_out_acked: Number of out fence acked * @flushed: Request is flushed * @ctx: The context to which this request belongs * @pf_data page fault debug data * */ struct cam_ctx_request { Loading @@ -74,6 +75,7 @@ struct cam_ctx_request { uint32_t num_out_acked; int flushed; struct cam_context *ctx; struct cam_hw_mgr_dump_pf_data pf_data; }; /** Loading @@ -85,6 +87,8 @@ struct cam_ctx_request { * @start_dev: Function pointer for start device * @stop_dev: Function pointer for stop device * @flush_dev: Function pointer for flush device * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * */ struct cam_ctx_ioctl_ops { Loading @@ -100,6 +104,8 @@ struct cam_ctx_ioctl_ops { struct cam_start_stop_dev_cmd *cmd); int (*flush_dev)(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); int (*acquire_hw)(struct cam_context *ctx, void *args); int (*release_hw)(struct cam_context *ctx, void *args); }; /** Loading Loading @@ -135,12 +141,14 @@ struct cam_ctx_crm_ops { * @ioctl_ops: Ioctl funciton table * @crm_ops: CRM to context interface function table * @irq_ops: Hardware event handle function * @pagefault_ops: Function to be called on page fault * */ struct cam_ctx_ops { struct cam_ctx_ioctl_ops ioctl_ops; struct cam_ctx_crm_ops crm_ops; cam_hw_event_cb_func irq_ops; cam_hw_pagefault_cb_func pagefault_ops; }; /** Loading Loading @@ -291,6 +299,19 @@ int cam_context_handle_crm_flush_req(struct cam_context *ctx, int cam_context_handle_crm_process_evt(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *process_evt); /** * cam_context_dump_pf_info() * * @brief: Handle dump active request request command * * @ctx: Object pointer for cam_context * @iova: Page fault address * @buf_info: Information about closest memory handle * */ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, uint32_t buf_info); /** * cam_context_handle_acquire_dev() * Loading @@ -303,6 +324,18 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd); /** * cam_context_handle_acquire_hw() * * @brief: Handle acquire HW command * * @ctx: Object pointer for cam_context * @cmd: Acquire HW command payload * */ int cam_context_handle_acquire_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_release_dev() * Loading @@ -315,6 +348,18 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd); /** * cam_context_handle_release_hw() * * @brief: Handle release HW command * * @ctx: Object pointer for cam_context * @cmd: Release HW command payload * */ int cam_context_handle_release_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_config_dev() * Loading Loading
arch/arm64/boot/dts/qcom/sm6150-camera-sensor-idp.dtsi +6 −6 Original line number Diff line number Diff line Loading @@ -17,9 +17,9 @@ cell-index = <0>; reg = <0x00 0x00>; compatible = "qcom,camera-flash"; flash-source = <&pm6150l_flash0>; torch-source = <&pm6150l_torch1>; switch-source = <&pm6150l_switch0>; flash-source = <&pm6150l_flash0 &pm6150l_flash1>; torch-source = <&pm6150l_torch0 &pm6150l_torch1>; switch-source = <&pm6150l_switch2 &pm6150l_switch2>; status = "ok"; }; Loading @@ -27,9 +27,9 @@ cell-index = <1>; reg = <0x01 0x00>; compatible = "qcom,camera-flash"; flash-source = <&pm6150l_flash1>; torch-source = <&pm6150l_torch1>; switch-source = <&pm6150l_switch1>; flash-source = <&pm6150l_flash0 &pm6150l_flash1>; torch-source = <&pm6150l_torch0 &pm6150l_torch1>; switch-source = <&pm6150l_switch2 &pm6150l_switch2>; status = "ok"; }; Loading
arch/arm64/boot/dts/qcom/sm6150-camera.dtsi +6 −6 Original line number Diff line number Diff line Loading @@ -625,9 +625,9 @@ <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, <&clock_camcc CAM_CC_IFE_0_AXI_CLK>; clock-rates = <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; clock-cntl-level = "svs", "turbo"; clock-cntl-level = "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; status = "ok"; }; Loading Loading @@ -712,9 +712,9 @@ <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, <&clock_camcc CAM_CC_IFE_1_AXI_CLK>; clock-rates = <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; clock-cntl-level = "svs", "turbo"; clock-cntl-level = "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; status = "ok"; }; Loading Loading @@ -796,9 +796,9 @@ <&clock_camcc CAM_CC_IFE_LITE_CLK_SRC>, <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>; clock-rates = <0 0 0 0 0 0 200000000 0 0 0 360000000 0>, <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, <0 0 0 0 0 0 540000000 0 0 0 600000000 0>; clock-cntl-level = "svs", "turbo"; clock-cntl-level = "svs_l1", "turbo"; src-clock-name = "ife_csid_clk_src"; status = "ok"; }; Loading
drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c +6 −5 Original line number Diff line number Diff line Loading @@ -624,7 +624,8 @@ static void cam_hw_cdm_work(struct work_struct *work) } static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *token) struct device *dev, unsigned long iova, int flags, void *token, uint32_t buf_info) { struct cam_hw_info *cdm_hw = NULL; struct cam_cdm *core = NULL; Loading Loading @@ -910,7 +911,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) CAM_ERR(CAM_CDM, "cpas-cdm get iommu handle failed"); goto unlock_release_mem; } cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_hw_cdm_iommu_fault_handler, cdm_hw); rc = cam_smmu_ops(cdm_core->iommu_hdl.non_secure, CAM_SMMU_ATTACH); Loading Loading @@ -1034,7 +1035,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev) flush_workqueue(cdm_core->work_queue); destroy_workqueue(cdm_core->work_queue); destroy_non_secure_hdl: cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, cam_smmu_set_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, NULL, cdm_hw); if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); Loading Loading @@ -1106,8 +1107,8 @@ int cam_hw_cdm_remove(struct platform_device *pdev) if (cam_smmu_destroy_handle(cdm_core->iommu_hdl.non_secure)) CAM_ERR(CAM_CDM, "Release iommu secure hdl failed"); cam_smmu_reg_client_page_fault_handler(cdm_core->iommu_hdl.non_secure, NULL, cdm_hw); cam_smmu_unset_client_page_fault_handler( cdm_core->iommu_hdl.non_secure, cdm_hw); mutex_destroy(&cdm_hw->hw_mutex); kfree(cdm_hw->soc_info.soc_private); Loading
drivers/media/platform/msm/camera/cam_core/cam_context.c +82 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ int cam_context_shutdown(struct cam_context *ctx) int rc = 0; int32_t ctx_hdl = ctx->dev_hdl; mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.stop_dev) { rc = ctx->state_machine[ctx->state].ioctl_ops.stop_dev( ctx, NULL); Loading @@ -56,6 +57,7 @@ int cam_context_shutdown(struct cam_context *ctx) if (rc < 0) CAM_ERR(CAM_CORE, "Error while dev release %d", rc); } mutex_unlock(&ctx->ctx_mutex); if (!rc) rc = cam_destroy_device_hdl(ctx_hdl); Loading Loading @@ -223,6 +225,27 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, return rc; } int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, uint32_t buf_info) { int rc = 0; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (ctx->state_machine[ctx->state].pagefault_ops) { rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova, buf_info); } else { CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d", ctx->dev_hdl, ctx->state); } return rc; } int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { Loading Loading @@ -264,6 +287,36 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, return rc; } int cam_context_handle_acquire_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid acquire device hw command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.acquire_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No acquire hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd) { Loading Loading @@ -293,6 +346,35 @@ int cam_context_handle_release_dev(struct cam_context *ctx, return rc; } int cam_context_handle_release_hw(struct cam_context *ctx, void *args) { int rc; if (!ctx->state_machine) { CAM_ERR(CAM_CORE, "Context is not ready"); return -EINVAL; } if (!args) { CAM_ERR(CAM_CORE, "Invalid release HW command payload"); return -EINVAL; } mutex_lock(&ctx->ctx_mutex); if (ctx->state_machine[ctx->state].ioctl_ops.release_hw) { rc = ctx->state_machine[ctx->state].ioctl_ops.release_hw( ctx, args); } else { CAM_ERR(CAM_CORE, "No release hw for dev %s, state %d", ctx->dev_name, ctx->state); rc = -EPROTO; } mutex_unlock(&ctx->ctx_mutex); return rc; } int cam_context_handle_flush_dev(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { Loading
drivers/media/platform/msm/camera/cam_core/cam_context.h +58 −13 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ enum cam_context_state { * @num_out_acked: Number of out fence acked * @flushed: Request is flushed * @ctx: The context to which this request belongs * @pf_data page fault debug data * */ struct cam_ctx_request { Loading @@ -74,6 +75,7 @@ struct cam_ctx_request { uint32_t num_out_acked; int flushed; struct cam_context *ctx; struct cam_hw_mgr_dump_pf_data pf_data; }; /** Loading @@ -85,6 +87,8 @@ struct cam_ctx_request { * @start_dev: Function pointer for start device * @stop_dev: Function pointer for stop device * @flush_dev: Function pointer for flush device * @acquire_hw: Function pointer for acquire hw * @release_hw: Function pointer for release hw * */ struct cam_ctx_ioctl_ops { Loading @@ -100,6 +104,8 @@ struct cam_ctx_ioctl_ops { struct cam_start_stop_dev_cmd *cmd); int (*flush_dev)(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd); int (*acquire_hw)(struct cam_context *ctx, void *args); int (*release_hw)(struct cam_context *ctx, void *args); }; /** Loading Loading @@ -135,12 +141,14 @@ struct cam_ctx_crm_ops { * @ioctl_ops: Ioctl funciton table * @crm_ops: CRM to context interface function table * @irq_ops: Hardware event handle function * @pagefault_ops: Function to be called on page fault * */ struct cam_ctx_ops { struct cam_ctx_ioctl_ops ioctl_ops; struct cam_ctx_crm_ops crm_ops; cam_hw_event_cb_func irq_ops; cam_hw_pagefault_cb_func pagefault_ops; }; /** Loading Loading @@ -291,6 +299,19 @@ int cam_context_handle_crm_flush_req(struct cam_context *ctx, int cam_context_handle_crm_process_evt(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *process_evt); /** * cam_context_dump_pf_info() * * @brief: Handle dump active request request command * * @ctx: Object pointer for cam_context * @iova: Page fault address * @buf_info: Information about closest memory handle * */ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova, uint32_t buf_info); /** * cam_context_handle_acquire_dev() * Loading @@ -303,6 +324,18 @@ int cam_context_handle_crm_process_evt(struct cam_context *ctx, int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd); /** * cam_context_handle_acquire_hw() * * @brief: Handle acquire HW command * * @ctx: Object pointer for cam_context * @cmd: Acquire HW command payload * */ int cam_context_handle_acquire_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_release_dev() * Loading @@ -315,6 +348,18 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx, int cam_context_handle_release_dev(struct cam_context *ctx, struct cam_release_dev_cmd *cmd); /** * cam_context_handle_release_hw() * * @brief: Handle release HW command * * @ctx: Object pointer for cam_context * @cmd: Release HW command payload * */ int cam_context_handle_release_hw(struct cam_context *ctx, void *cmd); /** * cam_context_handle_config_dev() * Loading