aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-01-22 02:47:23 -0800
committerLinux Build Service Account <lnxbuild@localhost>2019-01-22 02:47:23 -0800
commit6bb42bc6259b5549d6ca6cb655cd5d7aec65a5de (patch)
treef8890cacaef4e07ca0ad0cc3c9ea4193e7331075
parentd89b07f7fa015c63937d29a3443e776e83d614a5 (diff)
parentd6def77b82151788b2fe7ecb0406b780a5ea8fde (diff)
Merge d6def77b82151788b2fe7ecb0406b780a5ea8fde on remote branchLA.UM.6.3.r7-01200-sdm845.0
Change-Id: I3c365d632047ef2a073abfafbe1da930dab33f2e
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/configs/sdm845-perf_defconfig1
-rw-r--r--arch/arm64/configs/sdm845_defconfig1
-rw-r--r--drivers/android/binder.c81
-rw-r--r--drivers/bluetooth/hci_qca.c19
-rw-r--r--drivers/char/adsprpc.c335
-rw-r--r--drivers/char/adsprpc_compat.c18
-rw-r--r--drivers/char/adsprpc_shared.h14
-rw-r--r--drivers/char/diag/diag_memorydevice.c2
-rw-r--r--drivers/char/diag/diagfwd_peripheral.c20
-rw-r--r--drivers/crypto/msm/qcedev.c5
-rw-r--r--drivers/devfreq/governor_gpubw_mon.c11
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-msm-smp2p-test.c763
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c12
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_display.c19
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c3
-rw-r--r--drivers/gpu/drm/msm/sde_dbg.c34
-rw-r--r--drivers/hid/hidraw.c5
-rw-r--r--drivers/i2c/busses/i2c-msm-v2.c8
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h6
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c11
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h6
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c7
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context.c23
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context.h43
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context_utils.c44
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context_utils.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h65
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_node.c21
-rw-r--r--drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c8
-rw-r--r--drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h2
-rw-r--r--drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c4
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c17
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c10
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c40
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c29
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/hfi.c19
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h2
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c6
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c170
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h2
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c7
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c206
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h1
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c58
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h7
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c202
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h11
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c6
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c8
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c141
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h1
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h3
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c4
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c33
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h11
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c41
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c59
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c151
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h2
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c16
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c17
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c12
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c24
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c52
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c36
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c188
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h20
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h2
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c29
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile13
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c897
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h14
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c341
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h81
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c21
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c22
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c65
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c77
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_smmu/Makefile1
-rw-r--r--drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c149
-rw-r--r--drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h35
-rw-r--r--drivers/media/platform/msm/camera/cam_sync/cam_sync.c24
-rw-r--r--drivers/media/platform/msm/camera/cam_utils/cam_common_util.h6
-rw-r--r--drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c13
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c8
-rw-r--r--drivers/misc/qseecom.c117
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c1
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_nat.c14
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_rt.c23
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c1
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_rt.c48
-rw-r--r--drivers/platform/msm/sps/sps.c3
-rw-r--r--drivers/power/supply/qcom/smb-lib.c20
-rw-r--r--drivers/power/supply/qcom/smb-lib.h1
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c10
-rw-r--r--drivers/scsi/ufs/ufshcd.c31
-rw-r--r--drivers/soc/qcom/icnss.c4
-rw-r--r--drivers/soc/qcom/ipc_router_glink_xprt.c4
-rw-r--r--drivers/soc/qcom/pil-msa.c2
-rw-r--r--drivers/soc/qcom/rpmh.c17
-rw-r--r--drivers/spi/spi-geni-qcom.c6
-rw-r--r--drivers/staging/android/ion/ion_cma_heap.c29
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c12
-rw-r--r--drivers/staging/android/ion/ion_system_secure_heap.c10
-rw-r--r--drivers/usb/gadget/function/f_gsi.c5
-rw-r--r--drivers/usb/host/xhci.c1
-rw-r--r--fs/sdcardfs/file.c24
-rw-r--r--fs/sdcardfs/inode.c213
-rw-r--r--fs/sdcardfs/lookup.c9
-rw-r--r--fs/sdcardfs/sdcardfs.h25
-rw-r--r--include/net/sock.h11
-rw-r--r--include/uapi/linux/msm_ipa.h8
-rw-r--r--include/uapi/media/cam_req_mgr.h3
-rw-r--r--include/uapi/media/cam_sync.h2
-rw-r--r--kernel/events/core.c22
-rw-r--r--net/core/dst.c11
-rw-r--r--net/key/af_key.c40
-rw-r--r--net/socket.c35
-rw-r--r--net/xfrm/xfrm_user.c3
138 files changed, 3853 insertions, 1996 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 87a98bc70af3..cce7a4c0cb8c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -84,6 +84,7 @@ config ARM64
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENT
+ select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP if NUMA
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index b6b66117035c..eaa56a4bdf6f 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -225,6 +225,7 @@ CONFIG_NET_ACT_SKBEDIT=y
CONFIG_RMNET_DATA=y
CONFIG_RMNET_DATA_FC=y
CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_SOCKEV_NLMCAST=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 69efd3b281ad..8c569a365b11 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -230,6 +230,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_RMNET_DATA=y
CONFIG_RMNET_DATA_FC=y
CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_SOCKEV_NLMCAST=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1ef2f68bfcb2..a9ae0620eb8a 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -465,8 +465,9 @@ struct binder_ref {
};
enum binder_deferred_state {
- BINDER_DEFERRED_FLUSH = 0x01,
- BINDER_DEFERRED_RELEASE = 0x02,
+ BINDER_DEFERRED_PUT_FILES = 0x01,
+ BINDER_DEFERRED_FLUSH = 0x02,
+ BINDER_DEFERRED_RELEASE = 0x04,
};
/**
@@ -503,6 +504,9 @@ struct binder_priority {
* (invariant after initialized)
* @tsk task_struct for group_leader of process
* (invariant after initialized)
+ * @files files_struct for process
+ * (protected by @files_lock)
+ * @files_lock mutex to protect @files
* @deferred_work_node: element for binder_deferred_list
* (protected by binder_deferred_lock)
* @deferred_work: bitmap of deferred work to perform
@@ -549,6 +553,8 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
+ struct files_struct *files;
+ struct mutex files_lock;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -944,33 +950,27 @@ static void binder_free_thread(struct binder_thread *thread);
static void binder_free_proc(struct binder_proc *proc);
static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
-struct files_struct *binder_get_files_struct(struct binder_proc *proc)
-{
- return get_files_struct(proc->tsk);
-}
-
static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
{
- struct files_struct *files;
unsigned long rlim_cur;
unsigned long irqs;
int ret;
- files = binder_get_files_struct(proc);
- if (files == NULL)
- return -ESRCH;
-
+ mutex_lock(&proc->files_lock);
+ if (proc->files == NULL) {
+ ret = -ESRCH;
+ goto err;
+ }
if (!lock_task_sighand(proc->tsk, &irqs)) {
ret = -EMFILE;
goto err;
}
-
rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
unlock_task_sighand(proc->tsk, &irqs);
- ret = __alloc_fd(files, 0, rlim_cur, flags);
+ ret = __alloc_fd(proc->files, 0, rlim_cur, flags);
err:
- put_files_struct(files);
+ mutex_unlock(&proc->files_lock);
return ret;
}
@@ -980,12 +980,10 @@ err:
static void task_fd_install(
struct binder_proc *proc, unsigned int fd, struct file *file)
{
- struct files_struct *files = binder_get_files_struct(proc);
-
- if (files) {
- __fd_install(files, fd, file);
- put_files_struct(files);
- }
+ mutex_lock(&proc->files_lock);
+ if (proc->files)
+ __fd_install(proc->files, fd, file);
+ mutex_unlock(&proc->files_lock);
}
/*
@@ -993,21 +991,22 @@ static void task_fd_install(
*/
static long task_close_fd(struct binder_proc *proc, unsigned int fd)
{
- struct files_struct *files = binder_get_files_struct(proc);
int retval;
- if (files == NULL)
- return -ESRCH;
-
- retval = __close_fd(files, fd);
+ mutex_lock(&proc->files_lock);
+ if (proc->files == NULL) {
+ retval = -ESRCH;
+ goto err;
+ }
+ retval = __close_fd(proc->files, fd);
/* can't restart close syscall because file table entry was cleared */
if (unlikely(retval == -ERESTARTSYS ||
retval == -ERESTARTNOINTR ||
retval == -ERESTARTNOHAND ||
retval == -ERESTART_RESTARTBLOCK))
retval = -EINTR;
- put_files_struct(files);
-
+err:
+ mutex_unlock(&proc->files_lock);
return retval;
}
@@ -4831,6 +4830,7 @@ static void binder_vma_close(struct vm_area_struct *vma)
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
binder_alloc_vma_close(&proc->alloc);
+ binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
}
static int binder_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -4872,8 +4872,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_private_data = proc;
ret = binder_alloc_mmap_handler(&proc->alloc, vma);
-
- return ret;
+ if (ret)
+ return ret;
+ mutex_lock(&proc->files_lock);
+ proc->files = get_files_struct(current);
+ mutex_unlock(&proc->files_lock);
+ return 0;
err_bad_arg:
pr_err("binder_mmap: %d %lx-%lx %s failed %d\n",
@@ -4896,6 +4900,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
spin_lock_init(&proc->outer_lock);
get_task_struct(current->group_leader);
proc->tsk = current->group_leader;
+ mutex_init(&proc->files_lock);
INIT_LIST_HEAD(&proc->todo);
if (binder_supported_policy(current->policy)) {
proc->default_priority.sched_policy = current->policy;
@@ -5052,6 +5057,8 @@ static void binder_deferred_release(struct binder_proc *proc)
struct rb_node *n;
int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
+ BUG_ON(proc->files);
+
mutex_lock(&binder_procs_lock);
hlist_del(&proc->proc_node);
mutex_unlock(&binder_procs_lock);
@@ -5133,6 +5140,8 @@ static void binder_deferred_release(struct binder_proc *proc)
static void binder_deferred_func(struct work_struct *work)
{
struct binder_proc *proc;
+ struct files_struct *files;
+
int defer;
do {
@@ -5149,11 +5158,23 @@ static void binder_deferred_func(struct work_struct *work)
}
mutex_unlock(&binder_deferred_lock);
+ files = NULL;
+ if (defer & BINDER_DEFERRED_PUT_FILES) {
+ mutex_lock(&proc->files_lock);
+ files = proc->files;
+ if (files)
+ proc->files = NULL;
+ mutex_unlock(&proc->files_lock);
+ }
+
if (defer & BINDER_DEFERRED_FLUSH)
binder_deferred_flush(proc);
if (defer & BINDER_DEFERRED_RELEASE)
binder_deferred_release(proc); /* frees proc */
+
+ if (files)
+ put_files_struct(files);
} while (proc);
}
static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 6c867fbc56a7..688a0b0d93a4 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -231,11 +231,11 @@ static void qca_wq_awake_device(struct work_struct *work)
BT_DBG("hu %p wq awake device", hu);
+ spin_lock(&qca->hci_ibs_lock);
+
/* Vote for serial clock */
serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
- spin_lock(&qca->hci_ibs_lock);
-
/* Send wake indication to device */
if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
BT_ERR("Failed to send WAKE to device");
@@ -260,9 +260,10 @@ static void qca_wq_awake_rx(struct work_struct *work)
BT_DBG("hu %p wq awake rx", hu);
+ spin_lock(&qca->hci_ibs_lock);
+
serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
- spin_lock(&qca->hci_ibs_lock);
qca->rx_ibs_state = HCI_IBS_RX_AWAKE;
/* Always acknowledge device wake up,
@@ -287,7 +288,11 @@ static void qca_wq_serial_rx_clock_vote_off(struct work_struct *work)
BT_DBG("hu %p rx clock vote off", hu);
+ spin_lock(&qca->hci_ibs_lock);
+
serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
+
+ spin_unlock(&qca->hci_ibs_lock);
}
static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work)
@@ -298,6 +303,8 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work)
BT_DBG("hu %p tx clock vote off", hu);
+ spin_lock(&qca->hci_ibs_lock);
+
/* Run HCI tx handling unlocked */
hci_uart_tx_wakeup(hu);
@@ -305,6 +312,8 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work)
* It is up to the tty driver to pend the clocks off until tx done.
*/
serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
+
+ spin_unlock(&qca->hci_ibs_lock);
}
static void hci_ibs_tx_idle_timeout(unsigned long arg)
@@ -520,8 +529,12 @@ static int qca_close(struct hci_uart *hu)
BT_DBG("hu %p qca close", hu);
+ spin_lock(&qca->hci_ibs_lock);
+
serial_clock_vote(HCI_IBS_VOTE_STATS_UPDATE, hu);
+ spin_unlock(&qca->hci_ibs_lock);
+
skb_queue_purge(&qca->tx_wait_q);
skb_queue_purge(&qca->txq);
del_timer(&qca->tx_idle_timer);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index b8ec3d4c2fbd..9851bcff982b 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -55,6 +55,7 @@
#define TZ_PIL_AUTH_QDSP6_PROC 1
#define ADSP_MMAP_HEAP_ADDR 4
#define ADSP_MMAP_REMOTE_HEAP_ADDR 8
+#define ADSP_MMAP_ADD_PAGES 0x1000
#define FASTRPC_DMAHANDLE_NOMAP (16)
#define FASTRPC_ENOSUCH 39
@@ -173,10 +174,15 @@ struct fastrpc_file;
struct fastrpc_buf {
struct hlist_node hn;
+ struct hlist_node hn_rem;
struct fastrpc_file *fl;
void *virt;
uint64_t phys;
size_t size;
+ unsigned long dma_attr;
+ uintptr_t raddr;
+ uint32_t flags;
+ int remote;
};
struct fastrpc_ctx_lst;
@@ -333,9 +339,11 @@ struct fastrpc_file {
struct hlist_node hn;
spinlock_t hlock;
struct hlist_head maps;
- struct hlist_head bufs;
+ struct hlist_head cached_bufs;
+ struct hlist_head remote_bufs;
struct fastrpc_ctx_lst clst;
struct fastrpc_session_ctx *sctx;
+ struct fastrpc_buf *init_mem;
struct fastrpc_session_ctx *secsctx;
uint32_t mode;
uint32_t profile;
@@ -415,10 +423,17 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
return;
if (cache) {
spin_lock(&fl->hlock);
- hlist_add_head(&buf->hn, &fl->bufs);
+ hlist_add_head(&buf->hn, &fl->cached_bufs);
spin_unlock(&fl->hlock);
return;
}
+ if (buf->remote) {
+ spin_lock(&fl->hlock);
+ hlist_del_init(&buf->hn_rem);
+ spin_unlock(&fl->hlock);
+ buf->remote = 0;
+ buf->raddr = 0;
+ }
if (!IS_ERR_OR_NULL(buf->virt)) {
int destVM[1] = {VMID_HLOS};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
@@ -432,13 +447,13 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
hyp_assign_phys(buf->phys, buf_page_size(buf->size),
srcVM, 2, destVM, destVMperm, 1);
}
- dma_free_coherent(fl->sctx->smmu.dev, buf->size, buf->virt,
- buf->phys);
+ dma_free_attrs(fl->sctx->smmu.dev, buf->size, buf->virt,
+ buf->phys, buf->dma_attr);
}
kfree(buf);
}
-static void fastrpc_buf_list_free(struct fastrpc_file *fl)
+static void fastrpc_cached_buf_list_free(struct fastrpc_file *fl)
{
struct fastrpc_buf *buf, *free;
@@ -447,7 +462,7 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl)
free = NULL;
spin_lock(&fl->hlock);
- hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
+ hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) {
hlist_del_init(&buf->hn);
free = buf;
break;
@@ -458,6 +473,25 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl)
} while (free);
}
+static void fastrpc_remote_buf_list_free(struct fastrpc_file *fl)
+{
+ struct fastrpc_buf *buf, *free;
+
+ do {
+ struct hlist_node *n;
+
+ free = NULL;
+ spin_lock(&fl->hlock);
+ hlist_for_each_entry_safe(buf, n, &fl->remote_bufs, hn_rem) {
+ free = buf;
+ break;
+ }
+ spin_unlock(&fl->hlock);
+ if (free)
+ fastrpc_buf_free(free, 0);
+ } while (free);
+}
+
static void fastrpc_mmap_add(struct fastrpc_mmap *map)
{
if (map->flags == ADSP_MMAP_HEAP_ADDR ||
@@ -517,7 +551,8 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd,
return -ENOTTY;
}
-static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size)
+static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size,
+ unsigned long dma_attrs)
{
struct fastrpc_apps *me = &gfa;
@@ -525,10 +560,11 @@ static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size)
pr_err("device adsprpc-mem is not initialized\n");
return -ENODEV;
}
- *vaddr = dma_alloc_coherent(me->dev, size, region_phys, GFP_KERNEL);
- if (!*vaddr) {
- pr_err("ADSPRPC: Failed to allocate %x remote heap memory\n",
- (unsigned int)size);
+ *vaddr = dma_alloc_attrs(me->dev, size, region_phys, GFP_KERNEL,
+ dma_attrs);
+ if (IS_ERR_OR_NULL(*vaddr)) {
+ pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx, returned %pK\n",
+ current->comm, __func__, size, (*vaddr));
return -ENOMEM;
}
return 0;
@@ -600,14 +636,17 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
}
if (map->flags == ADSP_MMAP_HEAP_ADDR ||
map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+ unsigned long dma_attrs = 0;
if (me->dev == NULL) {
pr_err("failed to free remote heap allocation\n");
return;
}
if (map->phys) {
- dma_free_coherent(me->dev, map->size,
- (void *)map->va, (dma_addr_t)map->phys);
+ dma_attrs |=
+ DMA_ATTR_SKIP_ZEROING | DMA_ATTR_NO_KERNEL_MAPPING;
+ dma_free_attrs(me->dev, map->size, (void *)map->va,
+ (dma_addr_t)map->phys, dma_attrs);
}
} else if (map->flags == FASTRPC_DMAHANDLE_NOMAP) {
if (!IS_ERR_OR_NULL(map->handle))
@@ -682,10 +721,14 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
map->attr = attr;
if (mflags == ADSP_MMAP_HEAP_ADDR ||
mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+ unsigned long dma_attrs = DMA_ATTR_SKIP_ZEROING |
+ DMA_ATTR_NO_KERNEL_MAPPING;
+
map->apps = me;
map->fl = NULL;
+
VERIFY(err, !dma_alloc_memory(&region_phys, &region_vaddr,
- len));
+ len, dma_attrs));
if (err)
goto bail;
map->phys = (uintptr_t)region_phys;
@@ -824,7 +867,8 @@ bail:
}
static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
- struct fastrpc_buf **obuf)
+ unsigned long dma_attr, uint32_t rflags,
+ int remote, struct fastrpc_buf **obuf)
{
int err = 0, vmid;
struct fastrpc_buf *buf = NULL, *fr = NULL;
@@ -834,18 +878,20 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
if (err)
goto bail;
- /* find the smallest buffer that fits in the cache */
- spin_lock(&fl->hlock);
- hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
- if (buf->size >= size && (!fr || fr->size > buf->size))
- fr = buf;
- }
- if (fr)
- hlist_del_init(&fr->hn);
- spin_unlock(&fl->hlock);
- if (fr) {
- *obuf = fr;
- return 0;
+ if (!remote) {
+ /* find the smallest buffer that fits in the cache */
+ spin_lock(&fl->hlock);
+ hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) {
+ if (buf->size >= size && (!fr || fr->size > buf->size))
+ fr = buf;
+ }
+ if (fr)
+ hlist_del_init(&fr->hn);
+ spin_unlock(&fl->hlock);
+ if (fr) {
+ *obuf = fr;
+ return 0;
+ }
}
buf = NULL;
VERIFY(err, NULL != (buf = kzalloc(sizeof(*buf), GFP_KERNEL)));
@@ -856,17 +902,27 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
buf->virt = NULL;
buf->phys = 0;
buf->size = size;
- buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size,
- (void *)&buf->phys, GFP_KERNEL);
+ buf->dma_attr = dma_attr;
+ buf->flags = rflags;
+ buf->raddr = 0;
+ buf->remote = 0;
+ buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size,
+ (dma_addr_t *)&buf->phys,
+ GFP_KERNEL, buf->dma_attr);
if (IS_ERR_OR_NULL(buf->virt)) {
/* free cache and retry */
- fastrpc_buf_list_free(fl);
- buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size,
- (void *)&buf->phys, GFP_KERNEL);
+ fastrpc_cached_buf_list_free(fl);
+ buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size,
+ (dma_addr_t *)&buf->phys,
+ GFP_KERNEL, buf->dma_attr);
VERIFY(err, !IS_ERR_OR_NULL(buf->virt));
}
- if (err)
+ if (err) {
+ err = -ENOMEM;
+ pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx\n",
+ current->comm, __func__, size);
goto bail;
+ }
if (fl->sctx->smmu.cb)
buf->phys += ((uint64_t)fl->sctx->smmu.cb << 32);
vmid = fl->apps->channel[fl->cid].vmid;
@@ -882,6 +938,13 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
goto bail;
}
+ if (remote) {
+ INIT_HLIST_NODE(&buf->hn_rem);
+ spin_lock(&fl->hlock);
+ hlist_add_head(&buf->hn_rem, &fl->remote_bufs);
+ spin_unlock(&fl->hlock);
+ buf->remote = remote;
+ }
*obuf = buf;
bail:
if (err && buf)
@@ -1094,7 +1157,7 @@ static void context_save_interrupted(struct smq_invoke_ctx *ctx)
hlist_add_head(&ctx->hn, &clst->interrupted);
spin_unlock(&ctx->fl->hlock);
/* free the cache on power collapse */
- fastrpc_buf_list_free(ctx->fl);
+ fastrpc_cached_buf_list_free(ctx->fl);
}
static void context_free(struct smq_invoke_ctx *ctx)
@@ -1317,7 +1380,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
/* allocate new buffer */
if (copylen) {
- VERIFY(err, !fastrpc_buf_alloc(ctx->fl, copylen, &ctx->buf));
+ err = fastrpc_buf_alloc(ctx->fl, copylen, 0, 0, 0, &ctx->buf);
if (err)
goto bail;
}
@@ -1804,6 +1867,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
struct fastrpc_ioctl_init *init = &uproc->init;
struct smq_phy_page pages[1];
struct fastrpc_mmap *file = NULL, *mem = NULL;
+ struct fastrpc_buf *imem = NULL;
+ unsigned long imem_dma_attr = 0;
char *proc_name = NULL;
int srcVM[1] = {VMID_HLOS};
int destVM[1] = {me->channel[fl->cid].rhvmid};
@@ -1834,6 +1899,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
remote_arg_t ra[6];
int fds[6];
int mflags = 0;
+ int memlen;
struct {
int pgid;
unsigned int namelen;
@@ -1861,16 +1927,24 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
goto bail;
}
inbuf.pageslen = 1;
- VERIFY(err, access_ok(1, (void __user *)init->mem,
- init->memlen));
- if (err)
+
+ VERIFY(err, !init->mem);
+ if (err) {
+ err = -EINVAL;
+ pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n",
+ current->comm, __func__);
goto bail;
- mutex_lock(&fl->fl_map_mutex);
- VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, 0,
- init->mem, init->memlen, mflags, &mem));
- mutex_unlock(&fl->fl_map_mutex);
+ }
+ memlen = ALIGN(max(1024*1024*3, (int)init->filelen * 4),
+ 1024*1024);
+ imem_dma_attr = DMA_ATTR_EXEC_MAPPING |
+ DMA_ATTR_NO_KERNEL_MAPPING |
+ DMA_ATTR_FORCE_NON_COHERENT;
+ err = fastrpc_buf_alloc(fl, memlen, imem_dma_attr, 0, 0, &imem);
if (err)
goto bail;
+ fl->init_mem = imem;
+
inbuf.pageslen = 1;
ra[0].buf.pv = (void *)&inbuf;
ra[0].buf.len = sizeof(inbuf);
@@ -1884,8 +1958,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
ra[2].buf.len = inbuf.filelen;
fds[2] = init->filefd;
- pages[0].addr = mem->phys;
- pages[0].size = mem->size;
+ pages[0].addr = imem->phys;
+ pages[0].size = imem->size;
ra[3].buf.pv = (void *)pages;
ra[3].buf.len = 1 * sizeof(*pages);
fds[3] = 0;
@@ -2046,7 +2120,8 @@ bail:
}
static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
- struct fastrpc_mmap *map)
+ uintptr_t va, uint64_t phys,
+ size_t size, uintptr_t *raddr)
{
struct fastrpc_ioctl_invoke_crc ioctl;
struct fastrpc_apps *me = &gfa;
@@ -2065,13 +2140,13 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
} routargs;
inargs.pid = fl->tgid;
- inargs.vaddrin = (uintptr_t)map->va;
+ inargs.vaddrin = (uintptr_t)va;
inargs.flags = flags;
inargs.num = fl->apps->compat ? num * sizeof(page) : num;
ra[0].buf.pv = (void *)&inargs;
ra[0].buf.len = sizeof(inargs);
- page.addr = map->phys;
- page.size = map->size;
+ page.addr = phys;
+ page.size = size;
ra[1].buf.pv = (void *)&page;
ra[1].buf.len = num * sizeof(page);
@@ -2089,15 +2164,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
ioctl.crc = NULL;
VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
- map->raddr = (uintptr_t)routargs.vaddrout;
+ *raddr = (uintptr_t)routargs.vaddrout;
if (err)
goto bail;
if (flags == ADSP_MMAP_HEAP_ADDR) {
struct scm_desc desc = {0};
desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC;
- desc.args[1] = map->phys;
- desc.args[2] = map->size;
+ desc.args[1] = phys;
+ desc.args[2] = size;
desc.arginfo = SCM_ARGS(3);
err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL,
TZ_PIL_PROTECT_MEM_SUBSYS_ID), &desc);
@@ -2107,7 +2182,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
int destVM[1] = {me->channel[fl->cid].rhvmid};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
- VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size,
+ VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size,
srcVM, 1, destVM, destVMperm, 1));
if (err)
goto bail;
@@ -2116,8 +2191,8 @@ bail:
return err;
}
-static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
- struct fastrpc_mmap *map)
+static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys,
+ size_t size, uint32_t flags)
{
int err = 0;
struct fastrpc_apps *me = &gfa;
@@ -2125,7 +2200,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
int destVM[1] = {VMID_HLOS};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
- if (map->flags == ADSP_MMAP_HEAP_ADDR) {
+ if (flags == ADSP_MMAP_HEAP_ADDR) {
struct fastrpc_ioctl_invoke_crc ioctl;
struct scm_desc desc = {0};
remote_arg_t ra[1];
@@ -2151,14 +2226,14 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
if (err)
goto bail;
desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC;
- desc.args[1] = map->phys;
- desc.args[2] = map->size;
+ desc.args[1] = phys;
+ desc.args[2] = size;
desc.args[3] = routargs.skey;
desc.arginfo = SCM_ARGS(4);
err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL,
TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc);
- } else if (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
- VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size,
+ } else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+ VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size,
srcVM, 1, destVM, destVMperm, 1));
if (err)
goto bail;
@@ -2168,8 +2243,8 @@ bail:
return err;
}
-static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
- struct fastrpc_mmap *map)
+static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr,
+ uint64_t phys, size_t size, uint32_t flags)
{
struct fastrpc_ioctl_invoke_crc ioctl;
remote_arg_t ra[1];
@@ -2181,8 +2256,8 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
} inargs;
inargs.pid = fl->tgid;
- inargs.size = map->size;
- inargs.vaddrout = map->raddr;
+ inargs.size = size;
+ inargs.vaddrout = raddr;
ra[0].buf.pv = (void *)&inargs;
ra[0].buf.len = sizeof(inargs);
@@ -2199,9 +2274,9 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
if (err)
goto bail;
- if (map->flags == ADSP_MMAP_HEAP_ADDR ||
- map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
- VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map));
+ if (flags == ADSP_MMAP_HEAP_ADDR ||
+ flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+ VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, phys, size, flags));
if (err)
goto bail;
}
@@ -2228,7 +2303,8 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl)
spin_unlock(&me->hlock);
if (match) {
- VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match));
+ VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match->phys,
+ match->size, match->flags));
if (err)
goto bail;
if (me->channel[0].ramdumpenabled) {
@@ -2292,14 +2368,40 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl,
{
int err = 0;
struct fastrpc_mmap *map = NULL;
+ struct fastrpc_buf *rbuf = NULL, *free = NULL;
+ struct hlist_node *n;
mutex_lock(&fl->map_mutex);
+
+ spin_lock(&fl->hlock);
+ hlist_for_each_entry_safe(rbuf, n, &fl->remote_bufs, hn_rem) {
+ if (rbuf->raddr && (rbuf->flags == ADSP_MMAP_ADD_PAGES)) {
+ if ((rbuf->raddr == ud->vaddrout) &&
+ (rbuf->size == ud->size)) {
+ free = rbuf;
+ break;
+ }
+ }
+ }
+ spin_unlock(&fl->hlock);
+
+ if (free) {
+ VERIFY(err, !fastrpc_munmap_on_dsp(fl, free->raddr,
+ free->phys, free->size, free->flags));
+ if (err)
+ goto bail;
+ fastrpc_buf_free(rbuf, 0);
+ mutex_unlock(&fl->map_mutex);
+ return err;
+ }
+
mutex_lock(&fl->fl_map_mutex);
VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map));
mutex_unlock(&fl->fl_map_mutex);
if (err)
goto bail;
- VERIFY(err, !fastrpc_munmap_on_dsp(fl, map));
+ VERIFY(err, !fastrpc_munmap_on_dsp(fl, map->raddr,
+ map->phys, map->size, map->flags));
if (err)
goto bail;
mutex_lock(&fl->fl_map_mutex);
@@ -2345,26 +2447,62 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl,
{
struct fastrpc_mmap *map = NULL;
+ struct fastrpc_buf *rbuf = NULL;
+ unsigned long dma_attr = 0;
+ uintptr_t raddr = 0;
int err = 0;
mutex_lock(&fl->map_mutex);
- mutex_lock(&fl->fl_map_mutex);
- if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin,
- ud->size, ud->flags, 1, &map)) {
+ if (ud->flags == ADSP_MMAP_ADD_PAGES) {
+ if (ud->vaddrin) {
+ err = -EINVAL;
+ pr_err("adsprpc: %s: %s: ERROR: adding user allocated pages is not supported\n",
+ current->comm, __func__);
+ goto bail;
+ }
+ dma_attr = DMA_ATTR_EXEC_MAPPING |
+ DMA_ATTR_NO_KERNEL_MAPPING |
+ DMA_ATTR_FORCE_NON_COHERENT;
+ err = fastrpc_buf_alloc(fl, ud->size, dma_attr, ud->flags,
+ 1, &rbuf);
+ if (err)
+ goto bail;
+ err = fastrpc_mmap_on_dsp(fl, ud->flags, 0,
+ rbuf->phys, rbuf->size, &raddr);
+ if (err)
+ goto bail;
+ rbuf->raddr = raddr;
+ } else {
+
+ uintptr_t va_to_dsp;
+
+ mutex_lock(&fl->fl_map_mutex);
+ if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin,
+ ud->size, ud->flags, 1, &map)) {
+ mutex_unlock(&fl->fl_map_mutex);
+ mutex_unlock(&fl->map_mutex);
+ return 0;
+ }
+
+ VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0,
+ (uintptr_t)ud->vaddrin, ud->size,
+ ud->flags, &map));
mutex_unlock(&fl->fl_map_mutex);
- mutex_unlock(&fl->map_mutex);
- return 0;
+ if (err)
+ goto bail;
+
+ if (ud->flags == ADSP_MMAP_HEAP_ADDR ||
+ ud->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)
+ va_to_dsp = 0;
+ else
+ va_to_dsp = (uintptr_t)map->va;
+ VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, va_to_dsp,
+ map->phys, map->size, &raddr));
+ if (err)
+ goto bail;
+ map->raddr = raddr;
}
- VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0,
- (uintptr_t)ud->vaddrin, ud->size,
- ud->flags, &map));
- mutex_unlock(&fl->fl_map_mutex);
- if (err)
- goto bail;
- VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, map));
- if (err)
- goto bail;
- ud->vaddrout = map->raddr;
+ ud->vaddrout = raddr;
bail:
if (err && map) {
mutex_lock(&fl->fl_map_mutex);
@@ -2541,8 +2679,10 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
spin_lock(&fl->hlock);
fl->file_close = 1;
spin_unlock(&fl->hlock);
+ if (!IS_ERR_OR_NULL(fl->init_mem))
+ fastrpc_buf_free(fl->init_mem, 0);
fastrpc_context_list_dtor(fl);
- fastrpc_buf_list_free(fl);
+ fastrpc_cached_buf_list_free(fl);
mutex_lock(&fl->fl_map_mutex);
do {
lmap = NULL;
@@ -2561,6 +2701,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
fastrpc_session_free(&fl->apps->channel[cid], fl->sctx);
if (fl->secsctx)
fastrpc_session_free(&fl->apps->channel[cid], fl->secsctx);
+ fastrpc_remote_buf_list_free(fl);
bail:
mutex_destroy(&fl->fl_map_mutex);
mutex_destroy(&fl->map_mutex);
@@ -2759,14 +2900,18 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
"%s %d\n\n",
"DEV_MINOR:", fl->dev_minor);
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %d\n\n",
+ "KERNEL MEMORY ALLOCATION:", 1);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
"%s\n",
- "LIST OF BUFS:");
+ "LIST OF CACHED BUFS:");
spin_lock(&fl->hlock);
- hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
+ hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) {
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %pK %s %pK %s %llx\n", "buf:",
- buf, "buf->virt:", buf->virt,
- "buf->phys:", buf->phys);
+ "%s %pK %s %pK %s %llx %s %lx\n",
+ "buf:", buf, "buf->virt:", buf->virt,
+ "buf->phys:", buf->phys,
+ "buf->dma_attr:", buf->dma_attr);
}
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
"\n%s\n",
@@ -2906,7 +3051,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
context_list_ctor(&fl->clst);
spin_lock_init(&fl->hlock);
INIT_HLIST_HEAD(&fl->maps);
- INIT_HLIST_HEAD(&fl->bufs);
+ INIT_HLIST_HEAD(&fl->cached_bufs);
+ INIT_HLIST_HEAD(&fl->remote_bufs);
INIT_HLIST_NODE(&fl->hn);
fl->sessionid = 0;
fl->tgid = current->tgid;
@@ -2914,6 +3060,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->mode = FASTRPC_MODE_SERIAL;
fl->cid = -1;
fl->dev_minor = dev_minor;
+ fl->init_mem = NULL;
if (debugfs_file != NULL)
fl->debugfs_file = debugfs_file;
@@ -3001,6 +3148,9 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
} else
pm_qos_update_request(&fl->pm_qos_req, latency);
break;
+ case FASTRPC_CONTROL_KALLOC:
+ cp->kalloc.kalloc_support = 1;
+ break;
default:
err = -ENOTTY;
break;
@@ -3163,6 +3313,11 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp)));
if (err)
goto bail;
+ if (p.cp.req == FASTRPC_CONTROL_KALLOC) {
+ K_COPY_TO_USER(err, 0, param, &p.cp, sizeof(p.cp));
+ if (err)
+ goto bail;
+ }
break;
case FASTRPC_IOCTL_GETINFO:
K_COPY_FROM_USER(err, 0, &info, param, sizeof(info));
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 804cedade655..ea7967c55aa1 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -126,16 +126,22 @@ struct compat_fastrpc_ioctl_perf { /* kernel performance data */
compat_uptr_t keys;
};
-#define FASTRPC_CONTROL_LATENCY (1)
+#define FASTRPC_CONTROL_LATENCY (1)
struct compat_fastrpc_ctrl_latency {
compat_uint_t enable; /* latency control enable */
compat_uint_t level; /* level of control */
};
+#define FASTRPC_CONTROL_KALLOC (3)
+struct compat_fastrpc_ctrl_kalloc {
+ compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
+};
+
struct compat_fastrpc_ioctl_control {
compat_uint_t req;
union {
struct compat_fastrpc_ctrl_latency lp;
+ struct compat_fastrpc_ctrl_kalloc kalloc;
};
};
@@ -528,6 +534,7 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
{
struct compat_fastrpc_ioctl_control __user *ctrl32;
struct fastrpc_ioctl_control __user *ctrl;
+ compat_uptr_t p;
ctrl32 = compat_ptr(arg);
VERIFY(err, NULL != (ctrl = compat_alloc_user_space(
@@ -540,6 +547,15 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
return err;
err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL,
(unsigned long)ctrl);
+ if (err)
+ return err;
+ err = get_user(p, &ctrl32->req);
+ if (err)
+ return err;
+ if (p == FASTRPC_CONTROL_KALLOC) {
+ err = get_user(p, &ctrl->kalloc.kalloc_support);
+ err |= put_user(p, &ctrl32->kalloc.kalloc_support);
+ }
return err;
}
case COMPAT_FASTRPC_IOCTL_GETPERF:
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index e3c5ee0d87e9..c7f67fe695e1 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -220,7 +220,7 @@ struct fastrpc_ioctl_mmap {
};
struct fastrpc_ioctl_mmap_64 {
- int fd; /* ion fd */
+ int fd; /* ion fd */
uint32_t flags; /* flags for dsp to map with */
uint64_t vaddrin; /* optional virtual address */
size_t size; /* size */
@@ -240,16 +240,22 @@ struct fastrpc_ioctl_perf { /* kernel performance data */
uintptr_t keys;
};
-#define FASTRPC_CONTROL_LATENCY (1)
+#define FASTRPC_CONTROL_LATENCY (1)
struct fastrpc_ctrl_latency {
- uint32_t enable; //!latency control enable
- uint32_t level; //!level of control
+ uint32_t enable; /* latency control enable */
+ uint32_t level; /* level of control */
+};
+
+#define FASTRPC_CONTROL_KALLOC (3)
+struct fastrpc_ctrl_kalloc {
+ uint32_t kalloc_support; /* Remote memory allocation from kernel */
};
struct fastrpc_ioctl_control {
uint32_t req;
union {
struct fastrpc_ctrl_latency lp;
+ struct fastrpc_ctrl_kalloc kalloc;
};
};
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index ce0c7bb2fbef..46de6a67a0a4 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -194,6 +194,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx)
}
found = 0;
+ mutex_lock(&driver->diagchar_mutex);
for (i = 0; i < driver->num_clients && !found; i++) {
if ((driver->client_map[i].pid != pid) ||
(driver->client_map[i].pid == 0))
@@ -207,6 +208,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx)
pr_debug("diag: wake up logging process\n");
wake_up_interruptible(&driver->wait_q);
}
+ mutex_unlock(&driver->diagchar_mutex);
if (!found)
return -EINVAL;
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index cd65e0f52591..52b18d8cbf7a 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -389,6 +389,8 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info,
goto end;
}
}
+ mutex_unlock(&fwd_info->data_mutex);
+ mutex_unlock(&driver->hdlc_disable_mutex);
if (write_len > 0) {
err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len,
@@ -396,18 +398,18 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info,
if (err) {
pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n",
__func__, err);
- goto end;
+ goto end_write;
}
}
- mutex_unlock(&fwd_info->data_mutex);
- mutex_unlock(&driver->hdlc_disable_mutex);
+
diagfwd_queue_read(fwd_info);
return;
end:
- diag_ws_release();
mutex_unlock(&fwd_info->data_mutex);
mutex_unlock(&driver->hdlc_disable_mutex);
+end_write:
+ diag_ws_release();
if (buf) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"Marking buffer as free p: %d, t: %d, buf_num: %d\n",
@@ -699,24 +701,26 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
}
}
+ mutex_unlock(&fwd_info->data_mutex);
+ mutex_unlock(&driver->hdlc_disable_mutex);
+
if (write_len > 0) {
err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len,
temp_buf->ctxt);
if (err) {
pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n",
__func__, err);
- goto end;
+ goto end_write;
}
}
- mutex_unlock(&fwd_info->data_mutex);
- mutex_unlock(&driver->hdlc_disable_mutex);
diagfwd_queue_read(fwd_info);
return;
end:
- diag_ws_release();
mutex_unlock(&fwd_info->data_mutex);
mutex_unlock(&driver->hdlc_disable_mutex);
+end_write:
+ diag_ws_release();
if (temp_buf) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"Marking buffer as free p: %d, t: %d, buf_num: %d\n",
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 958fb9160c2d..6974e1038bc6 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1,7 +1,7 @@
/*
* QTI CE device driver.
*
- * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1227,8 +1227,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
goto exit;
}
- k_align_dst += creq->vbuf.dst[dst_i].len +
- byteoffset;
+ k_align_dst += creq->vbuf.dst[dst_i].len;
creq->data_len -= creq->vbuf.dst[dst_i].len;
dst_i++;
} else {
diff --git a/drivers/devfreq/governor_gpubw_mon.c b/drivers/devfreq/governor_gpubw_mon.c
index 9c24eef6a497..f7bb7ebf41ea 100644
--- a/drivers/devfreq/governor_gpubw_mon.c
+++ b/drivers/devfreq/governor_gpubw_mon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -224,10 +224,11 @@ static int devfreq_gpubw_event_handler(struct devfreq *devfreq,
case DEVFREQ_GOV_SUSPEND:
{
struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
-
- priv->bus.total_time = 0;
- priv->bus.gpu_time = 0;
- priv->bus.ram_time = 0;
+ if (priv) {
+ priv->bus.total_time = 0;
+ priv->bus.gpu_time = 0;
+ priv->bus.ram_time = 0;
+ }
}
break;
default:
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 68418a6536b0..beba6635cd2c 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -143,4 +143,3 @@ obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
obj-$(CONFIG_GPIO_ZX) += gpio-zx.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
obj-$(CONFIG_MSM_SMP2P) += gpio-msm-smp2p.o
-obj-$(CONFIG_MSM_SMP2P_TEST) += gpio-msm-smp2p-test.o
diff --git a/drivers/gpio/gpio-msm-smp2p-test.c b/drivers/gpio/gpio-msm-smp2p-test.c
deleted file mode 100644
index 1067c4aade39..000000000000
--- a/drivers/gpio/gpio-msm-smp2p-test.c
+++ /dev/null
@@ -1,763 +0,0 @@
-/* drivers/gpio/gpio-msm-smp2p-test.c
- *
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of_irq.h>
-#include <linux/gpio.h>
-#include <linux/debugfs.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-#include <linux/bitmap.h>
-#include "../soc/qcom/smp2p_private.h"
-#include "../soc/qcom/smp2p_test_common.h"
-
-/* Interrupt callback data */
-struct gpio_info {
- int gpio_base_id;
- int irq_base_id;
-
- bool initialized;
- struct completion cb_completion;
- int cb_count;
- DECLARE_BITMAP(triggered_irqs, SMP2P_BITS_PER_ENTRY);
-};
-
-/* GPIO Inbound/Outbound callback info */
-struct gpio_inout {
- struct gpio_info in;
- struct gpio_info out;
-};
-
-static struct gpio_inout gpio_info[SMP2P_NUM_PROCS];
-
-/**
- * Init/reset the callback data.
- *
- * @info: Pointer to callback data
- */
-static void cb_data_reset(struct gpio_info *info)
-{
- int n;
-
- if (!info)
- return;
-
- if (!info->initialized) {
- init_completion(&info->cb_completion);
- info->initialized = true;
- }
- info->cb_count = 0;
-
- for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n)
- clear_bit(n, info->triggered_irqs);
-
- reinit_completion(&info->cb_completion);
-}
-
-static int smp2p_gpio_test_probe(struct platform_device *pdev)
-{
- int id;
- int cnt;
- struct device_node *node = pdev->dev.of_node;
- struct gpio_info *gpio_info_ptr = NULL;
-
- /*
- * NOTE: This does a string-lookup of the GPIO pin name and doesn't
- * actually directly link to the SMP2P GPIO driver since all
- * GPIO/Interrupt access must be through standard
- * Linux GPIO / Interrupt APIs.
- */
- if (strcmp("qcom,smp2pgpio_test_smp2p_1_in", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].in;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_1_out", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].out;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_in", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].in;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_out", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].out;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_in", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].in;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_out", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].out;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_in", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_in", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_out", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].in;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].out;
- } else if (strcmp("qcom,smp2pgpio_test_smp2p_15_in", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
- } else if (
- strcmp("qcom,smp2pgpio_test_smp2p_15_out", node->name) == 0) {
- gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out;
- } else {
- pr_err("%s: unable to match device type '%s'\n",
- __func__, node->name);
- return -ENODEV;
- }
-
- /* retrieve the GPIO and interrupt ID's */
- cnt = of_gpio_count(node);
- if (cnt && gpio_info_ptr) {
- /*
- * Instead of looping through all 32-bits, we can just get the
- * first pin to get the base IDs. This saves on the verbosity
- * of the device tree nodes as well.
- */
- id = of_get_gpio(node, 0);
- if (id == -EPROBE_DEFER)
- return id;
- gpio_info_ptr->gpio_base_id = id;
- gpio_info_ptr->irq_base_id = gpio_to_irq(id);
- }
- return 0;
-}
-
-/*
- * NOTE: Instead of match table and device driver, you may be able to just
- * call of_find_compatible_node() in your init function.
- */
-static const struct of_device_id msm_smp2p_match_table[] = {
- /* modem */
- {.compatible = "qcom,smp2pgpio_test_smp2p_1_out", },
- {.compatible = "qcom,smp2pgpio_test_smp2p_1_in", },
-
- /* audio (adsp) */
- {.compatible = "qcom,smp2pgpio_test_smp2p_2_out", },
- {.compatible = "qcom,smp2pgpio_test_smp2p_2_in", },
-
- /* sensor */
- {.compatible = "qcom,smp2pgpio_test_smp2p_3_out", },
- {.compatible = "qcom,smp2pgpio_test_smp2p_3_in", },
-
- /* wcnss */
- {.compatible = "qcom,smp2pgpio_test_smp2p_4_out", },
- {.compatible = "qcom,smp2pgpio_test_smp2p_4_in", },
-
- /* CDSP */
- {.compatible = "qcom,smp2pgpio_test_smp2p_5_out", },
- {.compatible = "qcom,smp2pgpio_test_smp2p_5_in", },
-
- /* TZ */
- {.compatible = "qcom,smp2pgpio_test_smp2p_7_out", },
- {.compatible = "qcom,smp2pgpio_test_smp2p_7_in", },
-
- /* mock loopback */
- {.compatible = "qcom,smp2pgpio_test_smp2p_15_out", },
- {.compatible = "qcom,smp2pgpio_test_smp2p_15_in", },
- {},
-};
-
-static struct platform_driver smp2p_gpio_driver = {
- .probe = smp2p_gpio_test_probe,
- .driver = {
- .name = "smp2pgpio_test",
- .owner = THIS_MODULE,
- .of_match_table = msm_smp2p_match_table,
- },
-};
-
-/**
- * smp2p_ut_local_gpio_out - Verify outbound functionality.
- *
- * @s: pointer to output file
- */
-static void smp2p_ut_local_gpio_out(struct seq_file *s)
-{
- int failed = 0;
- struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out;
- int ret;
- int id;
- struct msm_smp2p_remote_mock *mock;
-
- seq_printf(s, "Running %s\n", __func__);
- do {
- /* initialize mock edge */
- ret = smp2p_reset_mock_edge();
- UT_ASSERT_INT(ret, ==, 0);
-
- mock = msm_smp2p_get_remote_mock();
- UT_ASSERT_PTR(mock, !=, NULL);
-
- mock->rx_interrupt_count = 0;
- memset(&mock->remote_item, 0,
- sizeof(struct smp2p_smem_item));
- smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
- SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
- 0, 1);
- strlcpy(mock->remote_item.entries[0].name, "smp2p",
- SMP2P_MAX_ENTRY_NAME);
- SMP2P_SET_ENT_VALID(
- mock->remote_item.header.valid_total_ent, 1);
- msm_smp2p_set_remote_mock_exists(true);
- mock->tx_interrupt();
-
- /* open GPIO entry */
- smp2p_gpio_open_test_entry("smp2p",
- SMP2P_REMOTE_MOCK_PROC, true);
-
- /* verify set/get functions */
- UT_ASSERT_INT(0, <, cb_info->gpio_base_id);
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- int pin = cb_info->gpio_base_id + id;
-
- mock->rx_interrupt_count = 0;
- gpio_set_value(pin, 1);
- UT_ASSERT_INT(1, ==, mock->rx_interrupt_count);
- UT_ASSERT_INT(1, ==, gpio_get_value(pin));
-
- gpio_set_value(pin, 0);
- UT_ASSERT_INT(2, ==, mock->rx_interrupt_count);
- UT_ASSERT_INT(0, ==, gpio_get_value(pin));
- }
- if (failed)
- break;
-
- seq_puts(s, "\tOK\n");
- } while (0);
-
- if (failed) {
- pr_err("%s: Failed\n", __func__);
- seq_puts(s, "\tFailed\n");
- }
-
- smp2p_gpio_open_test_entry("smp2p",
- SMP2P_REMOTE_MOCK_PROC, false);
-}
-
-/**
- * smp2p_gpio_irq - Interrupt handler for inbound entries.
- *
- * @irq: Virtual IRQ being triggered
- * @data: Cookie data (struct gpio_info * in this case)
- * @returns: Number of bytes written
- */
-static irqreturn_t smp2p_gpio_irq(int irq, void *data)
-{
- struct gpio_info *gpio_ptr = (struct gpio_info *)data;
- int offset;
-
- if (!gpio_ptr) {
- pr_err("%s: gpio_ptr is NULL for irq %d\n", __func__, irq);
- return IRQ_HANDLED;
- }
-
- offset = irq - gpio_ptr->irq_base_id;
- if (offset >= 0 && offset < SMP2P_BITS_PER_ENTRY)
- set_bit(offset, gpio_ptr->triggered_irqs);
- else
- pr_err("%s: invalid irq offset base %d; irq %d\n",
- __func__, gpio_ptr->irq_base_id, irq);
-
- ++gpio_ptr->cb_count;
- complete(&gpio_ptr->cb_completion);
- return IRQ_HANDLED;
-}
-
-/**
- * smp2p_ut_local_gpio_in - Verify inbound functionality.
- *
- * @s: pointer to output file
- */
-static void smp2p_ut_local_gpio_in(struct seq_file *s)
-{
- int failed = 0;
- struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
- int id;
- int ret;
- int virq;
- struct msm_smp2p_remote_mock *mock;
-
- seq_printf(s, "Running %s\n", __func__);
-
- cb_data_reset(cb_info);
- do {
- /* initialize mock edge */
- ret = smp2p_reset_mock_edge();
- UT_ASSERT_INT(ret, ==, 0);
-
- mock = msm_smp2p_get_remote_mock();
- UT_ASSERT_PTR(mock, !=, NULL);
-
- mock->rx_interrupt_count = 0;
- memset(&mock->remote_item, 0,
- sizeof(struct smp2p_smem_item));
- smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
- SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
- 0, 1);
- strlcpy(mock->remote_item.entries[0].name, "smp2p",
- SMP2P_MAX_ENTRY_NAME);
- SMP2P_SET_ENT_VALID(
- mock->remote_item.header.valid_total_ent, 1);
- msm_smp2p_set_remote_mock_exists(true);
- mock->tx_interrupt();
-
- smp2p_gpio_open_test_entry("smp2p",
- SMP2P_REMOTE_MOCK_PROC, true);
-
- /* verify set/get functions locally */
- UT_ASSERT_INT(0, <, cb_info->gpio_base_id);
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- int pin;
- int current_value;
-
- /* verify pin value cannot be set */
- pin = cb_info->gpio_base_id + id;
- current_value = gpio_get_value(pin);
-
- gpio_set_value(pin, 0);
- UT_ASSERT_INT(current_value, ==, gpio_get_value(pin));
- gpio_set_value(pin, 1);
- UT_ASSERT_INT(current_value, ==, gpio_get_value(pin));
-
- /* verify no interrupts */
- UT_ASSERT_INT(0, ==, cb_info->cb_count);
- }
- if (failed)
- break;
-
- /* register for interrupts */
- UT_ASSERT_INT(0, <, cb_info->irq_base_id);
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- virq = cb_info->irq_base_id + id;
- UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq));
- ret = request_irq(virq,
- smp2p_gpio_irq, IRQF_TRIGGER_RISING,
- "smp2p_test", cb_info);
- UT_ASSERT_INT(0, ==, ret);
- }
- if (failed)
- break;
-
- /* verify both rising and falling edge interrupts */
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- virq = cb_info->irq_base_id + id;
- irq_set_irq_type(virq, IRQ_TYPE_EDGE_BOTH);
- cb_data_reset(cb_info);
-
- /* verify rising-edge interrupt */
- mock->remote_item.entries[0].entry = 1 << id;
- mock->tx_interrupt();
- UT_ASSERT_INT(cb_info->cb_count, ==, 1);
- UT_ASSERT_INT(0, <,
- test_bit(id, cb_info->triggered_irqs));
- test_bit(id, cb_info->triggered_irqs);
-
- /* verify falling-edge interrupt */
- mock->remote_item.entries[0].entry = 0;
- mock->tx_interrupt();
- UT_ASSERT_INT(cb_info->cb_count, ==, 2);
- UT_ASSERT_INT(0, <,
- test_bit(id, cb_info->triggered_irqs));
- }
- if (failed)
- break;
-
- /* verify rising-edge interrupts */
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- virq = cb_info->irq_base_id + id;
- irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
- cb_data_reset(cb_info);
-
- /* verify only rising-edge interrupt is triggered */
- mock->remote_item.entries[0].entry = 1 << id;
- mock->tx_interrupt();
- UT_ASSERT_INT(cb_info->cb_count, ==, 1);
- UT_ASSERT_INT(0, <,
- test_bit(id, cb_info->triggered_irqs));
- test_bit(id, cb_info->triggered_irqs);
-
- mock->remote_item.entries[0].entry = 0;
- mock->tx_interrupt();
- UT_ASSERT_INT(cb_info->cb_count, ==, 1);
- UT_ASSERT_INT(0, <,
- test_bit(id, cb_info->triggered_irqs));
- }
- if (failed)
- break;
-
- /* verify falling-edge interrupts */
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- virq = cb_info->irq_base_id + id;
- irq_set_irq_type(virq, IRQ_TYPE_EDGE_FALLING);
- cb_data_reset(cb_info);
-
- /* verify only rising-edge interrupt is triggered */
- mock->remote_item.entries[0].entry = 1 << id;
- mock->tx_interrupt();
- UT_ASSERT_INT(cb_info->cb_count, ==, 0);
- UT_ASSERT_INT(0, ==,
- test_bit(id, cb_info->triggered_irqs));
-
- mock->remote_item.entries[0].entry = 0;
- mock->tx_interrupt();
- UT_ASSERT_INT(cb_info->cb_count, ==, 1);
- UT_ASSERT_INT(0, <,
- test_bit(id, cb_info->triggered_irqs));
- }
- if (failed)
- break;
-
- seq_puts(s, "\tOK\n");
- } while (0);
-
- if (failed) {
- pr_err("%s: Failed\n", __func__);
- seq_puts(s, "\tFailed\n");
- }
-
- /* unregister for interrupts */
- if (cb_info->irq_base_id) {
- for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
- free_irq(cb_info->irq_base_id + id, cb_info);
- }
-
- smp2p_gpio_open_test_entry("smp2p",
- SMP2P_REMOTE_MOCK_PROC, false);
-}
-
-/**
- * smp2p_ut_local_gpio_in_update_open - Verify combined open/update.
- *
- * @s: pointer to output file
- *
- * If the remote side updates the SMP2P bits and sends before negotiation is
- * complete, then the UPDATE event will have to be delayed until negotiation is
- * complete. This should result in both the OPEN and UPDATE events coming in
- * right after each other and the behavior should be transparent to the clients
- * of SMP2P GPIO.
- */
-static void smp2p_ut_local_gpio_in_update_open(struct seq_file *s)
-{
- int failed = 0;
- struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in;
- int id;
- int ret;
- int virq;
- struct msm_smp2p_remote_mock *mock;
-
- seq_printf(s, "Running %s\n", __func__);
-
- cb_data_reset(cb_info);
- do {
- /* initialize mock edge */
- ret = smp2p_reset_mock_edge();
- UT_ASSERT_INT(ret, ==, 0);
-
- mock = msm_smp2p_get_remote_mock();
- UT_ASSERT_PTR(mock, !=, NULL);
-
- mock->rx_interrupt_count = 0;
- memset(&mock->remote_item, 0,
- sizeof(struct smp2p_smem_item));
- smp2p_init_header((struct smp2p_smem *)&mock->remote_item,
- SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC,
- 0, 1);
- strlcpy(mock->remote_item.entries[0].name, "smp2p",
- SMP2P_MAX_ENTRY_NAME);
- SMP2P_SET_ENT_VALID(
- mock->remote_item.header.valid_total_ent, 1);
-
- /* register for interrupts */
- smp2p_gpio_open_test_entry("smp2p",
- SMP2P_REMOTE_MOCK_PROC, true);
-
- UT_ASSERT_INT(0, <, cb_info->irq_base_id);
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- virq = cb_info->irq_base_id + id;
- UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq));
- ret = request_irq(virq,
- smp2p_gpio_irq, IRQ_TYPE_EDGE_BOTH,
- "smp2p_test", cb_info);
- UT_ASSERT_INT(0, ==, ret);
- }
- if (failed)
- break;
-
- /* update the state value and complete negotiation */
- mock->remote_item.entries[0].entry = 0xDEADDEAD;
- msm_smp2p_set_remote_mock_exists(true);
- mock->tx_interrupt();
-
- /* verify delayed state updates were processed */
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- virq = cb_info->irq_base_id + id;
-
- UT_ASSERT_INT(cb_info->cb_count, >, 0);
- if (0x1 & (0xDEADDEAD >> id)) {
- /* rising edge should have been triggered */
- if (!test_bit(id, cb_info->triggered_irqs)) {
- seq_printf(s, "%s:%d bit %d clear, ",
- __func__, __LINE__, id);
- seq_puts(s, "expected set\n");
- failed = 1;
- break;
- }
- } else {
- /* edge should not have been triggered */
- if (test_bit(id, cb_info->triggered_irqs)) {
- seq_printf(s, "%s:%d bit %d set, ",
- __func__, __LINE__, id);
- seq_puts(s, "expected clear\n");
- failed = 1;
- break;
- }
- }
- }
- if (failed)
- break;
-
- seq_puts(s, "\tOK\n");
- } while (0);
-
- if (failed) {
- pr_err("%s: Failed\n", __func__);
- seq_puts(s, "\tFailed\n");
- }
-
- /* unregister for interrupts */
- if (cb_info->irq_base_id) {
- for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
- free_irq(cb_info->irq_base_id + id, cb_info);
- }
-
- smp2p_gpio_open_test_entry("smp2p",
- SMP2P_REMOTE_MOCK_PROC, false);
-}
-
-/**
- * smp2p_gpio_write_bits - writes value to each GPIO pin specified in mask.
- *
- * @gpio: gpio test structure
- * @mask: 1 = write gpio_value to this GPIO pin
- * @gpio_value: value to write to GPIO pin
- */
-static void smp2p_gpio_write_bits(struct gpio_info *gpio, uint32_t mask,
- int gpio_value)
-{
- int n;
-
- for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) {
- if (mask & 0x1)
- gpio_set_value(gpio->gpio_base_id + n, gpio_value);
- mask >>= 1;
- }
-}
-
-static void smp2p_gpio_set_bits(struct gpio_info *gpio, uint32_t mask)
-{
- smp2p_gpio_write_bits(gpio, mask, 1);
-}
-
-static void smp2p_gpio_clr_bits(struct gpio_info *gpio, uint32_t mask)
-{
- smp2p_gpio_write_bits(gpio, mask, 0);
-}
-
-/**
- * smp2p_gpio_get_value - reads entire 32-bits of GPIO
- *
- * @gpio: gpio structure
- * @returns: 32 bit value of GPIO pins
- */
-static uint32_t smp2p_gpio_get_value(struct gpio_info *gpio)
-{
- int n;
- uint32_t value = 0;
-
- for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) {
- if (gpio_get_value(gpio->gpio_base_id + n))
- value |= 1 << n;
- }
- return value;
-}
-
-/**
- * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality.
- *
- * @s: pointer to output file
- * @remote_pid: Remote processor to test
- * @name: Name of the test for reporting
- *
- * This test verifies inbound/outbound functionality for the remote processor.
- */
-static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid,
- const char *name)
-{
- int failed = 0;
- uint32_t request;
- uint32_t response;
- struct gpio_info *cb_in;
- struct gpio_info *cb_out;
- int id;
- int ret;
-
- seq_printf(s, "Running %s for '%s' remote pid %d\n",
- __func__, smp2p_pid_to_name(remote_pid), remote_pid);
-
- cb_in = &gpio_info[remote_pid].in;
- cb_out = &gpio_info[remote_pid].out;
- cb_data_reset(cb_in);
- cb_data_reset(cb_out);
- do {
- /* open test entries */
- msm_smp2p_deinit_rmt_lpb_proc(remote_pid);
- smp2p_gpio_open_test_entry("smp2p", remote_pid, true);
-
- /* register for interrupts */
- UT_ASSERT_INT(0, <, cb_in->gpio_base_id);
- UT_ASSERT_INT(0, <, cb_in->irq_base_id);
- for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) {
- int virq = cb_in->irq_base_id + id;
-
- UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq));
- ret = request_irq(virq,
- smp2p_gpio_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "smp2p_test", cb_in);
- UT_ASSERT_INT(0, ==, ret);
- }
- if (failed)
- break;
-
- /* write echo of data value 0 */
- UT_ASSERT_INT(0, <, cb_out->gpio_base_id);
- request = 0x0;
- SMP2P_SET_RMT_CMD_TYPE(request, 1);
- SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO);
- SMP2P_SET_RMT_DATA(request, 0x0);
-
- smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
- smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK);
- smp2p_gpio_set_bits(cb_out, request);
-
- UT_ASSERT_INT(cb_in->cb_count, ==, 0);
- smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
-
- /* verify response */
- do {
- /* wait for up to 32 changes */
- if (wait_for_completion_timeout(
- &cb_in->cb_completion, HZ / 2) == 0)
- break;
- reinit_completion(&cb_in->cb_completion);
- } while (cb_in->cb_count < 32);
- UT_ASSERT_INT(cb_in->cb_count, >, 0);
- response = smp2p_gpio_get_value(cb_in);
- SMP2P_SET_RMT_CMD_TYPE(request, 0);
- UT_ASSERT_HEX(request, ==, response);
-
- /* write echo of data value of all 1's */
- request = 0x0;
- SMP2P_SET_RMT_CMD_TYPE(request, 1);
- SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO);
- SMP2P_SET_RMT_DATA(request, ~0);
-
- smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
- cb_data_reset(cb_in);
- smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK);
- smp2p_gpio_set_bits(cb_out, request);
-
- UT_ASSERT_INT(cb_in->cb_count, ==, 0);
- smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK);
-
- /* verify response including 24 interrupts */
- do {
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_in->cb_completion, HZ / 2),
- >, 0);
- reinit_completion(&cb_in->cb_completion);
- } while (cb_in->cb_count < 24);
- response = smp2p_gpio_get_value(cb_in);
- SMP2P_SET_RMT_CMD_TYPE(request, 0);
- UT_ASSERT_HEX(request, ==, response);
- UT_ASSERT_INT(24, ==, cb_in->cb_count);
-
- seq_puts(s, "\tOK\n");
- } while (0);
-
- if (failed) {
- pr_err("%s: Failed\n", name);
- seq_puts(s, "\tFailed\n");
- }
-
- /* unregister for interrupts */
- if (cb_in->irq_base_id) {
- for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id)
- free_irq(cb_in->irq_base_id + id, cb_in);
- }
-
- smp2p_gpio_open_test_entry("smp2p", remote_pid, false);
- msm_smp2p_init_rmt_lpb_proc(remote_pid);
-}
-
-/**
- * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all.
- *
- * @s: pointer to output file
- *
- * This test verifies inbound and outbound functionality for all
- * configured remote processor.
- */
-static void smp2p_ut_remote_inout(struct seq_file *s)
-{
- struct smp2p_interrupt_config *int_cfg;
- int pid;
-
- int_cfg = smp2p_get_interrupt_config();
- if (!int_cfg) {
- seq_puts(s, "Remote processor config unavailable\n");
- return;
- }
-
- for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) {
- if (!int_cfg[pid].is_configured)
- continue;
-
- smp2p_ut_remote_inout_core(s, pid, __func__);
- }
-}
-
-static int __init smp2p_debugfs_init(void)
-{
- /* register GPIO pins */
- (void)platform_driver_register(&smp2p_gpio_driver);
-
- /*
- * Add Unit Test entries.
- *
- * The idea with unit tests is that you can run all of them
- * from ADB shell by doing:
- * adb shell
- * cat ut*
- *
- * And if particular tests fail, you can then repeatedly run the
- * failing tests as you debug and resolve the failing test.
- */
- smp2p_debug_create("ut_local_gpio_out", smp2p_ut_local_gpio_out);
- smp2p_debug_create("ut_local_gpio_in", smp2p_ut_local_gpio_in);
- smp2p_debug_create("ut_local_gpio_in_update_open",
- smp2p_ut_local_gpio_in_update_open);
- smp2p_debug_create("ut_remote_gpio_inout", smp2p_ut_remote_inout);
- return 0;
-}
-late_initcall(smp2p_debugfs_init);
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 78bea02955fb..0589bda19884 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -104,7 +104,7 @@ static ssize_t dp_debug_write_edid(struct file *file,
size = min_t(size_t, count, SZ_1K);
buf = kzalloc(size, GFP_KERNEL);
- if (!buf) {
+ if (ZERO_OR_NULL_PTR(buf)) {
rc = -ENOMEM;
goto bail;
}
@@ -172,7 +172,7 @@ static ssize_t dp_debug_write_dpcd(struct file *file,
size = min_t(size_t, count, SZ_2K);
buf = kzalloc(size, GFP_KERNEL);
- if (!buf) {
+ if (ZERO_OR_NULL_PTR(buf)) {
rc = -ENOMEM;
goto bail;
}
@@ -493,7 +493,7 @@ static ssize_t dp_debug_read_edid_modes(struct file *file,
goto error;
buf = kzalloc(SZ_4K, GFP_KERNEL);
- if (!buf) {
+ if (ZERO_OR_NULL_PTR(buf)) {
rc = -ENOMEM;
goto error;
}
@@ -538,7 +538,7 @@ static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff,
return 0;
buf = kzalloc(SZ_4K, GFP_KERNEL);
- if (!buf)
+ if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
rc = snprintf(buf + len, max_size, "\tstate=0x%x\n", debug->aux->state);
@@ -624,7 +624,7 @@ static ssize_t dp_debug_bw_code_read(struct file *file,
return 0;
buf = kzalloc(SZ_4K, GFP_KERNEL);
- if (!buf)
+ if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
len += snprintf(buf + len, (SZ_4K - len),
@@ -745,7 +745,7 @@ static ssize_t dp_debug_read_hdr(struct file *file,
goto error;
buf = kzalloc(SZ_4K, GFP_KERNEL);
- if (!buf) {
+ if (ZERO_OR_NULL_PTR(buf)) {
rc = -ENOMEM;
goto error;
}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index ca9935c9741f..c429975dbc20 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1099,7 +1099,7 @@ static ssize_t debugfs_misr_read(struct file *file,
return 0;
buf = kzalloc(max_len, GFP_KERNEL);
- if (!buf)
+ if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
mutex_lock(&display->display_lock);
@@ -1130,7 +1130,7 @@ static ssize_t debugfs_misr_read(struct file *file,
goto error;
}
- if (copy_to_user(user_buf, buf, len)) {
+ if (copy_to_user(user_buf, buf, max_len)) {
rc = -EFAULT;
goto error;
}
@@ -1162,6 +1162,9 @@ static ssize_t debugfs_esd_trigger_check(struct file *file,
if (user_len > sizeof(u32))
return -EINVAL;
+ if (!user_len || !user_buf)
+ return -EINVAL;
+
buf = kzalloc(user_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -1217,7 +1220,7 @@ static ssize_t debugfs_alter_esd_check_mode(struct file *file,
return 0;
buf = kzalloc(len, GFP_KERNEL);
- if (!buf)
+ if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
if (copy_from_user(buf, user_buf, user_len)) {
@@ -1289,7 +1292,7 @@ static ssize_t debugfs_read_esd_check_mode(struct file *file,
}
buf = kzalloc(len, GFP_KERNEL);
- if (!buf)
+ if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
esd_config = &display->panel->esd_config;
@@ -3067,9 +3070,6 @@ int dsi_post_clkon_cb(void *priv,
__func__, rc);
goto error;
}
-
- /* enable dsi to serve irqs */
- dsi_display_ctrl_irq_update(display, true);
}
if ((clk & DSI_LINK_CLK) && (l_type & DSI_LINK_HS_CLK)) {
@@ -3091,6 +3091,11 @@ int dsi_post_clkon_cb(void *priv,
}
}
}
+
+ /* enable dsi to serve irqs */
+ if (clk & DSI_CORE_CLK)
+ dsi_display_ctrl_irq_update(display, true);
+
error:
return rc;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
index 05ac8930ce2d..01d2f527d041 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
@@ -24,8 +24,7 @@
#define GAMUT_LUT_MEM_SIZE ((sizeof(struct drm_msm_3d_gamut)) + \
REG_DMA_HEADERS_BUFFER_SZ)
-#define GAMUT_SCALE_OFF_LEN (GAMUT_3D_SCALE_OFF_SZ * \
- GAMUT_3D_SCALE_OFF_TBL_NUM * sizeof(u32))
+#define GAMUT_SCALE_OFF_LEN (GAMUT_3D_SCALE_OFF_SZ * sizeof(u32))
#define GAMUT_SCALE_OFF_LEN_12 (GAMUT_3D_SCALEB_OFF_SZ * sizeof(u32))
#define GC_LUT_MEM_SIZE ((sizeof(struct drm_msm_pgc_lut)) + \
diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c
index 582909580be9..d8f75c05f739 100644
--- a/drivers/gpu/drm/msm/sde_dbg.c
+++ b/drivers/gpu/drm/msm/sde_dbg.c
@@ -3002,6 +3002,37 @@ static int sde_dbg_reg_base_release(struct inode *inode, struct file *file)
return 0;
}
+/**
+ * sde_dbg_reg_base_is_valid_range - verify if requested memory range is valid
+ * @off: address offset in bytes
+ * @cnt: memory size in bytes
+ * Return: true if valid; false otherwise
+ */
+static bool sde_dbg_reg_base_is_valid_range(u32 off, u32 cnt)
+{
+ static struct sde_dbg_base *dbg_base = &sde_dbg_base;
+ struct sde_dbg_reg_range *node;
+ struct sde_dbg_reg_base *base;
+
+ pr_debug("check offset=0x%x cnt=0x%x\n", off, cnt);
+
+ list_for_each_entry(base, &dbg_base->reg_base_list, reg_base_head) {
+ list_for_each_entry(node, &base->sub_range_list, head) {
+ pr_debug("%s: start=0x%x end=0x%x\n", node->range_name,
+ node->offset.start, node->offset.end);
+
+ if (node->offset.start <= off
+ && off <= node->offset.end
+ && off + cnt <= node->offset.end) {
+ pr_debug("valid range requested\n");
+ return true;
+ }
+ }
+ }
+
+ pr_err("invalid range requested\n");
+ return false;
+}
/**
* sde_dbg_reg_base_offset_write - set new offset and len to debugfs reg base
@@ -3048,6 +3079,9 @@ static ssize_t sde_dbg_reg_base_offset_write(struct file *file,
if (cnt == 0)
return -EINVAL;
+ if (!sde_dbg_reg_base_is_valid_range(off, cnt))
+ return -EINVAL;
+
mutex_lock(&sde_dbg_base.mutex);
dbg->off = off;
dbg->cnt = cnt;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index f0e2757cb909..216f0338a1f7 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -192,6 +192,11 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
int ret = 0, len;
unsigned char report_number;
+ if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+ ret = -ENODEV;
+ goto out;
+ }
+
dev = hidraw_table[minor]->hid;
if (!dev->ll_driver->raw_request) {
diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c
index 4daed7f4875f..fa55b6e8d163 100644
--- a/drivers/i2c/busses/i2c-msm-v2.c
+++ b/drivers/i2c/busses/i2c-msm-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2321,6 +2321,12 @@ i2c_msm_frmwrk_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
struct i2c_msm_ctrl *ctrl = i2c_get_adapdata(adap);
struct i2c_msm_xfer *xfer = &ctrl->xfer;
+ if (num < 1) {
+ dev_err(ctrl->dev,
+ "error on number of msgs(%d) received\n", num);
+ return -EINVAL;
+ }
+
if (IS_ERR_OR_NULL(msgs)) {
dev_err(ctrl->dev, " error on msgs Accessing invalid pointer location\n");
return PTR_ERR(msgs);
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
index 03f6e0c4d5c8..ff8be3570bc5 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -195,11 +195,11 @@ struct cam_cdm_hw_intf_cmd_submit_bl {
struct cam_cdm_bl_request *data;
};
-/* struct cam_cdm_hw_mem - CDM hw memory.struct */
+/* struct cam_cdm_hw_mem - CDM hw memory struct */
struct cam_cdm_hw_mem {
int32_t handle;
uint32_t vaddr;
- uint64_t kmdvaddr;
+ uintptr_t kmdvaddr;
size_t size;
};
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
index f2796be6d682..4ae2f0a3bee2 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
@@ -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;
@@ -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);
@@ -1034,7 +1035,7 @@ release_platform_resource:
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");
@@ -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);
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h
index 2b00a87544fa..6aa6e6d2bc4c 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf_api.h
@@ -105,10 +105,10 @@ struct cam_cdm_bl_cmd {
union {
int32_t mem_handle;
uint32_t *hw_iova;
- void *kernel_iova;
+ uintptr_t kernel_iova;
} bl_addr;
- uint32_t offset;
- uint32_t len;
+ uint32_t offset;
+ uint32_t len;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
index d76f344c1efa..9021ecabb27c 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -87,7 +87,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
mutex_lock(&client->lock);
for (i = 0; i < req->data->cmd_arrary_count ; i++) {
- uint64_t vaddr_ptr = 0;
+ uintptr_t vaddr_ptr = 0;
size_t len = 0;
if ((!cdm_cmd->cmd[i].len) &&
@@ -106,8 +106,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
} else if (req->data->type ==
CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA) {
rc = 0;
- vaddr_ptr =
- (uint64_t)cdm_cmd->cmd[i].bl_addr.kernel_iova;
+ vaddr_ptr = cdm_cmd->cmd[i].bl_addr.kernel_iova;
len = cdm_cmd->cmd[i].offset + cdm_cmd->cmd[i].len;
} else {
CAM_ERR(CAM_CDM,
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index da785271053f..4ed53f9b576c 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -42,6 +42,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);
@@ -54,6 +55,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);
@@ -221,6 +223,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)
{
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h
index ffceea22ae0f..420f9f65987c 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h
@@ -57,23 +57,25 @@ 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 {
- struct list_head list;
- uint32_t status;
- uint64_t request_id;
+ struct list_head list;
+ uint32_t status;
+ uint64_t request_id;
void *req_priv;
- struct cam_hw_update_entry hw_update_entries[CAM_CTX_CFG_MAX];
- uint32_t num_hw_update_entries;
- struct cam_hw_fence_map_entry in_map_entries[CAM_CTX_CFG_MAX];
- uint32_t num_in_map_entries;
- struct cam_hw_fence_map_entry out_map_entries[CAM_CTX_CFG_MAX];
- uint32_t num_out_map_entries;
- atomic_t num_in_acked;
- uint32_t num_out_acked;
- int flushed;
- struct cam_context *ctx;
+ struct cam_hw_update_entry hw_update_entries[CAM_CTX_CFG_MAX];
+ uint32_t num_hw_update_entries;
+ struct cam_hw_fence_map_entry in_map_entries[CAM_CTX_CFG_MAX];
+ uint32_t num_in_map_entries;
+ struct cam_hw_fence_map_entry out_map_entries[CAM_CTX_CFG_MAX];
+ uint32_t num_out_map_entries;
+ atomic_t num_in_acked;
+ uint32_t num_out_acked;
+ int flushed;
+ struct cam_context *ctx;
+ struct cam_hw_mgr_dump_pf_data pf_data;
};
/**
@@ -135,12 +137,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;
};
/**
@@ -292,6 +296,19 @@ 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()
*
* @brief: Handle acquire device command
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index 6c2383ed8110..8021f12934a9 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -272,7 +272,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
int rc = 0;
struct cam_ctx_request *req = NULL;
struct cam_hw_prepare_update_args cfg;
- uint64_t packet_addr;
+ uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
int32_t i = 0, j = 0;
@@ -315,8 +315,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
/* for config dev, only memory handle is supported */
/* map packet from the memhandle */
rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle,
- (uint64_t *) &packet_addr,
- &len);
+ &packet_addr, &len);
if (rc != 0) {
CAM_ERR(CAM_CTXT, "[%s][%d] Can not get packet address",
ctx->dev_name, ctx->ctx_id);
@@ -324,7 +323,8 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
goto free_req;
}
- packet = (struct cam_packet *) (packet_addr + cmd->offset);
+ packet = (struct cam_packet *) ((uint8_t *)packet_addr +
+ (uint32_t)cmd->offset);
/* preprocess the configuration */
memset(&cfg, 0, sizeof(cfg));
@@ -337,6 +337,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
cfg.out_map_entries = req->out_map_entries;
cfg.max_in_map_entries = CAM_CTX_CFG_MAX;
cfg.in_map_entries = req->in_map_entries;
+ cfg.pf_data = &(req->pf_data);
rc = ctx->hw_mgr_intf->hw_prepare_update(
ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
@@ -905,3 +906,38 @@ int32_t cam_context_stop_dev_to_hw(struct cam_context *ctx)
end:
return rc;
}
+
+int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx,
+ struct cam_packet *packet, unsigned long iova, uint32_t buf_info,
+ bool *mem_found)
+{
+ int rc = 0;
+ struct cam_hw_cmd_args cmd_args;
+
+ if (!ctx) {
+ CAM_ERR(CAM_CTXT, "Invalid input params %pK ", ctx);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ if (!ctx->hw_mgr_intf) {
+ CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready",
+ ctx->dev_name, ctx->ctx_id);
+ rc = -EFAULT;
+ goto end;
+ }
+
+ if (ctx->hw_mgr_intf->hw_cmd) {
+ cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
+ cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_PF_INFO;
+ cmd_args.u.pf_args.pf_data.packet = packet;
+ cmd_args.u.pf_args.iova = iova;
+ cmd_args.u.pf_args.buf_info = buf_info;
+ cmd_args.u.pf_args.mem_found = mem_found;
+ ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+ &cmd_args);
+ }
+
+end:
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h
index 9b95eaddb3c7..43e69405ee3b 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,5 +31,8 @@ int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx,
int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx);
int32_t cam_context_flush_req_to_hw(struct cam_context *ctx,
struct cam_flush_dev_cmd *cmd);
+int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx,
+ struct cam_packet *packet, unsigned long iova, uint32_t buf_info,
+ bool *mem_found);
#endif /* _CAM_CONTEXT_UTILS_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
index f7990b6d5d4a..54b0f4d63bf8 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
@@ -13,6 +13,9 @@
#ifndef _CAM_HW_MGR_INTF_H_
#define _CAM_HW_MGR_INTF_H_
+#include <linux/time.h>
+#include <linux/types.h>
+
/*
* This file declares Constants, Enums, Structures and APIs to be used as
* Interface between HW Manager and Context.
@@ -29,6 +32,10 @@
typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id,
void *evt_data);
+/* hardware page fault callback function type */
+typedef int (*cam_hw_pagefault_cb_func)(void *context, unsigned long iova,
+ uint32_t buf_info);
+
/**
* struct cam_hw_update_entry - Entry for hardware config
*
@@ -44,7 +51,7 @@ struct cam_hw_update_entry {
uint32_t offset;
uint32_t len;
uint32_t flags;
- uint64_t addr;
+ uintptr_t addr;
};
/**
@@ -89,7 +96,7 @@ struct cam_hw_acquire_args {
void *context_data;
cam_hw_event_cb_func event_cb;
uint32_t num_acq;
- uint64_t acquire_info;
+ uintptr_t acquire_info;
void *ctxt_to_hw_map;
};
@@ -131,6 +138,16 @@ struct cam_hw_stop_args {
void *args;
};
+
+/**
+ * struct cam_hw_mgr_dump_pf_data - page fault debug data
+ *
+ * packet: pointer to packet
+ */
+struct cam_hw_mgr_dump_pf_data {
+ void *packet;
+};
+
/**
* struct cam_hw_prepare_update_args - Payload for prepare command
*
@@ -146,6 +163,7 @@ struct cam_hw_stop_args {
* @in_map_entries: Actual input fence mapping list (returned)
* @num_in_map_entries: Number of acutal input fence mapping (returned)
* @priv: Private pointer of hw update
+ * @pf_data: Debug data for page fault
*
*/
struct cam_hw_prepare_update_args {
@@ -161,6 +179,7 @@ struct cam_hw_prepare_update_args {
struct cam_hw_fence_map_entry *in_map_entries;
uint32_t num_in_map_entries;
void *priv;
+ struct cam_hw_mgr_dump_pf_data *pf_data;
};
/**
@@ -207,6 +226,48 @@ struct cam_hw_flush_args {
};
/**
+ * struct cam_hw_dump_pf_args - Payload for dump pf info command
+ *
+ * @pf_data: Debug data for page fault
+ * @iova: Page fault address
+ * @buf_info: Info about memory buffer where page
+ * fault occurred
+ * @mem_found: If fault memory found in current
+ * request
+ *
+ */
+struct cam_hw_dump_pf_args {
+ struct cam_hw_mgr_dump_pf_data pf_data;
+ unsigned long iova;
+ uint32_t buf_info;
+ bool *mem_found;
+};
+
+/* enum cam_hw_mgr_command - Hardware manager command type */
+enum cam_hw_mgr_command {
+ CAM_HW_MGR_CMD_INTERNAL,
+ CAM_HW_MGR_CMD_DUMP_PF_INFO,
+};
+
+/**
+ * struct cam_hw_cmd_args - Payload for hw manager command
+ *
+ * @ctxt_to_hw_map: HW context from the acquire
+ * @cmd_type HW command type
+ * @internal_args Arguments for internal command
+ * @pf_args Arguments for Dump PF info command
+ *
+ */
+struct cam_hw_cmd_args {
+ void *ctxt_to_hw_map;
+ uint32_t cmd_type;
+ union {
+ void *internal_args;
+ struct cam_hw_dump_pf_args pf_args;
+ } u;
+};
+
+/**
* cam_hw_mgr_intf - HW manager interface
*
* @hw_mgr_priv: HW manager object
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index 18d5446d24f7..212a11bf2ee7 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -430,6 +430,9 @@ int cam_node_shutdown(struct cam_node *node)
for (i = 0; i < node->ctx_size; i++) {
if (node->ctx_list[i].dev_hdl > 0) {
+ CAM_DBG(CAM_CORE,
+ "Node [%s] invoking shutdown on context [%d]",
+ node->name, i);
rc = cam_context_shutdown(&(node->ctx_list[i]));
if (rc)
continue;
@@ -501,7 +504,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
case CAM_QUERY_CAP: {
struct cam_query_cap_cmd query;
- if (copy_from_user(&query, (void __user *)cmd->handle,
+ if (copy_from_user(&query, u64_to_user_ptr(cmd->handle),
sizeof(query))) {
rc = -EFAULT;
break;
@@ -514,7 +517,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
break;
}
- if (copy_to_user((void __user *)cmd->handle, &query,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle), &query,
sizeof(query)))
rc = -EFAULT;
@@ -523,7 +526,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
case CAM_ACQUIRE_DEV: {
struct cam_acquire_dev_cmd acquire;
- if (copy_from_user(&acquire, (void __user *)cmd->handle,
+ if (copy_from_user(&acquire, u64_to_user_ptr(cmd->handle),
sizeof(acquire))) {
rc = -EFAULT;
break;
@@ -534,7 +537,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
rc);
break;
}
- if (copy_to_user((void __user *)cmd->handle, &acquire,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle), &acquire,
sizeof(acquire)))
rc = -EFAULT;
break;
@@ -542,7 +545,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
case CAM_START_DEV: {
struct cam_start_stop_dev_cmd start;
- if (copy_from_user(&start, (void __user *)cmd->handle,
+ if (copy_from_user(&start, u64_to_user_ptr(cmd->handle),
sizeof(start)))
rc = -EFAULT;
else {
@@ -556,7 +559,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
case CAM_STOP_DEV: {
struct cam_start_stop_dev_cmd stop;
- if (copy_from_user(&stop, (void __user *)cmd->handle,
+ if (copy_from_user(&stop, u64_to_user_ptr(cmd->handle),
sizeof(stop)))
rc = -EFAULT;
else {
@@ -570,7 +573,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
case CAM_CONFIG_DEV: {
struct cam_config_dev_cmd config;
- if (copy_from_user(&config, (void __user *)cmd->handle,
+ if (copy_from_user(&config, u64_to_user_ptr(cmd->handle),
sizeof(config)))
rc = -EFAULT;
else {
@@ -584,7 +587,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
case CAM_RELEASE_DEV: {
struct cam_release_dev_cmd release;
- if (copy_from_user(&release, (void __user *)cmd->handle,
+ if (copy_from_user(&release, u64_to_user_ptr(cmd->handle),
sizeof(release)))
rc = -EFAULT;
else {
@@ -598,7 +601,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
case CAM_FLUSH_REQ: {
struct cam_flush_dev_cmd flush;
- if (copy_from_user(&flush, (void __user *)cmd->handle,
+ if (copy_from_user(&flush, u64_to_user_ptr(cmd->handle),
sizeof(flush)))
rc = -EFAULT;
else {
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
index 053447e331a8..948485fa6474 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
@@ -933,7 +933,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args,
}
if (sizeof(struct cam_cpas_hw_cmd_start) != arg_size) {
- CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
+ CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
sizeof(struct cam_cpas_hw_cmd_start), arg_size);
return -EINVAL;
}
@@ -1065,7 +1065,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
}
if (sizeof(struct cam_cpas_hw_cmd_stop) != arg_size) {
- CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
+ CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
sizeof(struct cam_cpas_hw_cmd_stop), arg_size);
return -EINVAL;
}
@@ -1168,7 +1168,7 @@ static int cam_cpas_hw_init(void *hw_priv, void *init_hw_args,
}
if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
- CAM_ERR(CAM_CPAS, "INIT HW size mismatch %ld %d",
+ CAM_ERR(CAM_CPAS, "INIT HW size mismatch %zd %d",
sizeof(struct cam_cpas_hw_caps), arg_size);
return -EINVAL;
}
@@ -1325,7 +1325,7 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv,
}
if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
- CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
+ CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
sizeof(struct cam_cpas_hw_caps), arg_size);
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
index d51b15291142..eb8b156a4fc2 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
@@ -23,7 +23,7 @@
#define CAM_CPAS_AXI_MIN_MNOC_AB_BW (2048 * 1024)
#define CAM_CPAS_AXI_MIN_MNOC_IB_BW (2048 * 1024)
#define CAM_CPAS_AXI_MIN_CAMNOC_AB_BW (2048 * 1024)
-#define CAM_CPAS_AXI_MIN_CAMNOC_IB_BW (3000000000L)
+#define CAM_CPAS_AXI_MIN_CAMNOC_IB_BW (3000000000UL)
#define CAM_CPAS_GET_CLIENT_IDX(handle) (handle)
#define CAM_CPAS_GET_CLIENT_HANDLE(indx) (indx)
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
index cdc8a3baef28..a9f1e4f8364e 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
@@ -367,7 +367,7 @@ int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf,
case CAM_QUERY_CAP: {
struct cam_cpas_query_cap query;
- rc = copy_from_user(&query, (void __user *) cmd->handle,
+ rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle),
sizeof(query));
if (rc) {
CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d",
@@ -381,7 +381,7 @@ int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf,
if (rc)
break;
- rc = copy_to_user((void __user *) cmd->handle, &query,
+ rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query,
sizeof(query));
if (rc)
CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc);
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index 09388fe40c70..7e78f458ec2b 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -417,7 +417,7 @@ static int cam_fd_packet_generic_blob_handler(void *user_data,
uint32_t *get_raw_results = (uint32_t *)blob_data;
if (sizeof(uint32_t) != blob_size) {
- CAM_ERR(CAM_FD, "Invalid blob size %lu %u",
+ CAM_ERR(CAM_FD, "Invalid blob size %zu %u",
sizeof(uint32_t), blob_size);
return -EINVAL;
}
@@ -430,7 +430,7 @@ static int cam_fd_packet_generic_blob_handler(void *user_data,
(struct cam_fd_soc_clock_bw_request *)blob_data;
if (sizeof(struct cam_fd_soc_clock_bw_request) != blob_size) {
- CAM_ERR(CAM_FD, "Invalid blob size %lu %u",
+ CAM_ERR(CAM_FD, "Invalid blob size %zu %u",
sizeof(struct cam_fd_soc_clock_bw_request),
blob_size);
return -EINVAL;
@@ -537,7 +537,7 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
uint32_t i, j, plane, num_out_buf, num_in_buf;
struct cam_buf_io_cfg *io_cfg;
dma_addr_t io_addr[CAM_PACKET_MAX_PLANES];
- uint64_t cpu_addr[CAM_PACKET_MAX_PLANES];
+ uintptr_t cpu_addr[CAM_PACKET_MAX_PLANES];
size_t size;
bool need_io_map, need_cpu_map;
@@ -583,7 +583,7 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
rc = cam_mem_get_io_buf(
io_cfg[i].mem_handle[plane],
iommu_hdl, &io_addr[plane], &size);
- if ((rc) || (io_addr[plane] >> 32)) {
+ if (rc) {
CAM_ERR(CAM_FD,
"Invalid io buf %d %d %d %d",
io_cfg[i].direction,
@@ -599,7 +599,8 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
rc = cam_mem_get_cpu_buf(
io_cfg[i].mem_handle[plane],
&cpu_addr[plane], &size);
- if (rc) {
+ if (rc || ((io_addr[plane] & 0xFFFFFFFF)
+ != io_addr[plane])) {
CAM_ERR(CAM_FD,
"Invalid cpu buf %d %d %d %d",
io_cfg[i].direction,
@@ -1088,8 +1089,10 @@ static int cam_fd_mgr_hw_get_caps(void *hw_mgr_priv, void *hw_get_caps_args)
struct cam_fd_hw_mgr *hw_mgr = hw_mgr_priv;
struct cam_query_cap_cmd *query = hw_get_caps_args;
struct cam_fd_query_cap_cmd query_fd;
+ void __user *caps_handle =
+ u64_to_user_ptr(query->caps_handle);
- if (copy_from_user(&query_fd, (void __user *)query->caps_handle,
+ if (copy_from_user(&query_fd, caps_handle,
sizeof(struct cam_fd_query_cap_cmd))) {
CAM_ERR(CAM_FD, "Failed in copy from user, rc=%d", rc);
return -EFAULT;
@@ -1106,7 +1109,7 @@ static int cam_fd_mgr_hw_get_caps(void *hw_mgr_priv, void *hw_get_caps_args)
query_fd.hw_caps.wrapper_version.major,
query_fd.hw_caps.wrapper_version.minor);
- if (copy_to_user((void __user *)query->caps_handle, &query_fd,
+ if (copy_to_user(caps_handle, &query_fd,
sizeof(struct cam_fd_query_cap_cmd)))
rc = -EFAULT;
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
index 87dc6949de0c..fa648c7a773e 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
@@ -651,7 +651,7 @@ int cam_fd_hw_init(void *hw_priv, void *init_hw_args, uint32_t arg_size)
}
if (arg_size != sizeof(struct cam_fd_hw_init_args)) {
- CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size,
+ CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size,
sizeof(struct cam_fd_hw_init_args));
return -EINVAL;
}
@@ -735,7 +735,7 @@ int cam_fd_hw_deinit(void *hw_priv, void *deinit_hw_args, uint32_t arg_size)
}
if (arg_size != sizeof(struct cam_fd_hw_deinit_args)) {
- CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size,
+ CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size,
sizeof(struct cam_fd_hw_deinit_args));
return -EINVAL;
}
@@ -859,7 +859,7 @@ int cam_fd_hw_start(void *hw_priv, void *hw_start_args, uint32_t arg_size)
}
if (arg_size != sizeof(struct cam_fd_hw_cmd_start_args)) {
- CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size,
+ CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size,
sizeof(struct cam_fd_hw_cmd_start_args));
return -EINVAL;
}
@@ -1010,7 +1010,7 @@ int cam_fd_hw_reserve(void *hw_priv, void *hw_reserve_args, uint32_t arg_size)
}
if (arg_size != sizeof(struct cam_fd_hw_reserve_args)) {
- CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size,
+ CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size,
sizeof(struct cam_fd_hw_reserve_args));
return -EINVAL;
}
@@ -1079,7 +1079,7 @@ int cam_fd_hw_release(void *hw_priv, void *hw_release_args, uint32_t arg_size)
}
if (arg_size != sizeof(struct cam_fd_hw_release_args)) {
- CAM_ERR(CAM_FD, "Invalid arg size %u, %lu", arg_size,
+ CAM_ERR(CAM_FD, "Invalid arg size %u, %zu", arg_size,
sizeof(struct cam_fd_hw_release_args));
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h
index aae7648ba1e2..ef3b6c9314e2 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -111,7 +111,7 @@ struct cam_fd_hw_io_buffer {
struct cam_buf_io_cfg *io_cfg;
uint32_t num_buf;
uint64_t io_addr[CAM_PACKET_MAX_PLANES];
- uint64_t cpu_addr[CAM_PACKET_MAX_PLANES];
+ uintptr_t cpu_addr[CAM_PACKET_MAX_PLANES];
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
index 502c95d4c60e..522a602883eb 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
@@ -25,9 +25,46 @@
#include "cam_mem_mgr.h"
#include "cam_trace.h"
#include "cam_debug_util.h"
+#include "cam_packet_util.h"
static const char icp_dev_name[] = "icp";
+static int cam_icp_context_dump_active_request(void *data, unsigned long iova,
+ uint32_t buf_info)
+{
+ struct cam_context *ctx = (struct cam_context *)data;
+ struct cam_ctx_request *req = NULL;
+ struct cam_ctx_request *req_temp = NULL;
+ struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL;
+ int rc = 0;
+ bool b_mem_found = false;
+
+ if (!ctx) {
+ CAM_ERR(CAM_ICP, "Invalid ctx");
+ return -EINVAL;
+ }
+
+ CAM_INFO(CAM_ICP, "iommu fault for icp ctx %d state %d",
+ ctx->ctx_id, ctx->state);
+
+ list_for_each_entry_safe(req, req_temp,
+ &ctx->active_req_list, list) {
+ pf_dbg_entry = &(req->pf_data);
+ CAM_INFO(CAM_ICP, "req_id : %lld", req->request_id);
+
+ rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet,
+ iova, buf_info, &b_mem_found);
+ if (rc)
+ CAM_ERR(CAM_ICP, "Failed to dump pf info");
+
+ if (b_mem_found)
+ CAM_ERR(CAM_ICP, "Found page fault in req %lld %d",
+ req->request_id, rc);
+ }
+
+ return rc;
+}
+
static int __cam_icp_acquire_dev_in_available(struct cam_context *ctx,
struct cam_acquire_dev_cmd *cmd)
{
@@ -156,6 +193,7 @@ static struct cam_ctx_ops
},
.crm_ops = {},
.irq_ops = __cam_icp_handle_buf_done_in_ready,
+ .pagefault_ops = cam_icp_context_dump_active_request,
},
/* Ready */
{
@@ -167,12 +205,14 @@ static struct cam_ctx_ops
},
.crm_ops = {},
.irq_ops = __cam_icp_handle_buf_done_in_ready,
+ .pagefault_ops = cam_icp_context_dump_active_request,
},
/* Activated */
{
.ioctl_ops = {},
.crm_ops = {},
.irq_ops = NULL,
+ .pagefault_ops = cam_icp_context_dump_active_request,
},
};
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
index 7df806b1b7a3..2ea7738cbdef 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
@@ -35,6 +35,7 @@
#include "cam_hw_mgr_intf.h"
#include "cam_icp_hw_mgr_intf.h"
#include "cam_debug_util.h"
+#include "cam_smmu_api.h"
#define CAM_ICP_DEV_NAME "cam-icp"
@@ -55,6 +56,25 @@ static const struct of_device_id cam_icp_dt_match[] = {
{}
};
+static void cam_icp_dev_iommu_fault_handler(
+ struct iommu_domain *domain, struct device *dev, unsigned long iova,
+ int flags, void *token, uint32_t buf_info)
+{
+ int i = 0;
+ struct cam_node *node = NULL;
+
+ if (!token) {
+ CAM_ERR(CAM_ICP, "invalid token in page handler cb");
+ return;
+ }
+
+ node = (struct cam_node *)token;
+
+ for (i = 0; i < node->ctx_size; i++)
+ cam_context_dump_pf_info(&(node->ctx_list[i]), iova,
+ buf_info);
+}
+
static int cam_icp_subdev_open(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
{
@@ -96,7 +116,7 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd,
mutex_lock(&g_icp_dev.icp_lock);
if (g_icp_dev.open_cnt <= 0) {
- CAM_ERR(CAM_ICP, "ICP subdev is already closed");
+ CAM_DBG(CAM_ICP, "ICP subdev is already closed");
rc = -EINVAL;
goto end;
}
@@ -135,6 +155,7 @@ static int cam_icp_probe(struct platform_device *pdev)
int rc = 0, i = 0;
struct cam_node *node;
struct cam_hw_mgr_intf *hw_mgr_intf;
+ int iommu_hdl = -1;
if (!pdev) {
CAM_ERR(CAM_ICP, "pdev is NULL");
@@ -158,7 +179,8 @@ static int cam_icp_probe(struct platform_device *pdev)
goto hw_alloc_fail;
}
- rc = cam_icp_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf);
+ rc = cam_icp_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf,
+ &iommu_hdl);
if (rc) {
CAM_ERR(CAM_ICP, "ICP HW manager init failed: %d", rc);
goto hw_init_fail;
@@ -181,6 +203,9 @@ static int cam_icp_probe(struct platform_device *pdev)
goto ctx_fail;
}
+ cam_smmu_set_client_page_fault_handler(iommu_hdl,
+ cam_icp_dev_iommu_fault_handler, node);
+
g_icp_dev.open_cnt = 0;
mutex_init(&g_icp_dev.icp_lock);
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
index 3e636c65138d..3d0ee725dcad 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
@@ -23,10 +23,10 @@
* @reserved: reserved field
*/
struct hfi_mem {
- uint64_t len;
- uint64_t kva;
- uint32_t iova;
- uint32_t reserved;
+ uint64_t len;
+ uintptr_t kva;
+ uint32_t iova;
+ uint32_t reserved;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index 14a3e656e76d..cbe6886e5712 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -42,6 +42,9 @@
#define HFI_MAX_POLL_TRY 5
+#define HFI_MAX_PC_POLL_TRY 50
+#define HFI_POLL_TRY_SLEEP 20
+
static struct hfi_info *g_hfi;
unsigned int g_icp_mmu_hdl;
static DEFINE_MUTEX(hfi_cmd_q_mutex);
@@ -513,8 +516,8 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
uint32_t val;
uint32_t try = 0;
- while (try < HFI_MAX_POLL_TRY) {
- data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
+ while (try < HFI_MAX_PC_POLL_TRY) {
+ data = cam_io_r_mb(icp_base + HFI_REG_A5_CSR_A5_STATUS);
CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data);
if (data & ICP_CSR_A5_STATUS_WFI)
@@ -523,7 +526,7 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
* and Host can the proceed. No interrupt is expected from FW
* at this time.
*/
- msleep(100);
+ msleep_interruptible(HFI_POLL_TRY_SLEEP);
try++;
}
@@ -533,6 +536,11 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET);
cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
+
+ cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET,
+ icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
+ cam_io_w_mb((uint32_t)INTR_DISABLE,
+ g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN);
}
void cam_hfi_enable_cpu(void __iomem *icp_base)
@@ -883,11 +891,6 @@ void cam_hfi_deinit(void __iomem *icp_base)
g_hfi->cmd_q_state = false;
g_hfi->msg_q_state = false;
- cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET,
- icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
-
- cam_io_w_mb((uint32_t)INTR_DISABLE,
- g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN);
kzfree(g_hfi);
g_hfi = NULL;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
index 8f2c76943ebc..18bd6d8dd2c7 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
@@ -167,7 +167,7 @@ static int32_t cam_icp_program_fw(const uint8_t *elf,
if (prg_hdr->p_filesz != 0) {
src = (u8 *)((u8 *)elf + prg_hdr->p_offset);
dest = (u8 *)(((u8 *)core_info->fw_kva_addr) +
- prg_hdr->p_vaddr);
+ prg_hdr->p_vaddr);
memcpy_toio(dest, src, prg_hdr->p_filesz);
}
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h
index f4bc813353a8..9b02167b3c7f 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h
@@ -69,7 +69,7 @@ struct cam_a5_device_core_info {
const struct firmware *fw_elf;
void *fw;
uint32_t fw_buf;
- uint64_t fw_kva_addr;
+ uintptr_t fw_kva_addr;
uint64_t fw_buf_len;
struct cam_icp_a5_query_cap query_cap;
struct cam_icp_a5_acquire_dev a5_acquire[8];
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
index d01637436a51..b969c92ccbc8 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
@@ -199,8 +199,10 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev)
cam_cpas_reg_read(core_info->cpas_handle,
CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl);
if (pwr_ctrl & BPS_COLLAPSE_MASK) {
- CAM_ERR(CAM_ICP, "BPS: pwr_ctrl(%x)", pwr_ctrl);
- return -EINVAL;
+ CAM_DBG(CAM_ICP, "BPS: pwr_ctrl set(%x)", pwr_ctrl);
+ cam_cpas_reg_write(core_info->cpas_handle,
+ CAM_CPAS_REG_CPASTOP,
+ hw_info->pwr_ctrl, true, 0);
}
rc = cam_bps_transfer_gdsc_control(soc_info);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 1d5e4832535e..ca8bb3c8d543 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1455,7 +1455,8 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
request_id = ioconfig_ack->user_data2;
- ctx_data = (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
+ ctx_data = (struct cam_icp_hw_ctx_data *)
+ U64_TO_PTR(ioconfig_ack->user_data1);
if (!ctx_data) {
CAM_ERR(CAM_ICP, "Invalid Context");
return -EINVAL;
@@ -1562,8 +1563,8 @@ static int cam_icp_mgr_process_msg_config_io(uint32_t *msg_ptr)
ipe_config_ack->rc, ioconfig_ack->err_type);
return -EIO;
}
- ctx_data =
- (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
+ ctx_data = (struct cam_icp_hw_ctx_data *)
+ U64_TO_PTR(ioconfig_ack->user_data1);
if (!ctx_data) {
CAM_ERR(CAM_ICP, "wrong ctx data from IPE response");
return -EINVAL;
@@ -1577,8 +1578,8 @@ static int cam_icp_mgr_process_msg_config_io(uint32_t *msg_ptr)
bps_config_ack->rc, ioconfig_ack->opcode);
return -EIO;
}
- ctx_data =
- (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
+ ctx_data = (struct cam_icp_hw_ctx_data *)
+ U64_TO_PTR(ioconfig_ack->user_data1);
if (!ctx_data) {
CAM_ERR(CAM_ICP, "wrong ctx data from BPS response");
return -EINVAL;
@@ -1601,7 +1602,9 @@ static int cam_icp_mgr_process_msg_create_handle(uint32_t *msg_ptr)
return -EINVAL;
}
- ctx_data = (struct cam_icp_hw_ctx_data *)create_handle_ack->user_data1;
+ ctx_data =
+ (struct cam_icp_hw_ctx_data *)(uintptr_t)
+ create_handle_ack->user_data1;
if (!ctx_data) {
CAM_ERR(CAM_ICP, "Invalid ctx_data");
return -EINVAL;
@@ -1632,7 +1635,8 @@ static int cam_icp_mgr_process_msg_ping_ack(uint32_t *msg_ptr)
return -EINVAL;
}
- ctx_data = (struct cam_icp_hw_ctx_data *)ping_ack->user_data;
+ ctx_data = (struct cam_icp_hw_ctx_data *)
+ U64_TO_PTR(ping_ack->user_data);
if (!ctx_data) {
CAM_ERR(CAM_ICP, "Invalid ctx_data");
return -EINVAL;
@@ -1696,8 +1700,8 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr)
case HFI_IPEBPS_CMD_OPCODE_IPE_ABORT:
case HFI_IPEBPS_CMD_OPCODE_BPS_ABORT:
ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
- ctx_data =
- (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
+ ctx_data = (struct cam_icp_hw_ctx_data *)
+ U64_TO_PTR(ioconfig_ack->user_data1);
if (ctx_data->state != CAM_ICP_CTX_STATE_FREE)
complete(&ctx_data->wait_complete);
CAM_DBG(CAM_ICP, "received IPE/BPS/ ABORT: ctx_state =%d",
@@ -1706,8 +1710,8 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr)
case HFI_IPEBPS_CMD_OPCODE_IPE_DESTROY:
case HFI_IPEBPS_CMD_OPCODE_BPS_DESTROY:
ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
- ctx_data =
- (struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
+ ctx_data = (struct cam_icp_hw_ctx_data *)
+ U64_TO_PTR(ioconfig_ack->user_data1);
if ((ctx_data->state == CAM_ICP_CTX_STATE_RELEASE) ||
(ctx_data->state == CAM_ICP_CTX_STATE_IN_USE)) {
complete(&ctx_data->wait_complete);
@@ -2132,7 +2136,7 @@ static int cam_icp_alloc_shared_mem(struct cam_mem_mgr_memory_desc *qtbl)
static int cam_icp_allocate_fw_mem(void)
{
int rc;
- uint64_t kvaddr;
+ uintptr_t kvaddr;
size_t len;
dma_addr_t iova;
@@ -2146,7 +2150,7 @@ static int cam_icp_allocate_fw_mem(void)
icp_hw_mgr.hfi_mem.fw_buf.iova = iova;
icp_hw_mgr.hfi_mem.fw_buf.smmu_hdl = icp_hw_mgr.iommu_hdl;
- CAM_DBG(CAM_ICP, "kva: %llX, iova: %llx, len: %zu",
+ CAM_DBG(CAM_ICP, "kva: %zX, iova: %llx, len: %zu",
kvaddr, iova, len);
return rc;
@@ -2486,7 +2490,7 @@ static int cam_icp_mgr_abort_handle(
reinit_completion(&ctx_data->wait_complete);
abort_cmd->num_fw_handles = 1;
abort_cmd->fw_handles[0] = ctx_data->fw_handle;
- abort_cmd->user_data1 = (uint64_t)ctx_data;
+ abort_cmd->user_data1 = PTR_TO_U64(ctx_data);
abort_cmd->user_data2 = (uint64_t)0x0;
rc = hfi_write_cmd(abort_cmd);
@@ -2537,7 +2541,7 @@ static int cam_icp_mgr_destroy_handle(
reinit_completion(&ctx_data->wait_complete);
destroy_cmd->num_fw_handles = 1;
destroy_cmd->fw_handles[0] = ctx_data->fw_handle;
- destroy_cmd->user_data1 = (uint64_t)ctx_data;
+ destroy_cmd->user_data1 = PTR_TO_U64(ctx_data);
destroy_cmd->user_data2 = (uint64_t)0x0;
memcpy(destroy_cmd->payload.direct, &ctx_data->temp_payload,
sizeof(uint64_t));
@@ -3097,7 +3101,7 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
ioconfig_cmd.num_fw_handles = 1;
ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
ioconfig_cmd.payload.indirect = io_buf_addr;
- ioconfig_cmd.user_data1 = (uint64_t)ctx_data;
+ ioconfig_cmd.user_data1 = PTR_TO_U64(ctx_data);
ioconfig_cmd.user_data2 = (uint64_t)0x0;
task_data = (struct hfi_cmd_work_data *)task->payload;
task_data->data = (void *)&ioconfig_cmd;
@@ -3228,7 +3232,7 @@ static int cam_icp_mgr_prepare_frame_process_cmd(
hfi_cmd->num_fw_handles = 1;
hfi_cmd->fw_handles[0] = ctx_data->fw_handle;
hfi_cmd->payload.indirect = fw_cmd_buf_iova_addr;
- hfi_cmd->user_data1 = (uint64_t)ctx_data;
+ hfi_cmd->user_data1 = PTR_TO_U64(ctx_data);
hfi_cmd->user_data2 = request_id;
CAM_DBG(CAM_ICP, "ctx_data : %pK, request_id :%lld cmd_buf %x",
@@ -3277,7 +3281,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
dma_addr_t addr;
size_t len;
struct cam_cmd_buf_desc *cmd_desc = NULL;
- uint64_t cpu_addr = 0;
+ uintptr_t cpu_addr = 0;
struct ipe_frame_process_data *frame_process_data = NULL;
struct bps_frame_process_data *bps_frame_process_data = NULL;
struct frame_set *ipe_set = NULL;
@@ -3318,7 +3322,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
if (ctx_data->icp_dev_acquire_info->dev_type !=
CAM_ICP_RES_TYPE_BPS) {
- CAM_DBG(CAM_ICP, "cpu addr = %llx", cpu_addr);
+ CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr);
frame_process_data = (struct ipe_frame_process_data *)cpu_addr;
CAM_DBG(CAM_ICP, "%u %u %u", frame_process_data->max_num_cores,
frame_process_data->target_time,
@@ -3339,7 +3343,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
}
}
} else {
- CAM_DBG(CAM_ICP, "cpu addr = %llx", cpu_addr);
+ CAM_DBG(CAM_ICP, "cpu addr = %zx", cpu_addr);
bps_frame_process_data =
(struct bps_frame_process_data *)cpu_addr;
CAM_DBG(CAM_ICP, "%u %u",
@@ -3388,10 +3392,11 @@ static int cam_icp_mgr_process_io_cfg(struct cam_icp_hw_mgr *hw_mgr,
prepare_args->num_out_map_entries++;
}
CAM_DBG(CAM_REQ,
- "ctx_id: %u req_id: %llu dir[%d]: %u, fence: %u resource_type = %u",
+ "ctx_id: %u req_id: %llu dir[%d]: %u, fence: %u resource_type = %u memh %x",
ctx_data->ctx_id, packet->header.request_id, i,
io_cfg_ptr[i].direction, io_cfg_ptr[i].fence,
- io_cfg_ptr[i].resource_type);
+ io_cfg_ptr[i].resource_type,
+ io_cfg_ptr[i].mem_handle[0]);
}
if (prepare_args->num_in_map_entries > 1)
@@ -3439,7 +3444,7 @@ static int cam_icp_packet_generic_blob_handler(void *user_data,
uint32_t index;
size_t io_buf_size;
int rc = 0;
- uint64_t pResource;
+ uintptr_t pResource;
if (!blob_data || (blob_size == 0)) {
CAM_ERR(CAM_ICP, "Invalid blob info %pK %d", blob_data,
@@ -3545,7 +3550,7 @@ static int cam_icp_mgr_process_cfg_io_cmd(
ioconfig_cmd->num_fw_handles = 1;
ioconfig_cmd->fw_handles[0] = ctx_data->fw_handle;
ioconfig_cmd->payload.indirect = io_config;
- ioconfig_cmd->user_data1 = (uint64_t)ctx_data;
+ ioconfig_cmd->user_data1 = PTR_TO_U64(ctx_data);
ioconfig_cmd->user_data2 = request_id;
return 0;
@@ -3593,6 +3598,77 @@ static int cam_icp_mgr_update_hfi_frame_process(
return rc;
}
+static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet,
+ int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info,
+ bool *mem_found)
+{
+ uint64_t iova_addr;
+ size_t src_buf_size;
+ int i;
+ int j;
+ int rc = 0;
+ int32_t mmu_hdl;
+
+ struct cam_buf_io_cfg *io_cfg = NULL;
+
+ if (mem_found)
+ *mem_found = false;
+
+ io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
+ packet->io_configs_offset / 4);
+
+ for (i = 0; i < packet->num_io_configs; i++) {
+ for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
+ if (!io_cfg[i].mem_handle[j])
+ break;
+
+ if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
+ GET_FD_FROM_HANDLE(pf_buf_info)) {
+ CAM_INFO(CAM_ICP,
+ "Found PF at port: %d mem %x fd: %x",
+ io_cfg[i].resource_type,
+ io_cfg[i].mem_handle[j],
+ pf_buf_info);
+ if (mem_found)
+ *mem_found = true;
+ }
+
+ CAM_INFO(CAM_ICP, "port: %d f: %u format: %d dir %d",
+ io_cfg[i].resource_type,
+ io_cfg[i].fence,
+ io_cfg[i].format,
+ io_cfg[i].direction);
+
+ mmu_hdl = cam_mem_is_secure_buf(
+ io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
+ iommu_hdl;
+ rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
+ mmu_hdl, &iova_addr, &src_buf_size);
+ if (rc < 0) {
+ CAM_ERR(CAM_UTIL, "get src buf address fail");
+ continue;
+ }
+ if (iova_addr >> 32) {
+ CAM_ERR(CAM_ICP, "Invalid mapped address");
+ rc = -EINVAL;
+ continue;
+ }
+
+ CAM_INFO(CAM_ICP,
+ "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x",
+ j, io_cfg[i].planes[j].width,
+ io_cfg[i].planes[j].height,
+ (int32_t)src_buf_size,
+ (unsigned int)iova_addr,
+ io_cfg[i].offsets[j],
+ io_cfg[i].mem_handle[j]);
+
+ iova_addr += io_cfg[i].offsets[j];
+
+ }
+ }
+}
+
static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
void *prepare_hw_update_args)
{
@@ -3635,6 +3711,8 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
return rc;
}
+ prepare_args->pf_data->packet = packet;
+
CAM_DBG(CAM_REQ, "req id = %lld for ctx = %u",
packet->header.request_id, ctx_data->ctx_id);
/* Update Buffer Address from handles and patch information */
@@ -3671,7 +3749,7 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
fw_cmd_buf_iova_addr);
prepare_args->num_hw_update_entries = 1;
- prepare_args->hw_update_entries[0].addr = (uint64_t)hfi_cmd;
+ prepare_args->hw_update_entries[0].addr = (uintptr_t)hfi_cmd;
prepare_args->priv = &ctx_data->hfi_frame_process.frame_info[idx];
CAM_DBG(CAM_ICP, "X: req id = %lld ctx_id = %u",
@@ -3968,7 +4046,7 @@ static int cam_icp_mgr_create_handle(uint32_t dev_type,
create_handle.size = sizeof(struct hfi_cmd_create_handle);
create_handle.pkt_type = HFI_CMD_IPEBPS_CREATE_HANDLE;
create_handle.handle_type = dev_type;
- create_handle.user_data1 = (uint64_t)ctx_data;
+ create_handle.user_data1 = PTR_TO_U64(ctx_data);
reinit_completion(&ctx_data->wait_complete);
task_data = (struct hfi_cmd_work_data *)task->payload;
task_data->data = (void *)&create_handle;
@@ -4013,7 +4091,7 @@ static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data)
ping_pkt.size = sizeof(struct hfi_cmd_ping_pkt);
ping_pkt.pkt_type = HFI_CMD_SYS_PING;
- ping_pkt.user_data = (uint64_t)ctx_data;
+ ping_pkt.user_data = PTR_TO_U64(ctx_data);
init_completion(&ctx_data->wait_complete);
task_data = (struct hfi_cmd_work_data *)task->payload;
task_data->data = (void *)&ping_pkt;
@@ -4313,7 +4391,7 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args)
mutex_lock(&hw_mgr->hw_mgr_mutex);
if (copy_from_user(&icp_hw_mgr.icp_caps,
- (void __user *)query_cap->caps_handle,
+ u64_to_user_ptr(query_cap->caps_handle),
sizeof(struct cam_icp_query_cap_cmd))) {
CAM_ERR(CAM_ICP, "copy_from_user failed");
rc = -EFAULT;
@@ -4327,7 +4405,7 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args)
icp_hw_mgr.icp_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl;
icp_hw_mgr.icp_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl;
- if (copy_to_user((void __user *)query_cap->caps_handle,
+ if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle),
&icp_hw_mgr.icp_caps, sizeof(struct cam_icp_query_cap_cmd))) {
CAM_ERR(CAM_ICP, "copy_to_user failed");
rc = -EFAULT;
@@ -4551,7 +4629,35 @@ cmd_work_failed:
return rc;
}
-int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
+static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
+{
+ int rc = 0;
+ struct cam_hw_cmd_args *hw_cmd_args = cmd_args;
+ struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
+
+ if (!hw_mgr_priv || !cmd_args) {
+ CAM_ERR(CAM_ICP, "Invalid arguments");
+ return -EINVAL;
+ }
+
+ switch (hw_cmd_args->cmd_type) {
+ case CAM_HW_MGR_CMD_DUMP_PF_INFO:
+ cam_icp_mgr_print_io_bufs(
+ hw_cmd_args->u.pf_args.pf_data.packet,
+ hw_mgr->iommu_hdl,
+ hw_mgr->iommu_sec_hdl,
+ hw_cmd_args->u.pf_args.buf_info,
+ hw_cmd_args->u.pf_args.mem_found);
+ break;
+ default:
+ CAM_ERR(CAM_ICP, "Invalid cmd");
+ }
+
+ return rc;
+}
+
+int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
+ int *iommu_hdl)
{
int i, rc = 0;
struct cam_hw_mgr_intf *hw_mgr_intf;
@@ -4574,6 +4680,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
hw_mgr_intf->hw_open = cam_icp_mgr_hw_open_u;
hw_mgr_intf->hw_close = cam_icp_mgr_hw_close_u;
hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush;
+ hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd;
icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE;
mutex_init(&icp_hw_mgr.hw_mgr_mutex);
@@ -4617,6 +4724,9 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
if (rc)
goto icp_wq_create_failed;
+ if (iommu_hdl)
+ *iommu_hdl = icp_hw_mgr.iommu_hdl;
+
init_completion(&icp_hw_mgr.a5_complete);
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
index 771c4ed7c55c..7bb9b9ed18a2 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
@@ -28,7 +28,7 @@
#define CPAS_IPE1_BIT 0x2000
int cam_icp_hw_mgr_init(struct device_node *of_node,
- uint64_t *hw_mgr_hdl);
+ uint64_t *hw_mgr_hdl, int *iommu_hdl);
/**
* struct cam_icp_cpas_vote
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
index 620a4bd4943b..142fcdc6017d 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
@@ -195,9 +195,12 @@ static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev)
CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl,
true, &pwr_ctrl);
if (pwr_ctrl & IPE_COLLAPSE_MASK) {
- CAM_ERR(CAM_ICP, "IPE: resume failed : %d", pwr_ctrl);
- return -EINVAL;
+ CAM_DBG(CAM_ICP, "IPE pwr_ctrl set(%x)", pwr_ctrl);
+ cam_cpas_reg_write(core_info->cpas_handle,
+ CAM_CPAS_REG_CPASTOP,
+ hw_info->pwr_ctrl, true, 0);
}
+
rc = cam_ipe_transfer_gdsc_control(soc_info);
cam_cpas_reg_read(core_info->cpas_handle,
CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl);
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index 5760371bbde3..aaa172deea97 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -23,8 +23,15 @@
#include "cam_req_mgr_dev.h"
#include "cam_trace.h"
#include "cam_debug_util.h"
+#include "cam_packet_util.h"
+#include "cam_context_utils.h"
+#include "cam_common_util.h"
static const char isp_dev_name[] = "isp";
+
+static int cam_isp_context_dump_active_request(void *data, unsigned long iova,
+ uint32_t buf_info);
+
static void __cam_isp_ctx_update_state_monitor_array(
struct cam_isp_context *ctx_isp,
enum cam_isp_state_change_trigger trigger_type,
@@ -375,7 +382,7 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
continue;
}
- if (!bubble_state) {
+ if (!req_isp->bubble_detected) {
CAM_DBG(CAM_ISP,
"Sync with success: req %lld res 0x%x fd 0x%x",
req->request_id,
@@ -402,15 +409,14 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
} else {
/*
* Ignore the buffer done if bubble detect is on
- * In most case, active list should be empty when
- * bubble detects. But for safety, we just move the
- * current active request to the pending list here.
+ * Increment the ack number here, and queue the
+ * request back to pending list whenever all the
+ * buffers are done.
*/
+ req_isp->num_acked++;
CAM_DBG(CAM_ISP,
"buf done with bubble state %d recovery %d",
bubble_state, req_isp->bubble_report);
- list_del_init(&req->list);
- list_add(&req->list, &ctx->pending_req_list);
continue;
}
@@ -431,10 +437,25 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
req_isp->num_fence_map_out);
WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out);
}
- if (req_isp->num_acked == req_isp->num_fence_map_out) {
+
+ if (req_isp->num_acked != req_isp->num_fence_map_out)
+ return rc;
+
+ ctx_isp->active_req_cnt--;
+
+ if (req_isp->bubble_detected && req_isp->bubble_report) {
+ req_isp->num_acked = 0;
+ req_isp->bubble_detected = false;
+ list_del_init(&req->list);
+ list_add(&req->list, &ctx->pending_req_list);
+
+ CAM_DBG(CAM_REQ,
+ "Move active request %lld to pending list(cnt = %d) [bubble recovery]",
+ req->request_id, ctx_isp->active_req_cnt);
+ } else {
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->free_req_list);
- ctx_isp->active_req_cnt--;
+
CAM_DBG(CAM_REQ,
"Move active request %lld to free list(cnt = %d) [all fences done]",
req->request_id, ctx_isp->active_req_cnt);
@@ -732,15 +753,13 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request,
list);
req_isp = (struct cam_isp_ctx_req *)req->req_priv;
+ req_isp->bubble_detected = true;
CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
if (req_isp->bubble_report && ctx->ctx_crm_intf &&
ctx->ctx_crm_intf->notify_err) {
struct cam_req_mgr_error_notify notify;
- list_del_init(&req->list);
- list_add(&req->list, &ctx->pending_req_list);
-
notify.link_hdl = ctx->link_hdl;
notify.dev_hdl = ctx->dev_hdl;
notify.req_id = req->request_id;
@@ -749,18 +768,19 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
ctx_isp->frame_id);
} else {
- /*
- * Since can not bubble report, always move the request to
- * active list.
- */
- list_del_init(&req->list);
- list_add_tail(&req->list, &ctx->active_req_list);
- ctx_isp->active_req_cnt++;
- CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
req_isp->bubble_report = 0;
}
+ /*
+ * Always move the request to active list. Let buf done
+ * function handles the rest.
+ */
+ CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
+ req->request_id, ctx_isp->active_req_cnt);
+ ctx_isp->active_req_cnt++;
+ list_del_init(&req->list);
+ list_add_tail(&req->list, &ctx->active_req_list);
+
if (req->request_id > ctx_isp->reported_req_id) {
request_id = req->request_id;
ctx_isp->reported_req_id = request_id;
@@ -882,13 +902,12 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request,
list);
req_isp = (struct cam_isp_ctx_req *)req->req_priv;
- list_del_init(&req->list);
+ req_isp->bubble_detected = true;
if (req_isp->bubble_report && ctx->ctx_crm_intf &&
ctx->ctx_crm_intf->notify_err) {
struct cam_req_mgr_error_notify notify;
- list_add(&req->list, &ctx->pending_req_list);
notify.link_hdl = ctx->link_hdl;
notify.dev_hdl = ctx->dev_hdl;
notify.req_id = req->request_id;
@@ -898,17 +917,19 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
"Notify CRM about Bubble req_id %llu frame %lld",
req->request_id, ctx_isp->frame_id);
} else {
- /*
- * If we can not report bubble, then treat it as if no bubble
- * report. Just move the req to active list.
- */
- list_add_tail(&req->list, &ctx->active_req_list);
- ctx_isp->active_req_cnt++;
- CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
req_isp->bubble_report = 0;
}
+ /*
+ * Always move the request to active list. Let buf done
+ * function handles the rest.
+ */
+ CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+ req->request_id, ctx_isp->active_req_cnt);
+ ctx_isp->active_req_cnt++;
+ list_del_init(&req->list);
+ list_add_tail(&req->list, &ctx->active_req_list);
+
if (!req_isp->bubble_report) {
if (req->request_id > ctx_isp->reported_req_id) {
request_id = req->request_id;
@@ -1411,6 +1432,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
CAM_DBG(CAM_ISP, "try to flush active list");
rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list,
flush_req);
+ ctx_isp->active_req_cnt = 0;
spin_unlock_bh(&ctx->lock);
/* Start hw */
@@ -1609,12 +1631,12 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
- if (list_empty(&ctx->pending_req_list)) {
+ if (list_empty(&ctx->wait_req_list)) {
/*
* If no pending req in epoch, this is an error case.
* The recovery is to go back to sof state
*/
- CAM_ERR(CAM_ISP, "No pending request");
+ CAM_ERR(CAM_ISP, "No wait request");
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
/* Send SOF event as empty frame*/
@@ -1624,9 +1646,10 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
goto end;
}
- req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
+ req = list_first_entry(&ctx->wait_req_list, struct cam_ctx_request,
list);
req_isp = (struct cam_isp_ctx_req *)req->req_priv;
+ req_isp->bubble_detected = true;
CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
if (req_isp->bubble_report && ctx->ctx_crm_intf &&
@@ -1641,18 +1664,19 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
ctx_isp->frame_id);
} else {
- /*
- * Since can not bubble report, always move the request to
- * active list.
- */
- list_del_init(&req->list);
- list_add_tail(&req->list, &ctx->active_req_list);
- ctx_isp->active_req_cnt++;
- CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
req_isp->bubble_report = 0;
}
+ /*
+ * Always move the request to active list. Let buf done
+ * function handles the rest.
+ */
+ ctx_isp->active_req_cnt++;
+ list_del_init(&req->list);
+ list_add_tail(&req->list, &ctx->active_req_list);
+ CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+ req->request_id, ctx_isp->active_req_cnt);
+
if (!req_isp->bubble_report) {
if (req->request_id > ctx_isp->reported_req_id) {
request_id = req->request_id;
@@ -2008,7 +2032,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
int rc = 0, i;
struct cam_ctx_request *req = NULL;
struct cam_isp_ctx_req *req_isp;
- uint64_t packet_addr;
+ uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
struct cam_hw_prepare_update_args cfg;
@@ -2038,16 +2062,16 @@ static int __cam_isp_ctx_config_dev_in_top_state(
/* for config dev, only memory handle is supported */
/* map packet from the memhandle */
rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle,
- (uint64_t *) &packet_addr, &len);
+ &packet_addr, &len);
if (rc != 0) {
CAM_ERR(CAM_ISP, "Can not get packet address");
rc = -EINVAL;
goto free_req;
}
- packet = (struct cam_packet *) (packet_addr + cmd->offset);
+ packet = (struct cam_packet *)(packet_addr + (uint32_t)cmd->offset);
CAM_DBG(CAM_ISP, "pack_handle %llx", cmd->packet_handle);
- CAM_DBG(CAM_ISP, "packet address is 0x%llx", packet_addr);
+ CAM_DBG(CAM_ISP, "packet address is 0x%zx", packet_addr);
CAM_DBG(CAM_ISP, "packet with length %zu, offset 0x%llx",
len, cmd->offset);
CAM_DBG(CAM_ISP, "Packet request id %lld",
@@ -2066,6 +2090,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
cfg.out_map_entries = req_isp->fence_map_out;
cfg.in_map_entries = req_isp->fence_map_in;
cfg.priv = &req_isp->hw_update_data;
+ cfg.pf_data = &(req->pf_data);
CAM_DBG(CAM_ISP, "try to prepare config packet......");
@@ -2080,6 +2105,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
req_isp->num_fence_map_out = cfg.num_out_map_entries;
req_isp->num_fence_map_in = cfg.num_in_map_entries;
req_isp->num_acked = 0;
+ req_isp->bubble_detected = false;
for (i = 0; i < req_isp->num_fence_map_out; i++) {
rc = cam_sync_get_obj_ref(req_isp->fence_map_out[i].sync_id);
@@ -2164,7 +2190,8 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
struct cam_hw_release_args release;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *) ctx->ctx_priv;
- struct cam_isp_hw_cmd_args hw_cmd_args;
+ struct cam_hw_cmd_args hw_cmd_args;
+ struct cam_isp_hw_cmd_args isp_hw_cmd_args;
if (!ctx->hw_mgr_intf) {
CAM_ERR(CAM_ISP, "HW interface is not ready");
@@ -2200,7 +2227,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
CAM_DBG(CAM_ISP, "start copy %d resources from user",
cmd->num_resources);
- if (copy_from_user(isp_res, (void __user *)cmd->resource_hdl,
+ if (copy_from_user(isp_res, u64_to_user_ptr(cmd->resource_hdl),
sizeof(*isp_res)*cmd->num_resources)) {
rc = -EFAULT;
goto free_res;
@@ -2209,7 +2236,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
param.context_data = ctx;
param.event_cb = ctx->irq_cb_intf;
param.num_acq = cmd->num_resources;
- param.acquire_info = (uint64_t) isp_res;
+ param.acquire_info = (uintptr_t) isp_res;
/* call HW manager to reserve the resource */
rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv,
@@ -2221,7 +2248,9 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
/* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
- hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
+ hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
+ hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
if (rc) {
@@ -2229,7 +2258,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
goto free_hw;
}
- if (hw_cmd_args.u.is_rdi_only_context) {
+ if (isp_hw_cmd_args.u.is_rdi_only_context) {
/*
* this context has rdi only resource assign rdi only
* state machine
@@ -2248,8 +2277,9 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
cam_isp_ctx_activated_state_machine;
}
- ctx_isp->rdi_only_context = hw_cmd_args.u.is_rdi_only_context;
+ ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context;
ctx_isp->hw_ctx = param.ctxt_to_hw_map;
+ ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
req_hdl_param.session_hdl = cmd->session_handle;
/* bridge is not ready for these flags. so false for now */
@@ -2276,7 +2306,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
CAM_DBG(CAM_ISP,
"Acquire success on session_hdl 0x%x num_rsrces %d RDI only %d ctx %u",
cmd->session_handle, cmd->num_resources,
- (hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id);
+ (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id);
kfree(isp_res);
return rc;
@@ -2567,12 +2597,15 @@ static int __cam_isp_ctx_release_dev_in_activated(struct cam_context *ctx,
static int __cam_isp_ctx_link_pause(struct cam_context *ctx)
{
int rc = 0;
- struct cam_isp_hw_cmd_args hw_cmd_args;
+ struct cam_hw_cmd_args hw_cmd_args;
+ struct cam_isp_hw_cmd_args isp_hw_cmd_args;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *) ctx->ctx_priv;
hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
- hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_PAUSE_HW;
+ hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_PAUSE_HW;
+ hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
@@ -2582,12 +2615,15 @@ static int __cam_isp_ctx_link_pause(struct cam_context *ctx)
static int __cam_isp_ctx_link_resume(struct cam_context *ctx)
{
int rc = 0;
- struct cam_isp_hw_cmd_args hw_cmd_args;
+ struct cam_hw_cmd_args hw_cmd_args;
+ struct cam_isp_hw_cmd_args isp_hw_cmd_args;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *) ctx->ctx_priv;
hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
- hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW;
+ hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW;
+ hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
@@ -2598,13 +2634,16 @@ static int __cam_isp_ctx_handle_sof_freeze_evt(
struct cam_context *ctx)
{
int rc = 0;
- struct cam_isp_hw_cmd_args hw_cmd_args;
+ struct cam_hw_cmd_args hw_cmd_args;
+ struct cam_isp_hw_cmd_args isp_hw_cmd_args;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *) ctx->ctx_priv;
hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
- hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_SOF_DEBUG;
- hw_cmd_args.u.sof_irq_enable = 1;
+ hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_SOF_DEBUG;
+ isp_hw_cmd_args.u.sof_irq_enable = 1;
+ hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
@@ -2746,6 +2785,7 @@ static struct cam_ctx_ops
.flush_req = __cam_isp_ctx_flush_req_in_top_state,
},
.irq_ops = NULL,
+ .pagefault_ops = cam_isp_context_dump_active_request,
},
/* Ready */
{
@@ -2759,6 +2799,7 @@ static struct cam_ctx_ops
.flush_req = __cam_isp_ctx_flush_req_in_ready,
},
.irq_ops = NULL,
+ .pagefault_ops = cam_isp_context_dump_active_request,
},
/* Activated */
{
@@ -2774,10 +2815,55 @@ static struct cam_ctx_ops
.process_evt = __cam_isp_ctx_process_evt,
},
.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
+ .pagefault_ops = cam_isp_context_dump_active_request,
},
};
+static int cam_isp_context_dump_active_request(void *data, unsigned long iova,
+ uint32_t buf_info)
+{
+
+ struct cam_context *ctx = (struct cam_context *)data;
+ struct cam_ctx_request *req = NULL;
+ struct cam_ctx_request *req_temp = NULL;
+ struct cam_isp_ctx_req *req_isp = NULL;
+ struct cam_isp_prepare_hw_update_data *hw_update_data = NULL;
+ struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL;
+ bool mem_found = false;
+ int rc = 0;
+
+ struct cam_isp_context *isp_ctx =
+ (struct cam_isp_context *)ctx->ctx_priv;
+
+ if (!isp_ctx) {
+ CAM_ERR(CAM_ISP, "Invalid isp ctx");
+ return -EINVAL;
+ }
+
+ CAM_INFO(CAM_ISP, "iommu fault handler for isp ctx %d state %d",
+ ctx->ctx_id, ctx->state);
+
+ list_for_each_entry_safe(req, req_temp,
+ &ctx->active_req_list, list) {
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ hw_update_data = &req_isp->hw_update_data;
+ pf_dbg_entry = &(req->pf_data);
+ CAM_INFO(CAM_ISP, "req_id : %lld ", req->request_id);
+
+ rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet,
+ iova, buf_info, &mem_found);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Failed to dump pf info");
+
+ if (mem_found)
+ CAM_ERR(CAM_ISP, "Found page fault in req %lld %d",
+ req->request_id, rc);
+ }
+
+ return rc;
+}
+
int cam_isp_context_init(struct cam_isp_context *ctx,
struct cam_context *ctx_base,
struct cam_req_mgr_kmd_ops *crm_node_intf,
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index 4592e42932d8..6f89841d22bc 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -115,6 +115,7 @@ struct cam_isp_ctx_req {
uint32_t num_acked;
int32_t bubble_report;
struct cam_isp_prepare_hw_update_data hw_update_data;
+ bool bubble_detected;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
index a067915bed7d..c7e5d3836fda 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
@@ -26,9 +26,29 @@
#include "cam_isp_hw_mgr_intf.h"
#include "cam_node.h"
#include "cam_debug_util.h"
+#include "cam_smmu_api.h"
static struct cam_isp_dev g_isp_dev;
+static void cam_isp_dev_iommu_fault_handler(
+ struct iommu_domain *domain, struct device *dev, unsigned long iova,
+ int flags, void *token, uint32_t buf_info)
+{
+ int i = 0;
+ struct cam_node *node = NULL;
+
+ if (!token) {
+ CAM_ERR(CAM_ISP, "invalid token in page handler cb");
+ return;
+ }
+
+ node = (struct cam_node *)token;
+
+ for (i = 0; i < node->ctx_size; i++)
+ cam_context_dump_pf_info(&(node->ctx_list[i]), iova,
+ buf_info);
+}
+
static const struct of_device_id cam_isp_dt_match[] = {
{
.compatible = "qcom,cam-isp"
@@ -36,23 +56,47 @@ static const struct of_device_id cam_isp_dt_match[] = {
{}
};
+static int cam_isp_subdev_open(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh)
+{
+ mutex_lock(&g_isp_dev.isp_mutex);
+ g_isp_dev.open_cnt++;
+ mutex_unlock(&g_isp_dev.isp_mutex);
+
+ return 0;
+}
+
static int cam_isp_subdev_close(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
{
+ int rc = 0;
struct cam_node *node = v4l2_get_subdevdata(sd);
+ mutex_lock(&g_isp_dev.isp_mutex);
+ if (g_isp_dev.open_cnt <= 0) {
+ CAM_DBG(CAM_ISP, "ISP subdev is already closed");
+ rc = -EINVAL;
+ goto end;
+ }
+
+ g_isp_dev.open_cnt--;
if (!node) {
CAM_ERR(CAM_ISP, "Node ptr is NULL");
- return -EINVAL;
+ rc = -EINVAL;
+ goto end;
}
- cam_node_shutdown(node);
+ if (g_isp_dev.open_cnt == 0)
+ cam_node_shutdown(node);
- return 0;
+end:
+ mutex_unlock(&g_isp_dev.isp_mutex);
+ return rc;
}
static const struct v4l2_subdev_internal_ops cam_isp_subdev_internal_ops = {
.close = cam_isp_subdev_close,
+ .open = cam_isp_subdev_open,
};
static int cam_isp_dev_remove(struct platform_device *pdev)
@@ -82,6 +126,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev)
int i;
struct cam_hw_mgr_intf hw_mgr_intf;
struct cam_node *node;
+ int iommu_hdl = -1;
g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops;
/* Initialze the v4l2 subdevice first. (create cam_node) */
@@ -94,7 +139,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev)
node = (struct cam_node *) g_isp_dev.sd.token;
memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf));
- rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf);
+ rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf, &iommu_hdl);
if (rc != 0) {
CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!");
goto unregister;
@@ -119,6 +164,11 @@ static int cam_isp_dev_probe(struct platform_device *pdev)
goto unregister;
}
+ cam_smmu_set_client_page_fault_handler(iommu_hdl,
+ cam_isp_dev_iommu_fault_handler, node);
+
+ mutex_init(&g_isp_dev.isp_mutex);
+
CAM_INFO(CAM_ISP, "Camera ISP probe complete");
return 0;
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h
index 95463ca37a13..a88ed5533907 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,12 +24,15 @@
* @sd: Commone camera subdevice node
* @ctx: Isp base context storage
* @ctx_isp: Isp private context storage
- *
+ * @isp_mutex: ISP dev mutex
+ * @open_cnt: Open device count
*/
struct cam_isp_dev {
struct cam_subdev sd;
struct cam_context ctx[CAM_CTX_MAX];
struct cam_isp_context ctx_isp[CAM_CTX_MAX];
+ struct mutex isp_mutex;
+ int32_t open_cnt;
};
#endif /* __CAM_ISP_DEV_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 7e0aa4b62ba7..d29506fb8a21 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -28,6 +28,8 @@
#include "cam_packet_util.h"
#include "cam_debug_util.h"
#include "cam_cpas_api.h"
+#include "cam_mem_mgr_api.h"
+#include "cam_common_util.h"
#define CAM_IFE_HW_ENTRIES_MAX 20
@@ -94,7 +96,8 @@ static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv,
CAM_DBG(CAM_ISP, "enter");
- if (copy_from_user(&query_isp, (void __user *)query->caps_handle,
+ if (copy_from_user(&query_isp,
+ u64_to_user_ptr(query->caps_handle),
sizeof(struct cam_isp_query_cap_cmd))) {
rc = -EFAULT;
return rc;
@@ -113,8 +116,8 @@ static int cam_ife_mgr_get_hw_caps(void *hw_mgr_priv,
query_isp.dev_caps[i].hw_version.reserved = 0;
}
- if (copy_to_user((void __user *)query->caps_handle, &query_isp,
- sizeof(struct cam_isp_query_cap_cmd)))
+ if (copy_to_user(u64_to_user_ptr(query->caps_handle),
+ &query_isp, sizeof(struct cam_isp_query_cap_cmd)))
rc = -EFAULT;
CAM_DBG(CAM_ISP, "exit rc :%d", rc);
@@ -1561,7 +1564,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv,
goto free_res;
}
- in_port = memdup_user((void __user *)isp_resource[i].res_hdl,
+ in_port = memdup_user(
+ u64_to_user_ptr(isp_resource[i].res_hdl),
isp_resource[i].length);
if (!IS_ERR(in_port)) {
in_port_length = sizeof(struct cam_isp_in_port_info) +
@@ -2161,7 +2165,8 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
struct cam_isp_stop_args stop_isp;
struct cam_ife_hw_mgr_ctx *ctx;
struct cam_ife_hw_mgr_res *hw_mgr_res;
- uint32_t i;
+ struct cam_isp_resource_node *rsrc_node = NULL;
+ uint32_t i, camif_debug;
if (!hw_mgr_priv || !start_isp) {
CAM_ERR(CAM_ISP, "Invalid arguments");
@@ -2195,6 +2200,24 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
sizeof(g_ife_hw_mgr.debug_cfg.csid_debug));
}
+ camif_debug = g_ife_hw_mgr.debug_cfg.camif_debug;
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+
+ rsrc_node = hw_mgr_res->hw_res[i];
+ if (rsrc_node->process_cmd && (rsrc_node->res_id ==
+ CAM_ISP_HW_VFE_IN_CAMIF)) {
+ rc = hw_mgr_res->hw_res[i]->process_cmd(
+ hw_mgr_res->hw_res[i],
+ CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
+ &camif_debug,
+ sizeof(camif_debug));
+ }
+ }
+ }
+
rc = cam_ife_hw_mgr_init_hw(ctx);
if (rc) {
CAM_ERR(CAM_ISP, "Init failed");
@@ -2806,45 +2829,133 @@ static int cam_ife_mgr_sof_irq_debug(
return rc;
}
+static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
+ int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info,
+ bool *mem_found)
+{
+ uint64_t iova_addr;
+ size_t src_buf_size;
+ int i;
+ int j;
+ int rc = 0;
+ int32_t mmu_hdl;
+
+ struct cam_buf_io_cfg *io_cfg = NULL;
+
+ if (mem_found)
+ *mem_found = false;
+
+ io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
+ packet->io_configs_offset / 4);
+
+ for (i = 0; i < packet->num_io_configs; i++) {
+ for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
+ if (!io_cfg[i].mem_handle[j])
+ break;
+
+ if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
+ GET_FD_FROM_HANDLE(pf_buf_info)) {
+ CAM_INFO(CAM_ISP,
+ "Found PF at port: %d mem %x fd: %x",
+ io_cfg[i].resource_type,
+ io_cfg[i].mem_handle[j],
+ pf_buf_info);
+ if (mem_found)
+ *mem_found = true;
+ }
+
+ CAM_INFO(CAM_ISP, "port: %d f: %u format: %d dir %d",
+ io_cfg[i].resource_type,
+ io_cfg[i].fence,
+ io_cfg[i].format,
+ io_cfg[i].direction);
+
+ mmu_hdl = cam_mem_is_secure_buf(
+ io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
+ iommu_hdl;
+ rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
+ mmu_hdl, &iova_addr, &src_buf_size);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "get src buf address fail");
+ continue;
+ }
+ if (iova_addr >> 32) {
+ CAM_ERR(CAM_ISP, "Invalid mapped address");
+ rc = -EINVAL;
+ continue;
+ }
+
+ CAM_INFO(CAM_ISP,
+ "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x",
+ j, io_cfg[i].planes[j].width,
+ io_cfg[i].planes[j].height,
+ (int32_t)src_buf_size,
+ (unsigned int)iova_addr,
+ io_cfg[i].offsets[j],
+ io_cfg[i].mem_handle[j]);
+ }
+ }
+}
+
static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
int rc = 0;
- struct cam_isp_hw_cmd_args *hw_cmd_args = cmd_args;
- struct cam_ife_hw_mgr_ctx *ctx;
+ struct cam_hw_cmd_args *hw_cmd_args = cmd_args;
+ struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv;
+ struct cam_ife_hw_mgr_ctx *ctx = (struct cam_ife_hw_mgr_ctx *)
+ hw_cmd_args->ctxt_to_hw_map;
if (!hw_mgr_priv || !cmd_args) {
CAM_ERR(CAM_ISP, "Invalid arguments");
return -EINVAL;
}
- ctx = (struct cam_ife_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map;
if (!ctx || !ctx->ctx_in_use) {
CAM_ERR(CAM_ISP, "Fatal: Invalid context is used");
return -EPERM;
}
switch (hw_cmd_args->cmd_type) {
- case CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT:
- if (ctx->is_rdi_only_context)
- hw_cmd_args->u.is_rdi_only_context = 1;
- else
- hw_cmd_args->u.is_rdi_only_context = 0;
-
- break;
- case CAM_ISP_HW_MGR_CMD_PAUSE_HW:
- cam_ife_mgr_pause_hw(ctx);
- break;
- case CAM_ISP_HW_MGR_CMD_RESUME_HW:
- cam_ife_mgr_resume_hw(ctx);
+ case CAM_HW_MGR_CMD_INTERNAL: {
+ struct cam_isp_hw_cmd_args *isp_hw_cmd_args =
+ (struct cam_isp_hw_cmd_args *)hw_cmd_args->
+ u.internal_args;
+
+ switch (isp_hw_cmd_args->cmd_type) {
+ case CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT:
+ if (ctx->is_rdi_only_context)
+ isp_hw_cmd_args->u.is_rdi_only_context = 1;
+ else
+ isp_hw_cmd_args->u.is_rdi_only_context = 0;
+ break;
+ case CAM_ISP_HW_MGR_CMD_PAUSE_HW:
+ cam_ife_mgr_pause_hw(ctx);
+ break;
+ case CAM_ISP_HW_MGR_CMD_RESUME_HW:
+ cam_ife_mgr_resume_hw(ctx);
+ break;
+ case CAM_ISP_HW_MGR_CMD_SOF_DEBUG:
+ cam_ife_mgr_sof_irq_debug(ctx,
+ isp_hw_cmd_args->u.sof_irq_enable);
+ break;
+ default:
+ CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
+ hw_cmd_args->cmd_type);
+ rc = -EINVAL;
+ break;
+ }
break;
- case CAM_ISP_HW_MGR_CMD_SOF_DEBUG:
- cam_ife_mgr_sof_irq_debug(ctx, hw_cmd_args->u.sof_irq_enable);
+ }
+ case CAM_HW_MGR_CMD_DUMP_PF_INFO:
+ cam_ife_mgr_print_io_bufs(
+ hw_cmd_args->u.pf_args.pf_data.packet,
+ hw_mgr->mgr_common.img_iommu_hdl,
+ hw_mgr->mgr_common.img_iommu_hdl_secure,
+ hw_cmd_args->u.pf_args.buf_info,
+ hw_cmd_args->u.pf_args.mem_found);
break;
default:
- CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
- hw_cmd_args->cmd_type);
- rc = -EINVAL;
- break;
+ CAM_ERR(CAM_ISP, "Invalid cmd");
}
return rc;
@@ -4040,8 +4151,8 @@ int cam_ife_mgr_do_tasklet_buf_done(void *handler_priv,
evt_payload = evt_payload_priv;
ife_hwr_mgr_ctx = (struct cam_ife_hw_mgr_ctx *)evt_payload->ctx;
- CAM_DBG(CAM_ISP, "addr of evt_payload = %llx core index:0x%x",
- (uint64_t)evt_payload, evt_payload->core_index);
+ CAM_DBG(CAM_ISP, "addr of evt_payload = %pK core index:0x%x",
+ evt_payload, evt_payload->core_index);
CAM_DBG(CAM_ISP, "bus_irq_status_0: = %x", evt_payload->irq_reg_val[0]);
CAM_DBG(CAM_ISP, "bus_irq_status_1: = %x", evt_payload->irq_reg_val[1]);
CAM_DBG(CAM_ISP, "bus_irq_status_2: = %x", evt_payload->irq_reg_val[2]);
@@ -4176,6 +4287,28 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_ife_csid_debug,
cam_ife_get_csid_debug,
cam_ife_set_csid_debug, "%16llu");
+static int cam_ife_set_camif_debug(void *data, u64 val)
+{
+ g_ife_hw_mgr.debug_cfg.camif_debug = val;
+ CAM_DBG(CAM_ISP,
+ "Set camif enable_diag_sensor_status value :%lld", val);
+ return 0;
+}
+
+static int cam_ife_get_camif_debug(void *data, u64 *val)
+{
+ *val = g_ife_hw_mgr.debug_cfg.camif_debug;
+ CAM_DBG(CAM_ISP,
+ "Set camif enable_diag_sensor_status value :%lld",
+ g_ife_hw_mgr.debug_cfg.csid_debug);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cam_ife_camif_debug,
+ cam_ife_get_camif_debug,
+ cam_ife_set_camif_debug, "%16llu");
+
static int cam_ife_hw_mgr_debug_register(void)
{
g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife",
@@ -4201,6 +4334,14 @@ static int cam_ife_hw_mgr_debug_register(void)
CAM_ERR(CAM_ISP, "failed to create enable_recovery");
goto err;
}
+
+ if (!debugfs_create_file("ife_camif_debug",
+ 0644,
+ g_ife_hw_mgr.debug_cfg.dentry, NULL,
+ &cam_ife_camif_debug)) {
+ CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug");
+ goto err;
+ }
g_ife_hw_mgr.debug_cfg.enable_recovery = 0;
return 0;
@@ -4210,7 +4351,7 @@ err:
return -ENOMEM;
}
-int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf)
+int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
{
int rc = -EFAULT;
int i, j;
@@ -4382,6 +4523,9 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf)
hw_mgr_intf->hw_config = cam_ife_mgr_config_hw;
hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd;
+ if (iommu_hdl)
+ *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl;
+
cam_ife_hw_mgr_debug_register();
CAM_DBG(CAM_ISP, "Exit");
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 0198f3d62e9c..9bfa34fe91ab 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -81,15 +81,17 @@ struct ctx_base_info {
/**
* struct cam_ife_hw_mgr_debug - contain the debug information
*
- * @dentry: Debugfs entry
- * @csid_debug: csid debug information
- * @enable_recovery enable recovery
+ * @dentry: Debugfs entry
+ * @csid_debug: csid debug information
+ * @enable_recovery: enable recovery
+ * @enable_diag_sensor_status: enable sensor diagnosis status
*
*/
struct cam_ife_hw_mgr_debug {
struct dentry *dentry;
uint64_t csid_debug;
uint32_t enable_recovery;
+ uint32_t camif_debug;
};
/**
@@ -203,9 +205,10 @@ struct cam_ife_hw_mgr {
* etnry functinon for the IFE HW manager.
*
* @hw_mgr_intf: IFE hardware manager object returned
+ * @iommu_hdl: Iommu handle to be returned
*
*/
-int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf);
+int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl);
/**
* cam_ife_mgr_do_tasklet_buf_done()
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c
index 2f18895c2402..8b9c555cae17 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,7 +16,7 @@
int cam_isp_hw_mgr_init(struct device_node *of_node,
- struct cam_hw_mgr_intf *hw_mgr)
+ struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl)
{
int rc = 0;
const char *compat_str = NULL;
@@ -25,7 +25,7 @@ int cam_isp_hw_mgr_init(struct device_node *of_node,
(const char **)&compat_str);
if (strnstr(compat_str, "ife", strlen(compat_str)))
- rc = cam_ife_hw_mgr_init(hw_mgr);
+ rc = cam_ife_hw_mgr_init(hw_mgr, iommu_hdl);
else {
CAM_ERR(CAM_ISP, "Invalid ISP hw type");
rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index eaa7325fbca8..f652256d3dc5 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
@@ -457,6 +457,7 @@ int cam_isp_add_io_buffers(
num_out_buf = 0;
num_in_buf = 0;
io_cfg_used_bytes = 0;
+ prepare->pf_data->packet = prepare->packet;
/* Max one hw entries required for each base */
if (prepare->num_hw_update_entries + 1 >=
@@ -595,13 +596,6 @@ int cam_isp_add_io_buffers(
return rc;
}
- if (io_addr[plane_id] >> 32) {
- CAM_ERR(CAM_ISP,
- "Invalid mapped address");
- rc = -EINVAL;
- return rc;
- }
-
/* need to update with offset */
io_addr[plane_id] +=
io_cfg[i].offsets[plane_id];
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index fd71c37c8fa1..1586216f2073 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -203,13 +203,11 @@ enum cam_isp_hw_mgr_command {
/**
* struct cam_isp_hw_cmd_args - Payload for hw manager command
*
- * @ctxt_to_hw_map: HW context from the acquire
* @cmd_type HW command type
* @get_context Get context type information
*/
struct cam_isp_hw_cmd_args {
- void *ctxt_to_hw_map;
- uint32_t cmd_type;
+ uint32_t cmd_type;
union {
uint32_t is_rdi_only_context;
uint32_t sof_irq_enable;
@@ -225,9 +223,9 @@ struct cam_isp_hw_cmd_args {
* @of_node: Device node input
* @hw_mgr: Input/output structure for the ISP hardware manager
* initialization
- *
+ * @iommu_hdl: Iommu handle to be returned
*/
int cam_isp_hw_mgr_init(struct device_node *of_node,
- struct cam_hw_mgr_intf *hw_mgr);
+ struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl);
#endif /* __CAM_ISP_HW_MGR_INTF_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
index c68ddf7343fc..f90356aa2e5c 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -52,6 +52,7 @@ static struct cam_ife_csid_ipp_reg_offset cam_ife_csid_170_ipp_reg_offset = {
.csid_ipp_timestamp_perv1_eof_addr = 0x2ac,
/* configurations */
.pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
};
static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_170_rdi_0_reg_offset = {
@@ -286,6 +287,8 @@ static struct cam_ife_csid_common_reg_offset
.crop_shift = 16,
.ipp_irq_mask_all = 0x7FFF,
.rdi_irq_mask_all = 0x7FFF,
+ .measure_en_hbi_vbi_cnt_mask = 0xC,
+ .format_measure_en_val = 1,
};
struct cam_ife_csid_reg_offset cam_ife_csid_170_reg_offset = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 47f44ea4785c..9ffd923b55cb 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -1395,8 +1395,12 @@ static int cam_ife_csid_init_config_ipp_path(
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->ipp_reg->csid_ipp_cfg0_addr);
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_cfg1_addr);
+
/* select the post irq sub sample strobe for time stamp capture */
- cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base +
+ val |= CSID_TIMESTAMP_STB_POST_IRQ;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->ipp_reg->csid_ipp_cfg1_addr);
if (path_data->crop_enable) {
@@ -1415,6 +1419,16 @@ static int cam_ife_csid_init_config_ipp_path(
csid_reg->ipp_reg->csid_ipp_vcrop_addr);
CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x",
csid_hw->hw_intf->hw_idx, val);
+
+ /* Enable generating early eof strobe based on crop config */
+ if (!(csid_hw->csid_debug & CSID_DEBUG_DISABLE_EARLY_EOF)) {
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_cfg0_addr);
+ val |= (1 <<
+ csid_reg->ipp_reg->early_eof_en_shift_val);
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_cfg0_addr);
+ }
}
/* set frame drop pattern to 0 and period to 1 */
@@ -1443,9 +1457,23 @@ static int cam_ife_csid_init_config_ipp_path(
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->ipp_reg->csid_ipp_cfg0_addr);
val |= (1 << csid_reg->cmn_reg->path_en_shift_val);
+
+ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO)
+ val |= csid_reg->cmn_reg->format_measure_en_val;
+
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->ipp_reg->csid_ipp_cfg0_addr);
+ /* Enable the HBI/VBI counter */
+ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) {
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_format_measure_cfg0_addr);
+ val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask;
+ cam_io_w_mb(val,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_format_measure_cfg0_addr);
+ }
+
/* configure the rx packet capture based on csid debug set */
val = 0;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE)
@@ -1484,8 +1512,10 @@ static int cam_ife_csid_deinit_ipp_path(
struct cam_isp_resource_node *res)
{
int rc = 0;
+ uint32_t val = 0;
struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
+ struct cam_ife_csid_ipp_reg_offset *ipp_reg;
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
@@ -1503,8 +1533,26 @@ static int cam_ife_csid_deinit_ipp_path(
csid_hw->hw_intf->hw_idx,
res->res_id);
rc = -EINVAL;
+ goto end;
}
+ ipp_reg = csid_reg->ipp_reg;
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ ipp_reg->csid_ipp_cfg0_addr);
+ if (val & csid_reg->cmn_reg->format_measure_en_val) {
+ val &= ~csid_reg->cmn_reg->format_measure_en_val;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ ipp_reg->csid_ipp_cfg0_addr);
+
+ /* Disable the HBI/VBI counter */
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ ipp_reg->csid_ipp_format_measure_cfg0_addr);
+ val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ ipp_reg->csid_ipp_format_measure_cfg0_addr);
+ }
+
+end:
res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
return rc;
}
@@ -1649,6 +1697,7 @@ static int cam_ife_csid_init_config_rdi_path(
struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
uint32_t path_format = 0, plain_fmt = 0, val = 0, id;
+ uint32_t format_measure_addr;
path_data = (struct cam_ife_csid_path_cfg *) res->res_priv;
csid_reg = csid_hw->csid_info->csid_reg;
@@ -1742,9 +1791,24 @@ static int cam_ife_csid_init_config_rdi_path(
csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
val |= (1 << csid_reg->cmn_reg->path_en_shift_val);
+ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO)
+ val |= csid_reg->cmn_reg->format_measure_en_val;
+
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
+ format_measure_addr =
+ csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr;
+
+ /* Enable the HBI/VBI counter */
+ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) {
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ format_measure_addr);
+ val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask;
+ cam_io_w_mb(val,
+ soc_info->reg_map[0].mem_base + format_measure_addr);
+ }
+
/* configure the rx packet capture based on csid debug set */
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE)
val = ((1 <<
@@ -1780,7 +1844,7 @@ static int cam_ife_csid_deinit_rdi_path(
struct cam_isp_resource_node *res)
{
int rc = 0;
- uint32_t id;
+ uint32_t id, val, format_measure_addr;
struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
@@ -1797,6 +1861,24 @@ static int cam_ife_csid_deinit_rdi_path(
return -EINVAL;
}
+ format_measure_addr =
+ csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr;
+
+ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) {
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
+ val &= ~csid_reg->cmn_reg->format_measure_en_val;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
+
+ /* Disable the HBI/VBI counter */
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ format_measure_addr);
+ val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ format_measure_addr);
+ }
+
res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
return rc;
}
@@ -1899,6 +1981,55 @@ static int cam_ife_csid_disable_rdi_path(
return rc;
}
+static int cam_ife_csid_get_hbi_vbi(
+ struct cam_ife_csid_hw *csid_hw,
+ struct cam_isp_resource_node *res)
+{
+ uint32_t hbi, vbi;
+ const struct cam_ife_csid_reg_offset *csid_reg;
+ const struct cam_ife_csid_rdi_reg_offset *rdi_reg;
+ struct cam_hw_soc_info *soc_info;
+
+ csid_reg = csid_hw->csid_info->csid_reg;
+ soc_info = &csid_hw->hw_info->soc_info;
+
+ if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH ||
+ res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
+ CAM_ERR(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d",
+ csid_hw->hw_intf->hw_idx, res->res_type,
+ res->res_id);
+ return -EINVAL;
+ }
+
+ if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
+ CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d",
+ csid_hw->hw_intf->hw_idx,
+ csid_hw->hw_info->hw_state);
+ return -EINVAL;
+ }
+
+ if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) {
+ hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_format_measure1_addr);
+ vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_format_measure2_addr);
+ } else {
+ rdi_reg = csid_reg->rdi_reg[res->res_id];
+ hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ rdi_reg->csid_rdi_format_measure1_addr);
+ vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ rdi_reg->csid_rdi_format_measure2_addr);
+ }
+
+ CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u HBI: 0x%x", res->res_id,
+ hbi);
+ CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u VBI: 0x%x", res->res_id,
+ vbi);
+
+ return 0;
+}
+
+
static int cam_ife_csid_get_time_stamp(
struct cam_ife_csid_hw *csid_hw, void *cmd_args)
{
@@ -2552,6 +2683,7 @@ static int cam_ife_csid_process_cmd(void *hw_priv,
int rc = 0;
struct cam_ife_csid_hw *csid_hw;
struct cam_hw_info *csid_hw_info;
+ struct cam_isp_resource_node *res = NULL;
if (!hw_priv || !cmd_args) {
CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
@@ -2564,6 +2696,11 @@ static int cam_ife_csid_process_cmd(void *hw_priv,
switch (cmd_type) {
case CAM_IFE_CSID_CMD_GET_TIME_STAMP:
rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args);
+ if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) {
+ res = ((struct cam_csid_get_time_stamp_args *)
+ cmd_args)->node_res;
+ cam_ife_csid_get_hbi_vbi(csid_hw, res);
+ }
break;
case CAM_IFE_CSID_SET_CSID_DEBUG:
rc = cam_ife_csid_set_csid_debug(csid_hw, cmd_args);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index 74aa199aa848..c547f4cb5286 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -76,6 +76,8 @@
#define CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE BIT(4)
#define CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE BIT(5)
#define CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE BIT(6)
+#define CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7)
+#define CSID_DEBUG_DISABLE_EARLY_EOF BIT(8)
/* enum cam_csid_path_halt_mode select the path halt mode control */
enum cam_csid_path_halt_mode {
@@ -135,6 +137,7 @@ struct cam_ife_csid_ipp_reg_offset {
/* configuration */
uint32_t pix_store_en_shift_val;
+ uint32_t early_eof_en_shift_val;
};
struct cam_ife_csid_rdi_reg_offset {
@@ -285,6 +288,8 @@ struct cam_ife_csid_common_reg_offset {
uint32_t crop_shift;
uint32_t ipp_irq_mask_all;
uint32_t rdi_irq_mask_all;
+ uint32_t measure_en_hbi_vbi_cnt_mask;
+ uint32_t format_measure_en_val;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 28cfcc8bea74..54aa4c23b4d1 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -96,6 +96,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ,
CAM_ISP_HW_CMD_GET_REG_DUMP,
CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
+ CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
CAM_ISP_HW_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
index c7d3aa2fd487..d1284d9f23d2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
@@ -50,6 +50,8 @@ static struct cam_vfe_camif_ver2_reg vfe170_camif_reg = {
.raw_crop_width_cfg = 0x00000CE4,
.raw_crop_height_cfg = 0x00000CE8,
.reg_update_cmd = 0x000004AC,
+ .vfe_diag_config = 0x00000C48,
+ .vfe_diag_sensor_status = 0x00000C4C,
};
static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = {
@@ -79,6 +81,7 @@ static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = {
.eof_irq_mask = 0x00000002,
.error_irq_mask0 = 0x0003FC00,
.error_irq_mask1 = 0x0FFF7E80,
+ .enable_diagnostic_hw = 0x1,
};
struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 0bb13741f2b1..54ec2823ae11 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -2438,7 +2438,7 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
CAM_ERR(CAM_ISP,
- "reg_val_pair %d exceeds the array limit %lu",
+ "reg_val_pair %d exceeds the array limit %zu",
j, MAX_REG_VAL_PAIR_SIZE);
return -ENOMEM;
}
@@ -2711,7 +2711,7 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
CAM_ERR(CAM_ISP,
- "reg_val_pair %d exceeds the array limit %lu",
+ "reg_val_pair %d exceeds the array limit %zu",
j, MAX_REG_VAL_PAIR_SIZE);
return -ENOMEM;
}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index 1da2d2e9588e..fc257ecaa604 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -43,6 +43,7 @@ struct cam_vfe_mux_camif_data {
uint32_t last_line;
bool enable_sof_irq_debug;
uint32_t irq_debug_cnt;
+ uint32_t camif_debug;
};
static int cam_vfe_camif_validate_pix_pattern(uint32_t pattern)
@@ -309,6 +310,15 @@ static int cam_vfe_camif_resource_start(
rsrc_data->enable_sof_irq_debug = false;
rsrc_data->irq_debug_cnt = 0;
+ if (rsrc_data->camif_debug &
+ CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) {
+ val = cam_io_r_mb(rsrc_data->mem_base +
+ rsrc_data->camif_reg->vfe_diag_config);
+ val |= rsrc_data->reg_data->enable_diagnostic_hw;
+ cam_io_w_mb(val, rsrc_data->mem_base +
+ rsrc_data->camif_reg->vfe_diag_config);
+ }
+
CAM_DBG(CAM_ISP, "Start Camif IFE %d Done", camif_res->hw_intf->hw_idx);
return 0;
}
@@ -400,6 +410,14 @@ static int cam_vfe_camif_resource_stop(
if (camif_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING)
camif_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ val = cam_io_r_mb(camif_priv->mem_base +
+ camif_priv->camif_reg->vfe_diag_config);
+ if (val & camif_priv->reg_data->enable_diagnostic_hw) {
+ val &= ~camif_priv->reg_data->enable_diagnostic_hw;
+ cam_io_w_mb(val, camif_priv->mem_base +
+ camif_priv->camif_reg->vfe_diag_config);
+ }
+
return rc;
}
@@ -424,6 +442,7 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
{
int rc = -EINVAL;
+ struct cam_vfe_mux_camif_data *camif_priv = NULL;
if (!rsrc_node || !cmd_args) {
CAM_ERR(CAM_ISP, "Invalid input arguments");
@@ -441,6 +460,11 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
rc = cam_vfe_camif_sof_irq_debug(rsrc_node, cmd_args);
break;
+ case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG:
+ camif_priv =
+ (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv;
+ camif_priv->camif_debug = *((uint32_t *)cmd_args);
+ break;
default:
CAM_ERR(CAM_ISP,
"unsupported process command:%d", cmd_type);
@@ -465,6 +489,7 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv,
struct cam_vfe_top_irq_evt_payload *payload;
uint32_t irq_status0;
uint32_t irq_status1;
+ uint32_t val;
if (!handler_priv || !evt_payload_priv) {
CAM_ERR(CAM_ISP, "Invalid params");
@@ -527,6 +552,14 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv,
} else {
ret = CAM_ISP_HW_ERROR_NONE;
}
+
+ if (camif_priv->camif_debug &
+ CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS) {
+ val = cam_io_r(camif_priv->mem_base +
+ camif_priv->camif_reg->vfe_diag_sensor_status);
+ CAM_DBG(CAM_ISP, "VFE_DIAG_SENSOR_STATUS: 0x%x",
+ camif_priv->mem_base, val);
+ }
break;
default:
break;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
index 4a73bd74c097..7a6958930caa 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,11 @@
#include "cam_isp_hw.h"
#include "cam_vfe_top.h"
+/*
+ * Debug values for camif module
+ */
+#define CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS BIT(0)
+
struct cam_vfe_camif_ver2_reg {
uint32_t camif_cmd;
uint32_t camif_config;
@@ -27,6 +32,8 @@ struct cam_vfe_camif_ver2_reg {
uint32_t raw_crop_width_cfg;
uint32_t raw_crop_height_cfg;
uint32_t reg_update_cmd;
+ uint32_t vfe_diag_config;
+ uint32_t vfe_diag_sensor_status;
};
struct cam_vfe_camif_reg_data {
@@ -63,6 +70,8 @@ struct cam_vfe_camif_reg_data {
uint32_t eof_irq_mask;
uint32_t error_irq_mask0;
uint32_t error_irq_mask1;
+
+ uint32_t enable_diagnostic_hw;
};
struct cam_vfe_camif_ver2_hw_info {
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
index 02334a4e8195..287d4a4162fc 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
@@ -20,9 +20,49 @@
#include "cam_jpeg_context.h"
#include "cam_context_utils.h"
#include "cam_debug_util.h"
+#include "cam_packet_util.h"
static const char jpeg_dev_name[] = "jpeg";
+static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova,
+ uint32_t buf_info)
+{
+
+ struct cam_context *ctx = (struct cam_context *)data;
+ struct cam_ctx_request *req = NULL;
+ struct cam_ctx_request *req_temp = NULL;
+ struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL;
+ int rc = 0;
+ int closest_port;
+ bool b_mem_found = false;
+
+
+ if (!ctx) {
+ CAM_ERR(CAM_JPEG, "Invalid ctx");
+ return -EINVAL;
+ }
+
+ CAM_INFO(CAM_JPEG, "iommu fault for jpeg ctx %d state %d",
+ ctx->ctx_id, ctx->state);
+
+ list_for_each_entry_safe(req, req_temp,
+ &ctx->active_req_list, list) {
+ pf_dbg_entry = &(req->pf_data);
+ closest_port = -1;
+ CAM_INFO(CAM_JPEG, "req_id : %lld ", req->request_id);
+
+ rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet,
+ iova, buf_info, &b_mem_found);
+ if (rc)
+ CAM_ERR(CAM_JPEG, "Failed to dump pf info");
+
+ if (b_mem_found)
+ CAM_ERR(CAM_JPEG, "Found page fault in req %lld %d",
+ req->request_id, rc);
+ }
+ return rc;
+}
+
static int __cam_jpeg_ctx_acquire_dev_in_available(struct cam_context *ctx,
struct cam_acquire_dev_cmd *cmd)
{
@@ -116,6 +156,7 @@ static struct cam_ctx_ops
},
.crm_ops = { },
.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
+ .pagefault_ops = cam_jpeg_context_dump_active_request,
},
};
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
index 46cc08f7ea5f..14892224e412 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
@@ -22,11 +22,31 @@
#include "cam_jpeg_hw_mgr_intf.h"
#include "cam_jpeg_dev.h"
#include "cam_debug_util.h"
+#include "cam_smmu_api.h"
#define CAM_JPEG_DEV_NAME "cam-jpeg"
static struct cam_jpeg_dev g_jpeg_dev;
+static void cam_jpeg_dev_iommu_fault_handler(
+ struct iommu_domain *domain, struct device *dev, unsigned long iova,
+ int flags, void *token, uint32_t buf_info)
+{
+ int i = 0;
+ struct cam_node *node = NULL;
+
+ if (!token) {
+ CAM_ERR(CAM_JPEG, "invalid token in page handler cb");
+ return;
+ }
+
+ node = (struct cam_node *)token;
+
+ for (i = 0; i < node->ctx_size; i++)
+ cam_context_dump_pf_info(&(node->ctx_list[i]), iova,
+ buf_info);
+}
+
static const struct of_device_id cam_jpeg_dt_match[] = {
{
.compatible = "qcom,cam-jpeg"
@@ -34,23 +54,50 @@ static const struct of_device_id cam_jpeg_dt_match[] = {
{ }
};
+static int cam_jpeg_subdev_open(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh)
+{
+
+ mutex_lock(&g_jpeg_dev.jpeg_mutex);
+ g_jpeg_dev.open_cnt++;
+ mutex_unlock(&g_jpeg_dev.jpeg_mutex);
+
+ return 0;
+}
+
static int cam_jpeg_subdev_close(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
{
+ int rc = 0;
struct cam_node *node = v4l2_get_subdevdata(sd);
+
+ mutex_lock(&g_jpeg_dev.jpeg_mutex);
+ if (g_jpeg_dev.open_cnt <= 0) {
+ CAM_DBG(CAM_JPEG, "JPEG subdev is already closed");
+ rc = -EINVAL;
+ goto end;
+ }
+
+ g_jpeg_dev.open_cnt--;
+
if (!node) {
CAM_ERR(CAM_JPEG, "Node ptr is NULL");
- return -EINVAL;
+ rc = -EINVAL;
+ goto end;
}
- cam_node_shutdown(node);
+ if (g_jpeg_dev.open_cnt == 0)
+ cam_node_shutdown(node);
- return 0;
+end:
+ mutex_unlock(&g_jpeg_dev.jpeg_mutex);
+ return rc;
}
static const struct v4l2_subdev_internal_ops cam_jpeg_subdev_internal_ops = {
.close = cam_jpeg_subdev_close,
+ .open = cam_jpeg_subdev_open,
};
static int cam_jpeg_dev_remove(struct platform_device *pdev)
@@ -78,6 +125,7 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev)
int i;
struct cam_hw_mgr_intf hw_mgr_intf;
struct cam_node *node;
+ int iommu_hdl = -1;
g_jpeg_dev.sd.internal_ops = &cam_jpeg_subdev_internal_ops;
rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME,
@@ -89,7 +137,7 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev)
node = (struct cam_node *)g_jpeg_dev.sd.token;
rc = cam_jpeg_hw_mgr_init(pdev->dev.of_node,
- (uint64_t *)&hw_mgr_intf);
+ (uint64_t *)&hw_mgr_intf, &iommu_hdl);
if (rc) {
CAM_ERR(CAM_JPEG, "Can not initialize JPEG HWmanager %d", rc);
goto unregister;
@@ -114,6 +162,9 @@ static int cam_jpeg_dev_probe(struct platform_device *pdev)
goto ctx_init_fail;
}
+ cam_smmu_set_client_page_fault_handler(iommu_hdl,
+ cam_jpeg_dev_iommu_fault_handler, node);
+
mutex_init(&g_jpeg_dev.jpeg_mutex);
CAM_INFO(CAM_JPEG, "Camera JPEG probe complete");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h
index deab2d5c0d02..0d15ced16e80 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,7 @@
* @ctx: JPEG base context storage
* @ctx_jpeg: JPEG private context storage
* @jpeg_mutex: Jpeg dev mutex
+ * @open_cnt: Open device count
*/
struct cam_jpeg_dev {
struct cam_subdev sd;
@@ -33,5 +34,6 @@ struct cam_jpeg_dev {
struct cam_context ctx[CAM_CTX_MAX];
struct cam_jpeg_context ctx_jpeg[CAM_CTX_MAX];
struct mutex jpeg_mutex;
+ int32_t open_cnt;
};
#endif /* __CAM_JPEG_DEV_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index f0913b2df834..7f0199f6e119 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -34,6 +34,7 @@
#include "cam_mem_mgr.h"
#include "cam_cdm_intf_api.h"
#include "cam_debug_util.h"
+#include "cam_common_util.h"
#define CAM_JPEG_HW_ENTRIES_MAX 20
#define CAM_JPEG_CHBASE 0
@@ -55,8 +56,8 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data)
struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
struct cam_hw_done_event_data buf_data;
struct cam_jpeg_set_irq_cb irq_cb;
- uint32_t dev_type = 0;
- uint64_t kaddr;
+ uintptr_t dev_type = 0;
+ uintptr_t kaddr;
uint32_t *cmd_buf_kaddr;
size_t cmd_buf_len;
struct cam_jpeg_config_inout_param_info *p_params;
@@ -113,7 +114,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data)
rc = hw_mgr->devices[dev_type][0]->hw_ops.deinit(
hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0);
if (rc)
- CAM_ERR(CAM_JPEG, "Failed to Deinit %d HW", dev_type);
+ CAM_ERR(CAM_JPEG, "Failed to Deinit %lu HW", dev_type);
}
hw_mgr->device_in_use[dev_type][0] = false;
@@ -133,7 +134,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data)
CAM_ERR(CAM_JPEG, "task_data is NULL");
return -EINVAL;
}
- wq_task_data->data = (void *)(uint64_t)dev_type;
+ wq_task_data->data = (void *)dev_type;
wq_task_data->request_id = 0;
wq_task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE;
task->process_cb = cam_jpeg_mgr_process_cmd;
@@ -146,7 +147,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data)
rc = cam_mem_get_cpu_buf(
p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].handle,
- (uint64_t *)&kaddr, &cmd_buf_len);
+ &kaddr, &cmd_buf_len);
if (rc) {
CAM_ERR(CAM_JPEG, "unable to get info for cmd buf: %x %d",
hw_mgr->iommu_hdl, rc);
@@ -172,7 +173,7 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data)
p_cfg_req->hw_cfg_args.out_map_entries[i].resource_handle;
}
buf_data.request_id =
- (uint64_t)p_cfg_req->hw_cfg_args.priv;
+ PTR_TO_U64(p_cfg_req->hw_cfg_args.priv);
ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data);
list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list);
@@ -262,7 +263,7 @@ static int cam_jpeg_insert_cdm_change_base(
struct cam_cdm_bl_request *cdm_cmd;
uint32_t size;
uint32_t mem_cam_base;
- uint64_t iova_addr;
+ uintptr_t iova_addr;
uint32_t *ch_base_iova_addr;
size_t ch_base_len;
@@ -314,7 +315,7 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data)
struct cam_cdm_bl_request *cdm_cmd;
struct cam_hw_config_args *config_args = NULL;
struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
- uint64_t request_id = 0;
+ uintptr_t request_id = 0;
struct cam_jpeg_process_frame_work_data_t *task_data =
(struct cam_jpeg_process_frame_work_data_t *)data;
uint32_t dev_type;
@@ -357,9 +358,9 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data)
config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args;
request_id = task_data->request_id;
- if (request_id != (uint64_t)config_args->priv) {
- CAM_DBG(CAM_JPEG, "not a recent req %lld %lld",
- request_id, (uint64_t)config_args->priv);
+ if (request_id != (uintptr_t)config_args->priv) {
+ CAM_DBG(CAM_JPEG, "not a recent req %zd %zd",
+ request_id, (uintptr_t)config_args->priv);
}
if (!config_args->num_hw_update_entries) {
@@ -489,7 +490,8 @@ end_callcb:
buf_data.resource_handle[i] =
hw_cfg_args->out_map_entries[i].resource_handle;
}
- buf_data.request_id = (uint64_t)p_cfg_req->hw_cfg_args.priv;
+ buf_data.request_id =
+ (uintptr_t)p_cfg_req->hw_cfg_args.priv;
ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data);
}
@@ -509,7 +511,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
struct cam_hw_config_args *config_args = config_hw_args;
struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
- uint64_t request_id = 0;
+ uintptr_t request_id = 0;
struct cam_hw_update_entry *hw_update_entries;
struct crm_workq_task *task;
struct cam_jpeg_process_frame_work_data_t *task_data;
@@ -549,11 +551,11 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
p_cfg_req->hw_cfg_args = *config_args;
p_cfg_req->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
- request_id = (uint64_t)config_args->priv;
+ request_id = (uintptr_t)config_args->priv;
p_cfg_req->req_id = request_id;
hw_update_entries = config_args->hw_update_entries;
- CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %lld",
- ctx_data, request_id, (uint64_t)config_args->priv);
+ CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %zd",
+ ctx_data, request_id, (uintptr_t)config_args->priv);
task = cam_req_mgr_workq_get_task(g_jpeg_hw_mgr.work_process_frame);
if (!task) {
CAM_ERR(CAM_JPEG, "no empty task");
@@ -578,7 +580,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
list_add_tail(&p_cfg_req->list, &hw_mgr->hw_config_req_list);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
- task_data->data = (void *)(int64_t)p_cfg_req->dev_type;
+ task_data->data = (void *)(uintptr_t)p_cfg_req->dev_type;
task_data->request_id = request_id;
task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE;
task->process_cb = cam_jpeg_mgr_process_cmd;
@@ -600,6 +602,74 @@ err_after_dq_free_list:
return rc;
}
+static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet,
+ int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info,
+ bool *mem_found)
+{
+ uint64_t iova_addr;
+ size_t src_buf_size;
+ int i;
+ int j;
+ int rc = 0;
+ int32_t mmu_hdl;
+ struct cam_buf_io_cfg *io_cfg = NULL;
+
+ if (mem_found)
+ *mem_found = false;
+
+ io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
+ packet->io_configs_offset / 4);
+
+ for (i = 0; i < packet->num_io_configs; i++) {
+ for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
+ if (!io_cfg[i].mem_handle[j])
+ break;
+
+ if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
+ GET_FD_FROM_HANDLE(pf_buf_info)) {
+ CAM_INFO(CAM_JPEG,
+ "Found PF at port: %d mem %x fd: %x",
+ io_cfg[i].resource_type,
+ io_cfg[i].mem_handle[j],
+ pf_buf_info);
+ if (mem_found)
+ *mem_found = true;
+ }
+
+ CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d",
+ io_cfg[i].resource_type,
+ io_cfg[i].fence,
+ io_cfg[i].format,
+ io_cfg[i].direction);
+
+ mmu_hdl = cam_mem_is_secure_buf(
+ io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
+ iommu_hdl;
+ rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
+ mmu_hdl, &iova_addr, &src_buf_size);
+ if (rc < 0) {
+ CAM_ERR(CAM_UTIL, "get src buf address fail");
+ continue;
+ }
+ if (iova_addr >> 32) {
+ CAM_ERR(CAM_JPEG, "Invalid mapped address");
+ rc = -EINVAL;
+ continue;
+ }
+
+ CAM_INFO(CAM_JPEG,
+ "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x",
+ j, io_cfg[i].planes[j].width,
+ io_cfg[i].planes[j].height,
+ (int32_t)src_buf_size,
+ (unsigned int)iova_addr,
+ io_cfg[i].offsets[j],
+ io_cfg[i].mem_handle[j]);
+
+ iova_addr += io_cfg[i].offsets[j];
+ }
+ }
+}
static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
void *prepare_hw_update_args)
@@ -675,6 +745,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
CAM_DBG(CAM_JPEG, "packet = %pK io_cfg_ptr = %pK size = %lu",
(void *)packet, (void *)io_cfg_ptr,
sizeof(struct cam_buf_io_cfg));
+ prepare_args->pf_data->packet = packet;
prepare_args->num_out_map_entries = 0;
@@ -721,7 +792,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
(uint32_t)cmd_desc[i].offset;
}
prepare_args->num_hw_update_entries = j;
- prepare_args->priv = (void *)packet->header.request_id;
+ prepare_args->priv = (void *)(uintptr_t)packet->header.request_id;
CAM_DBG(CAM_JPEG, "will wait on input sync sync_id %d",
prepare_args->in_map_entries[0].sync_id);
@@ -827,7 +898,7 @@ static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv,
struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
struct cam_jpeg_hw_cfg_req *cfg_req = NULL;
struct cam_jpeg_hw_cfg_req *req_temp = NULL;
- int64_t request_id = 0;
+ long request_id = 0;
uint32_t dev_type;
struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
bool b_req_found = false;
@@ -842,13 +913,13 @@ static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv,
if (flush_args->num_req_pending)
return 0;
- request_id = (int64_t)flush_args->flush_req_active[0];
+ request_id = (uintptr_t)flush_args->flush_req_active[0];
if (!flush_args->num_req_active)
return 0;
if (request_id <= 0) {
- CAM_ERR(CAM_JPEG, "Invalid red id %lld", request_id);
+ CAM_ERR(CAM_JPEG, "Invalid red id %ld", request_id);
return -EINVAL;
}
@@ -885,7 +956,7 @@ static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv,
}
if (!b_req_found) {
- CAM_ERR(CAM_JPEG, "req not found %lld", request_id);
+ CAM_ERR(CAM_JPEG, "req not found %ld", request_id);
return -EINVAL;
}
@@ -1189,7 +1260,7 @@ static int cam_jpeg_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args)
mutex_lock(&hw_mgr->hw_mgr_mutex);
- if (copy_to_user((void __user *)query_cap->caps_handle,
+ if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle),
&g_jpeg_hw_mgr.jpeg_caps,
sizeof(struct cam_jpeg_query_cap_cmd))) {
CAM_ERR(CAM_JPEG, "copy_to_user failed");
@@ -1410,7 +1481,35 @@ num_dev_failed:
return rc;
}
-int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
+static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
+{
+ int rc = 0;
+ struct cam_hw_cmd_args *hw_cmd_args = cmd_args;
+ struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+
+ if (!hw_mgr_priv || !cmd_args) {
+ CAM_ERR(CAM_JPEG, "Invalid arguments");
+ return -EINVAL;
+ }
+
+ switch (hw_cmd_args->cmd_type) {
+ case CAM_HW_MGR_CMD_DUMP_PF_INFO:
+ cam_jpeg_mgr_print_io_bufs(
+ hw_cmd_args->u.pf_args.pf_data.packet,
+ hw_mgr->iommu_hdl,
+ hw_mgr->iommu_sec_hdl,
+ hw_cmd_args->u.pf_args.buf_info,
+ hw_cmd_args->u.pf_args.mem_found);
+ break;
+ default:
+ CAM_ERR(CAM_JPEG, "Invalid cmd");
+ }
+
+ return rc;
+}
+
+int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
+ int *iommu_hdl)
{
int i, rc;
uint32_t num_dev;
@@ -1434,6 +1533,7 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
hw_mgr_intf->hw_config = cam_jpeg_mgr_config_hw;
hw_mgr_intf->hw_flush = cam_jpeg_mgr_hw_flush;
hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop;
+ hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd;
mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);
@@ -1495,6 +1595,9 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
goto cdm_iommu_failed;
}
+ if (iommu_hdl)
+ *iommu_hdl = g_jpeg_hw_mgr.iommu_hdl;
+
return rc;
cdm_iommu_failed:
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
index 5e1016725095..82022ec24a77 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
@@ -38,7 +38,7 @@
struct cam_jpeg_process_frame_work_data_t {
uint32_t type;
void *data;
- uint64_t request_id;
+ uintptr_t request_id;
};
/**
@@ -81,7 +81,7 @@ struct cam_jpeg_hw_cfg_req {
struct list_head list;
struct cam_hw_config_args hw_cfg_args;
uint32_t dev_type;
- int64_t req_id;
+ uintptr_t req_id;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h
index 5fb4e3ad3399..5705890cd109 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,8 +17,7 @@
#include <uapi/media/cam_defs.h>
#include <linux/of.h>
-
int cam_jpeg_hw_mgr_init(struct device_node *of_node,
- uint64_t *hw_mgr_hdl);
+ uint64_t *hw_mgr_hdl, int *iommu_hdl);
#endif /* CAM_JPEG_HW_MGR_INTF_H */
diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c
index 5dc87633991f..99a8fe1f8eca 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c
@@ -22,7 +22,7 @@ static int __cam_lrme_ctx_acquire_dev_in_available(struct cam_context *ctx,
struct cam_acquire_dev_cmd *cmd)
{
int rc = 0;
- uint64_t ctxt_to_hw_map = (uint64_t)ctx->ctxt_to_hw_map;
+ uintptr_t ctxt_to_hw_map = (uintptr_t)ctx->ctxt_to_hw_map;
struct cam_lrme_context *lrme_ctx = ctx->ctx_priv;
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h
index 4c705c139405..dc1c8f4c10aa 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h
+++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.h
@@ -19,7 +19,7 @@
#include "cam_req_mgr_interface.h"
#include "cam_sync_api.h"
-#define CAM_LRME_CTX_INDEX_SHIFT 32
+#define CAM_LRME_CTX_INDEX_SHIFT 16
/**
* struct cam_lrme_context
diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c
index a4ee1040e4c8..6b1250aea714 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c
@@ -81,6 +81,7 @@ static int cam_lrme_dev_open(struct v4l2_subdev *sd,
static int cam_lrme_dev_close(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
{
+ int rc = 0;
struct cam_lrme_dev *lrme_dev = g_lrme_dev;
struct cam_node *node = v4l2_get_subdevdata(sd);
@@ -90,18 +91,25 @@ static int cam_lrme_dev_close(struct v4l2_subdev *sd,
}
mutex_lock(&lrme_dev->lock);
- lrme_dev->open_cnt--;
- mutex_unlock(&lrme_dev->lock);
+ if (lrme_dev->open_cnt <= 0) {
+ CAM_DBG(CAM_LRME, "LRME subdev is already closed");
+ rc = -EINVAL;
+ goto end;
+ }
+ lrme_dev->open_cnt--;
if (!node) {
CAM_ERR(CAM_LRME, "Node is NULL");
- return -EINVAL;
+ rc = -EINVAL;
+ goto end;
}
if (lrme_dev->open_cnt == 0)
cam_node_shutdown(node);
- return 0;
+end:
+ mutex_unlock(&lrme_dev->lock);
+ return rc;
}
static const struct v4l2_subdev_internal_ops cam_lrme_subdev_internal_ops = {
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index 79d23cbf79b6..eecba3972875 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -188,12 +188,6 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
io_addr[plane] += io_cfg[i].offsets[plane];
- if (io_addr[plane] >> 32) {
- CAM_ERR(CAM_LRME, "Invalid io addr for %d %d",
- plane, rc);
- return -ENOMEM;
- }
-
CAM_DBG(CAM_LRME, "IO Address[%d][%d] : %llu",
io_cfg[i].direction, plane, io_addr[plane]);
}
@@ -571,12 +565,13 @@ static int cam_lrme_mgr_get_caps(void *hw_mgr_priv, void *hw_get_caps_args)
if (sizeof(struct cam_lrme_query_cap_cmd) != args->size) {
CAM_ERR(CAM_LRME,
- "sizeof(struct cam_query_cap_cmd) = %lu, args->size = %d",
+ "sizeof(struct cam_query_cap_cmd) = %zu, args->size = %d",
sizeof(struct cam_query_cap_cmd), args->size);
return -EFAULT;
}
- if (copy_to_user((void __user *)args->caps_handle, &(hw_mgr->lrme_caps),
+ if (copy_to_user(u64_to_user_ptr(args->caps_handle),
+ &(hw_mgr->lrme_caps),
sizeof(struct cam_lrme_query_cap_cmd))) {
CAM_ERR(CAM_LRME, "copy to user failed");
return -EFAULT;
@@ -591,7 +586,7 @@ static int cam_lrme_mgr_hw_acquire(void *hw_mgr_priv, void *hw_acquire_args)
struct cam_hw_acquire_args *args =
(struct cam_hw_acquire_args *)hw_acquire_args;
struct cam_lrme_acquire_args lrme_acquire_args;
- uint64_t device_index;
+ uintptr_t device_index;
if (!hw_mgr_priv || !args) {
CAM_ERR(CAM_LRME,
@@ -612,7 +607,7 @@ static int cam_lrme_mgr_hw_acquire(void *hw_mgr_priv, void *hw_acquire_args)
CAM_DBG(CAM_LRME, "Get device id %llu", device_index);
if (device_index >= hw_mgr->device_count) {
- CAM_ERR(CAM_LRME, "Get wrong device id %llu", device_index);
+ CAM_ERR(CAM_LRME, "Get wrong device id %lu", device_index);
return -EINVAL;
}
@@ -667,7 +662,7 @@ static int cam_lrme_mgr_hw_flush(void *hw_mgr_priv, void *hw_flush_args)
}
args = (struct cam_hw_flush_args *)hw_flush_args;
- device_index = ((uint64_t)args->ctxt_to_hw_map & 0xF);
+ device_index = ((uintptr_t)args->ctxt_to_hw_map & 0xF);
if (device_index >= hw_mgr->device_count) {
CAM_ERR(CAM_LRME, "Invalid device index %d", device_index);
return -EPERM;
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h
index 53d3c6342ea5..87419cf59e00 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -30,13 +30,13 @@
#define CAM_LRME_WORKQ_NUM_TASK 10
#define CAM_LRME_DECODE_DEVICE_INDEX(ctxt_to_hw_map) \
- ((uint64_t)ctxt_to_hw_map & 0xF)
+ ((uintptr_t)ctxt_to_hw_map & 0xF)
#define CAM_LRME_DECODE_PRIORITY(ctxt_to_hw_map) \
- (((uint64_t)ctxt_to_hw_map & 0xF0) >> 4)
+ (((uintptr_t)ctxt_to_hw_map & 0xF0) >> 4)
#define CAM_LRME_DECODE_CTX_INDEX(ctxt_to_hw_map) \
- ((uint64_t)ctxt_to_hw_map >> CAM_LRME_CTX_INDEX_SHIFT)
+ ((uint64_t)(uintptr_t)ctxt_to_hw_map >> CAM_LRME_CTX_INDEX_SHIFT)
/**
* enum cam_lrme_hw_mgr_ctx_priority
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index 022e1a7fcf1e..a5f9ff17ad22 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -920,7 +920,7 @@ int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args,
if (sizeof(struct cam_lrme_hw_submit_args) != arg_size) {
CAM_ERR(CAM_LRME,
- "size of args %lu, arg_size %d",
+ "size of args %zu, arg_size %d",
sizeof(struct cam_lrme_hw_submit_args), arg_size);
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index 0e77a4c01fb4..f2c243e8c7a9 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -25,11 +25,11 @@
static struct cam_mem_table tbl;
static int cam_mem_util_map_cpu_va(struct ion_handle *hdl,
- uint64_t *vaddr,
+ uintptr_t *vaddr,
size_t *len)
{
*vaddr = (uintptr_t)ion_map_kernel(tbl.client, hdl);
- if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ if (IS_ERR_OR_NULL((void *)(uintptr_t)(*vaddr))) {
CAM_ERR(CAM_MEM, "kernel map fail");
return -ENOSPC;
}
@@ -183,12 +183,12 @@ handle_mismatch:
}
EXPORT_SYMBOL(cam_mem_get_io_buf);
-int cam_mem_get_cpu_buf(int32_t buf_handle, uint64_t *vaddr_ptr, size_t *len)
+int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
{
int rc = 0;
int idx;
struct ion_handle *ion_hdl = NULL;
- uint64_t kvaddr = 0;
+ uintptr_t kvaddr = 0;
size_t klen = 0;
if (!buf_handle || !vaddr_ptr || !len)
@@ -288,7 +288,7 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
rc = msm_ion_do_cache_op(tbl.client,
tbl.bufq[idx].i_hdl,
- (void *)tbl.bufq[idx].vaddr,
+ (void *)(uintptr_t)tbl.bufq[idx].vaddr,
tbl.bufq[idx].len,
ion_cache_ops);
if (rc)
@@ -926,7 +926,7 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp,
int rc = 0;
uint32_t heap_id;
int32_t ion_flag = 0;
- uint64_t kvaddr;
+ uintptr_t kvaddr;
dma_addr_t iova = 0;
size_t request_len = 0;
uint32_t mem_handle;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h
index 83727d20e685..92c366d723f9 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -56,7 +56,7 @@ struct cam_mem_buf_queue {
size_t len;
uint32_t flags;
uint64_t vaddr;
- uint64_t kmdvaddr;
+ uintptr_t kmdvaddr;
bool active;
bool is_imported;
};
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h
index 14b1a678e010..64258e8fb5ee 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h
@@ -43,7 +43,7 @@ struct cam_mem_mgr_request_desc {
* @region : Region to which allocated memory belongs
*/
struct cam_mem_mgr_memory_desc {
- uint64_t kva;
+ uintptr_t kva;
uint32_t iova;
int32_t smmu_hdl;
uint32_t mem_handle;
@@ -92,7 +92,7 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
*
* @return Status of operation. Negative in case of error. Zero otherwise.
*/
-int cam_mem_get_cpu_buf(int32_t buf_handle, uint64_t *vaddr_ptr,
+int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr,
size_t *len);
static inline bool cam_mem_is_secure_buf(int32_t buf_handle)
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index 460b3dfe59a2..4c4afc1841f8 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -1325,9 +1325,9 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
return NULL;
}
- if (session->num_links >= MAX_LINKS_PER_SESSION) {
+ if (session->num_links >= MAXIMUM_LINKS_PER_SESSION) {
CAM_ERR(CAM_CRM, "Reached max links %d per session limit %d",
- session->num_links, MAX_LINKS_PER_SESSION);
+ session->num_links, MAXIMUM_LINKS_PER_SESSION);
return NULL;
}
@@ -1362,7 +1362,7 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
mutex_lock(&session->lock);
/* Loop through and find a free index */
- for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
if (!session->links[i]) {
CAM_DBG(CAM_CRM,
"Free link index %d found, num_links=%d",
@@ -1372,7 +1372,7 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
}
}
- if (i == MAX_LINKS_PER_SESSION) {
+ if (i == MAXIMUM_LINKS_PER_SESSION) {
CAM_ERR(CAM_CRM, "Free link index not found");
goto error;
}
@@ -1433,7 +1433,7 @@ static void __cam_req_mgr_unreserve_link(
return;
}
- for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
if (session->links[i] == link)
session->links[i] = NULL;
}
@@ -1445,7 +1445,7 @@ static void __cam_req_mgr_unreserve_link(
* of only having 2 links in a given session
*/
session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
- for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
if (session->links[i])
session->links[i]->sync_link = NULL;
}
@@ -2387,7 +2387,7 @@ int cam_req_mgr_destroy_session(
ses_info->session_hdl,
cam_session->num_links);
- for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
link = cam_session->links[i];
if (!link)
@@ -2628,7 +2628,8 @@ int cam_req_mgr_sync_config(
}
if ((sync_info->num_links < 0) ||
- (sync_info->num_links > MAX_LINKS_PER_SESSION)) {
+ (sync_info->num_links >
+ MAX_LINKS_PER_SESSION)) {
CAM_ERR(CAM_CRM, "Invalid num links %d", sync_info->num_links);
return -EINVAL;
}
@@ -2777,6 +2778,13 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
goto end;
}
+ if (control->num_links > MAX_LINKS_PER_SESSION) {
+ CAM_ERR(CAM_CRM, "Invalid number of links %d",
+ control->num_links);
+ rc = -EINVAL;
+ goto end;
+ }
+
mutex_lock(&g_crm_core_dev->crm_lock);
for (i = 0; i < control->num_links; i++) {
link = (struct cam_req_mgr_core_link *)
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 68ec09b1e89e..8b86931cd1e3 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -34,6 +34,8 @@
#define SYNC_LINK_SOF_CNT_MAX_LMT 1
+#define MAXIMUM_LINKS_PER_SESSION 4
+
/**
* enum crm_workq_task_type
* @codes: to identify which type of task is present
@@ -353,7 +355,7 @@ struct cam_req_mgr_core_link {
struct cam_req_mgr_core_session {
int32_t session_hdl;
uint32_t num_links;
- struct cam_req_mgr_core_link *links[MAX_LINKS_PER_SESSION];
+ struct cam_req_mgr_core_link *links[MAXIMUM_LINKS_PER_SESSION];
struct list_head entry;
struct mutex lock;
int32_t force_err_recovery;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
index 0d21064afed7..cb60ef4abb5a 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
@@ -25,6 +25,7 @@
#include "cam_subdev.h"
#include "cam_mem_mgr.h"
#include "cam_debug_util.h"
+#include "cam_common_util.h"
#include <linux/slub_def.h>
#define CAM_REQ_MGR_EVENT_MAX 30
@@ -153,6 +154,10 @@ static unsigned int cam_req_mgr_poll(struct file *f,
static int cam_req_mgr_close(struct file *filep)
{
+ struct v4l2_subdev *sd;
+ struct v4l2_fh *vfh = filep->private_data;
+ struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+
mutex_lock(&g_dev.cam_lock);
if (g_dev.open_cnt <= 0) {
@@ -161,6 +166,17 @@ static int cam_req_mgr_close(struct file *filep)
}
cam_req_mgr_handle_core_shutdown();
+
+ list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) {
+ if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
+ continue;
+ if (sd->internal_ops && sd->internal_ops->close) {
+ CAM_DBG(CAM_CRM, "Invoke subdev close for device %s",
+ sd->name);
+ sd->internal_ops->close(sd, subdev_fh);
+ }
+ }
+
g_dev.open_cnt--;
v4l2_fh_release(filep);
@@ -220,14 +236,15 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&ses_info,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
return -EFAULT;
}
rc = cam_req_mgr_create_session(&ses_info);
if (!rc)
- if (copy_to_user((void *)k_ioctl->handle,
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->handle),
&ses_info, k_ioctl->size))
rc = -EFAULT;
}
@@ -240,7 +257,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&ses_info,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
return -EFAULT;
}
@@ -256,14 +273,15 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&link_info,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
return -EFAULT;
}
rc = cam_req_mgr_link(&link_info);
if (!rc)
- if (copy_to_user((void *)k_ioctl->handle,
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->handle),
&link_info, k_ioctl->size))
rc = -EFAULT;
}
@@ -276,7 +294,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&unlink_info,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
return -EFAULT;
}
@@ -292,7 +310,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&sched_req,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
return -EFAULT;
}
@@ -308,7 +326,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&flush_info,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
return -EFAULT;
}
@@ -324,7 +342,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&sync_info,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
return -EFAULT;
}
@@ -339,7 +357,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&cmd,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
rc = -EFAULT;
break;
@@ -347,7 +365,8 @@ static long cam_private_ioctl(struct file *file, void *fh,
rc = cam_mem_mgr_alloc_and_map(&cmd);
if (!rc)
- if (copy_to_user((void *)k_ioctl->handle,
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->handle),
&cmd, k_ioctl->size)) {
rc = -EFAULT;
break;
@@ -361,7 +380,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&cmd,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
rc = -EFAULT;
break;
@@ -369,7 +388,8 @@ static long cam_private_ioctl(struct file *file, void *fh,
rc = cam_mem_mgr_map(&cmd);
if (!rc)
- if (copy_to_user((void *)k_ioctl->handle,
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->handle),
&cmd, k_ioctl->size)) {
rc = -EFAULT;
break;
@@ -383,7 +403,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&cmd,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
rc = -EFAULT;
break;
@@ -399,7 +419,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&cmd,
- (void *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
rc = -EFAULT;
break;
@@ -417,7 +437,7 @@ static long cam_private_ioctl(struct file *file, void *fh,
return -EINVAL;
if (copy_from_user(&cmd,
- (void __user *)k_ioctl->handle,
+ u64_to_user_ptr(k_ioctl->handle),
k_ioctl->size)) {
rc = -EFAULT;
break;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
index 3798ef8e6d5f..68b5569097df 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
@@ -228,7 +228,7 @@ int cam_req_mgr_workq_create(char *name, int32_t num_tasks,
crm_workq->task.num_task,
GFP_KERNEL);
if (!crm_workq->task.pool) {
- CAM_WARN(CAM_CRM, "Insufficient memory %lu",
+ CAM_WARN(CAM_CRM, "Insufficient memory %zu",
sizeof(struct crm_workq_task) *
crm_workq->task.num_task);
kfree(crm_workq);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index ed0a26b70eff..c14a74d7c862 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -16,6 +16,7 @@
#include "cam_sensor_util.h"
#include "cam_trace.h"
#include "cam_res_mgr_api.h"
+#include "cam_common_util.h"
int32_t cam_actuator_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -141,7 +142,7 @@ static int32_t cam_actuator_power_down(struct cam_actuator_ctrl_t *a_ctrl)
CAM_ERR(CAM_ACTUATOR, "failed: power_info %pK", power_info);
return -EINVAL;
}
- rc = msm_camera_power_down(power_info, soc_info);
+ rc = cam_sensor_util_power_down(power_info, soc_info);
if (rc) {
CAM_ERR(CAM_ACTUATOR, "power down the core is failed:%d", rc);
return rc;
@@ -301,7 +302,7 @@ int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply)
trace_cam_apply_req("Actuator", apply->request_id);
CAM_DBG(CAM_ACTUATOR, "Request Id: %lld", apply->request_id);
-
+ mutex_lock(&(a_ctrl->actuator_mutex));
if ((apply->request_id ==
a_ctrl->i2c_data.per_frame[request_id].request_id) &&
(a_ctrl->i2c_data.per_frame[request_id].is_settings_valid)
@@ -312,7 +313,7 @@ int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply)
CAM_ERR(CAM_ACTUATOR,
"Failed in applying the request: %lld\n",
apply->request_id);
- return rc;
+ goto release_mutex;
}
}
del_req_id = (request_id +
@@ -327,12 +328,14 @@ int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply)
CAM_ERR(CAM_ACTUATOR,
"Fail deleting the req: %d err: %d\n",
del_req_id, rc);
- return rc;
+ goto release_mutex;
}
} else {
CAM_DBG(CAM_ACTUATOR, "No Valid Req to clean Up");
}
+release_mutex:
+ mutex_unlock(&(a_ctrl->actuator_mutex));
return rc;
}
@@ -352,6 +355,8 @@ int32_t cam_actuator_establish_link(
CAM_ERR(CAM_ACTUATOR, "Device data is NULL");
return -EINVAL;
}
+
+ mutex_lock(&(a_ctrl->actuator_mutex));
if (link->link_enable) {
a_ctrl->bridge_intf.link_hdl = link->link_hdl;
a_ctrl->bridge_intf.crm_cb = link->crm_cb;
@@ -359,6 +364,7 @@ int32_t cam_actuator_establish_link(
a_ctrl->bridge_intf.link_hdl = -1;
a_ctrl->bridge_intf.crm_cb = NULL;
}
+ mutex_unlock(&(a_ctrl->actuator_mutex));
return 0;
}
@@ -409,7 +415,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
size_t len_of_buff = 0;
uint32_t *offset = NULL;
uint32_t *cmd_buf = NULL;
- uint64_t generic_ptr;
+ uintptr_t generic_ptr;
struct common_header *cmm_hdr = NULL;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
@@ -431,11 +437,12 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
power_info = &soc_private->power_info;
ioctl_ctrl = (struct cam_control *)arg;
- if (copy_from_user(&config, (void __user *) ioctl_ctrl->handle,
+ if (copy_from_user(&config,
+ u64_to_user_ptr(ioctl_ctrl->handle),
sizeof(config)))
return -EFAULT;
rc = cam_mem_get_cpu_buf(config.packet_handle,
- (uint64_t *)&generic_ptr, &len_of_buff);
+ &generic_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Error in converting command Handle %d",
rc);
@@ -449,7 +456,8 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
return -EINVAL;
}
- csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
+ csl_packet =
+ (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
switch (csl_packet->header.op_code & 0xFFFFFF) {
@@ -464,7 +472,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
if (!total_cmd_buf_in_bytes)
continue;
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
- (uint64_t *)&generic_ptr, &len_of_buff);
+ &generic_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf");
return rc;
@@ -704,7 +712,7 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl,
goto release_mutex;
}
rc = copy_from_user(&actuator_acq_dev,
- (void __user *) cmd->handle,
+ u64_to_user_ptr(cmd->handle),
sizeof(actuator_acq_dev));
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed Copying from user\n");
@@ -725,7 +733,8 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl,
CAM_DBG(CAM_ACTUATOR, "Device Handle: %d",
actuator_acq_dev.device_handle);
- if (copy_to_user((void __user *) cmd->handle, &actuator_acq_dev,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
+ &actuator_acq_dev,
sizeof(struct cam_sensor_acquire_dev))) {
CAM_ERR(CAM_ACTUATOR, "Failed Copy to User");
rc = -EFAULT;
@@ -778,7 +787,8 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl,
struct cam_actuator_query_cap actuator_cap = {0};
actuator_cap.slot_info = a_ctrl->soc_info.index;
- if (copy_to_user((void __user *) cmd->handle, &actuator_cap,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
+ &actuator_cap,
sizeof(struct cam_actuator_query_cap))) {
CAM_ERR(CAM_ACTUATOR, "Failed Copy to User");
rc = -EFAULT;
@@ -891,7 +901,9 @@ int32_t cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush_req)
continue;
if (i2c_set->is_settings_valid == 1) {
+ mutex_lock(&(a_ctrl->actuator_mutex));
rc = delete_request(i2c_set);
+ mutex_unlock(&(a_ctrl->actuator_mutex));
if (rc < 0)
CAM_ERR(CAM_ACTUATOR,
"delete request: %lld rc: %d",
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 513e717eff49..cb0bcc292037 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -14,6 +14,7 @@
#include "cam_csiphy_core.h"
#include "cam_csiphy_dev.h"
#include "cam_csiphy_soc.h"
+#include "cam_common_util.h"
#include <soc/qcom/scm.h>
#include <cam_mem_mgr.h>
@@ -21,19 +22,23 @@
#define SCM_SVC_CAMERASS 0x18
#define SECURE_SYSCALL_ID 0x6
+#define SECURE_SYSCALL_ID_2 0x7
+
static int csiphy_dump;
module_param(csiphy_dump, int, 0644);
-static int cam_csiphy_notify_secure_mode(int phy, bool protect)
+static int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev,
+ bool protect, int32_t offset)
{
struct scm_desc desc = {0};
+ if (offset >= CSIPHY_MAX_INSTANCES)
+ return -EINVAL;
desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL);
desc.args[0] = protect;
- desc.args[1] = phy;
+ desc.args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset];
- CAM_DBG(CAM_CSIPHY, "phy : %d, protect : %d", phy, protect);
- if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID),
+ if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID_2),
&desc)) {
CAM_ERR(CAM_CSIPHY, "scm call to hypervisor failed");
return -EINVAL;
@@ -42,6 +47,27 @@ static int cam_csiphy_notify_secure_mode(int phy, bool protect)
return 0;
}
+static int32_t cam_csiphy_get_instance_offset(
+ struct csiphy_device *csiphy_dev,
+ int32_t dev_handle)
+{
+ int32_t i;
+
+ if (csiphy_dev->acquire_count >
+ CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid acquire count");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < csiphy_dev->acquire_count; i++) {
+ if (dev_handle ==
+ csiphy_dev->bridge_intf.device_hdl[i])
+ break;
+ }
+
+ return i;
+}
+
void cam_csiphy_query_cap(struct csiphy_device *csiphy_dev,
struct cam_csiphy_query_cap *csiphy_cap)
{
@@ -75,11 +101,56 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev)
}
}
+static int32_t cam_csiphy_update_secure_info(
+ struct csiphy_device *csiphy_dev,
+ struct cam_csiphy_info *cam_cmd_csiphy_info,
+ struct cam_config_dev_cmd *cfg_dev)
+{
+ uint32_t clock_lane, adj_lane_mask, temp;
+ int32_t offset;
+
+ if (csiphy_dev->acquire_count >=
+ CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid acquire count");
+ return -EINVAL;
+ }
+
+ offset = cam_csiphy_get_instance_offset(csiphy_dev,
+ cfg_dev->dev_handle);
+ if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid offset");
+ return -EINVAL;
+ }
+
+ if (cam_cmd_csiphy_info->combo_mode)
+ clock_lane =
+ csiphy_dev->ctrl_reg->csiphy_reg.csiphy_combo_clk_lane;
+ else
+ clock_lane =
+ csiphy_dev->ctrl_reg->csiphy_reg.csiphy_clock_lane;
+
+ adj_lane_mask = cam_cmd_csiphy_info->lane_mask & 0x1F &
+ ~clock_lane;
+ temp = adj_lane_mask & (clock_lane - 1);
+ adj_lane_mask =
+ ((adj_lane_mask & (~((clock_lane - 1)))) >> 1) | temp;
+
+ csiphy_dev->csiphy_info.secure_mode[offset] = 1;
+
+ csiphy_dev->csiphy_cpas_cp_reg_mask[offset] =
+ adj_lane_mask << (csiphy_dev->soc_info.index *
+ (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) +
+ (!cam_cmd_csiphy_info->csiphy_3phase) *
+ (CAM_CSIPHY_MAX_CPHY_LANES));
+
+ return 0;
+}
+
int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
struct cam_config_dev_cmd *cfg_dev)
{
int32_t rc = 0;
- uint64_t generic_ptr;
+ uintptr_t generic_ptr;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
uint32_t *cmd_buf = NULL;
@@ -92,7 +163,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
}
rc = cam_mem_get_cpu_buf((int32_t) cfg_dev->packet_handle,
- (uint64_t *)&generic_ptr, &len);
+ &generic_ptr, &len);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "Failed to get packet Mem address: %d", rc);
return rc;
@@ -105,14 +176,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
return -EINVAL;
}
- csl_packet = (struct cam_packet *)(generic_ptr + cfg_dev->offset);
+ csl_packet = (struct cam_packet *)
+ (generic_ptr + (uint32_t)cfg_dev->offset);
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&csl_packet->payload +
csl_packet->cmd_buf_offset / 4);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- (uint64_t *)&generic_ptr, &len);
+ &generic_ptr, &len);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY,
"Failed to get cmd buf Mem address : %d", rc);
@@ -136,7 +208,10 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
csiphy_dev->csiphy_info.settle_time =
cam_cmd_csiphy_info->settle_time;
csiphy_dev->csiphy_info.data_rate = cam_cmd_csiphy_info->data_rate;
- csiphy_dev->csiphy_info.secure_mode = cam_cmd_csiphy_info->secure_mode;
+
+ if (cam_cmd_csiphy_info->secure_mode == 1)
+ cam_csiphy_update_secure_info(csiphy_dev,
+ cam_cmd_csiphy_info, cfg_dev);
return rc;
}
@@ -347,6 +422,7 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev)
void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
{
struct cam_hw_soc_info *soc_info;
+ int32_t i = 0;
if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT)
return;
@@ -354,13 +430,17 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
soc_info = &csiphy_dev->soc_info;
- if (csiphy_dev->csiphy_info.secure_mode)
- cam_csiphy_notify_secure_mode(
- csiphy_dev->soc_info.index,
- CAM_SECURE_MODE_NON_SECURE);
+ for (i = 0; i < csiphy_dev->acquire_count; i++) {
+ if (csiphy_dev->csiphy_info.secure_mode[i])
+ cam_csiphy_notify_secure_mode(
+ csiphy_dev,
+ CAM_SECURE_MODE_NON_SECURE, i);
- csiphy_dev->csiphy_info.secure_mode =
- CAM_SECURE_MODE_NON_SECURE;
+ csiphy_dev->csiphy_info.secure_mode[i] =
+ CAM_SECURE_MODE_NON_SECURE;
+
+ csiphy_dev->csiphy_cpas_cp_reg_mask[i] = 0;
+ }
cam_csiphy_reset(csiphy_dev);
cam_soc_util_disable_platform_resource(soc_info, true, true);
@@ -398,7 +478,7 @@ static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev,
int32_t rc = 0;
if (copy_from_user(&cam_cmd_csiphy_info,
- (void __user *)p_submit_cmd->packet_handle,
+ u64_to_user_ptr(p_submit_cmd->packet_handle),
sizeof(struct cam_csiphy_info))) {
CAM_ERR(CAM_CSIPHY, "failed to copy cam_csiphy_info\n");
rc = -EFAULT;
@@ -458,7 +538,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_create_dev_hdl bridge_params;
rc = copy_from_user(&csiphy_acq_dev,
- (void __user *)cmd->handle,
+ u64_to_user_ptr(cmd->handle),
sizeof(csiphy_acq_dev));
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "Failed copying from User");
@@ -468,7 +548,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
csiphy_acq_params.combo_mode = 0;
if (copy_from_user(&csiphy_acq_params,
- (void __user *)csiphy_acq_dev.info_handle,
+ u64_to_user_ptr(csiphy_acq_dev.info_handle),
sizeof(csiphy_acq_params))) {
CAM_ERR(CAM_CSIPHY,
"Failed copying from User");
@@ -524,7 +604,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
bridge_intf->session_hdl[csiphy_acq_params.combo_mode] =
csiphy_acq_dev.session_handle;
- if (copy_to_user((void __user *)cmd->handle,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
&csiphy_acq_dev,
sizeof(struct cam_sensor_acquire_dev))) {
CAM_ERR(CAM_CSIPHY, "Failed copying from User");
@@ -542,7 +622,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_csiphy_query_cap csiphy_cap = {0};
cam_csiphy_query_cap(csiphy_dev, &csiphy_cap);
- if (copy_to_user((void __user *)cmd->handle,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
&csiphy_cap, sizeof(struct cam_csiphy_query_cap))) {
CAM_ERR(CAM_CSIPHY, "Failed copying from User");
rc = -EINVAL;
@@ -551,6 +631,16 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
}
break;
case CAM_STOP_DEV: {
+ int32_t offset, rc = 0;
+ struct cam_start_stop_dev_cmd config;
+
+ rc = copy_from_user(&config, u64_to_user_ptr(cmd->handle),
+ sizeof(config));
+ if (rc < 0) {
+ CAM_ERR(CAM_CSIPHY, "Failed copying from User");
+ goto release_mutex;
+ }
+
if ((csiphy_dev->csiphy_state != CAM_CSIPHY_START) ||
!csiphy_dev->start_dev_count) {
CAM_ERR(CAM_CSIPHY, "Not in right state to stop : %d",
@@ -558,20 +648,38 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
+ offset = cam_csiphy_get_instance_offset(csiphy_dev,
+ config.dev_handle);
+ if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid offset");
+ goto release_mutex;
+ }
+
if (--csiphy_dev->start_dev_count) {
CAM_DBG(CAM_CSIPHY, "Stop Dev ref Cnt: %d",
csiphy_dev->start_dev_count);
+ if (csiphy_dev->csiphy_info.secure_mode[offset])
+ cam_csiphy_notify_secure_mode(
+ csiphy_dev,
+ CAM_SECURE_MODE_NON_SECURE, offset);
+
+ csiphy_dev->csiphy_info.secure_mode[offset] =
+ CAM_SECURE_MODE_NON_SECURE;
+ csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0;
+
goto release_mutex;
}
- if (csiphy_dev->csiphy_info.secure_mode)
+ if (csiphy_dev->csiphy_info.secure_mode[offset])
cam_csiphy_notify_secure_mode(
- csiphy_dev->soc_info.index,
- CAM_SECURE_MODE_NON_SECURE);
+ csiphy_dev,
+ CAM_SECURE_MODE_NON_SECURE, offset);
- csiphy_dev->csiphy_info.secure_mode =
+ csiphy_dev->csiphy_info.secure_mode[offset] =
CAM_SECURE_MODE_NON_SECURE;
+ csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0;
+
rc = cam_csiphy_disable_hw(csiphy_dev);
if (rc < 0)
CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
@@ -592,7 +700,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
- if (copy_from_user(&release, (void __user *) cmd->handle,
+ if (copy_from_user(&release,
+ u64_to_user_ptr(cmd->handle),
sizeof(release))) {
rc = -EFAULT;
goto release_mutex;
@@ -630,7 +739,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
case CAM_CONFIG_DEV: {
struct cam_config_dev_cmd config;
- if (copy_from_user(&config, (void __user *)cmd->handle,
+ if (copy_from_user(&config,
+ u64_to_user_ptr(cmd->handle),
sizeof(config))) {
rc = -EFAULT;
} else {
@@ -645,12 +755,28 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
case CAM_START_DEV: {
struct cam_ahb_vote ahb_vote;
struct cam_axi_vote axi_vote;
+ struct cam_start_stop_dev_cmd config;
+ int32_t offset;
+
+ rc = copy_from_user(&config, u64_to_user_ptr(cmd->handle),
+ sizeof(config));
+ if (rc < 0) {
+ CAM_ERR(CAM_CSIPHY, "Failed copying from User");
+ goto release_mutex;
+ }
if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
csiphy_dev->start_dev_count++;
goto release_mutex;
}
+ offset = cam_csiphy_get_instance_offset(csiphy_dev,
+ config.dev_handle);
+ if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid offset");
+ goto release_mutex;
+ }
+
ahb_vote.type = CAM_VOTE_ABSOLUTE;
ahb_vote.vote.level = CAM_SVS_VOTE;
axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
@@ -663,12 +789,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
- if (csiphy_dev->csiphy_info.secure_mode) {
+ if (csiphy_dev->csiphy_info.secure_mode[offset] == 1) {
rc = cam_csiphy_notify_secure_mode(
- csiphy_dev->soc_info.index,
- CAM_SECURE_MODE_SECURE);
+ csiphy_dev,
+ CAM_SECURE_MODE_SECURE, offset);
if (rc < 0)
- csiphy_dev->csiphy_info.secure_mode =
+ csiphy_dev->csiphy_info.secure_mode[offset] =
CAM_SECURE_MODE_NON_SECURE;
}
@@ -696,7 +822,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_config_dev_cmd submit_cmd;
if (copy_from_user(&submit_cmd,
- (void __user *)cmd->handle,
+ u64_to_user_ptr(cmd->handle),
sizeof(struct cam_config_dev_cmd))) {
CAM_ERR(CAM_CSIPHY, "failed copy config ext\n");
rc = -EFAULT;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
index 9c85af39bd8c..ac9625501035 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
@@ -58,6 +58,11 @@
#define CSIPHY_SETTLE_CNT_HIGHER_BYTE 3
#define CSIPHY_DNP_PARAMS 4
+#define CSIPHY_MAX_INSTANCES 2
+
+#define CAM_CSIPHY_MAX_DPHY_LANES 4
+#define CAM_CSIPHY_MAX_CPHY_LANES 3
+
#define ENABLE_IRQ false
#undef CDBG
@@ -101,6 +106,12 @@ struct csiphy_reg_parms_t {
uint32_t csiphy_reset_array_size;
uint32_t csiphy_2ph_config_array_size;
uint32_t csiphy_3ph_config_array_size;
+ uint32_t csiphy_cpas_cp_bits_per_phy;
+ uint32_t csiphy_cpas_cp_is_interleaved;
+ uint32_t csiphy_cpas_cp_2ph_offset;
+ uint32_t csiphy_cpas_cp_3ph_offset;
+ uint32_t csiphy_clock_lane;
+ uint32_t csiphy_combo_clk_lane;
};
/**
@@ -111,9 +122,9 @@ struct csiphy_reg_parms_t {
* @crm_cb: Callback API pointers
*/
struct intf_params {
- int32_t device_hdl[2];
- int32_t session_hdl[2];
- int32_t link_hdl[2];
+ int32_t device_hdl[CSIPHY_MAX_INSTANCES];
+ int32_t session_hdl[CSIPHY_MAX_INSTANCES];
+ int32_t link_hdl[CSIPHY_MAX_INSTANCES];
struct cam_req_mgr_kmd_ops ops;
struct cam_req_mgr_crm_cb *crm_cb;
};
@@ -175,7 +186,7 @@ struct cam_csiphy_param {
uint8_t csiphy_3phase;
uint8_t combo_mode;
uint8_t lane_cnt;
- uint8_t secure_mode;
+ uint8_t secure_mode[CSIPHY_MAX_INSTANCES];
uint64_t settle_time;
uint64_t settle_time_combo_sensor;
uint64_t data_rate;
@@ -231,6 +242,7 @@ struct csiphy_device {
struct cam_hw_soc_info soc_info;
uint32_t cpas_handle;
uint32_t config_count;
+ uint64_t csiphy_cpas_cp_reg_mask[CSIPHY_MAX_INSTANCES];
};
#endif /* _CAM_CSIPHY_DEV_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
index 324509340054..82cff279fec4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
@@ -23,6 +23,8 @@ struct csiphy_reg_parms_t csiphy_v1_0 = {
.csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 14,
.csiphy_3ph_config_array_size = 19,
+ .csiphy_clock_lane = 0x1,
+ .csiphy_combo_clk_lane = 0x10,
};
struct csiphy_reg_t csiphy_common_reg_1_0[] = {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index c8730cab765c..277418a46d3d 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -17,6 +17,7 @@
#include "cam_eeprom_core.h"
#include "cam_eeprom_soc.h"
#include "cam_debug_util.h"
+#include "cam_common_util.h"
/**
* cam_eeprom_read_memory() - read map data into buffer
@@ -221,7 +222,7 @@ static int cam_eeprom_power_down(struct cam_eeprom_ctrl_t *e_ctrl)
CAM_ERR(CAM_EEPROM, "failed: power_info %pK", power_info);
return -EINVAL;
}
- rc = msm_camera_power_down(power_info, soc_info);
+ rc = cam_sensor_util_power_down(power_info, soc_info);
if (rc) {
CAM_ERR(CAM_EEPROM, "power down the core is failed:%d", rc);
return rc;
@@ -341,7 +342,8 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl,
CAM_ERR(CAM_EEPROM, "Device is already acquired");
return -EFAULT;
}
- if (copy_from_user(&eeprom_acq_dev, (void __user *) cmd->handle,
+ if (copy_from_user(&eeprom_acq_dev,
+ u64_to_user_ptr(cmd->handle),
sizeof(eeprom_acq_dev))) {
CAM_ERR(CAM_EEPROM,
"EEPROM:ACQUIRE_DEV: copy from user failed");
@@ -360,8 +362,8 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl,
e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle;
CAM_DBG(CAM_EEPROM, "Device Handle: %d", eeprom_acq_dev.device_handle);
- if (copy_to_user((void __user *) cmd->handle, &eeprom_acq_dev,
- sizeof(struct cam_sensor_acquire_dev))) {
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
+ &eeprom_acq_dev, sizeof(struct cam_sensor_acquire_dev))) {
CAM_ERR(CAM_EEPROM, "EEPROM:ACQUIRE_DEV: copy to user failed");
return -EFAULT;
}
@@ -530,7 +532,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
struct cam_cmd_buf_desc *cmd_desc = NULL;
uint32_t *offset = NULL;
uint32_t *cmd_buf = NULL;
- uint64_t generic_pkt_addr;
+ uintptr_t generic_pkt_addr;
size_t pkt_len = 0;
uint32_t total_cmd_buf_in_bytes = 0;
uint32_t processed_cmd_buf_in_bytes = 0;
@@ -564,7 +566,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
if (!total_cmd_buf_in_bytes)
continue;
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
- (uint64_t *)&generic_pkt_addr, &pkt_len);
+ &generic_pkt_addr, &pkt_len);
if (rc) {
CAM_ERR(CAM_EEPROM, "Failed to get cpu buf");
return rc;
@@ -641,7 +643,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
struct cam_buf_io_cfg *io_cfg;
uint32_t i = 0;
int rc = 0;
- uint64_t buf_addr;
+ uintptr_t buf_addr;
size_t buf_size;
uint8_t *read_buffer;
@@ -656,7 +658,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
CAM_DBG(CAM_EEPROM, "Direction: %d:", io_cfg->direction);
if (io_cfg->direction == CAM_BUF_OUTPUT) {
rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0],
- (uint64_t *)&buf_addr, &buf_size);
+ &buf_addr, &buf_size);
CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n",
(void *)buf_addr, buf_size);
@@ -699,7 +701,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
int32_t rc = 0;
struct cam_control *ioctl_ctrl = NULL;
struct cam_config_dev_cmd dev_config;
- uint64_t generic_pkt_addr;
+ uintptr_t generic_pkt_addr;
size_t pkt_len;
struct cam_packet *csl_packet = NULL;
struct cam_eeprom_soc_private *soc_private =
@@ -708,11 +710,12 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
ioctl_ctrl = (struct cam_control *)arg;
- if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
+ if (copy_from_user(&dev_config,
+ u64_to_user_ptr(ioctl_ctrl->handle),
sizeof(dev_config)))
return -EFAULT;
rc = cam_mem_get_cpu_buf(dev_config.packet_handle,
- (uint64_t *)&generic_pkt_addr, &pkt_len);
+ &generic_pkt_addr, &pkt_len);
if (rc) {
CAM_ERR(CAM_EEPROM,
"error in converting command Handle Error: %d", rc);
@@ -727,7 +730,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
}
csl_packet = (struct cam_packet *)
- (generic_pkt_addr + dev_config.offset);
+ (generic_pkt_addr + (uint32_t)dev_config.offset);
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_EEPROM_PACKET_OPCODE_INIT:
if (e_ctrl->userspace_probe == false) {
@@ -880,7 +883,7 @@ int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
else
eeprom_cap.eeprom_kernel_probe = false;
- if (copy_to_user((void __user *) cmd->handle,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
&eeprom_cap,
sizeof(struct cam_eeprom_query_cap_t))) {
CAM_ERR(CAM_EEPROM, "Failed Copy to User");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile
index c7889a5fc2f5..4d1cbdc3c5a2 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/Makefile
@@ -1,10 +1,11 @@
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash_dev.o cam_flash_core.o cam_flash_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
index 2820d7e353f7..8c075f576ce6 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -15,8 +15,9 @@
#include "cam_sensor_cmn_header.h"
#include "cam_flash_core.h"
#include "cam_res_mgr_api.h"
+#include "cam_common_util.h"
-int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
+static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
bool regulator_enable)
{
int rc = 0;
@@ -55,7 +56,7 @@ int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
return rc;
}
-static int cam_flash_flush_nrt(struct cam_flash_ctrl *fctrl)
+static int cam_flash_pmic_flush_nrt(struct cam_flash_ctrl *fctrl)
{
int j = 0;
struct cam_flash_frame_setting *nrt_settings;
@@ -86,20 +87,187 @@ static int cam_flash_flush_nrt(struct cam_flash_ctrl *fctrl)
return 0;
}
-int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush)
+static int cam_flash_i2c_flush_nrt(struct cam_flash_ctrl *fctrl)
+{
+ int rc = 0;
+
+ if (fctrl->i2c_data.init_settings.is_settings_valid == true) {
+ rc = delete_request(&fctrl->i2c_data.init_settings);
+ if (rc) {
+ CAM_WARN(CAM_FLASH,
+ "Failed to delete Init i2c_setting: %d",
+ rc);
+ return rc;
+ }
+ }
+ if (fctrl->i2c_data.config_settings.is_settings_valid == true) {
+ rc = delete_request(&fctrl->i2c_data.config_settings);
+ if (rc) {
+ CAM_WARN(CAM_FLASH,
+ "Failed to delete NRT i2c_setting: %d",
+ rc);
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+static int cam_flash_construct_default_power_setting(
+ struct cam_sensor_power_ctrl_t *power_info)
+{
+ int rc = 0;
+
+ power_info->power_setting_size = 1;
+ power_info->power_setting =
+ (struct cam_sensor_power_setting *)
+ kzalloc(sizeof(struct cam_sensor_power_setting),
+ GFP_KERNEL);
+ if (!power_info->power_setting)
+ return -ENOMEM;
+
+ power_info->power_setting[0].seq_type = SENSOR_CUSTOM_REG1;
+ power_info->power_setting[0].seq_val = CAM_V_CUSTOM1;
+ power_info->power_setting[0].config_val = 0;
+ power_info->power_setting[0].delay = 2;
+
+ power_info->power_down_setting_size = 1;
+ power_info->power_down_setting =
+ (struct cam_sensor_power_setting *)
+ kzalloc(sizeof(struct cam_sensor_power_setting),
+ GFP_KERNEL);
+ if (!power_info->power_down_setting) {
+ rc = -ENOMEM;
+ goto free_power_settings;
+ }
+
+ power_info->power_down_setting[0].seq_type = SENSOR_CUSTOM_REG1;
+ power_info->power_down_setting[0].seq_val = CAM_V_CUSTOM1;
+ power_info->power_down_setting[0].config_val = 0;
+
+ return rc;
+
+free_power_settings:
+ kfree(power_info->power_setting);
+ power_info->power_setting = NULL;
+ power_info->power_setting_size = 0;
+ return rc;
+}
+
+int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl,
+ bool regulator_enable)
+{
+ int rc = 0;
+
+ if (!(fctrl->switch_trigger)) {
+ CAM_ERR(CAM_FLASH, "Invalid argument");
+ return -EINVAL;
+ }
+
+ if (regulator_enable) {
+ rc = cam_flash_prepare(fctrl, true);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Enable Regulator Failed rc = %d", rc);
+ return rc;
+ }
+ }
+
+ if (!regulator_enable) {
+ if ((fctrl->flash_state == CAM_FLASH_STATE_START) &&
+ (fctrl->is_regulator_enabled == true)) {
+ rc = cam_flash_prepare(fctrl, false);
+ if (rc)
+ CAM_ERR(CAM_FLASH,
+ "Disable Regulator Failed rc: %d", rc);
+ }
+ }
+
+ return rc;
+}
+
+int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl,
+ bool regulator_enable)
+{
+ int rc = 0;
+ struct cam_hw_soc_info *soc_info = &fctrl->soc_info;
+ struct cam_sensor_power_ctrl_t *power_info =
+ &fctrl->power_info;
+
+ if (!power_info || !soc_info) {
+ CAM_ERR(CAM_FLASH, "Power Info is NULL");
+ return -EINVAL;
+ }
+ power_info->dev = soc_info->dev;
+
+ if (regulator_enable && (fctrl->is_regulator_enabled == false)) {
+ if ((power_info->power_setting == NULL) &&
+ (power_info->power_down_setting == NULL)) {
+ CAM_INFO(CAM_FLASH,
+ "Using default power settings");
+ rc = cam_flash_construct_default_power_setting(
+ power_info);
+ if (rc < 0) {
+ CAM_ERR(CAM_FLASH,
+ "Construct default pwr setting failed rc: %d",
+ rc);
+ return rc;
+ }
+ }
+
+ rc = cam_sensor_core_power_up(power_info, soc_info);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "power up the core is failed:%d",
+ rc);
+ goto free_pwr_settings;
+ }
+
+ rc = camera_io_init(&(fctrl->io_master_info));
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "cci_init failed: rc: %d", rc);
+ cam_sensor_util_power_down(power_info, soc_info);
+ goto free_pwr_settings;
+ }
+ fctrl->is_regulator_enabled = true;
+ } else if ((!regulator_enable) &&
+ (fctrl->is_regulator_enabled == true)) {
+ rc = cam_sensor_util_power_down(power_info, soc_info);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "power down the core is failed:%d",
+ rc);
+ return rc;
+ }
+ camera_io_release(&(fctrl->io_master_info));
+ fctrl->is_regulator_enabled = false;
+ goto free_pwr_settings;
+ }
+ return rc;
+
+free_pwr_settings:
+ kfree(power_info->power_setting);
+ kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
+ power_info->power_setting_size = 0;
+ power_info->power_down_setting_size = 0;
+
+ return rc;
+}
+
+int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
+ enum cam_flash_flush_type type, uint64_t req_id)
{
int rc = 0;
int i = 0, j = 0;
- struct cam_flash_ctrl *fctrl = NULL;
int frame_offset = 0;
- fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(flush->dev_hdl);
if (!fctrl) {
CAM_ERR(CAM_FLASH, "Device data is NULL");
return -EINVAL;
}
- if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+ if (type == FLUSH_ALL) {
+ cam_flash_off(fctrl);
/* flush all requests*/
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
fctrl->per_frame[i].cmn_attr.request_id = 0;
@@ -109,19 +277,105 @@ int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush)
fctrl->per_frame[i].led_current_ma[j] = 0;
}
- rc = cam_flash_flush_nrt(fctrl);
- if (rc)
- CAM_ERR(CAM_FLASH, "NonRealTime flush error");
- } else if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
+ cam_flash_pmic_flush_nrt(fctrl);
+ } else if ((type == FLUSH_REQ) && (req_id != 0)) {
/* flush request with req_id*/
- frame_offset = flush->req_id % MAX_PER_FRAME_ARRAY;
+ frame_offset = req_id % MAX_PER_FRAME_ARRAY;
fctrl->per_frame[frame_offset].cmn_attr.request_id = 0;
fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid =
false;
fctrl->per_frame[frame_offset].cmn_attr.count = 0;
for (i = 0; i < CAM_FLASH_MAX_LED_TRIGGERS; i++)
fctrl->per_frame[frame_offset].led_current_ma[i] = 0;
+ } else if ((type == FLUSH_REQ) && (req_id == 0)) {
+ /* Handels NonRealTime usecase */
+ cam_flash_pmic_flush_nrt(fctrl);
+ } else {
+ CAM_ERR(CAM_FLASH, "Invalid arguments");
+ return -EINVAL;
+ }
+
+ return rc;
+}
+
+int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl,
+ enum cam_flash_flush_type type, uint64_t req_id)
+{
+ int rc = 0;
+ int i = 0;
+ uint32_t cancel_req_id_found = 0;
+ struct i2c_settings_array *i2c_set = NULL;
+
+ if (!fctrl) {
+ CAM_ERR(CAM_FLASH, "Device data is NULL");
+ return -EINVAL;
+ }
+ if ((type == FLUSH_REQ) && (req_id == 0)) {
+ /* This setting will be called only when NonRealTime
+ * settings needs to clean.
+ */
+ cam_flash_i2c_flush_nrt(fctrl);
+ } else {
+ /* All other usecase will be handle here */
+ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
+ i2c_set = &(fctrl->i2c_data.per_frame[i]);
+
+ if ((type == FLUSH_REQ) &&
+ (i2c_set->request_id != req_id))
+ continue;
+
+ if (i2c_set->is_settings_valid == 1) {
+ rc = delete_request(i2c_set);
+ if (rc < 0)
+ CAM_ERR(CAM_FLASH,
+ "delete request: %lld rc: %d",
+ i2c_set->request_id, rc);
+
+ if (type == FLUSH_REQ) {
+ cancel_req_id_found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if ((type == FLUSH_REQ) && (req_id != 0) &&
+ (!cancel_req_id_found))
+ CAM_DBG(CAM_FLASH,
+ "Flush request id:%lld not found in the pending list",
+ req_id);
+
+ return rc;
+}
+
+int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush)
+{
+ int rc = 0;
+ struct cam_flash_ctrl *fctrl = NULL;
+
+ fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(flush->dev_hdl);
+ if (!fctrl) {
+ CAM_ERR(CAM_FLASH, "Device data is NULL");
+ return -EINVAL;
+ }
+
+ mutex_lock(&fctrl->flash_mutex);
+ if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+ rc = fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "FLUSH_TYPE_ALL failed rc: %d", rc);
+ goto end;
+ }
+ } else if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
+ rc = fctrl->func_tbl.flush_req(fctrl,
+ FLUSH_REQ, flush->req_id);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "FLUSH_REQ failed rc: %d", rc);
+ goto end;
+ }
}
+end:
+ mutex_unlock(&fctrl->flash_mutex);
return rc;
}
@@ -254,26 +508,51 @@ static int cam_flash_high(
return rc;
}
-static int delete_req(struct cam_flash_ctrl *fctrl, uint64_t req_id)
+static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl,
+ uint64_t req_id)
+{
+ int i = 0, rc = 0;
+ uint64_t top = 0, del_req_id = 0;
+
+ if (req_id != 0) {
+ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
+ if ((req_id >=
+ fctrl->i2c_data.per_frame[i].request_id) &&
+ (top <
+ fctrl->i2c_data.per_frame[i].request_id) &&
+ (fctrl->i2c_data.per_frame[i].is_settings_valid
+ == 1)) {
+ del_req_id = top;
+ top = fctrl->i2c_data.per_frame[i].request_id;
+ }
+ }
+
+ if (top < req_id) {
+ if ((((top % MAX_PER_FRAME_ARRAY) - (req_id %
+ MAX_PER_FRAME_ARRAY)) >= BATCH_SIZE_MAX) ||
+ (((top % MAX_PER_FRAME_ARRAY) - (req_id %
+ MAX_PER_FRAME_ARRAY)) <= -BATCH_SIZE_MAX))
+ del_req_id = req_id;
+ }
+
+ if (!del_req_id)
+ return rc;
+
+ CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu",
+ top, del_req_id);
+ }
+ fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id);
+ return 0;
+}
+
+static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl,
+ uint64_t req_id)
{
int i = 0;
struct cam_flash_frame_setting *flash_data = NULL;
uint64_t top = 0, del_req_id = 0;
- if (req_id == 0) {
- flash_data = &fctrl->nrt_info;
- if ((fctrl->nrt_info.cmn_attr.cmd_type ==
- CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) ||
- (fctrl->nrt_info.cmn_attr.cmd_type ==
- CAMERA_SENSOR_FLASH_CMD_TYPE_RER)) {
- flash_data->cmn_attr.is_settings_valid = false;
- for (i = 0; i < flash_data->cmn_attr.count; i++)
- flash_data->led_current_ma[i] = 0;
- } else {
- fctrl->flash_init_setting.cmn_attr.is_settings_valid
- = false;
- }
- } else {
+ if (req_id != 0) {
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
flash_data = &fctrl->per_frame[i];
if (req_id >= flash_data->cmn_attr.request_id &&
@@ -305,28 +584,100 @@ static int delete_req(struct cam_flash_ctrl *fctrl, uint64_t req_id)
CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu",
top, del_req_id);
+ }
- for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
- flash_data = &fctrl->per_frame[i];
- if ((del_req_id ==
- flash_data->cmn_attr.request_id) &&
- (flash_data->cmn_attr.
- is_settings_valid == 1)) {
- CAM_DBG(CAM_FLASH, "Deleting request[%d] %llu",
- i, flash_data->cmn_attr.request_id);
- flash_data->cmn_attr.request_id = 0;
- flash_data->cmn_attr.is_settings_valid = false;
- flash_data->opcode = 0;
- for (i = 0; i < flash_data->cmn_attr.count; i++)
- flash_data->led_current_ma[i] = 0;
+ fctrl->func_tbl.flush_req(fctrl, FLUSH_REQ, del_req_id);
+ return 0;
+}
+
+static int32_t cam_flash_slaveInfo_pkt_parser(struct cam_flash_ctrl *fctrl,
+ uint32_t *cmd_buf)
+{
+ int32_t rc = 0;
+ struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+
+ if (fctrl->io_master_info.master_type == CCI_MASTER) {
+ fctrl->io_master_info.cci_client->cci_i2c_master =
+ fctrl->cci_i2c_master;
+ fctrl->io_master_info.cci_client->i2c_freq_mode =
+ i2c_info->i2c_freq_mode;
+ fctrl->io_master_info.cci_client->sid =
+ i2c_info->slave_addr >> 1;
+ CAM_DBG(CAM_FLASH, "Slave addr: 0x%x Freq Mode: %d",
+ i2c_info->slave_addr, i2c_info->i2c_freq_mode);
+ } else if (fctrl->io_master_info.master_type == I2C_MASTER) {
+ fctrl->io_master_info.client->addr = i2c_info->slave_addr;
+ CAM_DBG(CAM_FLASH, "Slave addr: 0x%x", i2c_info->slave_addr);
+ } else {
+ CAM_ERR(CAM_FLASH, "Invalid Master type: %d",
+ fctrl->io_master_info.master_type);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl,
+ uint64_t req_id)
+{
+ struct i2c_settings_list *i2c_list;
+ struct i2c_settings_array *i2c_set = NULL;
+ int frame_offset = 0, rc = 0;
+
+ if (req_id == 0) {
+ /* NonRealTime Init settings*/
+ if (fctrl->i2c_data.init_settings.is_settings_valid == true) {
+ list_for_each_entry(i2c_list,
+ &(fctrl->i2c_data.init_settings.list_head),
+ list) {
+ rc = cam_sensor_util_i2c_apply_setting
+ (&(fctrl->io_master_info), i2c_list);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Failed to apply init settings: %d",
+ rc);
+ return rc;
+ }
+ }
+ }
+ /* NonRealTime (Widget/RER/INIT_FIRE settings) */
+ if (fctrl->i2c_data.config_settings.is_settings_valid == true) {
+ list_for_each_entry(i2c_list,
+ &(fctrl->i2c_data.config_settings.list_head),
+ list) {
+ rc = cam_sensor_util_i2c_apply_setting
+ (&(fctrl->io_master_info), i2c_list);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Failed to apply NRT settings: %d", rc);
+ return rc;
+ }
+ }
+ }
+ } else {
+ /* RealTime */
+ frame_offset = req_id % MAX_PER_FRAME_ARRAY;
+ i2c_set = &fctrl->i2c_data.per_frame[frame_offset];
+ if ((i2c_set->is_settings_valid == true) &&
+ (i2c_set->request_id == req_id)) {
+ list_for_each_entry(i2c_list,
+ &(i2c_set->list_head), list) {
+ rc = cam_sensor_util_i2c_apply_setting(
+ &(fctrl->io_master_info), i2c_list);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Failed to apply settings: %d", rc);
+ return rc;
+ }
}
}
}
- return 0;
+ cam_flash_i2c_delete_req(fctrl, req_id);
+ return rc;
}
-int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl,
+int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl,
uint64_t req_id)
{
int rc = 0, i = 0;
@@ -428,7 +779,6 @@ int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl,
} else if (fctrl->nrt_info.cmn_attr.cmd_type ==
CAMERA_SENSOR_FLASH_CMD_TYPE_RER) {
flash_data = &fctrl->nrt_info;
-
if (fctrl->flash_state != CAM_FLASH_STATE_START) {
rc = cam_flash_off(fctrl);
if (rc) {
@@ -461,8 +811,7 @@ int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl,
rc = cam_flash_off(fctrl);
if (rc) {
CAM_ERR(CAM_FLASH,
- "Flash off failed: %d",
- rc);
+ "Flash off failed: %d", rc);
continue;
}
fctrl->flash_state = CAM_FLASH_STATE_START;
@@ -524,15 +873,325 @@ int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl,
}
nrt_del_req:
- delete_req(fctrl, req_id);
+ cam_flash_pmic_delete_req(fctrl, req_id);
apply_setting_err:
return rc;
}
-int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
+int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
{
int rc = 0, i = 0;
- uint64_t generic_ptr;
+ uintptr_t generic_ptr;
+ uint32_t total_cmd_buf_in_bytes = 0;
+ uint32_t processed_cmd_buf_in_bytes = 0;
+ uint16_t cmd_length_in_bytes = 0;
+ uint32_t *cmd_buf = NULL;
+ uint32_t *offset = NULL;
+ uint32_t frm_offset = 0;
+ size_t len_of_buffer;
+ struct cam_flash_init *flash_init = NULL;
+ struct common_header *cmn_hdr = NULL;
+ struct cam_control *ioctl_ctrl = NULL;
+ struct cam_packet *csl_packet = NULL;
+ struct cam_cmd_buf_desc *cmd_desc = NULL;
+ struct cam_config_dev_cmd config;
+ struct cam_req_mgr_add_request add_req;
+ struct i2c_data_settings *i2c_data = NULL;
+ struct i2c_settings_array *i2c_reg_settings = NULL;
+ struct cam_sensor_power_ctrl_t *power_info = NULL;
+
+ if (!fctrl || !arg) {
+ CAM_ERR(CAM_FLASH, "fctrl/arg is NULL");
+ return -EINVAL;
+ }
+ /* getting CSL Packet */
+ ioctl_ctrl = (struct cam_control *)arg;
+
+ if (copy_from_user((&config), u64_to_user_ptr(ioctl_ctrl->handle),
+ sizeof(config))) {
+ CAM_ERR(CAM_FLASH, "Copy cmd handle from user failed");
+ return -EFAULT;
+ }
+
+ rc = cam_mem_get_cpu_buf(config.packet_handle,
+ &generic_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc);
+ return rc;
+ }
+
+ if (config.offset > len_of_buffer) {
+ CAM_ERR(CAM_FLASH,
+ "offset is out of bounds: offset: %lld len: %zu",
+ config.offset, len_of_buffer);
+ return -EINVAL;
+ }
+
+ /* Add offset to the flash csl header */
+ csl_packet = (struct cam_packet *)(uintptr_t)(generic_ptr +
+ config.offset);
+ switch (csl_packet->header.op_code & 0xFFFFFF) {
+ case CAM_FLASH_PACKET_OPCODE_INIT: {
+ /* INIT packet*/
+ offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
+ csl_packet->cmd_buf_offset);
+ cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+
+ /* Loop through multiple command buffers */
+ for (i = 1; i < csl_packet->num_cmd_buf; i++) {
+ total_cmd_buf_in_bytes = cmd_desc[i].length;
+ processed_cmd_buf_in_bytes = 0;
+ if (!total_cmd_buf_in_bytes)
+ continue;
+ rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
+ &generic_ptr, &len_of_buffer);
+ if (rc < 0) {
+ CAM_ERR(CAM_FLASH, "Failed to get cpu buf");
+ return rc;
+ }
+ cmd_buf = (uint32_t *)generic_ptr;
+ if (!cmd_buf) {
+ CAM_ERR(CAM_FLASH, "invalid cmd buf");
+ return -EINVAL;
+ }
+ cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+ cmn_hdr = (struct common_header *)cmd_buf;
+
+ /* Loop through cmd formats in one cmd buffer */
+ CAM_DBG(CAM_FLASH,
+ "command Type: %d,Processed: %d,Total: %d",
+ cmn_hdr->cmd_type, processed_cmd_buf_in_bytes,
+ total_cmd_buf_in_bytes);
+ switch (cmn_hdr->cmd_type) {
+ case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO:
+ flash_init = (struct cam_flash_init *)cmd_buf;
+ fctrl->flash_type = flash_init->flash_type;
+ cmd_length_in_bytes =
+ sizeof(struct cam_flash_init);
+ processed_cmd_buf_in_bytes +=
+ cmd_length_in_bytes;
+ cmd_buf += cmd_length_in_bytes/
+ sizeof(uint32_t);
+ break;
+ case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
+ rc = cam_flash_slaveInfo_pkt_parser(
+ fctrl, cmd_buf);
+ if (rc < 0) {
+ CAM_ERR(CAM_FLASH,
+ "Failed parsing slave info: rc: %d",
+ rc);
+ return rc;
+ }
+ cmd_length_in_bytes =
+ sizeof(struct cam_cmd_i2c_info);
+ processed_cmd_buf_in_bytes +=
+ cmd_length_in_bytes;
+ cmd_buf += cmd_length_in_bytes/
+ sizeof(uint32_t);
+ break;
+ case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
+ case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
+ CAM_DBG(CAM_FLASH,
+ "Received power settings");
+ cmd_length_in_bytes =
+ total_cmd_buf_in_bytes;
+ rc = cam_sensor_update_power_settings(
+ cmd_buf,
+ total_cmd_buf_in_bytes,
+ &fctrl->power_info);
+ processed_cmd_buf_in_bytes +=
+ cmd_length_in_bytes;
+ cmd_buf += cmd_length_in_bytes/
+ sizeof(uint32_t);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Failed update power settings");
+ return rc;
+ }
+ break;
+ default:
+ CAM_DBG(CAM_FLASH,
+ "Received initSettings");
+ i2c_data = &(fctrl->i2c_data);
+ i2c_reg_settings =
+ &fctrl->i2c_data.init_settings;
+
+ i2c_reg_settings->request_id = 0;
+ i2c_reg_settings->is_settings_valid = 1;
+ rc = cam_sensor_i2c_command_parser(
+ &fctrl->io_master_info,
+ i2c_reg_settings,
+ &cmd_desc[i], 1);
+ if (rc < 0) {
+ CAM_ERR(CAM_FLASH,
+ "pkt parsing failed: %d", rc);
+ return rc;
+ }
+ cmd_length_in_bytes =
+ cmd_desc[i].length;
+ processed_cmd_buf_in_bytes +=
+ cmd_length_in_bytes;
+ cmd_buf += cmd_length_in_bytes/
+ sizeof(uint32_t);
+
+ break;
+ }
+ }
+ power_info = &fctrl->power_info;
+ if (!power_info) {
+ CAM_ERR(CAM_FLASH, "Power_info is NULL");
+ return -EINVAL;
+ }
+
+ /* Parse and fill vreg params for power up settings */
+ rc = msm_camera_fill_vreg_params(&fctrl->soc_info,
+ power_info->power_setting,
+ power_info->power_setting_size);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "failed to fill vreg params for power up rc:%d",
+ rc);
+ return rc;
+ }
+
+ /* Parse and fill vreg params for power down settings*/
+ rc = msm_camera_fill_vreg_params(
+ &fctrl->soc_info,
+ power_info->power_down_setting,
+ power_info->power_down_setting_size);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "failed to fill vreg params power down rc:%d",
+ rc);
+ return rc;
+ }
+
+ rc = fctrl->func_tbl.power_ops(fctrl, true);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Enable Regulator Failed rc = %d", rc);
+ return rc;
+ }
+
+ rc = fctrl->func_tbl.apply_setting(fctrl, 0);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc);
+ return rc;
+ }
+
+ fctrl->flash_state = CAM_FLASH_STATE_CONFIG;
+ break;
+ }
+ case CAM_FLASH_PACKET_OPCODE_SET_OPS: {
+ offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
+ csl_packet->cmd_buf_offset);
+ frm_offset = csl_packet->header.request_id %
+ MAX_PER_FRAME_ARRAY;
+ /* add support for handling i2c_data*/
+ i2c_reg_settings =
+ &fctrl->i2c_data.per_frame[frm_offset];
+ if (i2c_reg_settings->is_settings_valid == true) {
+ i2c_reg_settings->request_id = 0;
+ i2c_reg_settings->is_settings_valid = false;
+ goto update_req_mgr;
+ }
+ i2c_reg_settings->is_settings_valid = true;
+ i2c_reg_settings->request_id =
+ csl_packet->header.request_id;
+ cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+ rc = cam_sensor_i2c_command_parser(
+ &fctrl->io_master_info,
+ i2c_reg_settings, cmd_desc, 1);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Failed in parsing i2c packets");
+ return rc;
+ }
+ break;
+ }
+ case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: {
+ offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
+ csl_packet->cmd_buf_offset);
+
+ /* add support for handling i2c_data*/
+ i2c_reg_settings = &fctrl->i2c_data.config_settings;
+ if (i2c_reg_settings->is_settings_valid == true) {
+ i2c_reg_settings->request_id = 0;
+ i2c_reg_settings->is_settings_valid = false;
+
+ rc = delete_request(i2c_reg_settings);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Failed in Deleting the err: %d", rc);
+ return rc;
+ }
+ }
+ i2c_reg_settings->is_settings_valid = true;
+ i2c_reg_settings->request_id =
+ csl_packet->header.request_id;
+ cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+ rc = cam_sensor_i2c_command_parser(
+ &fctrl->io_master_info,
+ i2c_reg_settings, cmd_desc, 1);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Failed in parsing i2c NRT packets");
+ return rc;
+ }
+ rc = fctrl->func_tbl.apply_setting(fctrl, 0);
+ if (rc)
+ CAM_ERR(CAM_FLASH,
+ "Apply setting failed: %d", rc);
+ return rc;
+ }
+ case CAM_PKT_NOP_OPCODE: {
+ if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) ||
+ (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) {
+ CAM_WARN(CAM_FLASH,
+ "Rxed NOP packets without linking");
+ frm_offset = csl_packet->header.request_id %
+ MAX_PER_FRAME_ARRAY;
+ fctrl->i2c_data.per_frame[frm_offset].is_settings_valid
+ = false;
+ return 0;
+ }
+
+ CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u",
+ csl_packet->header.request_id);
+ goto update_req_mgr;
+ }
+ default:
+ CAM_ERR(CAM_FLASH, "Wrong Opcode : %d",
+ (csl_packet->header.op_code & 0xFFFFFF));
+ return -EINVAL;
+ }
+update_req_mgr:
+ if (((csl_packet->header.op_code & 0xFFFFF) ==
+ CAM_PKT_NOP_OPCODE) ||
+ ((csl_packet->header.op_code & 0xFFFFF) ==
+ CAM_FLASH_PACKET_OPCODE_SET_OPS)) {
+ add_req.link_hdl = fctrl->bridge_intf.link_hdl;
+ add_req.req_id = csl_packet->header.request_id;
+ add_req.dev_hdl = fctrl->bridge_intf.device_hdl;
+
+ if ((csl_packet->header.op_code & 0xFFFFF) ==
+ CAM_FLASH_PACKET_OPCODE_SET_OPS)
+ add_req.skip_before_applying = 1;
+ else
+ add_req.skip_before_applying = 0;
+
+ if (fctrl->bridge_intf.crm_cb &&
+ fctrl->bridge_intf.crm_cb->add_req)
+ fctrl->bridge_intf.crm_cb->add_req(&add_req);
+ CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id);
+ }
+ return rc;
+}
+
+int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
+{
+ int rc = 0, i = 0;
+ uintptr_t generic_ptr;
uint32_t *cmd_buf = NULL;
uint32_t *offset = NULL;
uint32_t frm_offset = 0;
@@ -556,7 +1215,8 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
/* getting CSL Packet */
ioctl_ctrl = (struct cam_control *)arg;
- if (copy_from_user((&config), (void __user *) ioctl_ctrl->handle,
+ if (copy_from_user((&config),
+ u64_to_user_ptr(ioctl_ctrl->handle),
sizeof(config))) {
CAM_ERR(CAM_FLASH, "Copy cmd handle from user failed");
rc = -EFAULT;
@@ -564,7 +1224,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
}
rc = cam_mem_get_cpu_buf(config.packet_handle,
- (uint64_t *)&generic_ptr, &len_of_buffer);
+ &generic_ptr, &len_of_buffer);
if (rc) {
CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc);
return rc;
@@ -578,57 +1238,69 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
}
/* Add offset to the flash csl header */
- csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
+ csl_packet =
+ (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_FLASH_PACKET_OPCODE_INIT: {
/* INIT packet*/
offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
csl_packet->cmd_buf_offset);
- fctrl->flash_init_setting.cmn_attr.request_id = 0;
- fctrl->flash_init_setting.cmn_attr.is_settings_valid = true;
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- (uint64_t *)&generic_ptr, &len_of_buffer);
+ &generic_ptr, &len_of_buffer);
cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
cmd_desc->offset);
cam_flash_info = (struct cam_flash_init *)cmd_buf;
switch (cam_flash_info->cmd_type) {
- case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO:
+ case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO: {
+ CAM_DBG(CAM_FLASH, "INIT_INFO CMD CALLED");
+ fctrl->flash_init_setting.cmn_attr.request_id = 0;
+ fctrl->flash_init_setting.cmn_attr.is_settings_valid =
+ true;
fctrl->flash_type = cam_flash_info->flash_type;
fctrl->is_regulator_enabled = false;
fctrl->nrt_info.cmn_attr.cmd_type =
CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO;
+
+ rc = fctrl->func_tbl.power_ops(fctrl, true);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Enable Regulator Failed rc = %d", rc);
+ return rc;
+ }
+
fctrl->flash_state =
CAM_FLASH_STATE_CONFIG;
break;
- case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE:
- CAM_DBG(CAM_FLASH, "INIT Fire Operation");
- flash_operation_info =
- (struct cam_flash_set_on_off *) cmd_buf;
- fctrl->nrt_info.cmn_attr.count =
- flash_operation_info->count;
- fctrl->nrt_info.cmn_attr.request_id = 0;
- fctrl->nrt_info.opcode =
- flash_operation_info->opcode;
- fctrl->nrt_info.cmn_attr.cmd_type =
- CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE;
- for (i = 0;
- i < flash_operation_info->count; i++)
- fctrl->nrt_info.led_current_ma[i] =
- flash_operation_info->led_current_ma[i];
+ }
+ case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE: {
+ CAM_DBG(CAM_FLASH, "INIT_FIRE Operation");
- mutex_lock(&fctrl->flash_wq_mutex);
- rc = cam_flash_apply_setting(fctrl, 0);
- if (rc)
- CAM_ERR(CAM_FLASH,
- "Apply setting failed: %d",
- rc);
- mutex_unlock(&fctrl->flash_wq_mutex);
- fctrl->flash_state =
- CAM_FLASH_STATE_CONFIG;
+ flash_operation_info =
+ (struct cam_flash_set_on_off *) cmd_buf;
+ fctrl->nrt_info.cmn_attr.count =
+ flash_operation_info->count;
+ fctrl->nrt_info.cmn_attr.request_id = 0;
+ fctrl->nrt_info.opcode =
+ flash_operation_info->opcode;
+ fctrl->nrt_info.cmn_attr.cmd_type =
+ CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE;
+ for (i = 0;
+ i < flash_operation_info->count; i++)
+ fctrl->nrt_info.led_current_ma[i] =
+ flash_operation_info->led_current_ma[i];
+
+ rc = fctrl->func_tbl.apply_setting(fctrl, 0);
+ if (rc)
+ CAM_ERR(CAM_FLASH,
+ "Apply setting failed: %d",
+ rc);
+
+ fctrl->flash_state = CAM_FLASH_STATE_CONFIG;
break;
+ }
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
cam_flash_info->cmd_type);
@@ -654,7 +1326,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
flash_data->cmn_attr.is_settings_valid = true;
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- (uint64_t *)&generic_ptr, &len_of_buffer);
+ &generic_ptr, &len_of_buffer);
cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
cmd_desc->offset);
@@ -666,7 +1338,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
switch (cmn_hdr->cmd_type) {
case CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE: {
CAM_DBG(CAM_FLASH,
- "CAMERA_FLASH_CMD_TYPE_OPS case called");
+ "CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE cmd called");
if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) ||
(fctrl->flash_state ==
CAM_FLASH_STATE_ACQUIRE)) {
@@ -690,8 +1362,8 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
for (i = 0; i < flash_operation_info->count; i++)
flash_data->led_current_ma[i]
= flash_operation_info->led_current_ma[i];
- }
- break;
+ }
+ break;
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
cmn_hdr->cmd_type);
@@ -705,7 +1377,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->nrt_info.cmn_attr.is_settings_valid = true;
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- (uint64_t *)&generic_ptr, &len_of_buffer);
+ &generic_ptr, &len_of_buffer);
cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
cmd_desc->offset);
cmn_hdr = (struct common_header *)cmd_buf;
@@ -727,12 +1399,10 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->nrt_info.led_current_ma[i] =
flash_operation_info->led_current_ma[i];
- mutex_lock(&fctrl->flash_wq_mutex);
- rc = cam_flash_apply_setting(fctrl, 0);
+ rc = fctrl->func_tbl.apply_setting(fctrl, 0);
if (rc)
CAM_ERR(CAM_FLASH, "Apply setting failed: %d",
rc);
- mutex_unlock(&fctrl->flash_wq_mutex);
return rc;
}
case CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR: {
@@ -773,12 +1443,10 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
flash_rer_info->led_current_ma[i];
- mutex_lock(&fctrl->flash_wq_mutex);
- rc = cam_flash_apply_setting(fctrl, 0);
+ rc = fctrl->func_tbl.apply_setting(fctrl, 0);
if (rc)
CAM_ERR(CAM_FLASH, "apply_setting failed: %d",
rc);
- mutex_unlock(&fctrl->flash_wq_mutex);
return rc;
}
default:
@@ -786,7 +1454,6 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
cmn_hdr->cmd_type);
return -EINVAL;
}
-
break;
}
case CAM_PKT_NOP_OPCODE: {
@@ -804,7 +1471,7 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid = false;
fctrl->per_frame[frm_offset].cmn_attr.request_id = 0;
fctrl->per_frame[frm_offset].opcode = CAM_PKT_NOP_OPCODE;
- CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u",
+ CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %llu",
csl_packet->header.request_id);
goto update_req_mgr;
}
@@ -858,7 +1525,7 @@ int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link)
CAM_ERR(CAM_FLASH, " Device data is NULL");
return -EINVAL;
}
-
+ mutex_lock(&fctrl->flash_mutex);
if (link->link_enable) {
fctrl->bridge_intf.link_hdl = link->link_hdl;
fctrl->bridge_intf.crm_cb = link->crm_cb;
@@ -866,43 +1533,11 @@ int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link)
fctrl->bridge_intf.link_hdl = -1;
fctrl->bridge_intf.crm_cb = NULL;
}
+ mutex_unlock(&fctrl->flash_mutex);
return 0;
}
-
-int cam_flash_stop_dev(struct cam_flash_ctrl *fctrl)
-{
- int rc = 0, i, j;
-
- cam_flash_off(fctrl);
-
- for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
- fctrl->per_frame[i].cmn_attr.request_id = 0;
- fctrl->per_frame[i].cmn_attr.is_settings_valid = false;
- fctrl->per_frame[i].cmn_attr.count = 0;
- for (j = 0; j < CAM_FLASH_MAX_LED_TRIGGERS; j++)
- fctrl->per_frame[i].led_current_ma[j] = 0;
- }
-
- rc = cam_flash_flush_nrt(fctrl);
- if (rc) {
- CAM_ERR(CAM_FLASH,
- "NonRealTime Dev flush failed rc: %d", rc);
- return rc;
- }
-
- if ((fctrl->flash_state == CAM_FLASH_STATE_START) &&
- (fctrl->is_regulator_enabled == true)) {
- rc = cam_flash_prepare(fctrl, false);
- if (rc)
- CAM_ERR(CAM_FLASH, "Disable Regulator Failed rc: %d",
- rc);
- }
-
- return rc;
-}
-
int cam_flash_release_dev(struct cam_flash_ctrl *fctrl)
{
int rc = 0;
@@ -930,9 +1565,11 @@ void cam_flash_shutdown(struct cam_flash_ctrl *fctrl)
if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) ||
(fctrl->flash_state == CAM_FLASH_STATE_START)) {
- rc = cam_flash_stop_dev(fctrl);
+ fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
+ rc = fctrl->func_tbl.power_ops(fctrl, false);
if (rc)
- CAM_ERR(CAM_FLASH, "Stop Failed rc: %d", rc);
+ CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d",
+ rc);
}
rc = cam_flash_release_dev(fctrl);
@@ -956,12 +1593,12 @@ int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply)
return -EINVAL;
}
- mutex_lock(&fctrl->flash_wq_mutex);
- rc = cam_flash_apply_setting(fctrl, apply->request_id);
+ mutex_lock(&fctrl->flash_mutex);
+ rc = fctrl->func_tbl.apply_setting(fctrl, apply->request_id);
if (rc)
CAM_ERR(CAM_FLASH, "apply_setting failed with rc=%d",
rc);
- mutex_unlock(&fctrl->flash_wq_mutex);
+ mutex_unlock(&fctrl->flash_mutex);
return rc;
}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h
index f73409a0a935..1bd3b31c1668 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,20 +16,12 @@
#include <linux/leds-qpnp-flash.h>
#include <media/cam_sensor.h>
#include "cam_flash_dev.h"
-#include "cam_sync_api.h"
-#include "cam_mem_mgr_api.h"
-int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg);
int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info);
int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link);
-int cam_flash_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id);
int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply);
int cam_flash_process_evt(struct cam_req_mgr_link_evt_data *event_data);
int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush);
-int cam_flash_off(struct cam_flash_ctrl *fctrl);
-int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
- bool regulator_enable);
-void cam_flash_shutdown(struct cam_flash_ctrl *flash_ctrl);
-int cam_flash_stop_dev(struct cam_flash_ctrl *flash_ctrl);
-int cam_flash_release_dev(struct cam_flash_ctrl *fctrl);
+
+
#endif /*_CAM_FLASH_CORE_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
index f8be3de85708..4a6307da01b0 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -15,6 +15,7 @@
#include "cam_flash_dev.h"
#include "cam_flash_soc.h"
#include "cam_flash_core.h"
+#include "cam_common_util.h"
static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
void *arg, struct cam_flash_private_soc *soc_private)
@@ -57,7 +58,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
goto release_mutex;
}
- rc = copy_from_user(&flash_acq_dev, (void __user *)cmd->handle,
+ rc = copy_from_user(&flash_acq_dev,
+ u64_to_user_ptr(cmd->handle),
sizeof(flash_acq_dev));
if (rc) {
CAM_ERR(CAM_FLASH, "Failed Copying from User");
@@ -77,7 +79,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
fctrl->bridge_intf.session_hdl =
flash_acq_dev.session_handle;
- rc = copy_to_user((void __user *) cmd->handle, &flash_acq_dev,
+ rc = copy_to_user(u64_to_user_ptr(cmd->handle),
+ &flash_acq_dev,
sizeof(struct cam_sensor_acquire_dev));
if (rc) {
CAM_ERR(CAM_FLASH, "Failed Copy to User with rc = %d",
@@ -93,7 +96,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) ||
(fctrl->flash_state == CAM_FLASH_STATE_START)) {
CAM_WARN(CAM_FLASH,
- "Cannot apply Release dev: Prev state:%d",
+ "Wrong state for Release dev: Prev state:%d",
fctrl->flash_state);
}
@@ -106,11 +109,18 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
rc = -EINVAL;
goto release_mutex;
}
- rc = cam_flash_release_dev(fctrl);
- if (rc)
- CAM_ERR(CAM_FLASH,
- "Failed in destroying the device Handle rc= %d",
- rc);
+
+ if ((fctrl->flash_state == CAM_FLASH_STATE_CONFIG) ||
+ (fctrl->flash_state == CAM_FLASH_STATE_START))
+ fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
+
+ if (cam_flash_release_dev(fctrl))
+ CAM_WARN(CAM_FLASH,
+ "Failed in destroying the device Handle");
+
+ if (fctrl->func_tbl.power_ops(fctrl, false))
+ CAM_WARN(CAM_FLASH, "Power Down Failed");
+
fctrl->flash_state = CAM_FLASH_STATE_INIT;
break;
}
@@ -130,8 +140,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
flash_cap.max_current_torch[i] =
soc_private->torch_max_current[i];
- if (copy_to_user((void __user *) cmd->handle, &flash_cap,
- sizeof(struct cam_flash_query_cap_info))) {
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
+ &flash_cap, sizeof(struct cam_flash_query_cap_info))) {
CAM_ERR(CAM_FLASH, "Failed Copy to User");
rc = -EFAULT;
goto release_mutex;
@@ -149,15 +159,6 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
goto release_mutex;
}
- if (fctrl->is_regulator_enabled == false) {
- rc = cam_flash_prepare(fctrl, true);
- if (rc) {
- CAM_ERR(CAM_FLASH,
- "Enable Regulator Failed rc = %d", rc);
- goto release_mutex;
- }
- }
-
fctrl->flash_state = CAM_FLASH_STATE_START;
break;
}
@@ -171,18 +172,13 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
goto release_mutex;
}
- rc = cam_flash_stop_dev(fctrl);
- if (rc) {
- CAM_ERR(CAM_FLASH, "Stop Dev Failed rc = %d",
- rc);
- goto release_mutex;
- }
+ fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE;
break;
}
case CAM_CONFIG_DEV: {
CAM_DBG(CAM_FLASH, "CAM_CONFIG_DEV");
- rc = cam_flash_parser(fctrl, arg);
+ rc = fctrl->func_tbl.parser(fctrl, arg);
if (rc) {
CAM_ERR(CAM_FLASH, "Failed Flash Config: rc=%d\n", rc);
goto release_mutex;
@@ -199,6 +195,35 @@ release_mutex:
return rc;
}
+static int32_t cam_flash_init_default_params(struct cam_flash_ctrl *fctrl)
+{
+ /* Validate input parameters */
+ if (!fctrl) {
+ CAM_ERR(CAM_FLASH, "failed: invalid params fctrl %pK",
+ fctrl);
+ return -EINVAL;
+ }
+
+ CAM_DBG(CAM_FLASH,
+ "master_type: %d", fctrl->io_master_info.master_type);
+ /* Initialize cci_client */
+ if (fctrl->io_master_info.master_type == CCI_MASTER) {
+ fctrl->io_master_info.cci_client = kzalloc(sizeof(
+ struct cam_sensor_cci_client), GFP_KERNEL);
+ if (!(fctrl->io_master_info.cci_client))
+ return -ENOMEM;
+ } else if (fctrl->io_master_info.master_type == I2C_MASTER) {
+ if (!(fctrl->io_master_info.client))
+ return -EINVAL;
+ } else {
+ CAM_ERR(CAM_FLASH,
+ "Invalid master / Master type Not supported");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct of_device_id cam_flash_dt_match[] = {
{.compatible = "qcom,camera-flash", .data = NULL},
{}
@@ -289,20 +314,36 @@ static int cam_flash_platform_remove(struct platform_device *pdev)
return 0;
}
+static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client)
+{
+ int32_t rc = 0;
+ struct cam_flash_ctrl *fctrl = i2c_get_clientdata(client);
+ /* Handle I2C Devices */
+ if (!fctrl) {
+ CAM_ERR(CAM_FLASH, "Flash device is NULL");
+ return -EINVAL;
+ }
+ /*Free Allocated Mem */
+ kfree(fctrl->i2c_data.per_frame);
+ fctrl->i2c_data.per_frame = NULL;
+ kfree(fctrl);
+ return rc;
+}
+
static int cam_flash_subdev_close(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
{
- struct cam_flash_ctrl *flash_ctrl =
+ struct cam_flash_ctrl *fctrl =
v4l2_get_subdevdata(sd);
- if (!flash_ctrl) {
+ if (!fctrl) {
CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL");
return -EINVAL;
}
- mutex_lock(&flash_ctrl->flash_mutex);
- cam_flash_shutdown(flash_ctrl);
- mutex_unlock(&flash_ctrl->flash_mutex);
+ mutex_lock(&fctrl->flash_mutex);
+ cam_flash_shutdown(fctrl);
+ mutex_unlock(&fctrl->flash_mutex);
return 0;
}
@@ -322,10 +363,30 @@ static const struct v4l2_subdev_internal_ops cam_flash_internal_ops = {
.close = cam_flash_subdev_close,
};
+static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl)
+{
+ int rc = 0;
+
+ fctrl->v4l2_dev_str.internal_ops =
+ &cam_flash_internal_ops;
+ fctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops;
+ fctrl->v4l2_dev_str.name = CAMX_FLASH_DEV_NAME;
+ fctrl->v4l2_dev_str.sd_flags =
+ V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+ fctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE;
+ fctrl->v4l2_dev_str.token = fctrl;
+
+ rc = cam_register_subdev(&(fctrl->v4l2_dev_str));
+ if (rc)
+ CAM_ERR(CAM_FLASH, "Fail to create subdev with %d", rc);
+
+ return rc;
+}
+
static int32_t cam_flash_platform_probe(struct platform_device *pdev)
{
- int32_t rc = 0;
- struct cam_flash_ctrl *flash_ctrl = NULL;
+ int32_t rc = 0, i = 0;
+ struct cam_flash_ctrl *fctrl = NULL;
CAM_DBG(CAM_FLASH, "Enter");
if (!pdev->dev.of_node) {
@@ -333,53 +394,181 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
return -EINVAL;
}
- flash_ctrl = kzalloc(sizeof(struct cam_flash_ctrl), GFP_KERNEL);
- if (!flash_ctrl)
+ fctrl = kzalloc(sizeof(struct cam_flash_ctrl), GFP_KERNEL);
+ if (!fctrl)
return -ENOMEM;
- flash_ctrl->pdev = pdev;
- flash_ctrl->soc_info.pdev = pdev;
- flash_ctrl->soc_info.dev = &pdev->dev;
- flash_ctrl->soc_info.dev_name = pdev->name;
+ fctrl->pdev = pdev;
+ fctrl->soc_info.pdev = pdev;
+ fctrl->soc_info.dev = &pdev->dev;
+ fctrl->soc_info.dev_name = pdev->name;
+
+ platform_set_drvdata(pdev, fctrl);
- rc = cam_flash_get_dt_data(flash_ctrl, &flash_ctrl->soc_info);
+ rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info);
if (rc) {
CAM_ERR(CAM_FLASH, "cam_flash_get_dt_data failed with %d", rc);
- kfree(flash_ctrl);
+ kfree(fctrl);
return -EINVAL;
}
- flash_ctrl->v4l2_dev_str.internal_ops =
- &cam_flash_internal_ops;
- flash_ctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops;
- flash_ctrl->v4l2_dev_str.name = CAMX_FLASH_DEV_NAME;
- flash_ctrl->v4l2_dev_str.sd_flags =
- V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
- flash_ctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE;
- flash_ctrl->v4l2_dev_str.token = flash_ctrl;
+ if (of_find_property(pdev->dev.of_node, "cci-master", NULL)) {
+ /* Get CCI master */
+ rc = of_property_read_u32(pdev->dev.of_node, "cci-master",
+ &fctrl->cci_i2c_master);
+ CAM_DBG(CAM_FLASH, "cci-master %d, rc %d",
+ fctrl->cci_i2c_master, rc);
+ if (rc < 0) {
+ /* Set default master 0 */
+ fctrl->cci_i2c_master = MASTER_0;
+ rc = 0;
+ }
+
+ fctrl->io_master_info.master_type = CCI_MASTER;
+ rc = cam_flash_init_default_params(fctrl);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "failed: cam_flash_init_default_params rc %d",
+ rc);
+ return rc;
+ }
- rc = cam_register_subdev(&(flash_ctrl->v4l2_dev_str));
+ fctrl->i2c_data.per_frame = (struct i2c_settings_array *)
+ kzalloc(sizeof(struct i2c_settings_array) *
+ MAX_PER_FRAME_ARRAY, GFP_KERNEL);
+ if (fctrl->i2c_data.per_frame == NULL) {
+ CAM_ERR(CAM_FLASH, "No Memory");
+ rc = -ENOMEM;
+ goto free_cci_resource;
+ }
+
+ INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head));
+ INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head));
+ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++)
+ INIT_LIST_HEAD(
+ &(fctrl->i2c_data.per_frame[i].list_head));
+
+ fctrl->func_tbl.parser = cam_flash_i2c_pkt_parser;
+ fctrl->func_tbl.apply_setting = cam_flash_i2c_apply_setting;
+ fctrl->func_tbl.power_ops = cam_flash_i2c_power_ops;
+ fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request;
+ } else {
+ /* PMIC Flash */
+ fctrl->func_tbl.parser = cam_flash_pmic_pkt_parser;
+ fctrl->func_tbl.apply_setting = cam_flash_pmic_apply_setting;
+ fctrl->func_tbl.power_ops = cam_flash_pmic_power_ops;
+ fctrl->func_tbl.flush_req = cam_flash_pmic_flush_request;
+ }
+
+ rc = cam_flash_init_subdev(fctrl);
if (rc) {
- CAM_ERR(CAM_FLASH, "Fail to create subdev with %d", rc);
- goto free_resource;
+ if (fctrl->io_master_info.cci_client != NULL)
+ goto free_cci_resource;
+ else
+ goto free_resource;
}
- flash_ctrl->bridge_intf.device_hdl = -1;
- flash_ctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info;
- flash_ctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
- flash_ctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
- flash_ctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
- platform_set_drvdata(pdev, flash_ctrl);
- v4l2_set_subdevdata(&flash_ctrl->v4l2_dev_str.sd, flash_ctrl);
+ fctrl->bridge_intf.device_hdl = -1;
+ fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info;
+ fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
+ fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
+ fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
- mutex_init(&(flash_ctrl->flash_mutex));
- mutex_init(&(flash_ctrl->flash_wq_mutex));
+ mutex_init(&(fctrl->flash_mutex));
- flash_ctrl->flash_state = CAM_FLASH_STATE_INIT;
+ fctrl->flash_state = CAM_FLASH_STATE_INIT;
CAM_DBG(CAM_FLASH, "Probe success");
return rc;
+
+free_cci_resource:
+ kfree(fctrl->io_master_info.cci_client);
+ fctrl->io_master_info.cci_client = NULL;
free_resource:
- kfree(flash_ctrl);
+ kfree(fctrl->i2c_data.per_frame);
+ kfree(fctrl->soc_info.soc_private);
+ cam_soc_util_release_platform_resource(&fctrl->soc_info);
+ fctrl->i2c_data.per_frame = NULL;
+ fctrl->soc_info.soc_private = NULL;
+ kfree(fctrl);
+ fctrl = NULL;
+ return rc;
+}
+
+static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int32_t rc = 0, i = 0;
+ struct cam_flash_ctrl *fctrl;
+
+ if (client == NULL || id == NULL) {
+ CAM_ERR(CAM_FLASH, "Invalid Args client: %pK id: %pK",
+ client, id);
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed",
+ client->name);
+ return -EFAULT;
+ }
+
+ /* Create sensor control structure */
+ fctrl = kzalloc(sizeof(*fctrl), GFP_KERNEL);
+ if (!fctrl)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, fctrl);
+
+ fctrl->io_master_info.client = client;
+ fctrl->soc_info.dev = &client->dev;
+ fctrl->soc_info.dev_name = client->name;
+ fctrl->io_master_info.master_type = I2C_MASTER;
+
+ rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "failed: cam_sensor_parse_dt rc %d", rc);
+ goto free_ctrl;
+ }
+
+ rc = cam_flash_init_subdev(fctrl);
+ if (rc)
+ goto free_ctrl;
+
+ fctrl->i2c_data.per_frame =
+ (struct i2c_settings_array *)
+ kzalloc(sizeof(struct i2c_settings_array) *
+ MAX_PER_FRAME_ARRAY, GFP_KERNEL);
+ if (fctrl->i2c_data.per_frame == NULL) {
+ rc = -ENOMEM;
+ goto unreg_subdev;
+ }
+
+ INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head));
+ INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head));
+ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++)
+ INIT_LIST_HEAD(&(fctrl->i2c_data.per_frame[i].list_head));
+
+ fctrl->func_tbl.parser = cam_flash_i2c_pkt_parser;
+ fctrl->func_tbl.apply_setting = cam_flash_i2c_apply_setting;
+ fctrl->func_tbl.power_ops = cam_flash_i2c_power_ops;
+ fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request;
+
+ fctrl->bridge_intf.device_hdl = -1;
+ fctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info;
+ fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
+ fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
+ fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
+
+ mutex_init(&(fctrl->flash_mutex));
+ fctrl->flash_state = CAM_FLASH_STATE_INIT;
+
+ return rc;
+
+unreg_subdev:
+ cam_unregister_subdev(&(fctrl->v4l2_dev_str));
+free_ctrl:
+ kfree(fctrl);
+ fctrl = NULL;
return rc;
}
@@ -396,20 +585,40 @@ static struct platform_driver cam_flash_platform_driver = {
},
};
-static int __init cam_flash_init_module(void)
+static const struct i2c_device_id i2c_id[] = {
+ {FLASH_DRIVER_I2C, (kernel_ulong_t)NULL},
+ { }
+};
+
+static struct i2c_driver cam_flash_i2c_driver = {
+ .id_table = i2c_id,
+ .probe = cam_flash_i2c_driver_probe,
+ .remove = cam_flash_i2c_driver_remove,
+ .driver = {
+ .name = FLASH_DRIVER_I2C,
+ },
+};
+
+static int32_t __init cam_flash_init_module(void)
{
int32_t rc = 0;
rc = platform_driver_register(&cam_flash_platform_driver);
- if (rc)
- CAM_ERR(CAM_FLASH, "platform probe for flash failed");
+ if (rc == 0) {
+ CAM_DBG(CAM_FLASH, "platform probe success");
+ return 0;
+ }
+ rc = i2c_add_driver(&cam_flash_i2c_driver);
+ if (rc)
+ CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc);
return rc;
}
static void __exit cam_flash_exit_module(void)
{
platform_driver_unregister(&cam_flash_platform_driver);
+ i2c_del_driver(&cam_flash_i2c_driver);
}
module_init(cam_flash_init_module);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
index 4adc1b2e32a9..cb542395df38 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
@@ -33,15 +33,21 @@
#include "cam_sensor_cmn_header.h"
#include "cam_soc_util.h"
#include "cam_debug_util.h"
+#include "cam_sensor_io.h"
+#include "cam_flash_core.h"
#define CAMX_FLASH_DEV_NAME "cam-flash-dev"
#define CAM_FLASH_PIPELINE_DELAY 1
+#define FLASH_DRIVER_I2C "i2c_flash"
+
#define CAM_FLASH_PACKET_OPCODE_INIT 0
#define CAM_FLASH_PACKET_OPCODE_SET_OPS 1
#define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2
+struct cam_flash_ctrl;
+
enum cam_flash_switch_trigger_ops {
LED_SWITCH_OFF = 0,
LED_SWITCH_ON,
@@ -54,6 +60,12 @@ enum cam_flash_state {
CAM_FLASH_STATE_START,
};
+enum cam_flash_flush_type {
+ FLUSH_ALL = 0,
+ FLUSH_REQ,
+ FLUSH_MAX,
+};
+
/**
* struct cam_flash_intf_params
* @device_hdl : Device Handle
@@ -136,6 +148,14 @@ struct cam_flash_private_soc {
uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
};
+struct cam_flash_func_tbl {
+ int (*parser)(struct cam_flash_ctrl *fctrl, void *arg);
+ int (*apply_setting)(struct cam_flash_ctrl *fctrl, uint64_t req_id);
+ int (*power_ops)(struct cam_flash_ctrl *fctrl, bool regulator_enable);
+ int (*flush_req)(struct cam_flash_ctrl *fctrl,
+ enum cam_flash_flush_type type, uint64_t req_id);
+};
+
/**
* struct cam_flash_ctrl
* @soc_info : Soc related information
@@ -150,32 +170,57 @@ struct cam_flash_private_soc {
* @flash_num_sources : Number of flash sources
* @torch_num_source : Number of torch sources
* @flash_mutex : Mutex for flash operations
- * @flash_wq_mutex : Mutex for flash apply setting
- * @flash_state : Current flash state (LOW/OFF/ON/INIT)
+ * @flash_state : Current flash state (LOW/OFF/ON/INIT)
* @flash_type : Flash types (PMIC/I2C/GPIO)
* @is_regulator_enable : Regulator disable/enable notifier
+ * @func_tbl : Function table for different HW
+ * (e.g. i2c/pmic/gpio)
* @flash_trigger : Flash trigger ptr
* @torch_trigger : Torch trigger ptr
+ * @cci_i2c_master : I2C structure
+ * @io_master_info : Information about the communication master
+ * @i2c_data : I2C register settings
*/
struct cam_flash_ctrl {
- struct cam_hw_soc_info soc_info;
- struct platform_device *pdev;
- struct cam_flash_frame_setting per_frame[MAX_PER_FRAME_ARRAY];
- struct cam_flash_frame_setting nrt_info;
- struct device_node *of_node;
- struct cam_subdev v4l2_dev_str;
- struct cam_flash_intf_params bridge_intf;
- struct cam_flash_init_packet flash_init_setting;
- struct led_trigger *switch_trigger;
- uint32_t flash_num_sources;
- uint32_t torch_num_sources;
- struct mutex flash_mutex;
- struct mutex flash_wq_mutex;
- enum cam_flash_state flash_state;
- uint8_t flash_type;
- bool is_regulator_enabled;
+ struct cam_hw_soc_info soc_info;
+ struct platform_device *pdev;
+ struct cam_sensor_power_ctrl_t power_info;
+ struct cam_flash_frame_setting per_frame[MAX_PER_FRAME_ARRAY];
+ struct cam_flash_frame_setting nrt_info;
+ struct device_node *of_node;
+ struct cam_subdev v4l2_dev_str;
+ struct cam_flash_intf_params bridge_intf;
+ struct cam_flash_init_packet flash_init_setting;
+ struct led_trigger *switch_trigger;
+ uint32_t flash_num_sources;
+ uint32_t torch_num_sources;
+ struct mutex flash_mutex;
+ enum cam_flash_state flash_state;
+ uint8_t flash_type;
+ bool is_regulator_enabled;
+ struct cam_flash_func_tbl func_tbl;
struct led_trigger *flash_trigger[CAM_FLASH_MAX_LED_TRIGGERS];
struct led_trigger *torch_trigger[CAM_FLASH_MAX_LED_TRIGGERS];
+/* I2C related setting */
+ enum cci_i2c_master_t cci_i2c_master;
+ struct camera_io_master io_master_info;
+ struct i2c_data_settings i2c_data;
};
+int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);
+int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);
+int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id);
+int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id);
+int cam_flash_off(struct cam_flash_ctrl *fctrl);
+int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl,
+ bool regulator_enable);
+int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl,
+ bool regulator_enable);
+int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl,
+ enum cam_flash_flush_type type, uint64_t req_id);
+int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
+ enum cam_flash_flush_type, uint64_t req_id);
+void cam_flash_shutdown(struct cam_flash_ctrl *fctrl);
+int cam_flash_release_dev(struct cam_flash_ctrl *fctrl);
+
#endif /*_CAM_FLASH_DEV_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c
index a195762c249f..22a124d86f93 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -193,32 +193,31 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl,
return -EINVAL;
}
- of_node = fctrl->pdev->dev.of_node;
-
- rc = cam_soc_util_get_dt_properties(soc_info);
- if (rc < 0) {
- CAM_ERR(CAM_FLASH, "Get_dt_properties failed rc %d", rc);
- return rc;
- }
-
soc_info->soc_private =
kzalloc(sizeof(struct cam_flash_private_soc), GFP_KERNEL);
if (!soc_info->soc_private) {
rc = -ENOMEM;
goto release_soc_res;
}
+ of_node = fctrl->pdev->dev.of_node;
+
+ rc = cam_soc_util_get_dt_properties(soc_info);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Get_dt_properties failed rc %d", rc);
+ goto free_soc_private;
+ }
rc = cam_get_source_node_info(of_node, fctrl, soc_info->soc_private);
- if (rc < 0) {
+ if (rc) {
CAM_ERR(CAM_FLASH,
"cam_flash_get_pmic_source_info failed rc %d", rc);
goto free_soc_private;
}
-
return rc;
free_soc_private:
kfree(soc_info->soc_private);
+ soc_info->soc_private = NULL;
release_soc_res:
cam_soc_util_release_platform_resource(soc_info);
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
index 05706556d9db..850b315c26a7 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -18,6 +18,7 @@
#include "cam_sensor_util.h"
#include "cam_debug_util.h"
#include "cam_res_mgr_api.h"
+#include "cam_common_util.h"
int32_t cam_ois_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -79,7 +80,7 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl,
CAM_ERR(CAM_OIS, "Device is already acquired");
return -EFAULT;
}
- if (copy_from_user(&ois_acq_dev, (void __user *) cmd->handle,
+ if (copy_from_user(&ois_acq_dev, u64_to_user_ptr(cmd->handle),
sizeof(ois_acq_dev)))
return -EFAULT;
@@ -95,7 +96,7 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl,
o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle;
CAM_DBG(CAM_OIS, "Device Handle: %d", ois_acq_dev.device_handle);
- if (copy_to_user((void __user *) cmd->handle, &ois_acq_dev,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle), &ois_acq_dev,
sizeof(struct cam_sensor_acquire_dev))) {
CAM_ERR(CAM_OIS, "ACQUIRE_DEV: copy to user failed");
return -EFAULT;
@@ -193,7 +194,7 @@ static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl)
return -EINVAL;
}
- rc = msm_camera_power_down(power_info, soc_info);
+ rc = cam_sensor_util_power_down(power_info, soc_info);
if (rc) {
CAM_ERR(CAM_OIS, "power down the core is failed:%d", rc);
return rc;
@@ -425,12 +426,12 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
int32_t i = 0;
uint32_t total_cmd_buf_in_bytes = 0;
struct common_header *cmm_hdr = NULL;
- uint64_t generic_ptr;
+ uintptr_t generic_ptr;
struct cam_control *ioctl_ctrl = NULL;
struct cam_config_dev_cmd dev_config;
struct i2c_settings_array *i2c_reg_settings = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
- uint64_t generic_pkt_addr;
+ uintptr_t generic_pkt_addr;
size_t pkt_len;
struct cam_packet *csl_packet = NULL;
size_t len_of_buff = 0;
@@ -440,11 +441,12 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
ioctl_ctrl = (struct cam_control *)arg;
- if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
+ if (copy_from_user(&dev_config,
+ u64_to_user_ptr(ioctl_ctrl->handle),
sizeof(dev_config)))
return -EFAULT;
rc = cam_mem_get_cpu_buf(dev_config.packet_handle,
- (uint64_t *)&generic_pkt_addr, &pkt_len);
+ &generic_pkt_addr, &pkt_len);
if (rc) {
CAM_ERR(CAM_OIS,
"error in converting command Handle Error: %d", rc);
@@ -459,7 +461,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
}
csl_packet = (struct cam_packet *)
- (generic_pkt_addr + dev_config.offset);
+ (generic_pkt_addr + (uint32_t)dev_config.offset);
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_OIS_PACKET_OPCODE_INIT:
offset = (uint32_t *)&csl_packet->payload;
@@ -473,7 +475,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
continue;
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
- (uint64_t *)&generic_ptr, &len_of_buff);
+ &generic_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_OIS, "Failed to get cpu buf");
return rc;
@@ -716,7 +718,7 @@ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg)
case CAM_QUERY_CAP:
ois_cap.slot_info = o_ctrl->soc_info.index;
- if (copy_to_user((void __user *) cmd->handle,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
&ois_cap,
sizeof(struct cam_ois_query_cap_t))) {
CAM_ERR(CAM_OIS, "Failed Copy to User");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index a2431be71176..c88e96980ff9 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -16,6 +16,7 @@
#include "cam_sensor_util.h"
#include "cam_soc_util.h"
#include "cam_trace.h"
+#include "cam_common_util.h"
static void cam_sensor_update_req_mgr(
struct cam_sensor_ctrl_t *s_ctrl,
@@ -62,30 +63,12 @@ static void cam_sensor_release_stream_rsc(
}
}
-static void cam_sensor_release_resource(
+static void cam_sensor_release_per_frame_resource(
struct cam_sensor_ctrl_t *s_ctrl)
{
struct i2c_settings_array *i2c_set = NULL;
int i, rc;
- i2c_set = &(s_ctrl->i2c_data.init_settings);
- if (i2c_set->is_settings_valid == 1) {
- i2c_set->is_settings_valid = -1;
- rc = delete_request(i2c_set);
- if (rc < 0)
- CAM_ERR(CAM_SENSOR,
- "failed while deleting Init settings");
- }
-
- i2c_set = &(s_ctrl->i2c_data.config_settings);
- if (i2c_set->is_settings_valid == 1) {
- i2c_set->is_settings_valid = -1;
- rc = delete_request(i2c_set);
- if (rc < 0)
- CAM_ERR(CAM_SENSOR,
- "failed while deleting Res settings");
- }
-
if (s_ctrl->i2c_data.per_frame != NULL) {
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
i2c_set = &(s_ctrl->i2c_data.per_frame[i]);
@@ -105,7 +88,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
void *arg)
{
int32_t rc = 0;
- uint64_t generic_ptr;
+ uintptr_t generic_ptr;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
@@ -122,13 +105,14 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
return -EINVAL;
}
- if (copy_from_user(&config, (void __user *) ioctl_ctrl->handle,
+ if (copy_from_user(&config,
+ u64_to_user_ptr(ioctl_ctrl->handle),
sizeof(config)))
return -EFAULT;
rc = cam_mem_get_cpu_buf(
config.packet_handle,
- (uint64_t *)&generic_ptr,
+ &generic_ptr,
&len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Failed in getting the buffer: %d", rc);
@@ -136,7 +120,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
}
csl_packet = (struct cam_packet *)(generic_ptr +
- config.offset);
+ (uint32_t)config.offset);
if (config.offset > len_of_buff) {
CAM_ERR(CAM_SENSOR,
"offset is out of bounds: off: %lld len: %zu",
@@ -403,15 +387,16 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
{
int rc = 0, i;
- void *packet = NULL, *cmd_buf1 = NULL;
uint32_t *cmd_buf;
void *ptr;
size_t len;
struct cam_packet *pkt;
struct cam_cmd_buf_desc *cmd_desc;
+ uintptr_t cmd_buf1 = 0;
+ uintptr_t packet = 0;
rc = cam_mem_get_cpu_buf(handle,
- (uint64_t *)&packet, &len);
+ &packet, &len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Failed to get the command Buffer");
return -EINVAL;
@@ -432,7 +417,7 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
if (!(cmd_desc[i].length))
continue;
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
- (uint64_t *)&cmd_buf1, &len);
+ &cmd_buf1, &len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed to parse the command Buffer Header");
@@ -503,10 +488,9 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl)
(s_ctrl->is_probe_succeed == 0))
return;
- cam_sensor_release_resource(s_ctrl);
cam_sensor_release_stream_rsc(s_ctrl);
- if (s_ctrl->sensor_state >= CAM_SENSOR_ACQUIRE)
- cam_sensor_power_down(s_ctrl);
+ cam_sensor_release_per_frame_resource(s_ctrl);
+ cam_sensor_power_down(s_ctrl);
rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl);
if (rc < 0)
@@ -676,7 +660,8 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
goto release_mutex;
}
rc = copy_from_user(&sensor_acq_dev,
- (void __user *) cmd->handle, sizeof(sensor_acq_dev));
+ u64_to_user_ptr(cmd->handle),
+ sizeof(sensor_acq_dev));
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Failed Copying from user");
goto release_mutex;
@@ -695,7 +680,8 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
CAM_DBG(CAM_SENSOR, "Device Handle: %d",
sensor_acq_dev.device_handle);
- if (copy_to_user((void __user *) cmd->handle, &sensor_acq_dev,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
+ &sensor_acq_dev,
sizeof(struct cam_sensor_acquire_dev))) {
CAM_ERR(CAM_SENSOR, "Failed Copy to User");
rc = -EFAULT;
@@ -731,7 +717,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
goto release_mutex;
}
- cam_sensor_release_resource(s_ctrl);
+ cam_sensor_release_per_frame_resource(s_ctrl);
cam_sensor_release_stream_rsc(s_ctrl);
if (s_ctrl->bridge_intf.device_hdl == -1) {
CAM_ERR(CAM_SENSOR,
@@ -762,8 +748,8 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
struct cam_sensor_query_cap sensor_cap;
cam_sensor_query_cap(s_ctrl, &sensor_cap);
- if (copy_to_user((void __user *) cmd->handle, &sensor_cap,
- sizeof(struct cam_sensor_query_cap))) {
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
+ &sensor_cap, sizeof(struct cam_sensor_query_cap))) {
CAM_ERR(CAM_SENSOR, "Failed Copy to User");
rc = -EFAULT;
goto release_mutex;
@@ -816,7 +802,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
}
}
- cam_sensor_release_resource(s_ctrl);
+ cam_sensor_release_per_frame_resource(s_ctrl);
s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE;
CAM_INFO(CAM_SENSOR,
"CAM_STOP_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x",
@@ -918,6 +904,8 @@ int cam_sensor_establish_link(struct cam_req_mgr_core_dev_link_setup *link)
CAM_ERR(CAM_SENSOR, "Device data is NULL");
return -EINVAL;
}
+
+ mutex_lock(&s_ctrl->cam_sensor_mutex);
if (link->link_enable) {
s_ctrl->bridge_intf.link_hdl = link->link_hdl;
s_ctrl->bridge_intf.crm_cb = link->crm_cb;
@@ -925,6 +913,7 @@ int cam_sensor_establish_link(struct cam_req_mgr_core_dev_link_setup *link)
s_ctrl->bridge_intf.link_hdl = -1;
s_ctrl->bridge_intf.crm_cb = NULL;
}
+ mutex_unlock(&s_ctrl->cam_sensor_mutex);
return 0;
}
@@ -1005,7 +994,7 @@ int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl)
CAM_ERR(CAM_SENSOR, "failed: power_info %pK", power_info);
return -EINVAL;
}
- rc = msm_camera_power_down(power_info, soc_info);
+ rc = cam_sensor_util_power_down(power_info, soc_info);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "power down the core is failed:%d", rc);
return rc;
@@ -1155,8 +1144,10 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply)
}
CAM_DBG(CAM_REQ, " Sensor update req id: %lld", apply->request_id);
trace_cam_apply_req("Sensor", apply->request_id);
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
rc = cam_sensor_apply_settings(s_ctrl, apply->request_id,
CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE);
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
return rc;
}
@@ -1190,7 +1181,9 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req)
continue;
if (i2c_set->is_settings_valid == 1) {
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
rc = delete_request(i2c_set);
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
if (rc < 0)
CAM_ERR(CAM_SENSOR,
"delete request: %lld rc: %d",
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index 46bda0589c52..5c1143ece162 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -296,7 +296,7 @@ int cam_sensor_i2c_command_parser(
{
int16_t rc = 0, i = 0;
size_t len_of_buff = 0;
- uint64_t generic_ptr;
+ uintptr_t generic_ptr;
uint16_t cmd_length_in_bytes = 0;
for (i = 0; i < num_cmd_buffers; i++) {
@@ -318,11 +318,11 @@ int cam_sensor_i2c_command_parser(
continue;
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
- (uint64_t *)&generic_ptr, &len_of_buff);
+ &generic_ptr, &len_of_buff);
cmd_buf = (uint32_t *)generic_ptr;
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
- "cmd hdl failed:%d, Err: %d, Buffer_len: %ld",
+ "cmd hdl failed:%d, Err: %d, Buffer_len: %zd",
cmd_desc[i].mem_handle, rc, len_of_buff);
return rc;
}
@@ -439,6 +439,75 @@ int cam_sensor_i2c_command_parser(
return rc;
}
+int cam_sensor_util_i2c_apply_setting(
+ struct camera_io_master *io_master_info,
+ struct i2c_settings_list *i2c_list)
+{
+ int32_t rc = 0;
+ uint32_t i, size;
+
+ switch (i2c_list->op_code) {
+ case CAM_SENSOR_I2C_WRITE_RANDOM: {
+ rc = camera_io_dev_write(io_master_info,
+ &(i2c_list->i2c_settings));
+ if (rc < 0) {
+ CAM_ERR(CAM_SENSOR,
+ "Failed to random write I2C settings: %d",
+ rc);
+ return rc;
+ }
+ break;
+ }
+ case CAM_SENSOR_I2C_WRITE_SEQ: {
+ rc = camera_io_dev_write_continuous(
+ io_master_info, &(i2c_list->i2c_settings), 0);
+ if (rc < 0) {
+ CAM_ERR(CAM_SENSOR,
+ "Failed to seq write I2C settings: %d",
+ rc);
+ return rc;
+ }
+ break;
+ }
+ case CAM_SENSOR_I2C_WRITE_BURST: {
+ rc = camera_io_dev_write_continuous(
+ io_master_info, &(i2c_list->i2c_settings), 1);
+ if (rc < 0) {
+ CAM_ERR(CAM_SENSOR,
+ "Failed to burst write I2C settings: %d",
+ rc);
+ return rc;
+ }
+ break;
+ }
+ case CAM_SENSOR_I2C_POLL: {
+ size = i2c_list->i2c_settings.size;
+ for (i = 0; i < size; i++) {
+ rc = camera_io_dev_poll(
+ io_master_info,
+ i2c_list->i2c_settings.reg_setting[i].reg_addr,
+ i2c_list->i2c_settings.reg_setting[i].reg_data,
+ i2c_list->i2c_settings.reg_setting[i].data_mask,
+ i2c_list->i2c_settings.addr_type,
+ i2c_list->i2c_settings.data_type,
+ i2c_list->i2c_settings.reg_setting[i].delay);
+ if (rc < 0) {
+ CAM_ERR(CAM_SENSOR,
+ "i2c poll apply setting Fail: %d", rc);
+ return rc;
+ }
+ }
+ break;
+ }
+ default:
+ CAM_ERR(CAM_SENSOR, "Wrong Opcode: %d", i2c_list->op_code);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
int32_t msm_camera_fill_vreg_params(
struct cam_hw_soc_info *soc_info,
struct cam_sensor_power_setting *power_setting,
@@ -1710,7 +1779,7 @@ msm_camera_get_power_settings(struct cam_sensor_power_ctrl_t *ctrl,
return ps;
}
-int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl,
+int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
struct cam_hw_soc_info *soc_info)
{
int index = 0, ret = 0, num_vreg = 0, i;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
index 6c0287e48487..583ddb14243b 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
@@ -39,6 +39,9 @@ int cam_sensor_i2c_command_parser(struct camera_io_master *io_master,
struct i2c_settings_array *i2c_reg_settings,
struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers);
+int cam_sensor_util_i2c_apply_setting(struct camera_io_master *io_master_info,
+ struct i2c_settings_list *i2c_list);
+
int32_t delete_request(struct i2c_settings_array *i2c_array);
int cam_sensor_util_request_gpio_table(
struct cam_hw_soc_info *soc_info, int gpio_en);
@@ -49,7 +52,7 @@ int cam_sensor_util_init_gpio_pin_tbl(
int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
struct cam_hw_soc_info *soc_info);
-int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl,
+int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
struct cam_hw_soc_info *soc_info);
int msm_camera_fill_vreg_params(struct cam_hw_soc_info *soc_info,
diff --git a/drivers/media/platform/msm/camera/cam_smmu/Makefile b/drivers/media/platform/msm/camera/cam_smmu/Makefile
index e17dac6c0d9d..96f39680fd0c 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/Makefile
+++ b/drivers/media/platform/msm/camera/cam_smmu/Makefile
@@ -1,3 +1,4 @@
ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
obj-$(CONFIG_SPECTRA_CAMERA) += cam_smmu_api.o
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
index 52da37f8239b..56209c67255e 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
@@ -23,6 +23,7 @@
#include <linux/genalloc.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/secure_buffer.h>
+#include <uapi/media/cam_req_mgr.h>
#include "cam_smmu_api.h"
#include "cam_debug_util.h"
@@ -34,11 +35,14 @@
#define COOKIE_SIZE (BYTE_SIZE*COOKIE_NUM_BYTE)
#define COOKIE_MASK ((1<<COOKIE_SIZE)-1)
#define HANDLE_INIT (-1)
-#define CAM_SMMU_CB_MAX 2
+#define CAM_SMMU_CB_MAX 5
#define GET_SMMU_HDL(x, y) (((x) << COOKIE_SIZE) | ((y) & COOKIE_MASK))
#define GET_SMMU_TABLE_IDX(x) (((x) >> COOKIE_SIZE) & COOKIE_MASK)
+static int g_num_pf_handled = 4;
+module_param(g_num_pf_handled, int, 0644);
+
struct firmware_alloc_info {
struct device *fw_dev;
void *fw_kva;
@@ -129,12 +133,11 @@ struct cam_context_bank_info {
int handle;
enum cam_smmu_ops_param state;
- void (*handler[CAM_SMMU_CB_MAX])(struct iommu_domain *,
- struct device *, unsigned long,
- int, void*);
+ cam_smmu_client_page_fault_handler handler[CAM_SMMU_CB_MAX];
void *token[CAM_SMMU_CB_MAX];
int cb_count;
int secure_count;
+ int pf_count;
};
struct cam_iommu_cb_set {
@@ -252,13 +255,14 @@ static void cam_smmu_print_table(void);
static int cam_smmu_probe(struct platform_device *pdev);
-static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr);
+static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr);
static void cam_smmu_page_fault_work(struct work_struct *work)
{
int j;
int idx;
struct cam_smmu_work_payload *payload;
+ uint32_t buf_info;
mutex_lock(&iommu_cb_set.payload_list_lock);
if (list_empty(&iommu_cb_set.payload_list)) {
@@ -275,8 +279,11 @@ static void cam_smmu_page_fault_work(struct work_struct *work)
/* Dereference the payload to call the handler */
idx = payload->idx;
- mutex_lock(&iommu_cb_set.cb_info[idx].lock);
- cam_smmu_check_vaddr_in_range(idx, (void *)payload->iova);
+ buf_info = cam_smmu_find_closest_mapping(idx, (void *)payload->iova);
+ if (buf_info != 0) {
+ CAM_INFO(CAM_SMMU, "closest buf 0x%x idx %d", buf_info, idx);
+ }
+
for (j = 0; j < CAM_SMMU_CB_MAX; j++) {
if ((iommu_cb_set.cb_info[idx].handler[j])) {
iommu_cb_set.cb_info[idx].handler[j](
@@ -284,10 +291,10 @@ static void cam_smmu_page_fault_work(struct work_struct *work)
payload->dev,
payload->iova,
payload->flags,
- iommu_cb_set.cb_info[idx].token[j]);
+ iommu_cb_set.cb_info[idx].token[j],
+ buf_info);
}
}
- mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
kfree(payload);
}
@@ -333,10 +340,13 @@ static void cam_smmu_print_table(void)
}
}
-static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr)
+static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr)
{
- struct cam_dma_buff_info *mapping;
+ struct cam_dma_buff_info *mapping, *closest_mapping = NULL;
unsigned long start_addr, end_addr, current_addr;
+ uint32_t buf_handle = 0;
+
+ long delta = 0, lowest_delta = 0;
current_addr = (unsigned long)vaddr;
list_for_each_entry(mapping,
@@ -344,31 +354,51 @@ static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr)
start_addr = (unsigned long)mapping->paddr;
end_addr = (unsigned long)mapping->paddr + mapping->len;
- if (start_addr <= current_addr && current_addr < end_addr) {
- CAM_ERR(CAM_SMMU,
- "va %pK valid: range:%pK-%pK, fd = %d cb: %s",
- vaddr, (void *)start_addr, (void *)end_addr,
- mapping->ion_fd,
+ if (start_addr <= current_addr && current_addr <= end_addr) {
+ closest_mapping = mapping;
+ CAM_INFO(CAM_SMMU,
+ "Found va 0x%lx in:0x%lx-0x%lx, fd %d cb:%s",
+ current_addr, start_addr,
+ end_addr, mapping->ion_fd,
iommu_cb_set.cb_info[idx].name);
goto end;
} else {
+ if (start_addr > current_addr)
+ delta = start_addr - current_addr;
+ else
+ delta = current_addr - end_addr - 1;
+
+ if (delta < lowest_delta || lowest_delta == 0) {
+ lowest_delta = delta;
+ closest_mapping = mapping;
+ }
CAM_DBG(CAM_SMMU,
- "va %pK is not in this range: %pK-%pK, fd = %d",
- vaddr, (void *)start_addr, (void *)end_addr,
- mapping->ion_fd);
+ "approx va %lx not in range: %lx-%lx fd = %0x",
+ current_addr, start_addr,
+ end_addr, mapping->ion_fd);
}
}
- CAM_ERR(CAM_SMMU,
- "Cannot find vaddr:%pK in SMMU %s uses invalid virt address",
- vaddr, iommu_cb_set.cb_info[idx].name);
-end:
- return;
-}
-void cam_smmu_reg_client_page_fault_handler(int handle,
- void (*client_page_fault_handler)(struct iommu_domain *,
- struct device *, unsigned long,
- int, void*), void *token)
+end:
+ if (closest_mapping) {
+ buf_handle = GET_MEM_HANDLE(idx, closest_mapping->ion_fd);
+ CAM_INFO(CAM_SMMU,
+ "Closest map fd %d 0x%lx 0x%lx-0x%lx buf=%pK mem %0x",
+ closest_mapping->ion_fd, current_addr,
+ (unsigned long)closest_mapping->paddr,
+ (unsigned long)closest_mapping->paddr + mapping->len,
+ closest_mapping->buf,
+ buf_handle);
+ } else
+ CAM_INFO(CAM_SMMU,
+ "Cannot find vaddr:%lx in SMMU %s virt address",
+ current_addr, iommu_cb_set.cb_info[idx].name);
+
+ return buf_handle;
+}
+
+void cam_smmu_set_client_page_fault_handler(int handle,
+ cam_smmu_client_page_fault_handler handler_cb, void *token)
{
int idx, i = 0;
@@ -394,7 +424,7 @@ void cam_smmu_reg_client_page_fault_handler(int handle,
return;
}
- if (client_page_fault_handler) {
+ if (handler_cb) {
if (iommu_cb_set.cb_info[idx].cb_count == CAM_SMMU_CB_MAX) {
CAM_ERR(CAM_SMMU,
"%s Should not regiester more handlers",
@@ -402,12 +432,14 @@ void cam_smmu_reg_client_page_fault_handler(int handle,
mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
return;
}
+
iommu_cb_set.cb_info[idx].cb_count++;
+
for (i = 0; i < iommu_cb_set.cb_info[idx].cb_count; i++) {
if (iommu_cb_set.cb_info[idx].token[i] == NULL) {
iommu_cb_set.cb_info[idx].token[i] = token;
iommu_cb_set.cb_info[idx].handler[i] =
- client_page_fault_handler;
+ handler_cb;
break;
}
}
@@ -429,6 +461,47 @@ void cam_smmu_reg_client_page_fault_handler(int handle,
mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
}
+void cam_smmu_unset_client_page_fault_handler(int handle, void *token)
+{
+ int idx, i = 0;
+
+ if (!token || (handle == HANDLE_INIT)) {
+ CAM_ERR(CAM_SMMU, "Error: token is NULL or invalid handle");
+ return;
+ }
+
+ idx = GET_SMMU_TABLE_IDX(handle);
+ if (idx < 0 || idx >= iommu_cb_set.cb_num) {
+ CAM_ERR(CAM_SMMU,
+ "Error: handle or index invalid. idx = %d hdl = %x",
+ idx, handle);
+ return;
+ }
+
+ mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ if (iommu_cb_set.cb_info[idx].handle != handle) {
+ CAM_ERR(CAM_SMMU,
+ "Error: hdl is not valid, table_hdl = %x, hdl = %x",
+ iommu_cb_set.cb_info[idx].handle, handle);
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+ return;
+ }
+
+ for (i = 0; i < CAM_SMMU_CB_MAX; i++) {
+ if (iommu_cb_set.cb_info[idx].token[i] == token) {
+ iommu_cb_set.cb_info[idx].token[i] = NULL;
+ iommu_cb_set.cb_info[idx].handler[i] =
+ NULL;
+ iommu_cb_set.cb_info[idx].cb_count--;
+ break;
+ }
+ }
+ if (i == CAM_SMMU_CB_MAX)
+ CAM_ERR(CAM_SMMU, "Error: hdl %x no matching tokens: %s",
+ handle, iommu_cb_set.cb_info[idx].name);
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+}
+
static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain,
struct device *dev, unsigned long iova,
int flags, void *token)
@@ -459,6 +532,13 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain,
return -EINVAL;
}
+ if (++iommu_cb_set.cb_info[idx].pf_count > g_num_pf_handled) {
+ CAM_INFO(CAM_SMMU, "PF already handled %d %d %d",
+ g_num_pf_handled, idx,
+ iommu_cb_set.cb_info[idx].pf_count);
+ return -EINVAL;
+ }
+
payload = kzalloc(sizeof(struct cam_smmu_work_payload), GFP_ATOMIC);
if (!payload)
return -EINVAL;
@@ -474,7 +554,7 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain,
list_add_tail(&payload->list, &iommu_cb_set.payload_list);
mutex_unlock(&iommu_cb_set.payload_list_lock);
- schedule_work(&iommu_cb_set.smmu_work);
+ cam_smmu_page_fault_work(&iommu_cb_set.smmu_work);
return -EINVAL;
}
@@ -528,6 +608,7 @@ void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops)
iommu_cb_set.cb_info[i].state = CAM_SMMU_DETACH;
iommu_cb_set.cb_info[i].dev = NULL;
iommu_cb_set.cb_info[i].cb_count = 0;
+ iommu_cb_set.cb_info[i].pf_count = 0;
for (j = 0; j < CAM_SMMU_CB_MAX; j++) {
iommu_cb_set.cb_info[i].token[j] = NULL;
iommu_cb_set.cb_info[i].handler[j] = NULL;
@@ -1009,7 +1090,7 @@ get_addr_end:
int cam_smmu_alloc_firmware(int32_t smmu_hdl,
dma_addr_t *iova,
- uint64_t *cpuva,
+ uintptr_t *cpuva,
size_t *len)
{
int rc;
@@ -1078,7 +1159,7 @@ int cam_smmu_alloc_firmware(int32_t smmu_hdl,
iommu_cb_set.cb_info[idx].is_fw_allocated = true;
*iova = iommu_cb_set.cb_info[idx].firmware_info.iova_start;
- *cpuva = (uint64_t)icp_fw.fw_kva;
+ *cpuva = (uintptr_t)icp_fw.fw_kva;
*len = firmware_len;
mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
index 254e382a99ad..caf326d6c716 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -51,6 +51,21 @@ enum cam_smmu_region_id {
};
/**
+ * @brief : Callback function type that gets called back on cam
+ * smmu page fault.
+ *
+ * @param domain : Iommu domain received in iommu page fault handler
+ * @param dev : Device received in iommu page fault handler
+ * @param iova : IOVA where page fault occurred
+ * @param flags : Flags received in iommu page fault handler
+ * @param token : Userdata given during callback registration
+ * @param buf_info : Closest mapped buffer info
+ */
+typedef void (*cam_smmu_client_page_fault_handler)(struct iommu_domain *domain,
+ struct device *dev, unsigned long iova, int flags, void *token,
+ uint32_t buf_info);
+
+/**
* @brief : Structure to store region information
*
* @param iova_start : Start address of region
@@ -215,13 +230,19 @@ int cam_smmu_find_index_by_handle(int hdl);
* @brief : Registers smmu fault handler for client
*
* @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.)
- * @param client_page_fault_handler: It is triggered in IOMMU page fault
+ * @param handler_cb: It is triggered in IOMMU page fault
+ * @param token: It is input param when trigger page fault handler
+ */
+void cam_smmu_set_client_page_fault_handler(int handle,
+ cam_smmu_client_page_fault_handler handler_cb, void *token);
+
+/**
+ * @brief : Unregisters smmu fault handler for client
+ *
+ * @param handle: Handle to identify the CAM SMMU client (VFE, CPP, FD etc.)
* @param token: It is input param when trigger page fault handler
*/
-void cam_smmu_reg_client_page_fault_handler(int handle,
- void (*client_page_fault_handler)(struct iommu_domain *,
- struct device *, unsigned long,
- int, void*), void *token);
+void cam_smmu_unset_client_page_fault_handler(int handle, void *token);
/**
* @brief Maps memory from an ION fd into IOVA space
@@ -297,7 +318,7 @@ int cam_smmu_unmap_stage2_iova(int handle, int ion_fd);
*/
int cam_smmu_alloc_firmware(int32_t smmu_hdl,
dma_addr_t *iova,
- uint64_t *kvaddr,
+ uintptr_t *kvaddr,
size_t *len);
/**
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index 4525bb5bce25..c9e6e5fe7f61 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -426,7 +426,7 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl)
return -EINVAL;
if (copy_from_user(&sync_create,
- (void *)k_ioctl->ioctl_ptr,
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size))
return -EFAULT;
@@ -434,7 +434,8 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl)
sync_create.name);
if (!result)
- if (copy_to_user((void *)k_ioctl->ioctl_ptr,
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
&sync_create,
k_ioctl->size))
return -EFAULT;
@@ -453,7 +454,7 @@ static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl)
return -EINVAL;
if (copy_from_user(&sync_signal,
- (void *)k_ioctl->ioctl_ptr,
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size))
return -EFAULT;
@@ -478,7 +479,7 @@ static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl)
return -EINVAL;
if (copy_from_user(&sync_merge,
- (void *)k_ioctl->ioctl_ptr,
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size))
return -EFAULT;
@@ -492,8 +493,8 @@ static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl)
return -ENOMEM;
if (copy_from_user(sync_objs,
- (void *)sync_merge.sync_objs,
- sizeof(uint32_t) * sync_merge.num_objs)) {
+ u64_to_user_ptr(sync_merge.sync_objs),
+ sizeof(uint32_t) * sync_merge.num_objs)) {
kfree(sync_objs);
return -EFAULT;
}
@@ -505,7 +506,8 @@ static int cam_sync_handle_merge(struct cam_private_ioctl_arg *k_ioctl)
&sync_merge.merged);
if (!result)
- if (copy_to_user((void *)k_ioctl->ioctl_ptr,
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
&sync_merge,
k_ioctl->size)) {
kfree(sync_objs);
@@ -528,7 +530,7 @@ static int cam_sync_handle_wait(struct cam_private_ioctl_arg *k_ioctl)
return -EINVAL;
if (copy_from_user(&sync_wait,
- (void *)k_ioctl->ioctl_ptr,
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size))
return -EFAULT;
@@ -549,7 +551,7 @@ static int cam_sync_handle_destroy(struct cam_private_ioctl_arg *k_ioctl)
return -EINVAL;
if (copy_from_user(&sync_create,
- (void *)k_ioctl->ioctl_ptr,
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size))
return -EFAULT;
@@ -573,7 +575,7 @@ static int cam_sync_handle_register_user_payload(
return -EINVAL;
if (copy_from_user(&userpayload_info,
- (void *)k_ioctl->ioctl_ptr,
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size))
return -EFAULT;
@@ -654,7 +656,7 @@ static int cam_sync_handle_deregister_user_payload(
}
if (copy_from_user(&userpayload_info,
- (void *)k_ioctl->ioctl_ptr,
+ u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size))
return -EFAULT;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h
index 3e1281b62567..47d441fe3aa1 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_common_util.h
@@ -13,8 +13,14 @@
#ifndef _CAM_COMMON_UTIL_H_
#define _CAM_COMMON_UTIL_H_
+#include <linux/types.h>
+#include <linux/kernel.h>
+
#define CAM_BITS_MASK_SHIFT(x, mask, shift) (((x) & (mask)) >> shift)
+#define PTR_TO_U64(ptr) ((uint64_t)(uintptr_t)ptr)
+#define U64_TO_PTR(ptr) ((void *)(uintptr_t)ptr)
+
/**
* cam_common_util_get_string_index()
*
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
index a88ccdb93641..66a4487af172 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
@@ -21,7 +21,7 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
size_t *len)
{
int rc = 0;
- uint64_t kmd_buf_addr = 0;
+ uintptr_t kmd_buf_addr = 0;
rc = cam_mem_get_cpu_buf(handle, &kmd_buf_addr, len);
if (rc) {
@@ -30,7 +30,7 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
if (kmd_buf_addr && *len) {
*buf_addr = (uint32_t *)kmd_buf_addr;
} else {
- CAM_ERR(CAM_UTIL, "Invalid addr and length :%ld", *len);
+ CAM_ERR(CAM_UTIL, "Invalid addr and length :%zd", *len);
rc = -ENOMEM;
}
}
@@ -101,7 +101,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
return rc;
if (len < cmd_desc->size) {
- CAM_ERR(CAM_UTIL, "invalid memory len:%ld and cmd desc size:%d",
+ CAM_ERR(CAM_UTIL, "invalid memory len:%zd and cmd desc size:%d",
len, cmd_desc->size);
return -EINVAL;
}
@@ -128,7 +128,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
{
struct cam_patch_desc *patch_desc = NULL;
dma_addr_t iova_addr;
- uint64_t cpu_addr;
+ uintptr_t cpu_addr;
uint32_t temp;
uint32_t *dst_cpu_addr;
uint32_t *src_buf_iova_addr;
@@ -209,7 +209,7 @@ int cam_packet_util_process_generic_cmd_buffer(
cam_packet_generic_blob_handler blob_handler_cb, void *user_data)
{
int rc;
- uint64_t cpu_addr;
+ uintptr_t cpu_addr;
size_t buf_size;
uint32_t *blob_ptr;
uint32_t blob_type, blob_size, blob_block_size, len_read;
@@ -233,7 +233,8 @@ int cam_packet_util_process_generic_cmd_buffer(
return rc;
}
- blob_ptr = (uint32_t *)((uint8_t *)cpu_addr + cmd_buf->offset);
+ blob_ptr = (uint32_t *)(((uint8_t *)cpu_addr) +
+ cmd_buf->offset);
CAM_DBG(CAM_UTIL,
"GenericCmdBuffer cpuaddr=%pK, blobptr=%pK, len=%d",
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index eaa06deb0e32..e522c829d47a 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1172,7 +1172,7 @@ static int __iface_cmdq_write_relaxed(struct venus_hfi_device *device,
__strict_check(device);
if (!__core_in_valid_state(device)) {
- dprintk(VIDC_DBG, "%s - fw not in init state\n", __func__);
+ dprintk(VIDC_ERR, "%s - fw not in init state\n", __func__);
result = -EINVAL;
goto err_q_null;
}
@@ -2901,8 +2901,6 @@ static void __process_sys_error(struct venus_hfi_device *device)
{
struct hfi_sfr_struct *vsfr = NULL;
- __set_state(device, VENUS_STATE_DEINIT);
-
if (__halt_axi(device))
dprintk(VIDC_WARN, "Failed to halt AXI after SYS_ERROR\n");
@@ -3160,6 +3158,10 @@ static int __response_handler(struct venus_hfi_device *device)
"Too many packets in message queue to handle at once, deferring read\n");
break;
}
+
+ /* do not read packets after sys error packet */
+ if (info->response_type == HAL_SYS_ERROR)
+ break;
}
if (requeue_pm_work && device->res->sw_power_collapsible) {
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index e6d91605905e..e04a24a363ef 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -182,6 +182,7 @@ struct qseecom_registered_listener_list {
size_t sb_length;
struct ion_handle *ihandle; /* Retrieve phy addr */
wait_queue_head_t rcv_req_wq;
+ /* rcv_req_flag: -1: not ready; 0: ready and empty; 1: received req */
int rcv_req_flag;
int send_resp_flag;
bool listener_in_use;
@@ -199,6 +200,7 @@ struct qseecom_registered_app_list {
char app_name[MAX_APP_NAME_SIZE];
u32 app_arch;
bool app_blocked;
+ u32 check_block;
u32 blocked_on_listener_id;
};
@@ -1190,9 +1192,10 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
rcvd_lstnr.sb_size))
return -EFAULT;
- data->listener.id = 0;
+ data->listener.id = rcvd_lstnr.listener_id;
if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
- pr_err("Service is not unique and is already registered\n");
+ pr_err("Service %d is not unique and failed to register\n",
+ rcvd_lstnr.listener_id);
data->released = true;
return -EBUSY;
}
@@ -1201,18 +1204,18 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
if (!new_entry)
return -ENOMEM;
memcpy(&new_entry->svc, &rcvd_lstnr, sizeof(rcvd_lstnr));
- new_entry->rcv_req_flag = 0;
+ new_entry->rcv_req_flag = -1;
new_entry->svc.listener_id = rcvd_lstnr.listener_id;
new_entry->sb_length = rcvd_lstnr.sb_size;
new_entry->user_virt_sb_base = rcvd_lstnr.virt_sb_base;
if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) {
- pr_err("qseecom_set_sb_memoryfailed\n");
+ pr_err("qseecom_set_sb_memory failed for listener %d, size %d\n",
+ rcvd_lstnr.listener_id, rcvd_lstnr.sb_size);
kzfree(new_entry);
return -ENOMEM;
}
- data->listener.id = rcvd_lstnr.listener_id;
init_waitqueue_head(&new_entry->rcv_req_wq);
init_waitqueue_head(&new_entry->listener_block_app_wq);
new_entry->send_resp_flag = 0;
@@ -1221,6 +1224,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
list_add_tail(&new_entry->list, &qseecom.registered_listener_list_head);
spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+ pr_warn("Service %d is registered\n", rcvd_lstnr.listener_id);
return ret;
}
@@ -1244,13 +1248,17 @@ static void __qseecom_listener_abort_all(int abort)
static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
{
int ret = 0;
- unsigned long flags;
- uint32_t unmap_mem = 0;
struct qseecom_register_listener_ireq req;
struct qseecom_registered_listener_list *ptr_svc = NULL;
struct qseecom_command_scm_resp resp;
struct ion_handle *ihandle = NULL; /* Retrieve phy addr */
+ ptr_svc = __qseecom_find_svc(data->listener.id);
+ if (!ptr_svc) {
+ pr_err("Unregiser invalid listener ID %d\n", data->listener.id);
+ return -ENODATA;
+ }
+
req.qsee_cmd_id = QSEOS_DEREGISTER_LISTENER;
req.listener_id = data->listener.id;
resp.result = QSEOS_RESULT_INCOMPLETE;
@@ -1260,59 +1268,41 @@ static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
if (ret) {
pr_err("scm_call() failed with err: %d (lstnr id=%d)\n",
ret, data->listener.id);
- return ret;
+ goto exit;
}
if (resp.result != QSEOS_RESULT_SUCCESS) {
pr_err("Failed resp.result=%d,(lstnr id=%d)\n",
resp.result, data->listener.id);
- return -EPERM;
+ ret = -EPERM;
+ goto exit;
}
data->abort = 1;
- spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
- list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head,
- list) {
- if (ptr_svc->svc.listener_id == data->listener.id) {
- ptr_svc->abort = 1;
- wake_up_all(&ptr_svc->rcv_req_wq);
- break;
- }
- }
- spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+ ptr_svc->abort = 1;
+ wake_up_all(&ptr_svc->rcv_req_wq);
while (atomic_read(&data->ioctl_count) > 1) {
if (wait_event_freezable(data->abort_wq,
atomic_read(&data->ioctl_count) <= 1)) {
pr_err("Interrupted from abort\n");
ret = -ERESTARTSYS;
- return ret;
- }
- }
-
- spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
- list_for_each_entry(ptr_svc,
- &qseecom.registered_listener_list_head, list) {
- if (ptr_svc->svc.listener_id == data->listener.id) {
- if (ptr_svc->sb_virt) {
- unmap_mem = 1;
- ihandle = ptr_svc->ihandle;
- }
- list_del(&ptr_svc->list);
- kzfree(ptr_svc);
- break;
}
}
- spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
- /* Unmap the memory */
- if (unmap_mem) {
+exit:
+ if (ptr_svc->sb_virt) {
+ ihandle = ptr_svc->ihandle;
if (!IS_ERR_OR_NULL(ihandle)) {
ion_unmap_kernel(qseecom.ion_clnt, ihandle);
ion_free(qseecom.ion_clnt, ihandle);
}
}
+ list_del(&ptr_svc->list);
+ kzfree(ptr_svc);
+
data->released = true;
+ pr_warn("Service %d is unregistered\n", data->listener.id);
return ret;
}
@@ -1650,6 +1640,12 @@ static void __qseecom_clean_listener_sglistinfo(
}
}
+static int __is_listener_rcv_wq_not_ready(
+ struct qseecom_registered_listener_list *ptr_svc)
+{
+ return ptr_svc->rcv_req_flag == -1;
+}
+
static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
struct qseecom_command_scm_resp *resp)
{
@@ -1667,6 +1663,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
void *cmd_buf = NULL;
size_t cmd_len;
struct sglist_info *table = NULL;
+ bool not_ready = false;
while (resp->result == QSEOS_RESULT_INCOMPLETE) {
lstnr = resp->data;
@@ -1678,6 +1675,10 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
list_for_each_entry(ptr_svc,
&qseecom.registered_listener_list_head, list) {
if (ptr_svc->svc.listener_id == lstnr) {
+ if (__is_listener_rcv_wq_not_ready(ptr_svc)) {
+ not_ready = true;
+ break;
+ }
ptr_svc->listener_in_use = true;
ptr_svc->rcv_req_flag = 1;
wake_up_interruptible(&ptr_svc->rcv_req_wq);
@@ -1717,6 +1718,16 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
status = QSEOS_RESULT_FAILURE;
goto err_resp;
}
+
+ if (not_ready) {
+ pr_err("Service %d is not ready to receive request\n",
+ lstnr);
+ rc = -ENOENT;
+ status = QSEOS_RESULT_FAILURE;
+ goto err_resp;
+
+ }
+
pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
/* initialize the new signal mask with all signals*/
@@ -1978,6 +1989,7 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
void *cmd_buf = NULL;
size_t cmd_len;
struct sglist_info *table = NULL;
+ bool not_ready = false;
while (ret == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
lstnr = resp->data;
@@ -1989,6 +2001,10 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
list_for_each_entry(ptr_svc,
&qseecom.registered_listener_list_head, list) {
if (ptr_svc->svc.listener_id == lstnr) {
+ if (__is_listener_rcv_wq_not_ready(ptr_svc)) {
+ not_ready = true;
+ break;
+ }
ptr_svc->listener_in_use = true;
ptr_svc->rcv_req_flag = 1;
wake_up_interruptible(&ptr_svc->rcv_req_wq);
@@ -2028,6 +2044,16 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
status = QSEOS_RESULT_FAILURE;
goto err_resp;
}
+
+ if (not_ready) {
+ pr_err("Service %d is not ready to receive request\n",
+ lstnr);
+ rc = -ENOENT;
+ status = QSEOS_RESULT_FAILURE;
+ goto err_resp;
+
+ }
+
pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
/* initialize the new signal mask with all signals*/
@@ -2203,6 +2229,7 @@ static void __qseecom_reentrancy_check_if_this_app_blocked(
sigset_t new_sigset, old_sigset;
if (qseecom.qsee_reentrancy_support) {
+ ptr_app->check_block++;
while (ptr_app->app_blocked || qseecom.app_block_ref_cnt > 1) {
/* thread sleep until this app unblocked */
sigfillset(&new_sigset);
@@ -2217,6 +2244,7 @@ static void __qseecom_reentrancy_check_if_this_app_blocked(
mutex_lock(&app_access_lock);
sigprocmask(SIG_SETMASK, &old_sigset, NULL);
}
+ ptr_app->check_block--;
}
}
@@ -2485,6 +2513,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
MAX_APP_NAME_SIZE);
entry->app_blocked = false;
entry->blocked_on_listener_id = 0;
+ entry->check_block = 0;
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
@@ -2595,7 +2624,8 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
if (!strcmp((void *)ptr_app->app_name,
(void *)data->client.app_name)) {
found_app = true;
- if (ptr_app->app_blocked)
+ if (ptr_app->app_blocked ||
+ ptr_app->check_block)
app_crash = false;
if (app_crash || ptr_app->ref_cnt == 1)
unload = true;
@@ -3831,7 +3861,7 @@ static int __qseecom_listener_has_rcvd_req(struct qseecom_dev_handle *data,
{
int ret;
- ret = (svc->rcv_req_flag != 0);
+ ret = (svc->rcv_req_flag == 1);
return ret || data->abort || svc->abort;
}
@@ -3846,13 +3876,17 @@ static int qseecom_receive_req(struct qseecom_dev_handle *data)
return -ENODATA;
}
+ if (this_lstnr->rcv_req_flag == -1)
+ this_lstnr->rcv_req_flag = 0;
+
while (1) {
if (wait_event_freezable(this_lstnr->rcv_req_wq,
__qseecom_listener_has_rcvd_req(data,
this_lstnr))) {
- pr_debug("Interrupted: exiting Listener Service = %d\n",
+ pr_warn("Interrupted: exiting Listener Service = %d\n",
(uint32_t)data->listener.id);
/* woken up for different reason */
+ this_lstnr->rcv_req_flag = -1;
return -ERESTARTSYS;
}
@@ -4535,6 +4569,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
entry->app_arch = app_arch;
entry->app_blocked = false;
entry->blocked_on_listener_id = 0;
+ entry->check_block = 0;
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_add_tail(&entry->list, &qseecom.registered_app_list_head);
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
@@ -5449,6 +5484,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
MAX_APP_NAME_SIZE);
entry->app_blocked = false;
entry->blocked_on_listener_id = 0;
+ entry->check_block = 0;
spin_lock_irqsave(&qseecom.registered_app_list_lock,
flags);
list_add_tail(&entry->list,
@@ -7681,6 +7717,7 @@ static int qseecom_release(struct inode *inode, struct file *file)
data->type, data->mode, data);
switch (data->type) {
case QSEECOM_LISTENER_SERVICE:
+ pr_warn("release lsnr svc %d\n", data->listener.id);
__qseecom_listener_abort_all(1);
mutex_lock(&app_access_lock);
ret = qseecom_unregister_listener(data);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
index c90561d0cdfc..b7606775bdb8 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
@@ -89,6 +89,7 @@ const char *ipa_event_name[] = {
__stringify(DEL_L2TP_VLAN_MAPPING),
__stringify(IPA_PER_CLIENT_STATS_CONNECT_EVENT),
__stringify(IPA_PER_CLIENT_STATS_DISCONNECT_EVENT),
+ __stringify(WLAN_FWR_SSR_BEFORE_SHUTDOWN),
};
const char *ipa_hdr_l2_type_name[] = {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
index 579ab1ce40d0..81e98f2c8697 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
@@ -35,6 +35,13 @@ enum nat_table_type {
#define NAT_TABLE_ENTRY_SIZE_BYTE 32
#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4
+/*
+ * Max NAT table entries is limited 1000 entries.
+ * Limit the memory size required by user to prevent kernel memory starvation
+ */
+#define IPA_TABLE_MAX_ENTRIES 1000
+#define MAX_ALLOC_NAT_SIZE (IPA_TABLE_MAX_ENTRIES * NAT_TABLE_ENTRY_SIZE_BYTE)
+
static int ipa_nat_vma_fault_remap(
struct vm_area_struct *vma, struct vm_fault *vmf)
{
@@ -270,6 +277,13 @@ int ipa2_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem)
goto bail;
}
+ if (mem->size > MAX_ALLOC_NAT_SIZE) {
+ IPAERR("Trying allocate more size = %zu, Max allowed = %d\n",
+ mem->size, MAX_ALLOC_NAT_SIZE);
+ result = -EPERM;
+ goto bail;
+ }
+
if (mem->size <= 0 ||
nat_ctx->is_dev_init == true) {
IPAERR_RL("Invalid Parameters or device is already init\n");
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index 41b1783b9f64..f041be906446 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -1325,6 +1325,8 @@ int ipa2_reset_rt(enum ipa_ip_type ip)
struct ipa_rt_entry *rule_next;
struct ipa_rt_tbl_set *rset;
u32 apps_start_idx;
+ struct ipa_hdr_entry *hdr_entry;
+ struct ipa_hdr_proc_ctx_entry *hdr_proc_entry;
int id;
if (ip >= IPA_IP_MAX) {
@@ -1369,6 +1371,27 @@ int ipa2_reset_rt(enum ipa_ip_type ip)
continue;
list_del(&rule->link);
+ if (rule->hdr) {
+ hdr_entry = ipa_id_find(
+ rule->rule.hdr_hdl);
+ if (!hdr_entry ||
+ hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL(
+ "Header already deleted\n");
+ return -EINVAL;
+ }
+ } else if (rule->proc_ctx) {
+ hdr_proc_entry =
+ ipa_id_find(
+ rule->rule.hdr_proc_ctx_hdl);
+ if (!hdr_proc_entry ||
+ hdr_proc_entry->cookie !=
+ IPA_PROC_HDR_COOKIE) {
+ IPAERR_RL(
+ "Proc entry already deleted\n");
+ return -EINVAL;
+ }
+ }
tbl->rule_cnt--;
if (rule->hdr)
__ipa_release_hdr(rule->hdr->id);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index edc5c2cb3d08..752658cb9317 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -73,6 +73,7 @@ const char *ipa3_event_name[] = {
__stringify(DEL_L2TP_VLAN_MAPPING),
__stringify(IPA_PER_CLIENT_STATS_CONNECT_EVENT),
__stringify(IPA_PER_CLIENT_STATS_DISCONNECT_EVENT),
+ __stringify(WLAN_FWR_SSR_BEFORE_SHUTDOWN),
};
const char *ipa3_hdr_l2_type_name[] = {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index dacccbc4d033..d17f8098552c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -1046,13 +1046,12 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name,
goto error;
}
/*
- * do not allow any rules to be added at end of the "default" routing
- * tables
+ * do not allow any rule to be added at "default" routing
+ * table
*/
if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) &&
- (tbl->rule_cnt > 0) && (at_rear != 0)) {
- IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d at_rear=%d"
- , tbl->rule_cnt, at_rear);
+ (tbl->rule_cnt > 0)) {
+ IPAERR_RL("cannot add rules to default rt table\n");
goto error;
}
@@ -1258,13 +1257,12 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules)
}
/*
- * do not allow any rules to be added at end of the "default" routing
- * tables
+ * do not allow any rule to be added at "default" routing
+ * table
*/
if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) &&
- (&entry->link == tbl->head_rt_rule_list.prev)) {
- IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d\n",
- tbl->rule_cnt);
+ (tbl->rule_cnt > 0)) {
+ IPAERR_RL("cannot add rules to default rt table\n");
ret = -EINVAL;
goto bail;
}
@@ -1470,6 +1468,8 @@ int ipa3_reset_rt(enum ipa_ip_type ip)
struct ipa3_rt_entry *rule;
struct ipa3_rt_entry *rule_next;
struct ipa3_rt_tbl_set *rset;
+ struct ipa3_hdr_entry *hdr_entry;
+ struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
u32 apps_start_idx;
int id;
@@ -1513,13 +1513,35 @@ int ipa3_reset_rt(enum ipa_ip_type ip)
continue;
list_del(&rule->link);
+ if (rule->hdr) {
+ hdr_entry = ipa3_id_find(
+ rule->rule.hdr_hdl);
+ if (!hdr_entry ||
+ hdr_entry->cookie != IPA_HDR_COOKIE) {
+ IPAERR_RL(
+ "Header already deleted\n");
+ return -EINVAL;
+ }
+ } else if (rule->proc_ctx) {
+ hdr_proc_entry =
+ ipa3_id_find(
+ rule->rule.hdr_proc_ctx_hdl);
+ if (!hdr_proc_entry ||
+ hdr_proc_entry->cookie !=
+ IPA_PROC_HDR_COOKIE) {
+ IPAERR_RL(
+ "Proc entry already deleted\n");
+ return -EINVAL;
+ }
+ }
tbl->rule_cnt--;
if (rule->hdr)
__ipa3_release_hdr(rule->hdr->id);
else if (rule->proc_ctx)
__ipa3_release_hdr_proc_ctx(rule->proc_ctx->id);
rule->cookie = 0;
- idr_remove(tbl->rule_ids, rule->rule_id);
+ if (!rule->rule_id_valid)
+ idr_remove(tbl->rule_ids, rule->rule_id);
id = rule->id;
kmem_cache_free(ipa3_ctx->rt_rule_cache, rule);
@@ -1697,6 +1719,10 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule)
goto error;
}
+ if (!strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) {
+ IPAERR_RL("Default tbl rule cannot be modified\n");
+ return -EINVAL;
+ }
/* Adding check to confirm still
* header entry present in header table or not
*/
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 8ac7a3b3c719..05a8c66d57aa 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -2334,8 +2334,11 @@ int sps_deregister_bam_device(unsigned long dev_handle)
mutex_lock(&bam->lock);
sps_bam_device_de_init(bam);
mutex_unlock(&bam->lock);
+ ipc_log_context_destroy(bam->ipc_log0);
ipc_log_context_destroy(bam->ipc_log1);
ipc_log_context_destroy(bam->ipc_log2);
+ ipc_log_context_destroy(bam->ipc_log3);
+ ipc_log_context_destroy(bam->ipc_log4);
if (bam->props.virt_size)
(void)iounmap(bam->props.virt_addr);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index d284d30910fc..01680c8a9498 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -3094,7 +3094,9 @@ static int smblib_cc2_sink_removal_exit(struct smb_charger *chg)
return 0;
chg->cc2_detach_wa_active = false;
+ chg->in_chg_lock = true;
cancel_work_sync(&chg->rdstd_cc2_detach_work);
+ chg->in_chg_lock = false;
smblib_reg_block_restore(chg, cc2_detach_settings);
return 0;
}
@@ -4641,7 +4643,6 @@ static void rdstd_cc2_detach_work(struct work_struct *work)
{
int rc;
u8 stat4, stat5;
- bool lock = false;
struct smb_charger *chg = container_of(work, struct smb_charger,
rdstd_cc2_detach_work);
@@ -4710,22 +4711,15 @@ static void rdstd_cc2_detach_work(struct work_struct *work)
* during pd_hard_reset from the function smblib_cc2_sink_removal_exit
* which is called in the same lock context that we try to acquire in
* this work routine.
- * Check if this work is running during pd_hard_reset and use trylock
- * instead of mutex_lock to prevent any deadlock if mutext is already
- * held.
+ * Check if this work is running during pd_hard_reset and skip holding
+ * mutex if lock is already held.
*/
- if (chg->pd_hard_reset) {
- if (mutex_trylock(&chg->lock))
- lock = true;
- } else {
+ if (!chg->in_chg_lock)
mutex_lock(&chg->lock);
- lock = true;
- }
-
smblib_usb_typec_change(chg);
-
- if (lock)
+ if (!chg->in_chg_lock)
mutex_unlock(&chg->lock);
+
return;
rerun:
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index d6189db72e3a..233ab50f4a79 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -349,6 +349,7 @@ struct smb_charger {
bool use_extcon;
bool otg_present;
bool is_audio_adapter;
+ bool in_chg_lock;
/* workaround flag */
u32 wa_flags;
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 1ec6202bec8d..e8d41f1f274f 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -727,6 +727,11 @@ static int ufs_qcom_config_vreg(struct device *dev,
reg = vreg->reg;
if (regulator_count_voltages(reg) > 0) {
+ uA_load = on ? vreg->max_uA : 0;
+ ret = regulator_set_load(vreg->reg, uA_load);
+ if (ret)
+ goto out;
+
min_uV = on ? vreg->min_uV : 0;
ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
if (ret) {
@@ -734,11 +739,6 @@ static int ufs_qcom_config_vreg(struct device *dev,
__func__, vreg->name, ret);
goto out;
}
-
- uA_load = on ? vreg->max_uA : 0;
- ret = regulator_set_load(vreg->reg, uA_load);
- if (ret)
- goto out;
}
out:
return ret;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index acd170d04db6..ce411897c886 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3382,6 +3382,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
int tag;
struct completion wait;
unsigned long flags;
+ bool has_read_lock = false;
/*
* May get invoked from shutdown and IOCTL contexts.
@@ -3389,8 +3390,10 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
* In error recovery context, it may come with lock acquired.
*/
- if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba))
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
down_read(&hba->lock);
+ has_read_lock = true;
+ }
/*
* Get free slot, sleep if slots are unavailable.
@@ -3423,7 +3426,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
out_put_tag:
ufshcd_put_dev_cmd_tag(hba, tag);
wake_up(&hba->dev_cmd.tag_wq);
- if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba))
+ if (has_read_lock)
up_read(&hba->lock);
return err;
}
@@ -7431,7 +7434,7 @@ static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba)
dev_err(hba->dev,
"%s: Failed reading power descriptor.len = %d ret = %d",
__func__, buff_len, ret);
- return;
+ goto out;
}
icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf,
@@ -7445,6 +7448,9 @@ static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba)
dev_err(hba->dev,
"%s: Failed configuring bActiveICCLevel = %d ret = %d",
__func__, icc_level, ret);
+
+out:
+ kfree(desc_buf);
}
/**
@@ -7802,7 +7808,7 @@ out:
static int ufs_read_device_desc_data(struct ufs_hba *hba)
{
- int err;
+ int err = 0;
u8 *desc_buf = NULL;
if (hba->desc_size.dev_desc) {
@@ -7816,7 +7822,7 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba)
}
err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc);
if (err)
- return err;
+ goto out;
/*
* getting vendor (manufacturerID) and Bank Index in big endian
@@ -7828,8 +7834,9 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba)
hba->dev_info.b_device_sub_class =
desc_buf[DEVICE_DESC_PARAM_DEVICE_SUB_CLASS];
hba->dev_info.i_product_name = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
-
- return 0;
+out:
+ kfree(desc_buf);
+ return err;
}
static void ufshcd_init_desc_sizes(struct ufs_hba *hba)
@@ -8528,6 +8535,11 @@ static int ufshcd_config_vreg(struct device *dev,
BUG_ON(!vreg);
if (regulator_count_voltages(reg) > 0) {
+ uA_load = on ? vreg->max_uA : 0;
+ ret = ufshcd_config_vreg_load(dev, vreg, uA_load);
+ if (ret)
+ goto out;
+
min_uV = on ? vreg->min_uV : 0;
ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
if (ret) {
@@ -8535,11 +8547,6 @@ static int ufshcd_config_vreg(struct device *dev,
__func__, name, ret);
goto out;
}
-
- uA_load = on ? vreg->max_uA : 0;
- ret = ufshcd_config_vreg_load(dev, vreg, uA_load);
- if (ret)
- goto out;
}
out:
return ret;
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 4aab90904f07..161257b17446 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -3125,6 +3125,8 @@ EXPORT_SYMBOL(icnss_disable_irq);
int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info)
{
+ char *fw_build_timestamp = NULL;
+
if (!penv || !dev) {
icnss_pr_err("Platform driver not initialized\n");
return -EINVAL;
@@ -3137,6 +3139,8 @@ int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info)
info->board_id = penv->board_info.board_id;
info->soc_id = penv->soc_info.soc_id;
info->fw_version = penv->fw_version_info.fw_version;
+ fw_build_timestamp = penv->fw_version_info.fw_build_timestamp;
+ fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01] = '\0';
strlcpy(info->fw_build_timestamp,
penv->fw_version_info.fw_build_timestamp,
QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1);
diff --git a/drivers/soc/qcom/ipc_router_glink_xprt.c b/drivers/soc/qcom/ipc_router_glink_xprt.c
index cef3c7716e8f..ada7d5efbc6c 100644
--- a/drivers/soc/qcom/ipc_router_glink_xprt.c
+++ b/drivers/soc/qcom/ipc_router_glink_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,7 @@ static int ipc_router_glink_xprt_debug_mask;
module_param_named(debug_mask, ipc_router_glink_xprt_debug_mask,
int, 0664);
+#define IPCRTR_INTENT_REQ_TIMEOUT_MS 5000
#if defined(DEBUG)
#define D(x...) do { \
if (ipc_router_glink_xprt_debug_mask) \
@@ -602,6 +603,7 @@ static void glink_xprt_ch_open(struct ipc_router_glink_xprt *glink_xprtp)
open_cfg.notify_state = glink_xprt_notify_state;
open_cfg.notify_rx_intent_req = glink_xprt_notify_rx_intent_req;
open_cfg.priv = glink_xprtp;
+ open_cfg.rx_intent_req_timeout_ms = IPCRTR_INTENT_REQ_TIMEOUT_MS;
glink_xprtp->pil = msm_ipc_load_subsystem(glink_xprtp);
glink_xprtp->ch_hndl = glink_open(&open_cfg);
diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c
index 9cd9309fd433..d15a6048d530 100644
--- a/drivers/soc/qcom/pil-msa.c
+++ b/drivers/soc/qcom/pil-msa.c
@@ -827,7 +827,7 @@ int pil_mss_debug_reset(struct pil_desc *pil)
* complete before returning
*/
pr_info("Minidump: waiting encryption to complete\n");
- msleep(10000);
+ msleep(13000);
if (pil->minidump) {
writel_relaxed(0x2, drv->reg_base + QDSP6SS_NMI_CFG);
/* Let write complete before proceeding */
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index f7902e18b05c..06002485070e 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -258,21 +258,28 @@ existing:
switch (state) {
case RPMH_ACTIVE_ONLY_STATE:
case RPMH_AWAKE_STATE:
- if (req->sleep_val != UINT_MAX)
+ if (req->sleep_val != UINT_MAX) {
req->wake_val = cmd->data;
+ rpm->dirty = true;
+ }
break;
case RPMH_WAKE_ONLY_STATE:
- req->wake_val = cmd->data;
+ if (req->wake_val != cmd->data) {
+ req->wake_val = cmd->data;
+ rpm->dirty = true;
+ }
break;
case RPMH_SLEEP_STATE:
- req->sleep_val = cmd->data;
+ if (req->sleep_val != cmd->data) {
+ req->sleep_val = cmd->data;
+ rpm->dirty = true;
+ }
break;
default:
break;
};
unlock:
- rpm->dirty = true;
spin_unlock_irqrestore(&rpm->lock, flags);
return req;
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 71e076badc9a..2112d14f5945 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -1173,12 +1173,12 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas)
mas->rx_rem_bytes -= rx_bytes;
}
-static irqreturn_t geni_spi_irq(int irq, void *dev)
+static irqreturn_t geni_spi_irq(int irq, void *data)
{
- struct spi_geni_master *mas = dev;
+ struct spi_geni_master *mas = data;
u32 m_irq = 0;
- if (pm_runtime_status_suspended(dev)) {
+ if (pm_runtime_status_suspended(mas->dev)) {
GENI_SE_DBG(mas->ipc, false, mas->dev,
"%s: device is suspended\n", __func__);
goto exit_geni_spi_irq;
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index 72f2b6a1b9ed..3f0ebe861e2f 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -4,7 +4,7 @@
* Copyright (C) Linaro 2012
* Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -390,14 +390,37 @@ out:
return ret;
}
+static void *ion_secure_cma_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ if (!is_buffer_hlos_assigned(buffer)) {
+ pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n",
+ __func__);
+ return NULL;
+ }
+ return ion_cma_map_kernel(heap, buffer);
+}
+
+static int ion_secure_cma_map_user(struct ion_heap *mapper,
+ struct ion_buffer *buffer,
+ struct vm_area_struct *vma)
+{
+ if (!is_buffer_hlos_assigned(buffer)) {
+ pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n",
+ __func__);
+ return -EINVAL;
+ }
+ return ion_cma_mmap(mapper, buffer, vma);
+}
+
static struct ion_heap_ops ion_secure_cma_ops = {
.allocate = ion_secure_cma_allocate,
.free = ion_secure_cma_free,
.map_dma = ion_cma_heap_map_dma,
.unmap_dma = ion_cma_heap_unmap_dma,
.phys = ion_cma_phys,
- .map_user = ion_cma_mmap,
- .map_kernel = ion_cma_map_kernel,
+ .map_user = ion_secure_cma_map_user,
+ .map_kernel = ion_secure_cma_map_kernel,
.unmap_kernel = ion_cma_unmap_kernel,
.print_debug = ion_cma_print_debug,
};
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index 37b6ad4235f5..eb7c61b8d375 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -102,6 +102,11 @@ size_t ion_system_heap_secure_page_pool_total(struct ion_heap *heap,
return total << PAGE_SHIFT;
}
+static int ion_heap_is_system_heap_type(enum ion_heap_type type)
+{
+ return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM);
+}
+
static struct page *alloc_buffer_page(struct ion_system_heap *heap,
struct ion_buffer *buffer,
unsigned long order,
@@ -357,6 +362,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
int vmid = get_secure_vmid(buffer->flags);
struct device *dev = heap->priv;
+ if (ion_heap_is_system_heap_type(buffer->heap->type) &&
+ is_secure_vmid_valid(vmid)) {
+ pr_info("%s: System heap doesn't support secure allocations\n",
+ __func__);
+ return -EINVAL;
+ }
+
if (align > PAGE_SIZE)
return -EINVAL;
diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c
index 5bf484beed96..cf86ea21838a 100644
--- a/drivers/staging/android/ion/ion_system_secure_heap.c
+++ b/drivers/staging/android/ion/ion_system_secure_heap.c
@@ -1,6 +1,6 @@
/*
*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016,2018 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -171,14 +171,15 @@ out:
sys_heap->ops->free(&buffer);
}
-static void process_one_shrink(struct ion_heap *sys_heap,
+static void process_one_shrink(struct ion_system_secure_heap *secure_heap,
+ struct ion_heap *sys_heap,
struct prefetch_info *info)
{
struct ion_buffer buffer;
size_t pool_size, size;
int ret;
- buffer.heap = sys_heap;
+ buffer.heap = &secure_heap->heap;
buffer.flags = info->vmid;
pool_size = ion_system_heap_secure_page_pool_total(sys_heap,
@@ -193,6 +194,7 @@ static void process_one_shrink(struct ion_heap *sys_heap,
}
buffer.private_flags = ION_PRIV_FLAG_SHRINKER_FREE;
+ buffer.heap = sys_heap;
sys_heap->ops->free(&buffer);
}
@@ -212,7 +214,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work)
spin_unlock_irqrestore(&secure_heap->work_lock, flags);
if (info->shrink)
- process_one_shrink(sys_heap, info);
+ process_one_shrink(secure_heap, sys_heap, info);
else
process_one_prefetch(sys_heap, info);
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 7e4e7ceb25a6..257cb88b7edc 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -675,6 +675,11 @@ static void ipa_work_handler(struct work_struct *w)
log_event_dbg("%s: ST_CON_IN_PROG_EVT_HOST_READY",
__func__);
} else if (event == EVT_CONNECTED) {
+ if (peek_event(d_port) == EVT_SUSPEND) {
+ log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUSPEND",
+ __func__);
+ break;
+ }
ipa_data_path_enable(d_port);
d_port->sm_state = STATE_CONNECTED;
log_event_dbg("%s: ST_CON_IN_PROG_EVT_CON %d",
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 7198328253cd..1cfe036e061b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3655,6 +3655,7 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
+ virt_dev->udev = NULL;
spin_lock_irqsave(&xhci->lock, flags);
/* Don't disable the slot if the host controller is dead. */
state = readl(&xhci->op_regs->status);
diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c
index 5ac0b0bbb0ec..399531bc1f6f 100644
--- a/fs/sdcardfs/file.c
+++ b/fs/sdcardfs/file.c
@@ -115,7 +115,11 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd,
goto out;
/* save current_cred and override it */
- OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file)));
+ saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data);
+ if (!saved_cred) {
+ err = -ENOMEM;
+ goto out;
+ }
if (lower_file->f_op->unlocked_ioctl)
err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
@@ -124,7 +128,7 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd,
if (!err)
sdcardfs_copy_and_fix_attrs(file_inode(file),
file_inode(lower_file));
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out:
return err;
}
@@ -146,12 +150,16 @@ static long sdcardfs_compat_ioctl(struct file *file, unsigned int cmd,
goto out;
/* save current_cred and override it */
- OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file)));
+ saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data);
+ if (!saved_cred) {
+ err = -ENOMEM;
+ goto out;
+ }
if (lower_file->f_op->compat_ioctl)
err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out:
return err;
}
@@ -238,7 +246,11 @@ static int sdcardfs_open(struct inode *inode, struct file *file)
}
/* save current_cred and override it */
- OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(inode));
+ saved_cred = override_fsids(sbi, SDCARDFS_I(inode)->data);
+ if (!saved_cred) {
+ err = -ENOMEM;
+ goto out_err;
+ }
file->private_data =
kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL);
@@ -268,7 +280,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file)
sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode));
out_revert_cred:
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_err:
dput(parent);
return err;
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 8ed0ea17de5a..4af7c87c40ac 100644
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -22,7 +22,6 @@
#include <linux/fs_struct.h>
#include <linux/ratelimit.h>
-/* Do not directly use this function. Use OVERRIDE_CRED() instead. */
const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
struct sdcardfs_inode_data *data)
{
@@ -50,7 +49,6 @@ const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
return old_cred;
}
-/* Do not directly use this function, use REVERT_CRED() instead. */
void revert_fsids(const struct cred *old_cred)
{
const struct cred *cur_cred;
@@ -78,7 +76,10 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
}
/* save current_cred and override it */
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
+ SDCARDFS_I(dir)->data);
+ if (!saved_cred)
+ return -ENOMEM;
sdcardfs_get_lower_path(dentry, &lower_path);
lower_dentry = lower_path.dentry;
@@ -95,8 +96,11 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
err = -ENOMEM;
goto out_unlock;
}
+ copied_fs->umask = 0;
+ task_lock(current);
current->fs = copied_fs;
- current->fs->umask = 0;
+ task_unlock(current);
+
err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl);
if (err)
goto out;
@@ -110,58 +114,18 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
fixup_lower_ownership(dentry, dentry->d_name.name);
out:
+ task_lock(current);
current->fs = saved_fs;
+ task_unlock(current);
free_fs_struct(copied_fs);
out_unlock:
unlock_dir(lower_parent_dentry);
sdcardfs_put_lower_path(dentry, &lower_path);
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_eacces:
return err;
}
-#if 0
-static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry)
-{
- struct dentry *lower_old_dentry;
- struct dentry *lower_new_dentry;
- struct dentry *lower_dir_dentry;
- u64 file_size_save;
- int err;
- struct path lower_old_path, lower_new_path;
-
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb));
-
- file_size_save = i_size_read(d_inode(old_dentry));
- sdcardfs_get_lower_path(old_dentry, &lower_old_path);
- sdcardfs_get_lower_path(new_dentry, &lower_new_path);
- lower_old_dentry = lower_old_path.dentry;
- lower_new_dentry = lower_new_path.dentry;
- lower_dir_dentry = lock_parent(lower_new_dentry);
-
- err = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry),
- lower_new_dentry, NULL);
- if (err || !d_inode(lower_new_dentry))
- goto out;
-
- err = sdcardfs_interpose(new_dentry, dir->i_sb, &lower_new_path);
- if (err)
- goto out;
- fsstack_copy_attr_times(dir, d_inode(lower_new_dentry));
- fsstack_copy_inode_size(dir, d_inode(lower_new_dentry));
- set_nlink(d_inode(old_dentry),
- sdcardfs_lower_inode(d_inode(old_dentry))->i_nlink);
- i_size_write(d_inode(new_dentry), file_size_save);
-out:
- unlock_dir(lower_dir_dentry);
- sdcardfs_put_lower_path(old_dentry, &lower_old_path);
- sdcardfs_put_lower_path(new_dentry, &lower_new_path);
- REVERT_CRED();
- return err;
-}
-#endif
-
static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
{
int err;
@@ -178,7 +142,10 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
}
/* save current_cred and override it */
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
+ SDCARDFS_I(dir)->data);
+ if (!saved_cred)
+ return -ENOMEM;
sdcardfs_get_lower_path(dentry, &lower_path);
lower_dentry = lower_path.dentry;
@@ -209,43 +176,11 @@ out:
unlock_dir(lower_dir_dentry);
dput(lower_dentry);
sdcardfs_put_lower_path(dentry, &lower_path);
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_eacces:
return err;
}
-#if 0
-static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry,
- const char *symname)
-{
- int err;
- struct dentry *lower_dentry;
- struct dentry *lower_parent_dentry = NULL;
- struct path lower_path;
-
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb));
-
- sdcardfs_get_lower_path(dentry, &lower_path);
- lower_dentry = lower_path.dentry;
- lower_parent_dentry = lock_parent(lower_dentry);
-
- err = vfs_symlink(d_inode(lower_parent_dentry), lower_dentry, symname);
- if (err)
- goto out;
- err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path);
- if (err)
- goto out;
- fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
- fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry));
-
-out:
- unlock_dir(lower_parent_dentry);
- sdcardfs_put_lower_path(dentry, &lower_path);
- REVERT_CRED();
- return err;
-}
-#endif
-
static int touch(char *abs_path, mode_t mode)
{
struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode);
@@ -286,7 +221,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
}
/* save current_cred and override it */
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
+ SDCARDFS_I(dir)->data);
+ if (!saved_cred)
+ return -ENOMEM;
/* check disk space */
if (!check_min_free_space(dentry, 0, 1)) {
@@ -312,8 +250,11 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
unlock_dir(lower_parent_dentry);
goto out_unlock;
}
+ copied_fs->umask = 0;
+ task_lock(current);
current->fs = copied_fs;
- current->fs->umask = 0;
+ task_unlock(current);
+
err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode);
if (err) {
@@ -362,23 +303,34 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
if (make_nomedia_in_obb ||
((pd->perm == PERM_ANDROID)
&& (qstr_case_eq(&dentry->d_name, &q_data)))) {
- REVERT_CRED(saved_cred);
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(d_inode(dentry)));
+ revert_fsids(saved_cred);
+ saved_cred = override_fsids(sbi,
+ SDCARDFS_I(d_inode(dentry))->data);
+ if (!saved_cred) {
+ pr_err("sdcardfs: failed to set up .nomedia in %s: %d\n",
+ lower_path.dentry->d_name.name,
+ -ENOMEM);
+ goto out;
+ }
set_fs_pwd(current->fs, &lower_path);
touch_err = touch(".nomedia", 0664);
if (touch_err) {
pr_err("sdcardfs: failed to create .nomedia in %s: %d\n",
- lower_path.dentry->d_name.name, touch_err);
+ lower_path.dentry->d_name.name,
+ touch_err);
goto out;
}
}
out:
+ task_lock(current);
current->fs = saved_fs;
+ task_unlock(current);
+
free_fs_struct(copied_fs);
out_unlock:
sdcardfs_put_lower_path(dentry, &lower_path);
out_revert:
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_eacces:
return err;
}
@@ -398,7 +350,10 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry)
}
/* save current_cred and override it */
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
+ SDCARDFS_I(dir)->data);
+ if (!saved_cred)
+ return -ENOMEM;
/* sdcardfs_get_real_lower(): in case of remove an user's obb dentry
* the dentry on the original path should be deleted.
@@ -423,44 +378,11 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry)
out:
unlock_dir(lower_dir_dentry);
sdcardfs_put_real_lower(dentry, &lower_path);
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_eacces:
return err;
}
-#if 0
-static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
- dev_t dev)
-{
- int err;
- struct dentry *lower_dentry;
- struct dentry *lower_parent_dentry = NULL;
- struct path lower_path;
-
- OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb));
-
- sdcardfs_get_lower_path(dentry, &lower_path);
- lower_dentry = lower_path.dentry;
- lower_parent_dentry = lock_parent(lower_dentry);
-
- err = vfs_mknod(d_inode(lower_parent_dentry), lower_dentry, mode, dev);
- if (err)
- goto out;
-
- err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path);
- if (err)
- goto out;
- fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
- fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry));
-
-out:
- unlock_dir(lower_parent_dentry);
- sdcardfs_put_lower_path(dentry, &lower_path);
- REVERT_CRED();
- return err;
-}
-#endif
-
/*
* The locking rules in sdcardfs_rename are complex. We could use a simpler
* superblock-level name-space lock for renames and copy-ups.
@@ -489,7 +411,10 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
}
/* save current_cred and override it */
- OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred, SDCARDFS_I(new_dir));
+ saved_cred = override_fsids(SDCARDFS_SB(old_dir->i_sb),
+ SDCARDFS_I(new_dir)->data);
+ if (!saved_cred)
+ return -ENOMEM;
sdcardfs_get_real_lower(old_dentry, &lower_old_path);
sdcardfs_get_lower_path(new_dentry, &lower_new_path);
@@ -536,7 +461,7 @@ out:
dput(lower_new_dir_dentry);
sdcardfs_put_real_lower(old_dentry, &lower_old_path);
sdcardfs_put_lower_path(new_dentry, &lower_new_path);
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_eacces:
return err;
}
@@ -653,33 +578,7 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma
if (IS_POSIXACL(inode))
pr_warn("%s: This may be undefined behavior...\n", __func__);
err = generic_permission(&tmp, mask);
- /* XXX
- * Original sdcardfs code calls inode_permission(lower_inode,.. )
- * for checking inode permission. But doing such things here seems
- * duplicated work, because the functions called after this func,
- * such as vfs_create, vfs_unlink, vfs_rename, and etc,
- * does exactly same thing, i.e., they calls inode_permission().
- * So we just let they do the things.
- * If there are any security hole, just uncomment following if block.
- */
-#if 0
- if (!err) {
- /*
- * Permission check on lower_inode(=EXT4).
- * we check it with AID_MEDIA_RW permission
- */
- struct inode *lower_inode;
-
- OVERRIDE_CRED(SDCARDFS_SB(inode->sb));
-
- lower_inode = sdcardfs_lower_inode(inode);
- err = inode_permission(lower_inode, mask);
-
- REVERT_CRED();
- }
-#endif
return err;
-
}
static int sdcardfs_setattr_wrn(struct dentry *dentry, struct iattr *ia)
@@ -757,7 +656,10 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct
goto out_err;
/* save current_cred and override it */
- OVERRIDE_CRED(SDCARDFS_SB(dentry->d_sb), saved_cred, SDCARDFS_I(inode));
+ saved_cred = override_fsids(SDCARDFS_SB(dentry->d_sb),
+ SDCARDFS_I(inode)->data);
+ if (!saved_cred)
+ return -ENOMEM;
sdcardfs_get_lower_path(dentry, &lower_path);
lower_dentry = lower_path.dentry;
@@ -816,7 +718,7 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct
out:
sdcardfs_put_lower_path(dentry, &lower_path);
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_err:
return err;
}
@@ -899,13 +801,6 @@ const struct inode_operations sdcardfs_dir_iops = {
.setattr = sdcardfs_setattr_wrn,
.setattr2 = sdcardfs_setattr,
.getattr = sdcardfs_getattr,
- /* XXX Following operations are implemented,
- * but FUSE(sdcard) or FAT does not support them
- * These methods are *NOT* perfectly tested.
- .symlink = sdcardfs_symlink,
- .link = sdcardfs_link,
- .mknod = sdcardfs_mknod,
- */
};
const struct inode_operations sdcardfs_main_iops = {
diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c
index 843fcd216116..e1bff0da1925 100644
--- a/fs/sdcardfs/lookup.c
+++ b/fs/sdcardfs/lookup.c
@@ -428,7 +428,12 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
}
/* save current_cred and override it */
- OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
+ SDCARDFS_I(dir)->data);
+ if (!saved_cred) {
+ ret = ERR_PTR(-ENOMEM);
+ goto out_err;
+ }
sdcardfs_get_lower_path(parent, &lower_parent_path);
@@ -459,7 +464,7 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
out:
sdcardfs_put_lower_path(parent, &lower_parent_path);
- REVERT_CRED(saved_cred);
+ revert_fsids(saved_cred);
out_err:
dput(parent);
return ret;
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index eda8e7aa6911..b2e7db857dcf 100644
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -88,31 +88,6 @@
(x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\
} while (0)
-/* OVERRIDE_CRED() and REVERT_CRED()
- * OVERRIDE_CRED()
- * backup original task->cred
- * and modifies task->cred->fsuid/fsgid to specified value.
- * REVERT_CRED()
- * restore original task->cred->fsuid/fsgid.
- * These two macro should be used in pair, and OVERRIDE_CRED() should be
- * placed at the beginning of a function, right after variable declaration.
- */
-#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred, info) \
- do { \
- saved_cred = override_fsids(sdcardfs_sbi, info->data); \
- if (!saved_cred) \
- return -ENOMEM; \
- } while (0)
-
-#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred, info) \
- do { \
- saved_cred = override_fsids(sdcardfs_sbi, info->data); \
- if (!saved_cred) \
- return ERR_PTR(-ENOMEM); \
- } while (0)
-
-#define REVERT_CRED(saved_cred) revert_fsids(saved_cred)
-
/* Android 5.0 support */
/* Permission mode for a specific node. Controls how file permissions
diff --git a/include/net/sock.h b/include/net/sock.h
index 97f8ed2202bf..76b170af1b0b 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2290,4 +2290,15 @@ extern int sysctl_optmem_max;
extern __u32 sysctl_wmem_default;
extern __u32 sysctl_rmem_default;
+/* SOCKEV Notifier Events */
+#define SOCKEV_SOCKET 0x00
+#define SOCKEV_BIND 0x01
+#define SOCKEV_LISTEN 0x02
+#define SOCKEV_ACCEPT 0x03
+#define SOCKEV_CONNECT 0x04
+#define SOCKEV_SHUTDOWN 0x05
+
+int sockev_register_notify(struct notifier_block *nb);
+int sockev_unregister_notify(struct notifier_block *nb);
+
#endif /* _SOCK_H */
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index ef07f7825101..7c8a02d5286f 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -507,7 +507,13 @@ enum ipa_per_client_stats_event {
IPA_PER_CLIENT_STATS_EVENT_MAX
};
-#define IPA_EVENT_MAX_NUM (IPA_PER_CLIENT_STATS_EVENT_MAX)
+enum ipa_wlan_fw_ssr_event {
+ WLAN_FWR_SSR_BEFORE_SHUTDOWN = IPA_PER_CLIENT_STATS_EVENT_MAX,
+ IPA_WLAN_FW_SSR_EVENT_MAX
+#define IPA_WLAN_FW_SSR_EVENT_MAX IPA_WLAN_FW_SSR_EVENT_MAX
+};
+
+#define IPA_EVENT_MAX_NUM (IPA_WLAN_FW_SSR_EVENT_MAX)
#define IPA_EVENT_MAX ((int)IPA_EVENT_MAX_NUM)
/**
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index 841c40af4d47..ae65649964ff 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -262,6 +262,9 @@ struct cam_req_mgr_link_control {
((idx & CAM_MEM_MGR_HDL_IDX_MASK) | \
(fd << (CAM_MEM_MGR_HDL_FD_END_POS - CAM_MEM_MGR_HDL_FD_SIZE))) \
+#define GET_FD_FROM_HANDLE(hdl) \
+ (hdl >> (CAM_MEM_MGR_HDL_FD_END_POS - CAM_MEM_MGR_HDL_FD_SIZE)) \
+
#define CAM_MEM_MGR_GET_HDL_IDX(hdl) (hdl & CAM_MEM_MGR_HDL_IDX_MASK)
#define CAM_MEM_MGR_SET_SECURE_HDL(hdl, flag) \
diff --git a/include/uapi/media/cam_sync.h b/include/uapi/media/cam_sync.h
index 003c9ad5ce20..4a8781fc823d 100644
--- a/include/uapi/media/cam_sync.h
+++ b/include/uapi/media/cam_sync.h
@@ -117,7 +117,7 @@ struct cam_private_ioctl_arg {
__u32 size;
__u32 result;
__u32 reserved;
- __user __u64 ioctl_ptr;
+ __u64 ioctl_ptr;
};
#define CAM_PRIVATE_IOCTL_CMD \
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 712ba4ea4d00..14bc686f6afa 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4275,7 +4275,7 @@ static DEFINE_SPINLOCK(zombie_list_lock);
* object, it will not preserve its functionality. Once the last 'user'
* gives up the object, we'll destroy the thing.
*/
-int perf_event_release_kernel(struct perf_event *event)
+static int __perf_event_release_kernel(struct perf_event *event)
{
struct perf_event_context *ctx = event->ctx;
struct perf_event *child, *tmp;
@@ -4286,7 +4286,7 @@ int perf_event_release_kernel(struct perf_event *event)
* back online.
*/
#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
- if (!cpu_online(event->cpu)) {
+ if (event->cpu != -1 && per_cpu(is_hotplugging, event->cpu)) {
if (event->state == PERF_EVENT_STATE_ZOMBIE)
return 0;
@@ -4403,6 +4403,17 @@ no_ctx:
put_event(event); /* Must be the 'last' reference */
return 0;
}
+
+int perf_event_release_kernel(struct perf_event *event)
+{
+ int ret;
+
+ mutex_lock(&pmus_lock);
+ ret = __perf_event_release_kernel(event);
+ mutex_unlock(&pmus_lock);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(perf_event_release_kernel);
/*
@@ -11090,7 +11101,7 @@ static void perf_event_zombie_cleanup(unsigned int cpu)
* PMU expects it to be in an active state
*/
event->state = PERF_EVENT_STATE_ACTIVE;
- perf_event_release_kernel(event);
+ __perf_event_release_kernel(event);
spin_lock(&zombie_list_lock);
}
@@ -11105,6 +11116,7 @@ static int perf_event_start_swevents(unsigned int cpu)
struct perf_event *event;
int idx;
+ mutex_lock(&pmus_lock);
perf_event_zombie_cleanup(cpu);
idx = srcu_read_lock(&pmus_srcu);
@@ -11119,6 +11131,8 @@ static int perf_event_start_swevents(unsigned int cpu)
}
srcu_read_unlock(&pmus_srcu, idx);
per_cpu(is_hotplugging, cpu) = false;
+ mutex_unlock(&pmus_lock);
+
return 0;
}
@@ -11180,8 +11194,10 @@ static void perf_event_exit_cpu_context(int cpu) { }
int perf_event_exit_cpu(unsigned int cpu)
{
+ mutex_lock(&pmus_lock);
per_cpu(is_hotplugging, cpu) = true;
perf_event_exit_cpu_context(cpu);
+ mutex_unlock(&pmus_lock);
return 0;
}
diff --git a/net/core/dst.c b/net/core/dst.c
index b5de3663926f..39cc11968cf9 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -349,15 +349,8 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old)
new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY;
prev = cmpxchg(&dst->_metrics, old, new);
- if (prev == old) {
- struct dst_metrics *old_p = (struct dst_metrics *)
- __DST_METRICS_PTR(old);
-
- if (prev & DST_METRICS_REFCOUNTED) {
- if (atomic_dec_and_test(&old_p->refcnt))
- kfree(old_p);
- }
- }
+ if (prev == old)
+ kfree(__DST_METRICS_PTR(old));
}
EXPORT_SYMBOL(__dst_destroy_metrics_generic);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 94bf810ad242..a30d87c5de76 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock)
return 0;
}
-static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
- gfp_t allocation, struct sock *sk)
+static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation,
+ struct sock *sk)
{
int err = -ENOBUFS;
- sock_hold(sk);
- if (*skb2 == NULL) {
- if (atomic_read(&skb->users) != 1) {
- *skb2 = skb_clone(skb, allocation);
- } else {
- *skb2 = skb;
- atomic_inc(&skb->users);
- }
- }
- if (*skb2 != NULL) {
- if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
- skb_set_owner_r(*skb2, sk);
- skb_queue_tail(&sk->sk_receive_queue, *skb2);
- sk->sk_data_ready(sk);
- *skb2 = NULL;
- err = 0;
- }
+ if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
+ return err;
+
+ skb = skb_clone(skb, allocation);
+
+ if (skb) {
+ skb_set_owner_r(skb, sk);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk);
+ err = 0;
}
- sock_put(sk);
return err;
}
@@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
{
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
struct sock *sk;
- struct sk_buff *skb2 = NULL;
int err = -ESRCH;
/* XXX Do we need something like netlink_overrun? I think
@@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
* socket.
*/
if (pfk->promisc)
- pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
+ pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
/* the exact target will be processed later */
if (sk == one_sk)
@@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
continue;
}
- err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
+ err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
/* Error is cleared after successful sending to at least one
* registered KM */
@@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
rcu_read_unlock();
if (one_sk != NULL)
- err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
+ err = pfkey_broadcast_one(skb, allocation, one_sk);
- kfree_skb(skb2);
kfree_skb(skb);
return err;
}
diff --git a/net/socket.c b/net/socket.c
index a4fb47262f0b..0678601ec720 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -117,6 +117,8 @@ unsigned int sysctl_net_busy_poll __read_mostly;
static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
+static BLOCKING_NOTIFIER_HEAD(sockev_notifier_list);
+
static int sock_mmap(struct file *file, struct vm_area_struct *vma);
static int sock_close(struct inode *inode, struct file *file);
@@ -171,6 +173,14 @@ static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
static DEFINE_PER_CPU(int, sockets_in_use);
/*
+ * Socket Event framework helpers
+ */
+static void sockev_notify(unsigned long event, struct socket *sk)
+{
+ blocking_notifier_call_chain(&sockev_notifier_list, event, sk);
+}
+
+/**
* Support routines.
* Move socket addresses back and forth across the kernel/user
* divide and look after the messy bits.
@@ -1255,6 +1265,9 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
if (retval < 0)
goto out;
+ if (retval == 0)
+ sockev_notify(SOCKEV_SOCKET, sock);
+
retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
if (retval < 0)
goto out_release;
@@ -1400,6 +1413,8 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
&address, addrlen);
}
fput_light(sock->file, fput_needed);
+ if (!err)
+ sockev_notify(SOCKEV_BIND, sock);
}
return err;
}
@@ -1427,6 +1442,8 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
err = sock->ops->listen(sock, backlog);
fput_light(sock->file, fput_needed);
+ if (!err)
+ sockev_notify(SOCKEV_LISTEN, sock);
}
return err;
}
@@ -1513,7 +1530,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
fd_install(newfd, newfile);
err = newfd;
-
+ if (!err)
+ sockev_notify(SOCKEV_ACCEPT, sock);
out_put:
fput_light(sock->file, fput_needed);
out:
@@ -1563,6 +1581,8 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
sock->file->f_flags);
+ if (!err)
+ sockev_notify(SOCKEV_CONNECT, sock);
out_put:
fput_light(sock->file, fput_needed);
out:
@@ -1822,6 +1842,7 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how)
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock != NULL) {
+ sockev_notify(SOCKEV_SHUTDOWN, sock);
err = security_socket_shutdown(sock, how);
if (!err)
err = sock->ops->shutdown(sock, how);
@@ -3330,3 +3351,15 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
return sock->ops->shutdown(sock, how);
}
EXPORT_SYMBOL(kernel_sock_shutdown);
+
+int sockev_register_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&sockev_notifier_list, nb);
+}
+EXPORT_SYMBOL(sockev_register_notify);
+
+int sockev_unregister_notify(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&sockev_notifier_list, nb);
+}
+EXPORT_SYMBOL(sockev_unregister_notify);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 3ce53cf82df5..dc0a82cc59c8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1411,6 +1411,9 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
(ut[i].family != prev_family))
return -EINVAL;
+ if (ut[i].mode >= XFRM_MODE_MAX)
+ return -EINVAL;
+
prev_family = ut[i].family;
switch (ut[i].family) {