Merge "ion: retry during race with shrinking/allocating"
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 4b8a3d4..1da84fa 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -3,7 +3,7 @@
* FocalTech ft5x06 TouchScreen driver.
*
* Copyright (c) 2010 Focal tech Ltd.
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -69,7 +69,6 @@
#define FT_REG_THGROUP 0x80
#define FT_REG_ECC 0xCC
#define FT_REG_RESET_FW 0x07
-#define FT_REG_FW_MAJ_VER 0xB1
#define FT_REG_FW_MIN_VER 0xB2
#define FT_REG_FW_SUB_MIN_VER 0xB3
@@ -289,7 +288,7 @@
u8 reg_addr;
int err;
- reg_addr = FT_REG_FW_MAJ_VER;
+ reg_addr = FT_REG_FW_VER;
err = ft5x06_i2c_read(client, ®_addr, 1, &data->fw_ver[0], 1);
if (err < 0)
dev_err(&client->dev, "fw major version read failed");
@@ -877,6 +876,11 @@
u8 fw_file_maj, fw_file_min, fw_file_sub_min;
bool fw_upgrade = false;
+ if (data->suspended) {
+ dev_info(dev, "Device is in suspend state: Exit FW upgrade\n");
+ return -EBUSY;
+ }
+
rc = request_firmware(&fw, data->fw_name, dev);
if (rc < 0) {
dev_err(dev, "Request firmware failed - %s (%d)\n",
@@ -899,17 +903,10 @@
dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj,
fw_file_min, fw_file_sub_min);
- if (force) {
+ if (force)
fw_upgrade = true;
- } else if (data->fw_ver[0] == fw_file_maj) {
- if (data->fw_ver[1] < fw_file_min)
- fw_upgrade = true;
- else if (data->fw_ver[2] < fw_file_sub_min)
- fw_upgrade = true;
- else
- dev_info(dev, "No need to upgrade\n");
- } else
- dev_info(dev, "Firmware versions do not match\n");
+ else if (data->fw_ver[0] < fw_file_maj)
+ fw_upgrade = true;
if (!fw_upgrade) {
dev_info(dev, "Exiting fw upgrade...\n");
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 911a9e7..50581f8 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -476,15 +476,14 @@
mb();
}
-static void __release_smg(void __iomem *base, int ctx)
+static void __release_smg(void __iomem *base)
{
int i, smt_size;
smt_size = GET_IDR0_NUMSMRG(base);
- /* Invalidate any SMGs associated with this context */
+ /* Invalidate all SMGs */
for (i = 0; i < smt_size; i++)
- if (GET_SMR_VALID(base, i) &&
- GET_S2CR_CBNDX(base, i) == ctx)
+ if (GET_SMR_VALID(base, i))
SET_SMR_VALID(base, i, 0);
}
@@ -527,17 +526,52 @@
}
}
+
+static int program_m2v_table(struct device *dev, void __iomem *base)
+{
+ struct msm_iommu_ctx_drvdata *ctx_drvdata = dev_get_drvdata(dev);
+ u32 *sids = ctx_drvdata->sids;
+ unsigned int ctx = ctx_drvdata->num;
+ int num = 0, i, smt_size;
+ int len = ctx_drvdata->nsid;
+
+ smt_size = GET_IDR0_NUMSMRG(base);
+ /* Program the M2V tables for this context */
+ for (i = 0; i < len / sizeof(*sids); i++) {
+ for (; num < smt_size; num++)
+ if (GET_SMR_VALID(base, num) == 0)
+ break;
+ BUG_ON(num >= smt_size);
+
+ SET_SMR_VALID(base, num, 1);
+ SET_SMR_MASK(base, num, 0);
+ SET_SMR_ID(base, num, sids[i]);
+
+ SET_S2CR_N(base, num, 0);
+ SET_S2CR_CBNDX(base, num, ctx);
+ SET_S2CR_MEMATTR(base, num, 0x0A);
+ /* Set security bit override to be Non-secure */
+ SET_S2CR_NSCFG(base, num, 3);
+ }
+
+ return 0;
+}
+
+static void program_all_m2v_tables(struct msm_iommu_drvdata *iommu_drvdata)
+{
+ device_for_each_child(iommu_drvdata->dev, iommu_drvdata->base,
+ program_m2v_table);
+}
+
static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
struct msm_iommu_ctx_drvdata *ctx_drvdata,
- struct msm_iommu_priv *priv, bool is_secure)
+ struct msm_iommu_priv *priv, bool is_secure,
+ bool program_m2v)
{
unsigned int prrr, nmrr;
- unsigned int pn;
- int num = 0, i, smt_size;
+ phys_addr_t pn;
void __iomem *base = iommu_drvdata->base;
unsigned int ctx = ctx_drvdata->num;
- u32 *sids = ctx_drvdata->sids;
- int len = ctx_drvdata->nsid;
phys_addr_t pgtable = __pa(priv->pt.fl_table);
__reset_context(base, ctx);
@@ -578,24 +612,9 @@
}
if (!is_secure) {
- smt_size = GET_IDR0_NUMSMRG(base);
- /* Program the M2V tables for this context */
- for (i = 0; i < len / sizeof(*sids); i++) {
- for (; num < smt_size; num++)
- if (GET_SMR_VALID(base, num) == 0)
- break;
- BUG_ON(num >= smt_size);
+ if (program_m2v)
+ program_all_m2v_tables(iommu_drvdata);
- SET_SMR_VALID(base, num, 1);
- SET_SMR_MASK(base, num, 0);
- SET_SMR_ID(base, num, sids[i]);
-
- SET_S2CR_N(base, num, 0);
- SET_S2CR_CBNDX(base, num, ctx);
- SET_S2CR_MEMATTR(base, num, 0x0A);
- /* Set security bit override to be Non-secure */
- SET_S2CR_NSCFG(base, num, 3);
- }
SET_CBAR_N(base, ctx, 0);
/* Stage 1 Context with Stage 2 bypass */
@@ -667,49 +686,55 @@
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata;
- int ret;
+ int ret = 0;
int is_secure;
+ bool set_m2v = false;
mutex_lock(&msm_iommu_lock);
priv = domain->priv;
if (!priv || !dev) {
ret = -EINVAL;
- goto fail;
+ goto unlock;
}
iommu_drvdata = dev_get_drvdata(dev->parent);
ctx_drvdata = dev_get_drvdata(dev);
if (!iommu_drvdata || !ctx_drvdata) {
ret = -EINVAL;
- goto fail;
+ goto unlock;
}
+ ++ctx_drvdata->attach_count;
+
+ if (ctx_drvdata->attach_count > 1)
+ goto already_attached;
+
if (!list_empty(&ctx_drvdata->attached_elm)) {
ret = -EBUSY;
- goto fail;
+ goto unlock;
}
list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
if (tmp_drvdata == ctx_drvdata) {
ret = -EBUSY;
- goto fail;
+ goto unlock;
}
is_secure = iommu_drvdata->sec_id != -1;
ret = __enable_regulators(iommu_drvdata);
if (ret)
- goto fail;
+ goto unlock;
ret = apply_bus_vote(iommu_drvdata, 1);
if (ret)
- goto fail;
+ goto unlock;
ret = __enable_clocks(iommu_drvdata);
if (ret) {
__disable_regulators(iommu_drvdata);
- goto fail;
+ goto unlock;
}
/* We can only do this once */
@@ -724,16 +749,17 @@
if (ret) {
__disable_regulators(iommu_drvdata);
__disable_clocks(iommu_drvdata);
- goto fail;
+ goto unlock;
}
}
program_iommu_bfb_settings(iommu_drvdata->base,
iommu_drvdata->bfb_settings);
+ set_m2v = true;
}
iommu_halt(iommu_drvdata);
- __program_context(iommu_drvdata, ctx_drvdata, priv, is_secure);
+ __program_context(iommu_drvdata, ctx_drvdata, priv, is_secure, set_m2v);
iommu_resume(iommu_drvdata);
@@ -743,11 +769,12 @@
ctx_drvdata->attached_domain = domain;
++iommu_drvdata->ctx_attach_count;
+already_attached:
mutex_unlock(&msm_iommu_lock);
msm_iommu_attached(dev->parent);
return ret;
-fail:
+unlock:
mutex_unlock(&msm_iommu_lock);
return ret;
}
@@ -766,16 +793,22 @@
mutex_lock(&msm_iommu_lock);
priv = domain->priv;
if (!priv || !dev)
- goto fail;
+ goto unlock;
iommu_drvdata = dev_get_drvdata(dev->parent);
ctx_drvdata = dev_get_drvdata(dev);
if (!iommu_drvdata || !ctx_drvdata || !ctx_drvdata->attached_domain)
- goto fail;
+ goto unlock;
+
+ --ctx_drvdata->attach_count;
+ BUG_ON(ctx_drvdata->attach_count < 0);
+
+ if (ctx_drvdata->attach_count > 0)
+ goto unlock;
ret = __enable_clocks(iommu_drvdata);
if (ret)
- goto fail;
+ goto unlock;
is_secure = iommu_drvdata->sec_id != -1;
@@ -785,13 +818,15 @@
iommu_drvdata->asid[ctx_drvdata->asid - 1]--;
ctx_drvdata->asid = -1;
- iommu_halt(iommu_drvdata);
-
__reset_context(iommu_drvdata->base, ctx_drvdata->num);
- if (!is_secure)
- __release_smg(iommu_drvdata->base, ctx_drvdata->num);
- iommu_resume(iommu_drvdata);
+ /*
+ * Only reset the M2V tables on the very last detach */
+ if (!is_secure && iommu_drvdata->ctx_attach_count == 1) {
+ iommu_halt(iommu_drvdata);
+ __release_smg(iommu_drvdata->base);
+ iommu_resume(iommu_drvdata);
+ }
__disable_clocks(iommu_drvdata);
@@ -803,7 +838,7 @@
ctx_drvdata->attached_domain = NULL;
BUG_ON(iommu_drvdata->ctx_attach_count == 0);
--iommu_drvdata->ctx_attach_count;
-fail:
+unlock:
mutex_unlock(&msm_iommu_lock);
}