summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-04-20 16:10:24 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-20 16:10:22 -0700
commit68ddf4f0c2eec13613c4f3051651b02b2a93a7bd (patch)
treed83f5f90d77bdb13b9f08ebfcb2ef80c2efef5d5
parent661a45ee187da47b01664da9e55b1f1675fdba1a (diff)
parentfd7aadcb297abfadd11de5fddcdaa196de0a9929 (diff)
Merge "msm: camera: Add spinlock protection for flags in CCI driver"
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c59
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h3
2 files changed, 60 insertions, 2 deletions
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index b067c4916341..0ff270bb8410 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -201,6 +201,7 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
enum cci_i2c_queue_t queue)
{
int32_t rc = 0;
+ unsigned long flags;
uint32_t read_val = 0;
uint32_t reg_offset = master * 0x200 + queue * 0x100;
read_val = msm_camera_io_r_mb(cci_dev->base +
@@ -223,6 +224,8 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
reg_val = 1 << ((master * 2) + queue);
CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__);
+ spin_lock_irqsave(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
atomic_set(&cci_dev->cci_master_info[master].
done_pending[queue], 1);
msm_camera_io_w_mb(reg_val, cci_dev->base +
@@ -230,6 +233,8 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
CDBG("%s line %d wait_for_completion_timeout\n",
__func__, __LINE__);
atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
rc = wait_for_completion_timeout(&cci_dev->
cci_master_info[master].report_q[queue], CCI_TIMEOUT);
if (rc <= 0) {
@@ -438,10 +443,17 @@ static int32_t msm_cci_wait_report_cmd(struct cci_device *cci_dev,
enum cci_i2c_master_t master,
enum cci_i2c_queue_t queue)
{
+ unsigned long flags;
uint32_t reg_val = 1 << ((master * 2) + queue);
msm_cci_load_report_cmd(cci_dev, master, queue);
+
+ spin_lock_irqsave(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
atomic_set(&cci_dev->cci_master_info[master].done_pending[queue], 1);
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
+
msm_camera_io_w_mb(reg_val, cci_dev->base +
CCI_QUEUE_START_ADDR);
return msm_cci_wait(cci_dev, master, queue);
@@ -451,13 +463,19 @@ static void msm_cci_process_half_q(struct cci_device *cci_dev,
enum cci_i2c_master_t master,
enum cci_i2c_queue_t queue)
{
+ unsigned long flags;
uint32_t reg_val = 1 << ((master * 2) + queue);
+
+ spin_lock_irqsave(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
if (0 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
msm_cci_load_report_cmd(cci_dev, master, queue);
atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
msm_camera_io_w_mb(reg_val, cci_dev->base +
CCI_QUEUE_START_ADDR);
}
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
}
static int32_t msm_cci_process_full_q(struct cci_device *cci_dev,
@@ -465,15 +483,23 @@ static int32_t msm_cci_process_full_q(struct cci_device *cci_dev,
enum cci_i2c_queue_t queue)
{
int32_t rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
if (1 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
atomic_set(&cci_dev->cci_master_info[master].
done_pending[queue], 1);
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
rc = msm_cci_wait(cci_dev, master, queue);
if (rc < 0) {
pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
return rc;
}
} else {
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
rc = msm_cci_wait_report_cmd(cci_dev, master, queue);
if (rc < 0) {
pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
@@ -501,8 +527,13 @@ static int32_t msm_cci_transfer_end(struct cci_device *cci_dev,
enum cci_i2c_queue_t queue)
{
int32_t rc = 0;
+ unsigned long flags;
+ spin_lock_irqsave(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
if (0 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
rc = msm_cci_lock_queue(cci_dev, master, queue, 0);
if (rc < 0) {
pr_err("%s failed line %d\n", __func__, __LINE__);
@@ -516,6 +547,8 @@ static int32_t msm_cci_transfer_end(struct cci_device *cci_dev,
} else {
atomic_set(&cci_dev->cci_master_info[master].
done_pending[queue], 1);
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
rc = msm_cci_wait(cci_dev, master, queue);
if (rc < 0) {
pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
@@ -570,6 +603,7 @@ static int32_t msm_cci_data_queue(struct cci_device *cci_dev,
uint32_t reg_offset;
uint32_t val = 0;
uint32_t max_queue_size;
+ unsigned long flags;
if (i2c_cmd == NULL) {
pr_err("%s:%d Failed line\n", __func__,
@@ -613,7 +647,11 @@ static int32_t msm_cci_data_queue(struct cci_device *cci_dev,
msm_camera_io_w_mb(val, cci_dev->base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
reg_offset);
+ spin_lock_irqsave(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0);
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
+ lock_q[queue], flags);
max_queue_size = cci_dev->cci_i2c_queue_info[master][queue].
max_queue_size;
@@ -1641,6 +1679,7 @@ static int32_t msm_cci_config(struct v4l2_subdev *sd,
static irqreturn_t msm_cci_irq(int irq_num, void *data)
{
uint32_t irq;
+ unsigned long flags;
struct cci_device *cci_dev = data;
irq = msm_camera_io_r_mb(cci_dev->base + CCI_IRQ_STATUS_0_ADDR);
msm_camera_io_w_mb(irq, cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
@@ -1667,22 +1706,30 @@ static irqreturn_t msm_cci_irq(int irq_num, void *data)
if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK) {
struct msm_camera_cci_master_info *cci_master_info;
cci_master_info = &cci_dev->cci_master_info[MASTER_0];
+ spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_0].
+ lock_q[QUEUE_0], flags);
atomic_set(&cci_master_info->q_free[QUEUE_0], 0);
cci_master_info->status = 0;
if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) {
complete(&cci_master_info->report_q[QUEUE_0]);
atomic_set(&cci_master_info->done_pending[QUEUE_0], 0);
}
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_0].
+ lock_q[QUEUE_0], flags);
}
if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK) {
struct msm_camera_cci_master_info *cci_master_info;
cci_master_info = &cci_dev->cci_master_info[MASTER_0];
+ spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_0].
+ lock_q[QUEUE_1], flags);
atomic_set(&cci_master_info->q_free[QUEUE_1], 0);
cci_master_info->status = 0;
if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) {
complete(&cci_master_info->report_q[QUEUE_1]);
atomic_set(&cci_master_info->done_pending[QUEUE_1], 0);
}
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_0].
+ lock_q[QUEUE_1], flags);
}
if (irq & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) {
cci_dev->cci_master_info[MASTER_1].status = 0;
@@ -1691,22 +1738,30 @@ static irqreturn_t msm_cci_irq(int irq_num, void *data)
if (irq & CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK) {
struct msm_camera_cci_master_info *cci_master_info;
cci_master_info = &cci_dev->cci_master_info[MASTER_1];
+ spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_1].
+ lock_q[QUEUE_0], flags);
atomic_set(&cci_master_info->q_free[QUEUE_0], 0);
cci_master_info->status = 0;
if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) {
complete(&cci_master_info->report_q[QUEUE_0]);
atomic_set(&cci_master_info->done_pending[QUEUE_0], 0);
}
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_1].
+ lock_q[QUEUE_0], flags);
}
if (irq & CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK) {
struct msm_camera_cci_master_info *cci_master_info;
cci_master_info = &cci_dev->cci_master_info[MASTER_1];
+ spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_1].
+ lock_q[QUEUE_1], flags);
atomic_set(&cci_master_info->q_free[QUEUE_1], 0);
cci_master_info->status = 0;
if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) {
complete(&cci_master_info->report_q[QUEUE_1]);
atomic_set(&cci_master_info->done_pending[QUEUE_1], 0);
}
+ spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_1].
+ lock_q[QUEUE_1], flags);
}
if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) {
cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
@@ -1795,7 +1850,9 @@ static void msm_cci_init_cci_params(struct cci_device *new_cci_dev)
mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]);
init_completion(&new_cci_dev->
cci_master_info[i].report_q[j]);
- }
+ spin_lock_init(&new_cci_dev->
+ cci_master_info[i].lock_q[j]);
+ }
}
return;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
index 6e39d814bd73..eb615cc7a62c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -125,6 +125,7 @@ struct msm_camera_cci_master_info {
struct mutex mutex_q[NUM_QUEUES];
struct completion report_q[NUM_QUEUES];
atomic_t done_pending[NUM_QUEUES];
+ spinlock_t lock_q[NUM_QUEUES];
};
struct msm_cci_clk_params_t {