Merge "msm: camera: add check for csid_cid to prevent of overwrite memory"
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
index 2cb528c..6ef897a 100644
--- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -39,7 +39,7 @@
1200 - WCN XO settling time (usec)
1 - WCN RPM power collapse enabled
1 - WCN standalone power collapse enabled
-
+ 6 - GPIO strength value
Example:
@@ -64,5 +64,5 @@
qcom,has-48mhz-xo;
qcom,has-pronto-hw;
qcom,wcnss-adc_tm = <&pm8226_adc_tm>;
- qcom,wcnss-pm = <11 21 1200 1 1>;
+ qcom,wcnss-pm = <11 21 1200 1 1 6>;
};
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 55bc185..a521cbc 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -74,6 +74,7 @@
CONFIG_ARM_ARCH_TIMER=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
CONFIG_KSM=y
CONFIG_CC_STACKPROTECTOR=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index b239bcb..1f7fcbd 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -75,6 +75,7 @@
CONFIG_ARM_ARCH_TIMER=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
CONFIG_KSM=y
CONFIG_CC_STACKPROTECTOR=y
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 28b2195..6a71e36 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -23,7 +23,7 @@
#include <linux/string.h>
#include <linux/atomic.h>
#include <linux/of.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm-generic/sizes.h>
#include <mach/memory.h>
#include <mach/msm_rtb.h>
@@ -38,18 +38,20 @@
/* Write
* 1) 3 bytes sentinel
* 2) 1 bytes of log type
- * 3) 4 bytes of where the caller came from
+ * 3) 8 bytes of where the caller came from
* 4) 4 bytes index
- * 4) 4 bytes extra data from the caller
+ * 4) 8 bytes extra data from the caller
+ * 5) 8 bytes for timestamp
*
- * Total = 16 bytes.
+ * Total = 32 bytes.
*/
struct msm_rtb_layout {
unsigned char sentinel[3];
unsigned char log_type;
- void *caller;
- unsigned long idx;
- void *data;
+ uint32_t idx;
+ uint64_t caller;
+ uint64_t data;
+ uint64_t timestamp;
} __attribute__ ((__packed__));
@@ -70,7 +72,7 @@
static atomic_t msm_rtb_idx;
#endif
-struct msm_rtb_state msm_rtb = {
+static struct msm_rtb_state msm_rtb = {
.filter = 1 << LOGK_LOGBUF,
.enabled = 1,
};
@@ -109,24 +111,29 @@
start->log_type = (char)log_type;
}
-static void msm_rtb_write_caller(void *caller, struct msm_rtb_layout *start)
+static void msm_rtb_write_caller(uint64_t caller, struct msm_rtb_layout *start)
{
start->caller = caller;
}
-static void msm_rtb_write_idx(unsigned long idx,
+static void msm_rtb_write_idx(uint32_t idx,
struct msm_rtb_layout *start)
{
start->idx = idx;
}
-static void msm_rtb_write_data(void *data, struct msm_rtb_layout *start)
+static void msm_rtb_write_data(uint64_t data, struct msm_rtb_layout *start)
{
start->data = data;
}
-static void uncached_logk_pc_idx(enum logk_event_type log_type, void *caller,
- void *data, int idx)
+static void msm_rtb_write_timestamp(struct msm_rtb_layout *start)
+{
+ start->timestamp = sched_clock();
+}
+
+static void uncached_logk_pc_idx(enum logk_event_type log_type, uint64_t caller,
+ uint64_t data, int idx)
{
struct msm_rtb_layout *start;
@@ -137,6 +144,7 @@
msm_rtb_write_caller(caller, start);
msm_rtb_write_idx(idx, start);
msm_rtb_write_data(data, start);
+ msm_rtb_write_timestamp(start);
mb();
return;
@@ -145,13 +153,10 @@
static void uncached_logk_timestamp(int idx)
{
unsigned long long timestamp;
- void *timestamp_upper, *timestamp_lower;
timestamp = sched_clock();
- timestamp_lower = (void *)lower_32_bits(timestamp);
- timestamp_upper = (void *)upper_32_bits(timestamp);
-
- uncached_logk_pc_idx(LOGK_TIMESTAMP|LOGTYPE_NOPC, timestamp_lower,
- timestamp_upper, idx);
+ uncached_logk_pc_idx(LOGK_TIMESTAMP|LOGTYPE_NOPC,
+ (uint64_t)lower_32_bits(timestamp),
+ (uint64_t)upper_32_bits(timestamp), idx);
}
#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
@@ -213,7 +218,8 @@
i = msm_rtb_get_idx();
- uncached_logk_pc_idx(log_type, caller, data, i);
+ uncached_logk_pc_idx(log_type, (uint64_t)((unsigned long) caller),
+ (uint64_t)((unsigned long) data), i);
return 1;
}
@@ -225,7 +231,7 @@
}
EXPORT_SYMBOL(uncached_logk);
-int msm_rtb_probe(struct platform_device *pdev)
+static int msm_rtb_probe(struct platform_device *pdev)
{
struct msm_rtb_platform_data *d = pdev->dev.platform_data;
#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
@@ -297,7 +303,6 @@
{.compatible = RTB_COMPAT_STR},
{},
};
-EXPORT_COMPAT(RTB_COMPAT_STR);
static struct platform_driver msm_rtb_driver = {
.driver = {
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index bcab791..d79a169 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -221,13 +221,17 @@
struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch)
{
unsigned int prev;
+ struct kgsl_device *device;
spin_lock(&drawctxt->lock);
if (kgsl_context_detached(&drawctxt->base) ||
drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) {
spin_unlock(&drawctxt->lock);
+ device = cmdbatch->device;
/* get rid of this cmdbatch since the context is bad */
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
kgsl_cmdbatch_destroy(cmdbatch);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
return -EINVAL;
}
@@ -414,7 +418,10 @@
*/
if (cmdbatch->flags & KGSL_CONTEXT_SYNC) {
+ struct kgsl_device *device = cmdbatch->device;
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
kgsl_cmdbatch_destroy(cmdbatch);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
continue;
}
@@ -931,11 +938,8 @@
drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) {
replay[i] = NULL;
- kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
kgsl_cancel_events_timestamp(device, cmd->context,
cmd->timestamp);
- kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
-
kgsl_cmdbatch_destroy(cmd);
}
}
@@ -1084,7 +1088,8 @@
kgsl_device_snapshot(device, 1);
}
- kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+
/* Allocate memory to store the inflight commands */
replay = kzalloc(sizeof(*replay) * dispatcher->inflight, GFP_KERNEL);
@@ -1092,6 +1097,7 @@
if (replay == NULL) {
unsigned int ptr = dispatcher->head;
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
/* Recovery failed - mark everybody guilty */
mark_guilty_context(device, 0);
@@ -1111,6 +1117,7 @@
*/
count = 0;
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
goto replay;
}
@@ -1168,7 +1175,9 @@
cmdbatch->context->id, cmdbatch->timestamp);
mark_guilty_context(device, cmdbatch->context->id);
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
adreno_drawctxt_invalidate(device, cmdbatch->context);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
}
/*
@@ -1277,7 +1286,9 @@
mark_guilty_context(device, cmdbatch->context->id);
/* Invalidate the context */
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
adreno_drawctxt_invalidate(device, cmdbatch->context);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
replay:
@@ -1296,8 +1307,10 @@
/* If adreno_reset() fails then what hope do we have for the future? */
BUG_ON(ret);
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
/* Remove any pending command batches that have been invalidated */
remove_invalidated_cmdbatches(device, replay, count);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
/* Replay the pending command buffers */
for (i = 0; i < count; i++) {
@@ -1339,9 +1352,11 @@
/* Mark this context as guilty (failed recovery) */
mark_guilty_context(device, replay[i]->context->id);
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
adreno_drawctxt_invalidate(device, replay[i]->context);
remove_invalidated_cmdbatches(device, &replay[i],
count - i);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
}
}
@@ -1449,8 +1464,10 @@
dispatcher->head = CMDQUEUE_NEXT(dispatcher->head,
ADRENO_DISPATCH_CMDQUEUE_SIZE);
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
/* Destroy the retired command batch */
kgsl_cmdbatch_destroy(cmdbatch);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
/* Update the expire time for the next command batch */
@@ -1695,16 +1712,19 @@
void adreno_dispatcher_close(struct adreno_device *adreno_dev)
{
struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
+ struct kgsl_device *device = &adreno_dev->dev;
mutex_lock(&dispatcher->mutex);
del_timer_sync(&dispatcher->timer);
del_timer_sync(&dispatcher->fault_timer);
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
while (dispatcher->head != dispatcher->tail) {
kgsl_cmdbatch_destroy(dispatcher->cmdqueue[dispatcher->head]);
dispatcher->head = (dispatcher->head + 1)
% ADRENO_DISPATCH_CMDQUEUE_SIZE;
}
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
mutex_unlock(&dispatcher->mutex);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9adede8..a5b25a0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1807,16 +1807,13 @@
list_for_each_entry_safe(event, tmp, &cancel_synclist, node) {
if (event->type == KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP) {
- struct kgsl_device *device = cmdbatch->device;
/*
* Timestamp events are guaranteed to signal
* when canceled
*/
- kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
- kgsl_cancel_event(device, event->context,
+ kgsl_cancel_event(cmdbatch->device, event->context,
event->timestamp, kgsl_cmdbatch_sync_func,
event);
- kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
} else if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) {
/* Put events that are successfully canceled */
if (kgsl_sync_fence_async_cancel(event->handle))
@@ -2314,8 +2311,11 @@
* -EPROTO is a "success" error - it just tells the user that the
* context had previously faulted
*/
- if (result && result != -EPROTO)
+ if (result && result != -EPROTO) {
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
kgsl_cmdbatch_destroy(cmdbatch);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+ }
done:
kgsl_context_put(context);
@@ -2366,8 +2366,11 @@
* -EPROTO is a "success" error - it just tells the user that the
* context had previously faulted
*/
- if (result && result != -EPROTO)
+ if (result && result != -EPROTO) {
+ kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
kgsl_cmdbatch_destroy(cmdbatch);
+ kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+ }
done:
kgsl_context_put(context);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 4a4a88c..887bb72 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1948,13 +1948,13 @@
return;
}
- pr_debug("%s:size=%d: <%d, %d, %d, %d, %d>\n", __func__,
+ pr_debug("%s:size=%d: <%d, %d, %d, %d, %d %d>\n", __func__,
prop_len, *payload, *(payload+1), *(payload+2),
- *(payload+3), *(payload+4));
+ *(payload+3), *(payload+4), *(payload+5));
hdr = (struct smd_msg_hdr *)msg;
hdr->msg_type = WCNSS_PM_CONFIG_REQ;
- hdr->msg_len = sizeof(struct smd_msg_hdr) + prop_len;
+ hdr->msg_len = sizeof(struct smd_msg_hdr) + (prop_len * sizeof(int));
rc = wcnss_smd_tx(msg, hdr->msg_len);
if (rc < 0)
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index e51da7f..b1681f1 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -61,7 +61,7 @@
#define CORE_RESET_RSP_GID (0x60)
#define CORE_RESET_OID (0x00)
#define CORE_RST_NTF_LENGTH (0x02)
-#define WAKE_TIMEOUT (10)
+#define WAKE_TIMEOUT (1000)
#define WAKE_REG (0x10)
#define EFUSE_REG (0xA0)
#define WAKEUP_SRC_TIMEOUT (2000)
@@ -101,6 +101,8 @@
struct workqueue_struct *my_wq;
};
+static int nfcc_reboot(struct notifier_block *notifier, unsigned long val,
+ void *v);
static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr);
static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr,
@@ -124,7 +126,7 @@
unsigned int disable_ctrl;
-bool region2_sent;
+bool region2_sent;
static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
{
@@ -163,15 +165,16 @@
if (device_may_wakeup(&qca199x_dev->client->dev) &&
(qca199x_dev->client->dev.power.is_suspended == true)) {
dev_dbg(&qca199x_dev->client->dev,
- "NFC:Processor in suspend state device_may_wakeup\n");
+ "%s: NFC:Processor in suspend state device_may_wakeup\n",
+ __func__);
/*
- * Keep system awake long enough to allow userspace
- * to process the packet.
- */
+ * Keep system awake long enough to allow userspace
+ * to process the packet.
+ */
pm_wakeup_event(&qca199x_dev->client->dev, WAKEUP_SRC_TIMEOUT);
} else {
dev_dbg(&qca199x_dev->client->dev,
- "NFC:Processor not in suspend state\n");
+ "%s: NFC:Processor not in suspend state\n", __func__);
}
spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
@@ -329,7 +332,12 @@
/* READ */
if ((ftm_raw_write_mode == 0) && (ftm_werr_code == 0)) {
ftm_rerr_code = i2c_master_recv(qca199x_dev->client,
- &rd_byte, 1);
+ &rd_byte, sizeof(rd_byte));
+
+ if (ftm_rerr_code != sizeof(rd_byte)) {
+ total = -EMSGSIZE;
+ goto err;
+ }
if (ftm_rerr_code == 0x1)
ftm_rerr_code = 0;
tmp[0] = (unsigned char)ftm_rerr_code;
@@ -388,8 +396,8 @@
if (total > 0) {
if ((total > count) || copy_to_user(buf, tmp, total)) {
dev_err(&qca199x_dev->client->dev,
- "failed to copy to user space, total = %d\n",
- total);
+ "%s: failed to copy to user space, total = %d\n",
+ __func__, total);
total = -EFAULT;
}
}
@@ -438,6 +446,9 @@
ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
PAYLOAD_HEADER_LENGTH));
total = ret;
+ if (ret != (length + PAYLOAD_HEADER_LENGTH))
+ goto leave;
+
}
dev_dbg(&qca199x_dev->client->dev, "%s : NfcNciRx %x %x %x\n",
__func__, tmp[0], tmp[1], tmp[2]);
@@ -456,12 +467,13 @@
int nfcc_buffer = 0;
if (count > MAX_BUFFER_SIZE) {
- dev_err(&qca199x_dev->client->dev, "out of memory\n");
+ dev_err(&qca199x_dev->client->dev, "%s: out of memory\n",
+ __func__);
return -ENOMEM;
}
if (copy_from_user(tmp, buf, count)) {
dev_err(&qca199x_dev->client->dev,
- "nfc-nci write: failed to copy from user space\n");
+ "%s: failed to copy from user space\n", __func__);
return -EFAULT;
}
/*
@@ -477,7 +489,8 @@
/* There has been an error while reading from nfcc */
if (nfcc_buffer < 0) {
dev_err(&qca199x_dev->client->dev,
- "nfc-nci write: error while servicing nfcc read buffer\n");
+ "%s: error while servicing nfcc read buffer\n"
+ , __func__);
}
qca199x_dev->sent_first_nci_write = true;
qca199x_enable_irq(qca199x_dev);
@@ -492,7 +505,7 @@
if (count == 1) {
ftm_raw_write_mode = 0;
ret = i2c_master_send(qca199x_dev->client, tmp, count);
- if (ret == 1)
+ if (ret == count)
ftm_werr_code = 0;
else
ftm_werr_code = ret;
@@ -502,7 +515,7 @@
if (count == 2) {
ftm_raw_write_mode = 1;
ret = i2c_master_send(qca199x_dev->client, tmp, count);
- if (ret == 2)
+ if (ret == count)
ftm_werr_code = 0;
else
ftm_werr_code = ret;
@@ -515,7 +528,7 @@
}
if (ret != count) {
dev_err(&qca199x_dev->client->dev,
- "NFC: failed to write %d\n", ret);
+ "%s: failed to write %d\n", __func__, ret);
ret = -EIO;
}
mutex_unlock(&qca199x_dev->read_mutex);
@@ -549,7 +562,7 @@
qca199x_enable_irq_clk_req(qca199x_dev);
}
dev_dbg(&qca199x_dev->client->dev,
- "%d,%d\n", imajor(inode), iminor(inode));
+ "%s: %d,%d\n", __func__, imajor(inode), iminor(inode));
return ret;
}
@@ -561,17 +574,21 @@
int r = 0;
int time_taken = 0;
unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
- /* Change slave address to 0xE */
unsigned char raw_nci_wake[] = {0x10, 0x0F};
- unsigned short slave_addr = 0xE;
+ /* Change slave address to 0xE */
+ unsigned short slave_addr = 0xE;
unsigned short curr_addr;
- unsigned char wake_status = WAKE_REG;
+ unsigned char wake_status = WAKE_REG;
struct qca199x_dev *qca199x_dev = filp->private_data;
- dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
+ dev_dbg(&qca199x_dev->client->dev, "%s: info: %p\n",
__func__, qca199x_dev);
+ curr_addr = qca199x_dev->client->addr;
if (level == NFCC_SLEEP) {
+ /*
+ * Normal NCI write
+ */
r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
sizeof(raw_nci_sleep));
@@ -579,57 +596,79 @@
return -EMSGSIZE;
qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
} else {
- curr_addr = qca199x_dev->client->addr;
qca199x_dev->client->addr = slave_addr;
r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
sizeof(raw_nci_wake));
+ if (r != sizeof(raw_nci_wake)) {
+ r = -EMSGSIZE;
+ dev_err(&qca199x_dev->client->dev,
+ "%s: nci wake write failed. Check hardware\n",
+ __func__);
+ goto leave;
+ }
do {
wake_status = WAKE_REG;
- r = nfc_i2c_write(qca199x_dev->client, &wake_status, 1);
+ r = nfc_i2c_write(qca199x_dev->client, &wake_status,
+ sizeof(wake_status));
+ if (r != sizeof(wake_status)) {
+ r = -EMSGSIZE;
+ dev_err(&qca199x_dev->client->dev,
+ "%s: wake status write fail.Check hardware\n",
+ __func__);
+ goto leave;
+ }
/*
- * NFCC chip needs to be at least
- * 10usec high before make it low
+ * I2C line is low after ~10 usec
*/
usleep_range(10, 15);
r = i2c_master_recv(qca199x_dev->client, &wake_status,
sizeof(wake_status));
+ if (r != sizeof(wake_status)) {
+ r = -EMSGSIZE;
+ dev_err(&qca199x_dev->client->dev,
+ "%s: wake status read fail.Check hardware\n",
+ __func__);
+ goto leave;
+ }
time_taken++;
+ /*
+ * Each NFCC wakeup cycle
+ * takes about 0.5 ms
+ */
if ((wake_status & NCI_WAKE) != 0)
/* NFCC wakeup time is between 0.5 and .52 ms */
- usleep_range(500, 520);
+ usleep_range(500, 550);
} while ((wake_status & NCI_WAKE)
&& (time_taken < WAKE_TIMEOUT));
- /* Restore original NFCC slave I2C address */
-
- qca199x_dev->client->addr = curr_addr;
- if (r != sizeof(wake_status))
- return -EMSGSIZE;
-
if (time_taken >= WAKE_TIMEOUT) {
dev_err(&qca199x_dev->client->dev,
- " %s : TIMED OUT to get WAKEUP bit\n", __func__);
+ "%s: timed out to get wakeup bit\n", __func__);
r = -EIO;
+ goto leave;
}
+ r = 0;
qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
}
-
+leave:
+ /* Restore original NFCC slave I2C address */
+ qca199x_dev->client->addr = curr_addr;
return r;
}
/*
* Inside nfc_ioctl_power_states
*
- * @brief ioctl functions
+ * @brief ioctl functions
*
*
* Device control
* remove control via ioctl
- * (arg = 0): NFC_DISABLE GPIO = 0
- * (arg = 1): NFC_DISABLE GPIO = 1
- * NOT USED (arg = 2): FW_DL GPIO = 0
- * NOT USED (arg = 3): FW_DL GPIO = 1
+ * (arg = 0): NFC_DISABLE GPIO = 0
+ * (arg = 1): NFC_DISABLE GPIO = 1
+ * NOT USED (arg = 2): FW_DL GPIO = 0
+ * NOT USED (arg = 3): FW_DL GPIO = 1
* (arg = 4): NFCC_WAKE = 1
* (arg = 5): NFCC_WAKE = 0
*
@@ -648,7 +687,7 @@
dev_dbg(&qca199x_dev->client->dev, "gpio_set_value disable: %s: info: %p\n",
__func__, qca199x_dev);
gpio_set_value(qca199x_dev->dis_gpio, 0);
- usleep(1000);
+ usleep_range(1000, 1100);
} else if (arg == 1) {
/*
* We are attempting a hardware reset so let us disable
@@ -670,7 +709,7 @@
dev_dbg(&qca199x_dev->client->dev, "gpio_set_value enable: %s: info: %p\n",
__func__, qca199x_dev);
gpio_set_value(qca199x_dev->dis_gpio, 1);
- /*nfcc needs atleast 100ms for the chip to power cycle*/
+ /* NFCC needs at least 100 ms to power cycle*/
msleep(100);
} else if (arg == 2) {
mutex_lock(&qca199x_dev->read_mutex);
@@ -708,14 +747,14 @@
/*
* Inside nfc_ioctl_nfcc_mode
*
- * @brief nfc_ioctl_nfcc_mode
+ * @brief nfc_ioctl_nfcc_mode
*
* (arg = 0) ; NORMAL_MODE - Standard mode, unsolicited read behaviour
* (arg = 1) ; SOLICITED_MODE - As above but reads are solicited from User Land
* (arg = 2) ; UNSOLICITED_FTM_RAW MODE - NORMAL_MODE but messages from FTM and
- * not NCI Host.
+ * not NCI Host.
* (arg = 2) ; SOLICITED_FTM_RAW_MODE - As SOLICITED_MODE but messages from FTM
- * and not NCI Host.
+ * and not NCI Host.
*
*
*
@@ -766,6 +805,7 @@
*
* @brief nfc_ioctl_nfcc_efuse
*
+ *
*/
int nfc_ioctl_nfcc_efuse(struct file *filp, unsigned int cmd,
unsigned long arg)
@@ -826,11 +866,8 @@
unsigned long arg)
{
int r = 0;
- int time_taken = 0;
- unsigned short slave_addr = 0xE;
+ unsigned short slave_addr = 0xE;
unsigned short curr_addr;
- unsigned char raw_nci_wake[] = {0x10, 0x0F};
- unsigned char raw_nci_read;
unsigned char raw_chip_version_addr = 0x00;
unsigned char raw_chip_rev_id_addr = 0x9C;
unsigned char raw_chip_version = 0xFF;
@@ -844,88 +881,56 @@
* Always wake up chip when reading 0x9C, otherwise this
* register is not updated
*/
+ r = nfcc_wake(NFCC_WAKE, filp);
curr_addr = qca199x_dev->client->addr;
qca199x_dev->client->addr = slave_addr;
- r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
- sizeof(raw_nci_wake));
- if (r != sizeof(raw_nci_wake))
+
+ if (r) {
dev_err(&qca199x_dev->client->dev,
- "nfc_ioctl_nfcc_version : failed to send wake command\n");
-
- /*
- * After placing the NFCC to sleep by a PROP
- * SLEEP NCI msg (2F 03) and we need to wake
- * it back up to obtain some information (by
- * setting the wake bit).We need to determine
- * when it has in actual fact woken before we
- * can read the required data. We do that by
- * reading back & testing if that wake bit has
- * been cleared.
- */
- do {
- raw_nci_read = 0x10;
- r = nfc_i2c_write(qca199x_dev->client, &raw_nci_read, 1);
- /*
- * NFCC chip needs to be at least
- * 10usec high before make it low
- */
- usleep_range(10, 15);
-
- r = i2c_master_recv(qca199x_dev->client, &raw_nci_read,
- sizeof(raw_nci_read));
-
- if ((raw_nci_read & NCI_WAKE) != 0)
- /* NFCC wakeup time is between 0.5 and .52 ms */
- usleep_range(500, 520);
-
- time_taken++;
-
- } while ((raw_nci_read & NCI_WAKE)
- && (time_taken < WAKE_TIMEOUT));
-
- if (time_taken < WAKE_TIMEOUT)
- qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
- else
- dev_err(&qca199x_dev->client->dev,
- "nfc_ioctl_nfcc_version : TIMED OUT to get WAKEUP bit\n");
-
-
- if (r != 1) {
- /*
- * r < 0 indicates an error, maybe chip isn't
- * up yet.What should we do??? r = 0 indicates
- * nothing read, maybe chip isn't up yet. (should
- * not happen) r > 1 indicates too many bytes read,
- * maybe ?(should not happen)
- */
- dev_err(&qca199x_dev->client->dev,
- "nfc_ioctl_nfcc_version : i2c error %d\n", r);
+ "%s: nfcc wake failed: %d\n", __func__, r);
+ r = -EIO;
+ goto leave;
}
if (arg == 0) {
r = nfc_i2c_write(qca199x_dev->client,
- &raw_chip_version_addr, 1);
+ &raw_chip_version_addr, sizeof(raw_chip_version_addr));
+ if (r != sizeof(raw_chip_version_addr)) {
+ r = -EMSGSIZE;
+ goto err;
+ }
} else if (arg == 1) {
r = nfc_i2c_write(qca199x_dev->client,
- &raw_chip_rev_id_addr, 1);
+ &raw_chip_rev_id_addr, sizeof(raw_chip_rev_id_addr));
+ if (r != sizeof(raw_chip_version_addr)) {
+ r = -EMSGSIZE;
+ goto err;
+ }
} else {
- /* Restore original NFCC slave I2C address */
- qca199x_dev->client->addr = curr_addr;
- return -EINVAL;
+ r = -EINVAL;
+ goto err;
}
if (r < 0) {
- /* Restore original NFCC slave I2C address */
- qca199x_dev->client->addr = curr_addr;
- dev_err(&qca199x_dev->client->dev,
- "NFCC_INVALID_CHIP_VERSION : i2c write fail\n");
- return -EIO;
+ r = -EIO;
+ goto err;
}
-
- usleep(10);
- r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
-
+ /*
+ * I2C line is low after ~10 usec
+ */
+ usleep_range(10, 15);
+ r = i2c_master_recv(qca199x_dev->client, &raw_chip_version,
+ sizeof(raw_chip_version));
+ if (r != sizeof(raw_chip_version)) {
+ r = -EMSGSIZE;
+ goto err;
+ }
+ goto leave;
+err:
+ dev_err(&qca199x_dev->client->dev,
+ "%s: i2c access failed\n", __func__);
+leave:
/* Restore original NFCC slave I2C address */
qca199x_dev->client->addr = curr_addr;
return raw_chip_version;
@@ -934,12 +939,12 @@
/*
* Inside nfc_ioctl_kernel_logging
*
- * @brief nfc_ioctl_kernel_logging
+ * @brief nfc_ioctl_kernel_logging
*
* (arg = 0) ; NO_LOGGING
* (arg = 1) ; COMMS_LOGGING - BASIC LOGGING - Mainly just comms over I2C
* (arg = 2) ; FULL_LOGGING - ENABLE ALL - DBG messages for handlers etc.
- * ; ! Be aware as amount of logging could impact behaviour !
+ * ; ! Be aware as amount of logging could impact behaviour !
*
*
*/
@@ -947,19 +952,19 @@
{
int retval = 0;
struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
- struct qca199x_dev,
- qca199x_device);
+ struct qca199x_dev,
+ qca199x_device);
if (arg == 0) {
dev_dbg(&qca199x_dev->client->dev,
- "nfc_ioctl_kernel_logging : level = NO_LOGGING\n");
+ "%s : level = NO_LOGGING\n", __func__);
logging_level = 0;
} else if (arg == 1) {
dev_dbg(&qca199x_dev->client->dev,
- "nfc_ioctl_kernel_logging: level = COMMS_LOGGING only\n");
+ "%s: level = COMMS_LOGGING only\n", __func__);
logging_level = 1;
} else if (arg == 2) {
dev_dbg(&qca199x_dev->client->dev,
- "nfc_ioctl_kernel_logging: level = FULL_LOGGING\n");
+ "%s: level = FULL_LOGGING\n", __func__);
logging_level = 2;
}
return retval;
@@ -968,7 +973,7 @@
/*
* Inside nfc_ioctl_core_reset_ntf
*
- * @brief nfc_ioctl_core_reset_ntf
+ * @brief nfc_ioctl_core_reset_ntf
*
* Allows callers to determine if a CORE_RESET_NTF has arrived
*
@@ -980,22 +985,23 @@
{
struct qca199x_dev *qca199x_dev = filp->private_data;
dev_dbg(&qca199x_dev->client->dev,
- "nfc_ioctl_core_reset_ntf: returning = %d\n",
+ "%s: returning = %d\n",
+ __func__,
qca199x_dev->core_reset_ntf);
return qca199x_dev->core_reset_ntf;
}
-static long nfc_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
+static long nfc_ioctl(struct file *pfile, unsigned int cmd,
+ unsigned long arg)
{
int r = 0;
struct qca199x_dev *qca199x_dev = pfile->private_data;
switch (cmd) {
-
case NFC_SET_PWR:
r = nfc_ioctl_power_states(pfile, cmd, arg);
break;
case NFCC_MODE:
- nfc_ioctl_nfcc_mode(pfile, cmd, arg);
+ r = nfc_ioctl_nfcc_mode(pfile, cmd, arg);
break;
case NFCC_VERSION:
r = nfc_ioctl_nfcc_version(pfile, cmd, arg);
@@ -1050,9 +1056,15 @@
((i > 0xF) && (i < 0x12)) || ((i > 0x39) && (i < 0x4d)) ||
((i > 0x69) && (i < 0x74)) || (i == 0x18) || (i == 0x30) ||
(i == 0x58)) {
- r = nfc_i2c_write(client, &raw_reg_rd, 1);
+ r = nfc_i2c_write(client, &raw_reg_rd,
+ sizeof(raw_reg_rd));
+ if (r != sizeof(raw_reg_rd))
+ break;
msleep(20);
- r = i2c_master_recv(client, &raw_reg_rd, 1);
+ r = i2c_master_recv(client, &raw_reg_rd,
+ sizeof(raw_reg_rd));
+ if (r != sizeof(raw_reg_rd))
+ break;
}
}
client->addr = temp_addr;
@@ -1063,11 +1075,11 @@
int r;
r = i2c_master_send(client, buf, len);
- dev_dbg(&client->dev, "send: %d\n", r);
+ dev_dbg(&client->dev, "%s: send: %d\n", __func__, r);
if (r == -EREMOTEIO) { /* Retry, chip was in standby */
usleep_range(6000, 10000);
r = i2c_master_send(client, buf, len);
- dev_dbg(&client->dev, "send2: %d\n", r);
+ dev_dbg(&client->dev, "%s: send attempt 2: %d\n", __func__, r);
}
if (r != len)
return -EREMOTEIO;
@@ -1083,22 +1095,23 @@
client->addr = curr_addr;
/* Set-up Addr 0. No data written */
- r = i2c_master_send(client, &buf, 1);
+ r = i2c_master_send(client, &buf, sizeof(buf));
if (r < 0)
goto err_presence_check;
buf = 0;
/* Read back from Addr 0 */
- r = i2c_master_recv(client, &buf, 1);
+ r = i2c_master_recv(client, &buf, sizeof(buf));
if (r < 0)
goto err_presence_check;
r = 0;
- return r;
+ goto leave;
err_presence_check:
r = -ENXIO;
dev_err(&client->dev,
- "nfc-nci nfcc_presence check - no NFCC available\n");
+ "%s: - no NFCC available\n", __func__);
+leave:
return r;
}
/* Initialise qca199x_ NFC controller hardware */
@@ -1106,7 +1119,7 @@
struct qca199x_dev *qca199x_dev)
{
int r = 0;
- unsigned char raw_1p8_CONTROL_011[] = {0x11, XTAL_CLOCK};
+ unsigned char raw_1P8_CONTROL_011[] = {0x11, XTAL_CLOCK};
unsigned char raw_1P8_CONTROL_010[] = {0x10, PWR_EN};
unsigned char raw_1P8_X0_0B0[] = {0xB0, (FREQ_SEL)};
unsigned char raw_slave1[] = {0x09, NCI_I2C_SLAVE};
@@ -1123,12 +1136,17 @@
client->addr = curr_addr;
qca199x_dev->core_reset_ntf = DEFAULT_INITIAL_CORE_RESET_NTF;
- r = i2c_master_send(client, &buf, 1);
+ r = i2c_master_send(client, &buf, sizeof(buf));
if (r < 0)
goto err_init;
+ /*
+ * I2C line is low after ~10 usec
+ */
+ usleep_range(10, 15);
+
buf = 0;
- r = i2c_master_recv(client, &buf, 1);
+ r = i2c_master_recv(client, &buf, sizeof(buf));
if (r < 0)
goto err_init;
@@ -1138,36 +1156,37 @@
if (r < 0)
goto err_init;
- usleep(1000);
- RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
+ usleep_range(1000, 1100);
- r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
- sizeof(raw_1p8_CONTROL_011));
+ RAW(1P8_CONTROL_011, XTAL_CLOCK | 0x01);
+
+ r = nfc_i2c_write(client, &raw_1P8_CONTROL_011[0],
+ sizeof(raw_1P8_CONTROL_011));
if (r < 0)
goto err_init;
- usleep(1000);
+ usleep_range(1000, 1100); /* 1 ms wait */
RAW(1P8_CONTROL_010, (0x8));
r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
sizeof(raw_1P8_CONTROL_010));
if (r < 0)
goto err_init;
- usleep(10000); /* 10ms wait */
+ usleep_range(10000, 11000); /* 10 ms wait */
RAW(1P8_CONTROL_010, (0xC));
r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
sizeof(raw_1P8_CONTROL_010));
if (r < 0)
goto err_init;
- usleep(100); /* 100uS wait */
+ usleep_range(100, 110); /* 100 us wait */
RAW(1P8_X0_0B0, (FREQ_SEL_19));
r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
sizeof(raw_1P8_X0_0B0));
if (r < 0)
goto err_init;
- usleep(1000);
+ usleep_range(1000, 1100); /* 1 ms wait */
/* PWR_EN = 1 */
RAW(1P8_CONTROL_010, (0xd));
@@ -1177,7 +1196,7 @@
goto err_init;
- usleep(20000); /* 20ms wait */
+ msleep(20); /* 20ms wait */
/* LS_EN = 1 */
RAW(1P8_CONTROL_010, 0xF);
r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
@@ -1185,41 +1204,43 @@
if (r < 0)
goto err_init;
- usleep(20000); /* 20ms wait */
+ msleep(20); /* 20ms wait */
/* Enable the PMIC clock */
RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
- sizeof(raw_1P8_PAD_CFG_CLK_REQ));
+ sizeof(raw_1P8_PAD_CFG_CLK_REQ));
if (r < 0)
goto err_init;
- usleep(1000);
+ usleep_range(1000, 1100); /* 1 ms wait */
RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
- sizeof(raw_1P8_PAD_CFG_PWR_REQ));
+ sizeof(raw_1P8_PAD_CFG_PWR_REQ));
if (r < 0)
goto err_init;
- usleep(1000);
+ usleep_range(1000, 1100); /* 1 ms wait */
RAW(slave2, 0x10);
r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
if (r < 0)
goto err_init;
- usleep(1000);
+ usleep_range(1000, 1100); /* 1 ms wait */
RAW(slave1, NCI_I2C_SLAVE);
r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
if (r < 0)
goto err_init;
- usleep(1000);
+ usleep_range(1000, 1100); /* 1 ms wait */
/* QCA199x NFCC CPU should now boot... */
- r = i2c_master_recv(client, &raw_slave1_rd, 1);
+ r = i2c_master_recv(client, &raw_slave1_rd, sizeof(raw_slave1_rd));
+ if (r < 0)
+ goto err_init;
/* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
client->addr = NCI_I2C_SLAVE;
@@ -1228,35 +1249,37 @@
* get a core reset notification - This is time for chip
* & NFCC controller to come-up.
*/
- usleep(15000); /* 15 ms */
+ usleep_range(15000, 16500); /* 15 ms */
do {
- ret = i2c_master_recv(client, rsp, 5);
+ ret = i2c_master_recv(client, rsp, sizeof(rsp));
+ if (ret < 0)
+ goto err_init;
/* Found core reset notification */
- if (((rsp[0] == CORE_RESET_RSP_GID) &&
+ if ((rsp[0] == CORE_RESET_RSP_GID) &&
(rsp[1] == CORE_RESET_OID) &&
- (rsp[2] == CORE_RST_NTF_LENGTH))
- || time_taken == NTF_TIMEOUT) {
+ (rsp[2] == CORE_RST_NTF_LENGTH)) {
dev_dbg(&client->dev,
- "NFC core reset recevd: %s: info: %p\n",
+ "NFC core reset recvd: %s: info: %p\n",
__func__, client);
core_reset_completed = true;
} else {
- usleep(2000); /* 2ms sleep before retry */
+ usleep_range(2000, 2200); /* 2 ms wait before retry */
}
time_taken++;
- } while (!core_reset_completed);
- if (time_taken == NTF_TIMEOUT)
+ } while (!core_reset_completed && (time_taken < NTF_TIMEOUT));
+ if (time_taken >= NTF_TIMEOUT) {
qca199x_dev->core_reset_ntf = TIMEDOUT_INITIAL_CORE_RESET_NTF;
- else
- qca199x_dev->core_reset_ntf = ARRIVED_INITIAL_CORE_RESET_NTF;
+ goto err_init;
+ }
+ qca199x_dev->core_reset_ntf = ARRIVED_INITIAL_CORE_RESET_NTF;
r = 0;
return r;
err_init:
r = 1;
dev_err(&client->dev,
- "nfc-nci nfcc_initialise: failed. Check Hardware\n");
+ "%s: failed. Check Hardware\n", __func__);
return r;
}
/*
@@ -1267,19 +1290,20 @@
int r = 0;
if (!strcmp(qca199x_dev->clk_src_name, "BBCLK2")) {
- qca199x_dev->s_clk =
+ qca199x_dev->s_clk =
clk_get(&qca199x_dev->client->dev, "ref_clk");
if (qca199x_dev->s_clk == NULL)
goto err_invalid_dis_gpio;
} else if (!strcmp(qca199x_dev->clk_src_name, "RFCLK3")) {
- qca199x_dev->s_clk =
+ qca199x_dev->s_clk =
clk_get(&qca199x_dev->client->dev, "ref_clk_rf");
if (qca199x_dev->s_clk == NULL)
goto err_invalid_dis_gpio;
} else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK")) {
if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
- qca199x_dev->s_clk =
- clk_get(&qca199x_dev->client->dev, "core_clk");
+ qca199x_dev->s_clk =
+ clk_get(&qca199x_dev->client->dev,
+ "core_clk");
if (qca199x_dev->s_clk == NULL)
goto err_invalid_dis_gpio;
} else {
@@ -1287,8 +1311,9 @@
}
} else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK2")) {
if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
- qca199x_dev->s_clk =
- clk_get(&qca199x_dev->client->dev, "core_clk_pvt");
+ qca199x_dev->s_clk =
+ clk_get(&qca199x_dev->client->dev,
+ "core_clk_pvt");
if (qca199x_dev->s_clk == NULL)
goto err_invalid_dis_gpio;
} else {
@@ -1364,7 +1389,7 @@
}
if ((!strcmp(pdata->clk_src_name, "GPCLK")) ||
- (!strcmp(pdata->clk_src_name, "GPCLK2"))) {
+ (!strcmp(pdata->clk_src_name, "GPCLK2"))) {
pdata->clk_src_gpio = of_get_named_gpio(np,
"qcom,clk-src-gpio", 0);
if ((!gpio_is_valid(pdata->clk_src_gpio)))
@@ -1393,7 +1418,7 @@
sizeof(struct qca199x_platform_data), GFP_KERNEL);
if (!platform_data) {
dev_err(&client->dev,
- "nfc-nci probe: Failed to allocate memory\n");
+ "%s: Failed to allocate memory\n", __func__);
return -ENOMEM;
}
r = nfc_parse_dt(&client->dev, platform_data);
@@ -1405,20 +1430,20 @@
if (!platform_data)
return -EINVAL;
dev_dbg(&client->dev,
- "nfc-nci probe: %s, inside nfc-nci flags = %x\n",
+ "%s, inside nfc-nci flags = %x\n",
__func__, client->flags);
if (platform_data == NULL) {
- dev_err(&client->dev, "nfc-nci probe: failed\n");
+ dev_err(&client->dev, "%s: failed\n", __func__);
return -ENODEV;
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "nfc-nci probe: need I2C_FUNC_I2C\n");
+ dev_err(&client->dev, "%s: need I2C_FUNC_I2C\n", __func__);
return -ENODEV;
}
qca199x_dev = kzalloc(sizeof(*qca199x_dev), GFP_KERNEL);
if (qca199x_dev == NULL) {
dev_err(&client->dev,
- "nfc-nci probe: failed to allocate memory for module data\n");
+ "%s: failed to allocate memory for module data\n", __func__);
return -ENOMEM;
}
qca199x_dev->client = client;
@@ -1436,27 +1461,29 @@
r = gpio_request(platform_data->dis_gpio, "nfc_reset_gpio");
if (r) {
dev_err(&client->dev,
- "NFC: unable to request gpio [%d]\n",
+ "%s: unable to request gpio [%d]\n",
+ __func__,
platform_data->dis_gpio);
goto err_free_dev;
}
r = gpio_direction_output(platform_data->dis_gpio, 1);
if (r) {
dev_err(&client->dev,
- "NFC: unable to set direction for gpio [%d]\n",
+ "%s: unable to set direction for gpio [%d]\n",
+ __func__,
platform_data->dis_gpio);
goto err_dis_gpio;
}
} else {
- dev_err(&client->dev, "dis gpio not provided\n");
+ dev_err(&client->dev, "%s: dis gpio not provided\n", __func__);
goto err_free_dev;
}
/* Guarantee that the NFCC starts in a clean state. */
gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
- usleep(200);
+ usleep_range(200, 220);
gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
- usleep(200);
+ usleep_range(200, 220);
r = nfcc_hw_check(client, platform_data->reg);
if (r) {
@@ -1468,7 +1495,8 @@
if (gpio_is_valid(platform_data->irq_gpio)) {
r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
if (r) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
+ dev_err(&client->dev, "%s: unable to request gpio [%d]\n",
+ __func__,
platform_data->irq_gpio);
goto err_dis_gpio;
}
@@ -1476,7 +1504,8 @@
if (r) {
dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
+ "%s: unable to set direction for gpio [%d]\n",
+ __func__,
platform_data->irq_gpio);
goto err_irq;
}
@@ -1488,7 +1517,7 @@
client->irq = irqn;
} else {
- dev_err(&client->dev, "irq gpio not provided\n");
+ dev_err(&client->dev, "%s: irq gpio not provided\n", __func__);
goto err_dis_gpio;
}
/* Interrupt from NFCC CLK_REQ to handle REF_CLK
@@ -1499,7 +1528,9 @@
r = gpio_request(platform_data->irq_gpio_clk_req,
"nfc_irq_gpio_clk_en");
if (r) {
- dev_err(&client->dev, "unable to request CLK_EN gpio [%d]\n",
+ dev_err(&client->dev,
+ "%s: unable to request CLK_EN gpio [%d]\n",
+ __func__,
platform_data->irq_gpio_clk_req);
goto err_irq;
}
@@ -1507,8 +1538,8 @@
platform_data->irq_gpio_clk_req);
if (r) {
dev_err(&client->dev,
- "unable to set direction for CLK_EN gpio [%d]\n",
- platform_data->irq_gpio_clk_req);
+ "%s: cannot set direction CLK_EN gpio [%d]\n",
+ __func__, platform_data->irq_gpio_clk_req);
goto err_irq_clk;
}
gpio_to_irq(0);
@@ -1519,7 +1550,8 @@
}
platform_data->clk_req_irq_num = irqn;
} else {
- dev_err(&client->dev, "irq CLK_EN gpio not provided\n");
+ dev_err(&client->dev,
+ "%s: irq CLK_EN gpio not provided\n", __func__);
goto err_irq;
}
}
@@ -1540,19 +1572,21 @@
r = gpio_request(platform_data->clkreq_gpio,
"nfc_clkreq_gpio");
if (r) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->clkreq_gpio);
+ dev_err(&client->dev,
+ "%s: unable to request gpio [%d]\n",
+ __func__, platform_data->clkreq_gpio);
goto err_clkreq_gpio;
}
r = gpio_direction_input(platform_data->clkreq_gpio);
if (r) {
dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
- platform_data->clkreq_gpio);
+ "%s: cannot set direction for gpio [%d]\n",
+ __func__, platform_data->clkreq_gpio);
goto err_clkreq_gpio;
}
} else {
- dev_err(&client->dev, "clkreq gpio not provided\n");
+ dev_err(&client->dev,
+ "%s: clkreq gpio not provided\n", __func__);
goto err_clk;
}
qca199x_dev->clkreq_gpio = platform_data->clkreq_gpio;
@@ -1579,7 +1613,7 @@
r = misc_register(&qca199x_dev->qca199x_device);
if (r) {
- dev_err(&client->dev, "misc_register failed\n");
+ dev_err(&client->dev, "%s: misc_register failed\n", __func__);
goto err_misc_register;
}
@@ -1616,7 +1650,7 @@
r = request_irq(client->irq, qca199x_dev_irq_handler,
IRQF_TRIGGER_RISING, client->name, qca199x_dev);
if (r) {
- dev_err(&client->dev, "nfc-nci probe: request_irq failed\n");
+ dev_err(&client->dev, "%s: request_irq failed\n", __func__);
goto err_request_irq_failed;
}
qca199x_disable_irq(qca199x_dev);
@@ -1629,7 +1663,8 @@
client->name, qca199x_dev);
if (r) {
dev_err(&client->dev,
- "nfc-nci probe: request_irq failed. irq no = %d\n, main irq = %d",
+ "%s: request_irq failed. irq no = %d\n, main irq = %d",
+ __func__,
qca199x_dev->clk_req_irq_num, client->irq);
goto err_request_irq_failed;
}
@@ -1654,13 +1689,13 @@
region2_sent = false;
dev_dbg(&client->dev,
- "nfc-nci probe: %s, probing qca1990 exited successfully\n",
+ "%s: probing qca1990 exited successfully\n",
__func__);
return 0;
err_create_workq:
dev_err(&client->dev,
- "nfc-nci probe: %s, work_queue creation failure\n",
+ "%s: work_queue creation failure\n",
__func__);
free_irq(client->irq, qca199x_dev);
err_nfcc_not_present:
@@ -1678,7 +1713,8 @@
(!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
r = gpio_direction_input(platform_data->irq_gpio_clk_req);
if (r)
- dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
+ dev_err(&client->dev,
+ "%s: Unable to set direction\n", __func__);
gpio_free(platform_data->irq_gpio_clk_req);
}
err_irq:
@@ -1752,7 +1788,7 @@
static int nfcc_reboot(struct notifier_block *notifier, unsigned long val,
- void *v)
+ void *v)
{
/*
* Set DISABLE=1 *ONLY* if the NFC service has been disabled.
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index c662a2b..924a028 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -207,8 +207,7 @@
* signalling completion/exiting ISR
*/
mb();
- if (dev->wr_comp)
- complete(dev->wr_comp);
+ msm_slim_manage_tx_msgq(dev, false, NULL);
}
if (stat & MGR_INT_RX_MSG_RCVD) {
u32 rx_buf[10];
@@ -372,8 +371,7 @@
}
}
txn->rl--;
- pbuf = msm_get_msg_buf(dev, txn->rl);
- dev->wr_comp = NULL;
+ pbuf = msm_get_msg_buf(dev, txn->rl, &done);
dev->err = 0;
if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
@@ -438,11 +436,8 @@
if (txn->mt == SLIM_MSG_MT_CORE &&
mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION)
dev->reconf_busy = true;
- dev->wr_comp = &done;
msm_send_msg_buf(dev, pbuf, txn->rl, MGR_TX_MSG);
timeout = wait_for_completion_timeout(&done, HZ);
- if (!timeout)
- dev->wr_comp = NULL;
if (mc == SLIM_MSG_MC_RECONFIGURE_NOW) {
if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
SLIM_MSG_CLK_PAUSE_SEQ_FLG)) &&
@@ -505,7 +500,9 @@
retry_laddr:
init_completion(&done);
mutex_lock(&dev->tx_lock);
- buf = msm_get_msg_buf(dev, 9);
+ buf = msm_get_msg_buf(dev, 9, &done);
+ if (buf == NULL)
+ return -ENOMEM;
buf[0] = SLIM_MSG_ASM_FIRST_WORD(9, SLIM_MSG_MT_CORE,
SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS,
SLIM_MSG_DEST_LOGICALADDR,
@@ -513,7 +510,6 @@
buf[1] = ea[3] | (ea[2] << 8) | (ea[1] << 16) | (ea[0] << 24);
buf[2] = laddr;
- dev->wr_comp = &done;
ret = msm_send_msg_buf(dev, buf, 9, MGR_TX_MSG);
timeout = wait_for_completion_timeout(&done, HZ);
if (!timeout)
@@ -521,7 +517,6 @@
if (dev->err) {
ret = dev->err;
dev->err = 0;
- dev->wr_comp = NULL;
}
mutex_unlock(&dev->tx_lock);
if (ret) {
@@ -1183,6 +1178,10 @@
ret = -ENOMEM;
goto err_get_res_failed;
}
+ dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS,
+ GFP_KERNEL);
+ if (!dev->wr_comp)
+ return -ENOMEM;
dev->dev = &pdev->dev;
platform_set_drvdata(pdev, dev);
slim_set_ctrldata(&dev->ctrl, dev);
@@ -1271,7 +1270,8 @@
dev->ctrl.dev.parent = &pdev->dev;
dev->ctrl.dev.of_node = pdev->dev.of_node;
- ret = request_irq(dev->irq, msm_slim_interrupt, IRQF_TRIGGER_HIGH,
+ ret = request_threaded_irq(dev->irq, NULL, msm_slim_interrupt,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"msm_slim_irq", dev);
if (ret) {
dev_err(&pdev->dev, "request IRQ failed\n");
@@ -1400,6 +1400,7 @@
err_ioremap_bam_failed:
iounmap(dev->base);
err_ioremap_failed:
+ kfree(dev->wr_comp);
kfree(dev);
err_get_res_failed:
release_mem_region(bam_mem->start, resource_size(bam_mem));
@@ -1437,6 +1438,7 @@
kthread_stop(dev->rx_msgq_thread);
iounmap(dev->bam.base);
iounmap(dev->base);
+ kfree(dev->wr_comp);
kfree(dev);
bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"slimbus_bam_physical");
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 299d3ee..f3a886b 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -101,15 +101,13 @@
dev->err);
/* Guarantee that error interrupts are cleared */
mb();
- if (dev->wr_comp)
- complete(dev->wr_comp);
+ msm_slim_manage_tx_msgq(dev, false, NULL);
} else if (stat & NGD_INT_TX_MSG_SENT) {
writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR);
/* Make sure interrupt is cleared */
mb();
- if (dev->wr_comp)
- complete(dev->wr_comp);
+ msm_slim_manage_tx_msgq(dev, false, NULL);
}
if (stat & NGD_INT_RX_MSG_RCVD) {
u32 rx_buf[10];
@@ -165,27 +163,51 @@
case QMI_SERVER_ARRIVE:
schedule_work(&qmi->ssr_up);
break;
- case QMI_SERVER_EXIT:
- dev->state = MSM_CTRL_DOWN;
- /* make sure autosuspend is not called until ADSP comes up*/
- pm_runtime_get_noresume(dev->dev);
- /* Reset ctrl_up completion */
- init_completion(&dev->ctrl_up);
- schedule_work(&qmi->ssr_down);
- break;
default:
break;
}
return 0;
}
+static int dsp_ssr_notify_cb(struct notifier_block *n, unsigned long code,
+ void *_cmd)
+{
+ struct msm_slim_ss *dsp = container_of(n, struct msm_slim_ss, nb);
+ struct msm_slim_ctrl *dev = container_of(dsp, struct msm_slim_ctrl,
+ dsp);
+
+ switch (code) {
+ case SUBSYS_BEFORE_SHUTDOWN:
+ SLIM_INFO(dev, "SLIM DSP SSR notify cb:%lu\n", code);
+ /* wait for current transaction */
+ mutex_lock(&dev->tx_lock);
+ /* make sure autosuspend is not called until ADSP comes up*/
+ pm_runtime_get_noresume(dev->dev);
+ dev->state = MSM_CTRL_DOWN;
+ /* Reset ctrl_up completion */
+ init_completion(&dev->ctrl_up);
+ /* disconnect BAM pipes */
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
+ dev->use_rx_msgqs = MSM_MSGQ_DOWN;
+ if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
+ dev->use_tx_msgqs = MSM_MSGQ_DOWN;
+ msm_slim_sps_exit(dev, false);
+ schedule_work(&dev->qmi.ssr_down);
+ mutex_unlock(&dev->tx_lock);
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
static int mdm_ssr_notify_cb(struct notifier_block *n, unsigned long code,
void *_cmd)
{
void __iomem *ngd;
- struct msm_slim_mdm *mdm = container_of(n, struct msm_slim_mdm, nb);
- struct msm_slim_ctrl *dev = container_of(mdm, struct msm_slim_ctrl,
- mdm);
+ struct msm_slim_ss *ext_mdm = container_of(n, struct msm_slim_ss, nb);
+ struct msm_slim_ctrl *dev = container_of(ext_mdm, struct msm_slim_ctrl,
+ ext_mdm);
struct slim_controller *ctrl = &dev->ctrl;
u32 laddr;
struct slim_device *sbdev;
@@ -200,11 +222,11 @@
* handover later
*/
msm_slim_qmi_check_framer_request(dev);
- dev->mdm.state = MSM_CTRL_DOWN;
+ dev->ext_mdm.state = MSM_CTRL_DOWN;
msm_slim_put_ctrl(dev);
break;
case SUBSYS_AFTER_POWERUP:
- if (dev->mdm.state != MSM_CTRL_DOWN)
+ if (dev->ext_mdm.state != MSM_CTRL_DOWN)
return NOTIFY_DONE;
SLIM_INFO(dev,
"SLIM %lu external_modem SSR notify cb\n", code);
@@ -215,19 +237,21 @@
ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
laddr = readl_relaxed(ngd + NGD_STATUS);
if (!(laddr & NGD_LADDR)) {
+ mutex_lock(&dev->tx_lock);
/* runtime-pm state should be consistent with HW */
pm_runtime_disable(dev->dev);
pm_runtime_set_suspended(dev->dev);
dev->state = MSM_CTRL_DOWN;
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev,
"SLIM MDM SSR (active framer on MDM) dev-down\n");
list_for_each_entry(sbdev, &ctrl->devs, dev_list)
slim_report_absent(sbdev);
- ngd_slim_power_up(dev, true);
+ ngd_slim_runtime_resume(dev->dev);
pm_runtime_set_active(dev->dev);
pm_runtime_enable(dev->dev);
}
- dev->mdm.state = MSM_CTRL_AWAKE;
+ dev->ext_mdm.state = MSM_CTRL_AWAKE;
msm_slim_put_ctrl(dev);
break;
default:
@@ -286,12 +310,24 @@
u16 txn_mc = txn->mc;
u8 wbuf[SLIM_MSGQ_BUF_LEN];
bool report_sat = false;
+ bool sync_wr = true;
+
+ if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
+ return -EPROTONOSUPPORT;
+
+ if (txn->mt == SLIM_MSG_MT_CORE &&
+ (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
+ txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
+ return 0;
if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE &&
txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER)
report_sat = true;
- if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
- report_sat == false) {
+ else
+ mutex_lock(&dev->tx_lock);
+
+ if (!report_sat && !pm_runtime_enabled(dev->dev) &&
+ dev->state == MSM_CTRL_ASLEEP) {
/*
* Counter-part of system-suspend when runtime-pm is not enabled
* This way, resume can be left empty and device will be put in
@@ -299,22 +335,24 @@
* If the state was DOWN, SSR UP notification will take
* care of putting the device in active state.
*/
- ngd_slim_runtime_resume(dev->dev);
+ mutex_unlock(&dev->tx_lock);
+ ret = ngd_slim_runtime_resume(dev->dev);
+
+ if (ret) {
+ SLIM_ERR(dev, "slim resume failed ret:%d, state:%d",
+ ret, dev->state);
+ return -EREMOTEIO;
+ }
+ mutex_lock(&dev->tx_lock);
}
- else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
- return -EPROTONOSUPPORT;
-
- if (txn->mt == SLIM_MSG_MT_CORE &&
- (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
- txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
- return 0;
- }
/* If txn is tried when controller is down, wait for ADSP to boot */
if (!report_sat) {
+
if (dev->state == MSM_CTRL_DOWN) {
u8 mc = (u8)txn->mc;
int timeout;
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev, "ADSP slimbus not up yet\n");
/*
* Messages related to data channel management can't
@@ -354,33 +392,31 @@
return -EREMOTEIO;
timeout = wait_for_completion_timeout(&dev->ctrl_up,
HZ);
- if (!timeout && dev->state == MSM_CTRL_DOWN)
+ if (!timeout)
return -ETIMEDOUT;
+ mutex_lock(&dev->tx_lock);
}
+
+ mutex_unlock(&dev->tx_lock);
ret = msm_slim_get_ctrl(dev);
+ mutex_lock(&dev->tx_lock);
/*
* Runtime-pm's callbacks are not called until runtime-pm's
* error status is cleared
* Setting runtime status to suspended clears the error
* It also makes HW status cosistent with what SW has it here
*/
- if (ret == -ENETRESET && dev->state == MSM_CTRL_DOWN) {
+ if ((pm_runtime_enabled(dev->dev) && ret < 0) ||
+ dev->state == MSM_CTRL_DOWN) {
+ SLIM_ERR(dev, "slim ctrl vote failed ret:%d, state:%d",
+ ret, dev->state);
pm_runtime_set_suspended(dev->dev);
+ mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
return -EREMOTEIO;
- } else if (ret >= 0) {
- dev->state = MSM_CTRL_AWAKE;
}
}
- mutex_lock(&dev->tx_lock);
- if (report_sat == false && dev->state != MSM_CTRL_AWAKE) {
- SLIM_ERR(dev, "controller not ready\n");
- mutex_unlock(&dev->tx_lock);
- pm_runtime_set_suspended(dev->dev);
- msm_slim_put_ctrl(dev);
- return -EREMOTEIO;
- }
if (txn->mt == SLIM_MSG_MT_CORE &&
(txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
@@ -438,7 +474,25 @@
txn->rl = txn->len + 4;
}
txn->rl--;
- pbuf = msm_get_msg_buf(dev, txn->rl);
+
+ if (txn->mt == SLIM_MSG_MT_CORE && txn->comp &&
+ dev->use_tx_msgqs == MSM_MSGQ_ENABLED &&
+ (txn_mc != SLIM_MSG_MC_REQUEST_INFORMATION &&
+ txn_mc != SLIM_MSG_MC_REQUEST_VALUE &&
+ txn_mc != SLIM_MSG_MC_REQUEST_CHANGE_VALUE &&
+ txn_mc != SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION)) {
+ sync_wr = false;
+ pbuf = msm_get_msg_buf(dev, txn->rl, txn->comp);
+ } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
+ dev->use_tx_msgqs == MSM_MSGQ_ENABLED &&
+ txn->mc == SLIM_USR_MC_REPEAT_CHANGE_VALUE &&
+ txn->comp) {
+ sync_wr = false;
+ pbuf = msm_get_msg_buf(dev, txn->rl, txn->comp);
+ } else {
+ pbuf = msm_get_msg_buf(dev, txn->rl, &tx_sent);
+ }
+
if (!pbuf) {
SLIM_ERR(dev, "Message buffer unavailable\n");
ret = -ENOMEM;
@@ -509,10 +563,9 @@
*/
txn_mc = txn->mc;
txn_mt = txn->mt;
- dev->wr_comp = &tx_sent;
ret = msm_send_msg_buf(dev, pbuf, txn->rl,
NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
- if (!ret) {
+ if (!ret && sync_wr) {
int timeout = wait_for_completion_timeout(&tx_sent, HZ);
if (!timeout) {
ret = -ETIMEDOUT;
@@ -521,14 +574,15 @@
* transactions don't timeout due to unavailable
* descriptors
*/
- msm_slim_disconnect_endp(dev, &dev->tx_msgq,
- &dev->use_tx_msgqs);
- msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
+ if (dev->state != MSM_CTRL_DOWN) {
+ msm_slim_disconnect_endp(dev, &dev->tx_msgq,
+ &dev->use_tx_msgqs);
+ msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
+ }
} else {
ret = dev->err;
}
}
- dev->wr_comp = NULL;
if (ret) {
u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
@@ -569,9 +623,10 @@
return ret ? ret : dev->err;
}
ngd_xfer_err:
- mutex_unlock(&dev->tx_lock);
- if (!report_sat)
+ if (!report_sat) {
+ mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
+ }
return ret ? ret : dev->err;
}
@@ -880,7 +935,6 @@
enum msm_ctrl_state prev_state = dev->state;
SLIM_INFO(dev,
"SLIM SAT: capability exchange successful\n");
- dev->state = MSM_CTRL_AWAKE;
if (prev_state >= MSM_CTRL_ASLEEP)
complete(&dev->reconf);
else
@@ -964,8 +1018,10 @@
if (!mdm_restart && cur_state == MSM_CTRL_DOWN) {
int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
HZ);
- if (!timeout)
+ if (!timeout) {
SLIM_ERR(dev, "slimbus QMI init timed out\n");
+ return -EREMOTEIO;
+ }
}
/* No need to vote if contorller is not in low power mode */
@@ -1052,11 +1108,11 @@
SLIM_ERR(dev, "Failed to receive master capability\n");
return -ETIMEDOUT;
}
- if (cur_state == MSM_CTRL_DOWN) {
- complete(&dev->ctrl_up);
- /* Resetting the log level */
- SLIM_RST_LOGLVL(dev);
- }
+ /* mutliple transactions waiting on slimbus to power up? */
+ if (cur_state == MSM_CTRL_DOWN)
+ complete_all(&dev->ctrl_up);
+ /* Resetting the log level */
+ SLIM_RST_LOGLVL(dev);
return 0;
}
@@ -1211,12 +1267,6 @@
struct slim_device *sbdev;
ngd_slim_enable(dev, false);
- /* disconnect BAM pipes */
- if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
- dev->use_rx_msgqs = MSM_MSGQ_DOWN;
- if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
- dev->use_tx_msgqs = MSM_MSGQ_DOWN;
- msm_slim_sps_exit(dev, false);
/* device up should be called again after SSR */
list_for_each_entry(sbdev, &ctrl->devs, dev_list)
slim_report_absent(sbdev);
@@ -1295,6 +1345,10 @@
dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
return PTR_ERR(dev);
}
+ dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS,
+ GFP_KERNEL);
+ if (!dev->wr_comp)
+ return -ENOMEM;
dev->dev = &pdev->dev;
platform_set_drvdata(pdev, dev);
slim_set_ctrldata(&dev->ctrl, dev);
@@ -1378,6 +1432,7 @@
init_completion(&dev->reconf);
init_completion(&dev->ctrl_up);
mutex_init(&dev->tx_lock);
+ mutex_init(&dev->tx_buf_lock);
spin_lock_init(&dev->rx_lock);
dev->ee = 1;
dev->irq = irq->start;
@@ -1405,8 +1460,9 @@
dev->ctrl.dev.of_node = pdev->dev.of_node;
dev->state = MSM_CTRL_DOWN;
- ret = request_irq(dev->irq, ngd_slim_interrupt,
- IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
+ ret = request_threaded_irq(dev->irq, NULL,
+ ngd_slim_interrupt,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "ngd_slim_irq", dev);
if (ret) {
dev_err(&pdev->dev, "request IRQ failed\n");
@@ -1420,14 +1476,21 @@
pm_runtime_set_suspended(dev->dev);
pm_runtime_enable(dev->dev);
+ dev->dsp.nb.notifier_call = dsp_ssr_notify_cb;
+ dev->dsp.ssr = subsys_notif_register_notifier("adsp",
+ &dev->dsp.nb);
+ if (IS_ERR_OR_NULL(dev->dsp.ssr))
+ dev_err(dev->dev,
+ "subsys_notif_register_notifier failed %p",
+ dev->dsp.ssr);
if (slim_mdm) {
- dev->mdm.nb.notifier_call = mdm_ssr_notify_cb;
- dev->mdm.ssr = subsys_notif_register_notifier(ext_modem_id,
- &dev->mdm.nb);
- if (IS_ERR_OR_NULL(dev->mdm.ssr))
+ dev->ext_mdm.nb.notifier_call = mdm_ssr_notify_cb;
+ dev->ext_mdm.ssr = subsys_notif_register_notifier(ext_modem_id,
+ &dev->ext_mdm.nb);
+ if (IS_ERR_OR_NULL(dev->ext_mdm.ssr))
dev_err(dev->dev,
"subsys_notif_register_notifier failed %p",
- dev->mdm.ssr);
+ dev->ext_mdm.ssr);
}
INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
@@ -1469,6 +1532,7 @@
if (dev->sysfs_created)
sysfs_remove_file(&dev->dev->kobj,
&dev_attr_debug_mask.attr);
+ kfree(dev->wr_comp);
kfree(dev);
return ret;
}
@@ -1484,13 +1548,18 @@
SLIMBUS_QMI_SVC_V1,
SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
pm_runtime_disable(&pdev->dev);
- if (!IS_ERR_OR_NULL(dev->mdm.ssr))
- subsys_notif_unregister_notifier(dev->mdm.ssr, &dev->mdm.nb);
+ if (!IS_ERR_OR_NULL(dev->dsp.ssr))
+ subsys_notif_unregister_notifier(dev->dsp.ssr,
+ &dev->dsp.nb);
+ if (!IS_ERR_OR_NULL(dev->ext_mdm.ssr))
+ subsys_notif_unregister_notifier(dev->ext_mdm.ssr,
+ &dev->ext_mdm.nb);
free_irq(dev->irq, dev);
slim_del_controller(&dev->ctrl);
kthread_stop(dev->rx_msgq_thread);
iounmap(dev->bam.base);
iounmap(dev->base);
+ kfree(dev->wr_comp);
kfree(dev);
return 0;
}
@@ -1500,8 +1569,10 @@
{
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
+ mutex_lock(&dev->tx_lock);
if (dev->state == MSM_CTRL_AWAKE)
dev->state = MSM_CTRL_IDLE;
+ mutex_unlock(&dev->tx_lock);
dev_dbg(device, "pm_runtime: idle...\n");
pm_request_autosuspend(device);
return -EAGAIN;
@@ -1518,6 +1589,7 @@
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
int ret = 0;
+ mutex_lock(&dev->tx_lock);
if (dev->state >= MSM_CTRL_ASLEEP)
ret = ngd_slim_power_up(dev, false);
if (ret) {
@@ -1529,6 +1601,7 @@
} else {
dev->state = MSM_CTRL_AWAKE;
}
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev, "Slim runtime resume: ret %d\n", ret);
return ret;
}
@@ -1539,6 +1612,7 @@
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
int ret = 0;
+ mutex_lock(&dev->tx_lock);
ret = ngd_slim_power_down(dev);
if (ret) {
if (ret != -EBUSY)
@@ -1547,6 +1621,7 @@
} else {
dev->state = MSM_CTRL_ASLEEP;
}
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev, "Slim runtime suspend: ret %d\n", ret);
return ret;
}
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 915bf88..c3f371c 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -11,6 +11,7 @@
*/
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include <linux/slimbus/slimbus.h>
#include <mach/sps.h>
#include "slim-msm.h"
@@ -390,9 +391,9 @@
struct msm_slim_endp *endpoint = &dev->tx_msgq;
struct sps_mem_buffer *mem = &endpoint->buf;
struct sps_pipe *pipe = endpoint->sps;
- int ix = (buf - (u8 *)mem->base) / SLIM_MSGQ_BUF_LEN;
+ int ix = (buf - (u8 *)mem->base);
- phys_addr_t phys_addr = mem->phys_base + (SLIM_MSGQ_BUF_LEN * ix);
+ phys_addr_t phys_addr = mem->phys_base + ix;
for (ret = 0; ret < ((len + 3) >> 2); ret++)
pr_debug("BAM TX buf[%d]:0x%x", ret, ((u32 *)buf)[ret]);
@@ -405,29 +406,110 @@
return ret;
}
-static u32 *msm_slim_tx_msgq_return(struct msm_slim_ctrl *dev)
+void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev)
{
struct msm_slim_endp *endpoint = &dev->tx_msgq;
struct sps_mem_buffer *mem = &endpoint->buf;
struct sps_pipe *pipe = endpoint->sps;
struct sps_iovec iovec;
- int ret;
-
- /* first transaction after establishing connection */
- if (dev->tx_idx == -1) {
- dev->tx_idx = 0;
- return mem->base;
+ int idx, ret = 0;
+ if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) {
+ /* use 1 buffer, non-blocking writes are not possible */
+ if (dev->wr_comp[0]) {
+ struct completion *comp = dev->wr_comp[0];
+ dev->wr_comp[0] = NULL;
+ complete(comp);
+ }
+ return;
}
- ret = sps_get_iovec(pipe, &iovec);
- if (ret || iovec.addr == 0) {
- dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret);
+ while (!ret) {
+ ret = sps_get_iovec(pipe, &iovec);
+ if (ret || iovec.addr == 0) {
+ if (ret)
+ pr_err("SLIM TX get IOVEC failed:%d", ret);
+ return;
+ }
+ idx = (int) ((iovec.addr - mem->phys_base) / SLIM_MSGQ_BUF_LEN);
+ if (idx < MSM_TX_BUFS && dev->wr_comp[idx]) {
+ struct completion *comp = dev->wr_comp[idx];
+ dev->wr_comp[idx] = NULL;
+ complete(comp);
+ }
+ /* reclaim all packets that were delivered out of order */
+ if (idx != dev->tx_head)
+ pr_err("SLIM OUT OF ORDER TX:idx:%d, head:%d", idx,
+ dev->tx_head);
+ while (idx == dev->tx_head) {
+ dev->tx_head = (dev->tx_head + 1) % MSM_TX_BUFS;
+ idx++;
+ if (dev->tx_head == dev->tx_tail ||
+ dev->wr_comp[idx] != NULL)
+ break;
+ }
+ }
+}
+
+static u32 *msm_slim_modify_tx_buf(struct msm_slim_ctrl *dev,
+ struct completion *comp)
+{
+ struct msm_slim_endp *endpoint = &dev->tx_msgq;
+ struct sps_mem_buffer *mem = &endpoint->buf;
+ u32 *retbuf = NULL;
+ if ((dev->tx_tail + 1) % MSM_TX_BUFS == dev->tx_head)
+ return NULL;
+
+ retbuf = (u32 *)((u8 *)mem->base +
+ (dev->tx_tail * SLIM_MSGQ_BUF_LEN));
+ dev->wr_comp[dev->tx_tail] = comp;
+ dev->tx_tail = (dev->tx_tail + 1) % MSM_TX_BUFS;
+ return retbuf;
+}
+u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf,
+ struct completion *comp)
+{
+ int ret = 0;
+ int retries = 0;
+ u32 *retbuf = NULL;
+
+ mutex_lock(&dev->tx_buf_lock);
+ if (!getbuf) {
+ msm_slim_tx_msg_return(dev);
+ mutex_unlock(&dev->tx_buf_lock);
return NULL;
}
- /* Calculate buffer index */
- dev->tx_idx = ((int)(iovec.addr - mem->phys_base)) / SLIM_MSGQ_BUF_LEN;
+ retbuf = msm_slim_modify_tx_buf(dev, comp);
+ if (retbuf) {
+ mutex_unlock(&dev->tx_buf_lock);
+ return retbuf;
+ }
- return (u32 *)((u8 *)mem->base + (dev->tx_idx * SLIM_MSGQ_BUF_LEN));
+ do {
+ msm_slim_tx_msg_return(dev);
+ retbuf = msm_slim_modify_tx_buf(dev, comp);
+ if (!retbuf)
+ ret = -EAGAIN;
+ else {
+ if (retries > 0)
+ SLIM_INFO(dev, "SLIM TX retrieved:%d retries",
+ retries);
+ mutex_unlock(&dev->tx_buf_lock);
+ return retbuf;
+ }
+
+ /*
+ * superframe size will vary based on clock gear
+ * 1 superframe will consume at least 1 message
+ * if HW is in good condition. With MX_RETRIES,
+ * make sure we wait for a [3, 10] superframes
+ * before deciding HW couldn't process descriptors
+ */
+ usleep_range(100, 250);
+ retries++;
+ } while (ret && (retries < INIT_MX_RETRIES));
+
+ mutex_unlock(&dev->tx_buf_lock);
+ return NULL;
}
int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg)
@@ -445,16 +527,19 @@
return msm_slim_post_tx_msgq(dev, (u8 *)buf, len);
}
-u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len)
+u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
+ struct completion *comp)
{
/*
* Currently we block a transaction until the current one completes.
* In case we need multiple transactions, use message Q
*/
- if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED)
+ if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) {
+ dev->wr_comp[0] = comp;
return dev->tx_buf;
+ }
- return msm_slim_tx_msgq_return(dev);
+ return msm_slim_manage_tx_msgq(dev, true, comp);
}
static void
@@ -604,7 +689,8 @@
}
dev->use_rx_msgqs = MSM_MSGQ_ENABLED;
} else {
- dev->tx_idx = -1;
+ dev->tx_tail = 0;
+ dev->tx_head = 0;
dev->use_tx_msgqs = MSM_MSGQ_ENABLED;
}
@@ -711,16 +797,18 @@
config->options = SPS_O_ERROR | SPS_O_NO_Q |
SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+ /* Desc and TX buf are circular queues */
/* Allocate memory for the FIFO descriptors */
ret = msm_slim_sps_mem_alloc(dev, descr,
- MSM_TX_BUFS * sizeof(struct sps_iovec));
+ (MSM_TX_BUFS + 1) * sizeof(struct sps_iovec));
if (ret) {
dev_err(dev->dev, "unable to allocate SPS descriptors\n");
goto alloc_descr_failed;
}
- /* Allocate memory for the message buffer(s), N descrs, 40-byte mesg */
- ret = msm_slim_sps_mem_alloc(dev, mem, MSM_TX_BUFS * SLIM_MSGQ_BUF_LEN);
+ /* Allocate TX buffer from which descriptors are created */
+ ret = msm_slim_sps_mem_alloc(dev, mem, ((MSM_TX_BUFS + 1) *
+ SLIM_MSGQ_BUF_LEN));
if (ret) {
dev_err(dev->dev, "dma_alloc_coherent failed\n");
goto alloc_buffer_failed;
@@ -863,10 +951,16 @@
void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg)
{
+ int i;
+
if (dev->use_rx_msgqs >= MSM_MSGQ_ENABLED)
msm_slim_remove_ep(dev, &dev->rx_msgq, &dev->use_rx_msgqs);
if (dev->use_tx_msgqs >= MSM_MSGQ_ENABLED)
msm_slim_remove_ep(dev, &dev->tx_msgq, &dev->use_tx_msgqs);
+ for (i = dev->port_b; i < MSM_SLIM_NPORTS; i++) {
+ if (dev->pipes[i - dev->port_b].connected)
+ msm_slim_disconn_pipe_port(dev, i - dev->port_b);
+ }
if (dereg) {
int i;
for (i = dev->port_b; i < MSM_SLIM_NPORTS; i++) {
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 9673208..99297a9 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -22,7 +22,7 @@
/* Per spec.max 40 bytes per received message */
#define SLIM_MSGQ_BUF_LEN 40
-#define MSM_TX_BUFS 2
+#define MSM_TX_BUFS 32
#define SLIM_USR_MC_GENERIC_ACK 0x25
#define SLIM_USR_MC_MASTER_CAPABILITY 0x0
@@ -214,7 +214,7 @@
struct work_struct ssr_up;
};
-struct msm_slim_mdm {
+struct msm_slim_ss {
struct notifier_block nb;
void *ssr;
enum msm_ctrl_state state;
@@ -236,14 +236,15 @@
u8 msg_cnt;
u32 tx_buf[10];
u8 rx_msgs[MSM_CONCUR_MSG][SLIM_MSGQ_BUF_LEN];
- int tx_idx;
+ int tx_tail;
+ int tx_head;
spinlock_t rx_lock;
int head;
int tail;
int irq;
int err;
int ee;
- struct completion *wr_comp;
+ struct completion **wr_comp;
struct msm_slim_sat *satd[MSM_MAX_NSATS];
struct msm_slim_endp pipes[7];
struct msm_slim_sps_bam bam;
@@ -254,6 +255,7 @@
struct clk *rclk;
struct clk *hclk;
struct mutex tx_lock;
+ struct mutex tx_buf_lock;
u8 pgdla;
enum msm_slim_msgq use_rx_msgqs;
enum msm_slim_msgq use_tx_msgqs;
@@ -267,7 +269,8 @@
u32 ver;
struct msm_slim_qmi qmi;
struct msm_slim_pdata pdata;
- struct msm_slim_mdm mdm;
+ struct msm_slim_ss ext_mdm;
+ struct msm_slim_ss dsp;
int default_ipc_log_mask;
int ipc_log_mask;
bool sysfs_created;
@@ -372,7 +375,10 @@
int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, phys_addr_t iobuf,
u32 len, struct completion *comp);
int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg);
-u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len);
+u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
+ struct completion *comp);
+u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf,
+ struct completion *comp);
int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset);
int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
u32 pipe_reg, bool remote);
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index fecf5ec..27b92ba 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1100,7 +1100,7 @@
} else
ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec,
SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen,
- NULL, sbdev->laddr, NULL);
+ msg->comp, sbdev->laddr, NULL);
xfer_err:
return ret;
}
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 592f70e..68c991c 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -653,14 +653,25 @@
return rc;
}
+/* MIPI_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd = {
+ {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
+ max_pktsize,
+};
+
int msm_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_buf *rp, int rlen)
{
- u32 *lp, data;
- int i, off, cnt;
+ u32 *lp, data, *temp;
+ int i, j = 0, off, cnt;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ char reg[16];
+ int repeated_bytes = 0;
lp = (u32 *)rp->data;
+ temp = (u32 *)reg;
cnt = rlen;
cnt += 3;
cnt >>= 2;
@@ -668,16 +679,52 @@
if (cnt > 4)
cnt = 4; /* 4 x 32 bits registers only */
+ if (rlen == 4)
+ rp->read_cnt = 4;
+ else
+ rp->read_cnt = (max_pktsize[0] + 6);
+
+ if (rp->read_cnt > 16) {
+ int bytes_shifted, data_lost = 0, rem_header_bytes = 0;
+ /* Any data more than 16 bytes will be shifted out */
+ bytes_shifted = rp->read_cnt - rlen;
+ if (bytes_shifted >= 4)
+ data_lost = bytes_shifted - 4; /* remove dcs header */
+ else
+ rem_header_bytes = 4 - bytes_shifted; /* rem header */
+ /*
+ * (rp->len - 4) -> current rx buffer data length.
+ * If data_lost > 0, then ((rp->len - 4) - data_lost) will be
+ * the number of repeating bytes.
+ * If data_lost == 0, then ((rp->len - 4) + rem_header_bytes)
+ * will be the number of bytes repeating in between rx buffer
+ * and the current RDBK_DATA registers. We need to skip the
+ * repeating bytes.
+ */
+ repeated_bytes = (rp->len - 4) - data_lost + rem_header_bytes;
+ }
+
off = DSI_RDBK_DATA0;
off += ((cnt - 1) * 4);
for (i = 0; i < cnt; i++) {
data = (u32)MIPI_INP(ctrl_base + off);
- *lp++ = ntohl(data); /* to network byte order */
+ /* to network byte order */
+ if (!repeated_bytes)
+ *lp++ = ntohl(data);
+ else
+ *temp++ = ntohl(data);
pr_debug("%s: data = 0x%x and ntohl(data) = 0x%x\n",
__func__, data, ntohl(data));
off -= 4;
- rp->len += sizeof(*lp);
+ if (rlen == 4)
+ rp->len += sizeof(*lp);
+ }
+
+ /* Skip duplicates and append other data to the rx buffer */
+ if (repeated_bytes) {
+ for (i = repeated_bytes; i < 16; i++)
+ rp->data[j++] = reg[i];
}
return rlen;
@@ -769,14 +816,6 @@
return rc;
}
-/* MIPI_DSI_MRPS, Maximum Return Packet Size */
-static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
-
-static struct dsi_cmd_desc pkt_size_cmd = {
- {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
- max_pktsize,
-};
-
static int msm_dsi_set_max_packet_size(struct mdss_dsi_ctrl_pdata *ctrl,
int size)
{
@@ -814,10 +853,23 @@
{
int rc;
struct dsi_buf *tp, *rp;
+ int rx_byte = 0;
+
+ if (rlen <= 2)
+ rx_byte = 4;
+ else
+ rx_byte = DSI_MAX_BYTES_TO_READ;
tp = &ctrl->tx_buf;
rp = &ctrl->rx_buf;
mdss_dsi_buf_init(rp);
+ rc = msm_dsi_set_max_packet_size(ctrl, rlen);
+ if (rc) {
+ pr_err("%s: dsi_set_max_pkt failed\n", __func__);
+ rc = -EINVAL;
+ goto dsi_cmds_rx_1_error;
+ }
+
mdss_dsi_buf_init(tp);
rc = mdss_dsi_cmd_dma_add(tp, cmds);
@@ -840,10 +892,12 @@
}
if (rlen <= DSI_SHORT_PKT_DATA_SIZE) {
- msm_dsi_cmd_dma_rx(ctrl, rp, rlen);
+ msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
} else {
- msm_dsi_cmd_dma_rx(ctrl, rp, rlen + DSI_HOST_HDR_SIZE);
- rp->len = rlen + DSI_HOST_HDR_SIZE;
+ msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
+ rp->len = rx_byte - 2; /*2 bytes for CRC*/
+ rp->len = rp->len - (DSI_MAX_PKT_SIZE - rlen);
+ rp->data = rp->start + (16 - (rlen + 2 + DSI_HOST_HDR_SIZE));
}
rc = msm_dsi_parse_rx_response(rp);
@@ -860,16 +914,15 @@
{
int rc;
struct dsi_buf *tp, *rp;
- int pkt_size, data_bytes, total;
+ int pkt_size, data_bytes, dlen, end = 0, diff;
tp = &ctrl->tx_buf;
rp = &ctrl->rx_buf;
mdss_dsi_buf_init(rp);
pkt_size = DSI_MAX_PKT_SIZE;
data_bytes = MDSS_DSI_LEN;
- total = 0;
- while (true) {
+ while (!end) {
rc = msm_dsi_set_max_packet_size(ctrl, pkt_size);
if (rc)
break;
@@ -880,7 +933,7 @@
pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
rc = -EINVAL;
break;
- }
+ }
rc = msm_dsi_wait4video_eng_busy(ctrl);
if (rc) {
pr_err("%s: wait4video_eng failed\n", __func__);
@@ -894,19 +947,32 @@
}
msm_dsi_cmd_dma_rx(ctrl, rp, DSI_MAX_BYTES_TO_READ);
+ if (rlen <= data_bytes) {
+ diff = data_bytes - rlen;
+ end = 1;
+ } else {
+ diff = 0;
+ rlen -= data_bytes;
+ }
+ dlen = DSI_MAX_BYTES_TO_READ - 2;
+ dlen -= diff;
+ rp->data += dlen;
+ rp->len += dlen;
- rp->data += DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
- total += data_bytes;
- if (total >= rlen)
- break;
-
- data_bytes = DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
- pkt_size += data_bytes;
+ if (!end) {
+ data_bytes = 14;
+ if (rlen < data_bytes)
+ pkt_size += rlen;
+ else
+ pkt_size += data_bytes;
+ }
+ pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
+ __func__, (int) (unsigned long) rp->data,
+ rp->len, dlen, diff);
}
if (!rc) {
rp->data = rp->start;
- rp->len = rlen + DSI_HOST_HDR_SIZE;
rc = msm_dsi_parse_rx_response(rp);
}
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index cd0af6d..27524af 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -1589,8 +1589,9 @@
lut_config.lut_sel = mdp3_session->lut_sel;
lut_config.lut_position = 0;
lut_config.lut_dirty = true;
- lut.color0_lut = r;
- lut.color1_lut = g;
+ /* In HW the order is color0 = g, color1 = r and color2 = b*/
+ lut.color0_lut = g;
+ lut.color1_lut = r;
lut.color2_lut = b;
mutex_lock(&mdp3_session->lock);
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.c b/drivers/video/msm/mdss/mdss_dsi_cmd.c
index 8fc1115c0..6d8f9e9 100644
--- a/drivers/video/msm/mdss/mdss_dsi_cmd.c
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -66,6 +66,7 @@
off = 8 - off;
dp->data += off;
dp->len = 0;
+ dp->read_cnt = 0;
return dp->data;
}
@@ -86,6 +87,7 @@
dp->data = dp->start;
dp->len = 0;
+ dp->read_cnt = 0;
return size;
}
@@ -574,6 +576,7 @@
/* strip out dcs type */
rp->data++;
rp->len = 1;
+ rp->read_cnt -= 3;
return rp->len;
}
@@ -585,6 +588,7 @@
/* strip out dcs type */
rp->data++;
rp->len = 2;
+ rp->read_cnt -= 2;
return rp->len;
}
@@ -593,6 +597,7 @@
/* strip out dcs header */
rp->data += 4;
rp->len -= 4;
+ rp->read_cnt -= 6;
return rp->len;
}
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.h b/drivers/video/msm/mdss/mdss_dsi_cmd.h
index f806e78..3abe4fc 100644
--- a/drivers/video/msm/mdss/mdss_dsi_cmd.h
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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,7 +30,7 @@
#define MDSS_DSI_MRPS 0x04 /* Maximum Return Packet Size */
-#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
+#define MDSS_DSI_LEN 10 /* 4 x 4 - 4 - 2, bytes dcs header+crc-align */
struct dsi_buf {
u32 *hdr; /* dsi host header */
@@ -40,6 +40,7 @@
char *data; /* buffer */
int len; /* data length */
dma_addr_t dmap; /* mapped dma addr */
+ int read_cnt;
};
/* dcs read/write */
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
old mode 100644
new mode 100755
index 4c72d28..70e2972
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -32,11 +32,11 @@
struct mdss_mdp_ctl *ctl;
u32 pp_num;
u8 ref_cnt;
- struct completion pp_comp;
struct completion stop_comp;
+ wait_queue_head_t pp_waitq;
struct list_head vsync_handlers;
int panel_on;
- int koff_cnt;
+ atomic_t koff_cnt;
int clk_enabled;
int vsync_enabled;
int rdptr_enabled;
@@ -55,10 +55,14 @@
u32 vclk_line; /* vsync clock per line */
struct mdss_panel_recovery recovery;
bool ulps;
+ struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */
+ u32 pp_timeout_report_cnt;
};
struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
+static int mdss_mdp_cmd_do_notifier(struct mdss_mdp_cmd_ctx *ctx);
+
static inline u32 mdss_mdp_cmd_line_count(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_mixer *mixer;
@@ -287,7 +291,7 @@
ctx->rdptr_enabled--;
/* keep clk on during kickoff */
- if (ctx->rdptr_enabled == 0 && ctx->koff_cnt)
+ if (ctx->rdptr_enabled == 0 && atomic_read(&ctx->koff_cnt))
ctx->rdptr_enabled++;
}
@@ -314,14 +318,13 @@
if (!ctx->ctl)
return;
spin_lock_irqsave(&ctx->clk_lock, flags);
- if (ctx->koff_cnt) {
+ if (atomic_read(&ctx->koff_cnt)) {
mdss_mdp_ctl_reset(ctx->ctl);
pr_debug("%s: intf_num=%d\n", __func__,
ctx->ctl->intf_num);
- ctx->koff_cnt--;
+ atomic_dec(&ctx->koff_cnt);
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
ctx->pp_num);
- complete_all(&ctx->pp_comp);
}
spin_unlock_irqrestore(&ctx->clk_lock, flags);
}
@@ -348,25 +351,27 @@
}
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
- complete_all(&ctx->pp_comp);
MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
ctx->rdptr_enabled);
- if (ctx->koff_cnt) {
- atomic_inc(&ctx->pp_done_cnt);
- schedule_work(&ctx->pp_done_work);
- ctx->koff_cnt--;
- if (ctx->koff_cnt) {
+ if (atomic_add_unless(&ctx->koff_cnt, -1, 0)) {
+ if (atomic_read(&ctx->koff_cnt))
pr_err("%s: too many kickoffs=%d!\n", __func__,
- ctx->koff_cnt);
- ctx->koff_cnt = 0;
+ atomic_read(&ctx->koff_cnt));
+ if (mdss_mdp_cmd_do_notifier(ctx)) {
+ atomic_inc(&ctx->pp_done_cnt);
+ schedule_work(&ctx->pp_done_work);
}
- } else
+ wake_up_all(&ctx->pp_waitq);
+ } else {
pr_err("%s: should not have pingpong interrupt!\n", __func__);
+ }
- trace_mdp_cmd_pingpong_done(ctl, ctx->pp_num, ctx->koff_cnt);
+ trace_mdp_cmd_pingpong_done(ctl, ctx->pp_num,
+ atomic_read(&ctx->koff_cnt));
pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d kcnt=%d\n", __func__,
- ctl->num, ctl->intf_num, ctx->pp_num, ctx->koff_cnt);
+ ctl->num, ctl->intf_num, ctx->pp_num,
+ atomic_read(&ctx->koff_cnt));
spin_unlock(&ctx->clk_lock);
}
@@ -504,7 +509,6 @@
struct mdss_mdp_cmd_ctx *ctx;
struct mdss_panel_data *pdata;
unsigned long flags;
- int need_wait = 0;
int rc = 0;
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
@@ -515,11 +519,6 @@
pdata = ctl->panel_data;
- spin_lock_irqsave(&ctx->clk_lock, flags);
- if (ctx->koff_cnt > 0)
- need_wait = 1;
- spin_unlock_irqrestore(&ctx->clk_lock, flags);
-
ctl->roi_bkup.w = ctl->width;
ctl->roi_bkup.h = ctl->height;
@@ -527,33 +526,95 @@
ctx->rdptr_enabled, ctl->roi_bkup.w,
ctl->roi_bkup.h);
- pr_debug("%s: need_wait=%d intf_num=%d ctx=%p\n",
- __func__, need_wait, ctl->intf_num, ctx);
+ pr_debug("%s: intf_num=%d ctx=%p koff_cnt=%d\n", __func__,
+ ctl->intf_num, ctx, atomic_read(&ctx->koff_cnt));
- if (need_wait) {
- rc = wait_for_completion_timeout(
- &ctx->pp_comp, KOFF_TIMEOUT);
+ rc = wait_event_timeout(ctx->pp_waitq,
+ atomic_read(&ctx->koff_cnt) == 0,
+ KOFF_TIMEOUT);
- trace_mdp_cmd_wait_pingpong(ctl->num, ctx->koff_cnt);
+ if (rc <= 0) {
+ u32 status, mask;
- if (rc <= 0) {
- WARN(1, "cmd kickoff timed out (%d) ctl=%d\n",
- rc, ctl->num);
- mdss_dsi_debug_check_te(pdata);
- MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0", "dsi1",
- "edp", "hdmi", "panic");
- rc = -EPERM;
- mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
- } else {
- rc = 0;
+ mask = BIT(MDSS_MDP_IRQ_PING_PONG_COMP + ctx->pp_num);
+ status = mask & readl_relaxed(ctl->mdata->mdp_base +
+ MDSS_MDP_REG_INTR_STATUS);
+ if (status) {
+ WARN(1, "pp done but irq not triggered\n");
+ mdss_mdp_irq_clear(ctl->mdata,
+ MDSS_MDP_IRQ_PING_PONG_COMP,
+ ctx->pp_num);
+ local_irq_save(flags);
+ mdss_mdp_cmd_pingpong_done(ctl);
+ local_irq_restore(flags);
+ rc = 1;
}
+
+ rc = atomic_read(&ctx->koff_cnt) == 0;
}
- MDSS_XLOG(ctl->num, ctx->koff_cnt, ctx->clk_enabled,
- ctx->rdptr_enabled, rc);
+ if (rc <= 0) {
+ if (!ctx->pp_timeout_report_cnt) {
+ WARN(1, "cmd kickoff timed out (%d) ctl=%d\n",
+ rc, ctl->num);
+ mdss_dsi_debug_check_te(pdata);
+ MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0", "dsi1",
+ "edp", "hdmi", "panic");
+ }
+ ctx->pp_timeout_report_cnt++;
+ rc = -EPERM;
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
+ atomic_add_unless(&ctx->koff_cnt, -1, 0);
+ } else {
+ rc = 0;
+ ctx->pp_timeout_report_cnt = 0;
+ }
+
+ /* signal any pending ping pong done events */
+ while (atomic_add_unless(&ctx->pp_done_cnt, -1, 0))
+ mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_DONE);
+
+ MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
+ ctx->rdptr_enabled, rc);
+
return rc;
}
+static int mdss_mdp_cmd_do_notifier(struct mdss_mdp_cmd_ctx *ctx)
+{
+ struct mdss_mdp_cmd_ctx *sctx;
+ sctx = ctx->sync_ctx;
+
+ if (!sctx || atomic_read(&sctx->koff_cnt) == 0)
+ return 1;
+
+ return 0;
+}
+
+static void mdss_mdp_cmd_set_sync_ctx(
+ struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl)
+{
+ struct mdss_mdp_cmd_ctx *ctx, *sctx;
+
+ ctx = (struct mdss_mdp_cmd_ctx *)ctl->priv_data;
+ if (!sctl) {
+ ctx->sync_ctx = NULL;
+ return;
+ }
+
+ sctx = (struct mdss_mdp_cmd_ctx *)sctl->priv_data;
+
+ if (!sctl->roi.w && !sctl->roi.h) {
+ /* left only */
+ ctx->sync_ctx = NULL;
+ sctx->sync_ctx = NULL;
+ } else {
+ /* left + right */
+ ctx->sync_ctx = sctx;
+ sctx->sync_ctx = ctx;
+ }
+}
+
static int mdss_mdp_cmd_set_partial_roi(struct mdss_mdp_ctl *ctl)
{
int rc = 0;
@@ -572,8 +633,7 @@
int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
{
- struct mdss_mdp_cmd_ctx *ctx;
- unsigned long flags;
+ struct mdss_mdp_cmd_ctx *ctx, *sctx = NULL;
int rc;
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
@@ -602,10 +662,11 @@
MDSS_XLOG(ctl->num, ctl->roi.x, ctl->roi.y, ctl->roi.w,
ctl->roi.h);
- spin_lock_irqsave(&ctx->clk_lock, flags);
- ctx->koff_cnt++;
- spin_unlock_irqrestore(&ctx->clk_lock, flags);
- trace_mdp_cmd_kickoff(ctl->num, ctx->koff_cnt);
+ atomic_inc(&ctx->koff_cnt);
+ if (sctx)
+ atomic_inc(&sctx->koff_cnt);
+
+ trace_mdp_cmd_kickoff(ctl->num, atomic_read(&ctx->koff_cnt));
mdss_mdp_cmd_clk_on(ctx);
@@ -615,7 +676,9 @@
* tx dcs command if had any
*/
mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_DSI_CMDLIST_KOFF, NULL);
- INIT_COMPLETION(ctx->pp_comp);
+
+ mdss_mdp_cmd_set_sync_ctx(ctl, NULL);
+
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
mdss_mdp_ctl_perf_set_transaction_status(ctl,
@@ -667,13 +730,10 @@
pr_err("no panel data\n");
} else {
pinfo = &ctl->panel_data->panel_info;
-
- if (pinfo->panel_dead) {
- mdss_mdp_irq_disable
- (MDSS_MDP_IRQ_PING_PONG_RD_PTR,
- ctx->pp_num);
- ctx->rdptr_enabled = 0;
- }
+ mdss_mdp_irq_disable
+ (MDSS_MDP_IRQ_PING_PONG_RD_PTR,
+ ctx->pp_num);
+ ctx->rdptr_enabled = 0;
}
}
@@ -754,7 +814,8 @@
ctx->ctl = ctl;
ctx->pp_num = mixer->num;
- init_completion(&ctx->pp_comp);
+ ctx->pp_timeout_report_cnt = 0;
+ init_waitqueue_head(&ctx->pp_waitq);
init_completion(&ctx->stop_comp);
spin_lock_init(&ctx->clk_lock);
mutex_init(&ctx->clk_mtx);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index b165664..27fe7bc 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -29,7 +29,7 @@
#include "q6voice.h"
-#define TIMEOUT_MS 300
+#define TIMEOUT_MS 500
#define CMD_STATUS_SUCCESS 0