aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/dvfs.c24
-rw-r--r--arch/arm/mach-omap2/dvfs.h5
-rw-r--r--arch/arm/mach-omap2/iommu2.c14
-rw-r--r--arch/arm/mach-omap2/pm44xx.c170
-rw-r--r--arch/arm/mach-omap2/remoteproc.c2
-rw-r--r--arch/arm/plat-omap/Makefile2
-rw-r--r--arch/arm/plat-omap/include/plat/gpio.h2
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h4
-rw-r--r--arch/arm/plat-omap/iommu.c49
-rw-r--r--arch/arm/plat-omap/omap_rpmsg.c2
-rw-r--r--arch/arm/plat-omap/rproc_user.c165
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c2
-rw-r--r--drivers/gpio/gpio-omap.c82
-rw-r--r--drivers/gpu/pvr/pvrversion.h4
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c42
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c176
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c3
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.c5
-rw-r--r--drivers/remoteproc/omap_remoteproc.c28
-rw-r--r--drivers/remoteproc/remoteproc.c107
-rw-r--r--drivers/video/omap2/dss/core.c1
-rw-r--r--drivers/video/omap2/dss/dispc.c358
-rw-r--r--drivers/video/omap2/dss/display.c12
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c4
-rw-r--r--drivers/video/omap2/dss/manager.c11
-rw-r--r--drivers/video/omap2/dsscomp/device.c5
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c13
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c8
-rw-r--r--include/linux/remoteproc.h13
-rw-r--r--include/video/omapdss.h6
-rw-r--r--net/netfilter/xt_qtaguid.c12
31 files changed, 1041 insertions, 290 deletions
diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c
index c1efdbf..6af0e67 100644
--- a/arch/arm/mach-omap2/dvfs.c
+++ b/arch/arm/mach-omap2/dvfs.c
@@ -1017,6 +1017,30 @@ bool omap_dvfs_is_scaling(struct voltagedomain *voltdm)
}
EXPORT_SYMBOL(omap_dvfs_is_scaling);
+/**
+ * omap_dvfs_is_any_dev_scaling() - returns true if any devices are scaling
+ *
+ * Should be called in non_preemptible context and is meant for
+ * Arch code to check and take appropriate measures if it is not-advisable
+ * for any activity which might conflict with scaling operation.
+ *
+ * IMPORTANT: This function is expected to be called with interrupt disabled,
+ * non-preemptible context.
+ */
+bool omap_dvfs_is_any_dev_scaling(void)
+{
+ struct omap_vdd_dvfs_info *dvfs_info;
+
+ WARN(!irqs_disabled(), "Called with IRQs enabled, inaccurate!\n");
+
+ list_for_each_entry(dvfs_info, &omap_dvfs_info_list, node) {
+ if (dvfs_info->is_scaling)
+ return true;
+ }
+ return false;
+}
+EXPORT_SYMBOL(omap_dvfs_is_any_dev_scaling);
+
#ifdef CONFIG_PM_DEBUG
static int dvfs_dump_vdd(struct seq_file *sf, void *unused)
{
diff --git a/arch/arm/mach-omap2/dvfs.h b/arch/arm/mach-omap2/dvfs.h
index 64f0afa..284e60f 100644
--- a/arch/arm/mach-omap2/dvfs.h
+++ b/arch/arm/mach-omap2/dvfs.h
@@ -23,6 +23,7 @@ int omap_device_scale(struct device *req_dev, struct device *target_dev,
unsigned long rate);
bool omap_dvfs_is_scaling(struct voltagedomain *voltdm);
+bool omap_dvfs_is_any_dev_scaling(void);
#else
static inline int omap_dvfs_register_device(struct device *dev,
char *voltdm_name, char *clk_name)
@@ -38,5 +39,9 @@ static inline bool omap_dvfs_is_scaling(struct voltagedomain *voltdm)
{
return false;
}
+static inline bool omap_dvfs_is_any_dev_scaling(void)
+{
+ return false;
+}
#endif
#endif
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index faa7646..f42a4a3 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -85,19 +85,21 @@ static void __iommu_set_twl(struct iommu *obj, bool on)
iommu_write_reg(obj, l, MMU_CNTL);
}
-
static int omap2_iommu_enable(struct iommu *obj)
{
u32 l, pa;
unsigned long timeout;
int ret = 0;
- if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
- return -EINVAL;
+ if (!obj->secure_mode) {
+ if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
+ return -EINVAL;
- pa = virt_to_phys(obj->iopgd);
- if (!IS_ALIGNED(pa, SZ_16K))
- return -EINVAL;
+ pa = virt_to_phys(obj->iopgd);
+ if (!IS_ALIGNED(pa, SZ_16K))
+ return -EINVAL;
+ } else
+ pa = (u32)obj->secure_ttb;
ret = omap_device_enable(obj->pdev);
if (ret)
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 01d022d..6cfd501 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -165,6 +165,8 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend)
}
}
+ omap2_gpio_set_edge_wakeup();
+
if (omap4_device_next_state_off()) {
omap2_gpio_prepare_for_idle(true);
omap_gpmc_save_context();
@@ -191,6 +193,8 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend)
omap4_enter_lowpower(cpu, power_state);
if (omap4_device_prev_state_off()) {
+ /* Reconfigure the trim settings as well */
+ omap4_ldo_trim_configure();
omap4_dpll_resume_off();
omap4_cm_resume_off();
#ifdef CONFIG_PM_DEBUG
@@ -216,8 +220,6 @@ abort_device_off:
if (omap4_device_prev_state_off()) {
omap_dma_global_context_restore();
omap_gpmc_restore_context();
- /* Reconfigure the trim settings as well */
- omap4_ldo_trim_configure();
}
if (omap4_device_next_state_off()) {
@@ -233,6 +235,8 @@ abort_device_off:
OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET);
}
+ omap2_gpio_restore_edge_wakeup();
+
if (mpu_next_state < PWRDM_POWER_INACTIVE) {
omap_vc_set_auto_trans(mpu_voltdm,
OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
@@ -487,6 +491,10 @@ static void omap4_configure_pwdm_suspend(bool is_off_mode)
list_for_each_entry(pwrst, &pwrst_list, node) {
bool parent_power_domain = false;
+
+ pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+ pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm);
+
if ((!strcmp(pwrst->pwrdm->name, "cpu0_pwrdm")) ||
(!strcmp(pwrst->pwrdm->name, "cpu1_pwrdm")))
continue;
@@ -505,33 +513,104 @@ static void omap4_configure_pwdm_suspend(bool is_off_mode)
als =
get_achievable_state(pwrst->pwrdm->pwrsts_logic_ret,
logic_state, parent_power_domain);
- pwrdm_set_logic_retst(pwrst->pwrdm, als);
+ if (als < pwrst->saved_logic_state)
+ pwrdm_set_logic_retst(pwrst->pwrdm, als);
}
if (pwrst->pwrdm->pwrsts) {
pwrst->next_state =
get_achievable_state(pwrst->pwrdm->pwrsts, state,
parent_power_domain);
- omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+ if (pwrst->next_state < pwrst->saved_state)
+ omap_set_pwrdm_state(pwrst->pwrdm,
+ pwrst->next_state);
+ else
+ pwrst->next_state = pwrst->saved_state;
}
}
}
-static int omap4_pm_suspend(void)
+/**
+ * omap4_restore_pwdms_after_suspend() - Restore powerdomains after suspend
+ *
+ * Re-program all powerdomains to saved power domain states.
+ *
+ * returns 0 if all power domains hit targeted power state, -1 if any domain
+ * failed to hit targeted power state (status related to the actual restore
+ * is not returned).
+ */
+static int omap4_restore_pwdms_after_suspend(void)
{
struct power_state *pwrst;
- int state, ret = 0;
+ int cstate, pstate, ret = 0;
+
+ /* Restore next powerdomain state */
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ cstate = pwrdm_read_pwrst(pwrst->pwrdm);
+ pstate = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+ if (pstate > pwrst->next_state) {
+ pr_info("Powerdomain (%s) didn't enter "
+ "target state %d Vs achieved state %d. "
+ "current state %d\n",
+ pwrst->pwrdm->name, pwrst->next_state,
+ pstate, cstate);
+ ret = -1;
+ }
+
+ /* If state already ON due to h/w dep, don't do anything */
+ if (cstate == PWRDM_POWER_ON)
+ continue;
+
+ /* If we have already achieved saved state, nothing to do */
+ if (cstate == pwrst->saved_state)
+ continue;
+
+ /* mpuss code takes care of this */
+ if ((!strcmp(pwrst->pwrdm->name, "cpu0_pwrdm")) ||
+ (!strcmp(pwrst->pwrdm->name, "cpu1_pwrdm")))
+ continue;
+
+ /*
+ * Skip pd program if saved state higher than current state
+ * Since we would have already returned if the state
+ * was ON, if the current state is yet another low power
+ * state, the PRCM specification clearly states that
+ * transition from a lower LP state to a higher LP state
+ * is forbidden.
+ */
+ if (pwrst->saved_state > cstate)
+ continue;
+
+ if (pwrst->pwrdm->pwrsts)
+ omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+
+ if (pwrst->pwrdm->pwrsts_logic_ret)
+ pwrdm_set_logic_retst(pwrst->pwrdm,
+ pwrst->saved_logic_state);
+ }
+
+ return ret;
+}
+
+static int omap4_pm_suspend(void)
+{
+ int ret = 0;
+
+ /*
+ * If any device was in the middle of a scale operation
+ * then abort, as we cannot predict which part of the scale
+ * operation we interrupted.
+ */
+ if (omap_dvfs_is_any_dev_scaling()) {
+ pr_err("%s: oops.. middle of scale op.. aborting suspend\n",
+ __func__);
+ return -EBUSY;
+ }
/* Wakeup timer from suspend */
if (wakeup_timer_seconds || wakeup_timer_milliseconds)
omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
wakeup_timer_milliseconds);
- /* Save current powerdomain state */
- list_for_each_entry(pwrst, &pwrst_list, node) {
- pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
- pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm);
- }
-
omap4_configure_pwdm_suspend(off_mode_enabled);
/* Enable Device OFF */
@@ -556,18 +635,8 @@ static int omap4_pm_suspend(void)
if (off_mode_enabled)
omap4_device_set_state_off(0);
- /* Restore next powerdomain state */
- list_for_each_entry(pwrst, &pwrst_list, node) {
- state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
- if (state > pwrst->next_state) {
- pr_info("Powerdomain (%s) didn't enter "
- "target state %d\n",
- pwrst->pwrdm->name, pwrst->next_state);
- ret = -1;
- }
- omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
- pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->saved_logic_state);
- }
+ ret = omap4_restore_pwdms_after_suspend();
+
if (ret)
pr_err("Could not enter target state in pm_suspend\n");
else
@@ -795,7 +864,8 @@ static void __init prcm_setup_regs(void)
* when a SWakeup is asserted from HSI to MPU (and DSP) :
* - force a DSP SW wakeup
* - wait DSP module to be fully ON
-* - force a DSP SW sleep
+* - Configure a DSP CLK CTRL to HW_AUTO
+* - Wait on DSP module to be OFF
*
* Note : we detect a Swakeup is asserted to MPU by checking when an interrupt
* is received while HSI module is ON.
@@ -804,26 +874,54 @@ static void __init prcm_setup_regs(void)
*/
static void omap_pm_clear_dsp_wake_up(void)
{
+ int ret;
+ int timeout = 10;
+
if (!tesla_pwrdm || !tesla_clkdm) {
WARN_ONCE(1, "%s: unable to use tesla workaround\n", __func__);
return;
}
- if (omap4_prminst_read_inst_reg(tesla_pwrdm->prcm_partition,
- tesla_pwrdm->prcm_offs,
- OMAP4_PM_PWSTST) & OMAP_INTRANSITION_MASK) {
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ /* If Tesla power state in RET or OFF, then not hit by errata */
+ if (ret <= PWRDM_POWER_RET)
+ return;
+
+ if (clkdm_wakeup(tesla_clkdm))
+ pr_err("%s: Failed to force wakeup of %s\n", __func__,
+ tesla_clkdm->name);
- if (clkdm_wakeup(tesla_clkdm))
- pr_err("%s: Failed to force wakeup of %s\n", __func__,
- tesla_clkdm->name);
+ /* This takes less than a few microseconds, hence in context */
+ pwrdm_wait_transition(tesla_pwrdm);
- /* This takes less than a few microseconds, hence in context */
+ /*
+ * Check current power state of Tesla after transition, to make sure
+ * that Tesla is indeed turned ON.
+ */
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ do {
pwrdm_wait_transition(tesla_pwrdm);
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ } while ((ret < PWRDM_POWER_INACTIVE) && --timeout);
+
+ if (!timeout)
+ pr_err("%s: Tesla failed to transition to ON state!\n",
+ __func__);
+
+ timeout = 10;
+ clkdm_allow_idle(tesla_clkdm);
+
+ /* Ensure Tesla power state in OFF state */
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ do {
+ pwrdm_wait_transition(tesla_pwrdm);
+ ret = pwrdm_read_pwrst(tesla_pwrdm);
+ } while ((ret >= PWRDM_POWER_INACTIVE) && --timeout);
+
+ if (!timeout)
+ pr_err("%s: Tesla failed to transition to OFF state\n",
+ __func__);
- if (clkdm_sleep(tesla_clkdm))
- pr_err("%s: Failed to force sleep of %s\n", __func__,
- tesla_clkdm->name);
- }
}
static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
diff --git a/arch/arm/mach-omap2/remoteproc.c b/arch/arm/mach-omap2/remoteproc.c
index 43d49eb..b8ae36f 100644
--- a/arch/arm/mach-omap2/remoteproc.c
+++ b/arch/arm/mach-omap2/remoteproc.c
@@ -59,7 +59,7 @@ static struct omap_rproc_pdata omap4_rproc_data[] = {
.timers_cnt = ARRAY_SIZE(ipu_timers),
.idle_addr = OMAP4430_CM_M3_M3_CLKCTRL,
.idle_mask = OMAP4430_STBYST_MASK,
- .suspend_addr = 0xb43f02d8,
+ .suspend_addr = 0xb3bf02d8,
.suspend_mask = ~0,
.sus_timeout = 5000,
.sus_mbox_name = "mailbox-1",
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index f3ab483..c3fa015 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
# omap_device support (OMAP2+ only at the moment)
obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
-obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
+obj-$(CONFIG_ARCH_OMAP4) += omap_device.o rproc_user.o
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
obj-$(CONFIG_OMAP_RPMSG) += omap_rpmsg.o
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index 24b61af..89af4ad 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -217,6 +217,8 @@ extern void omap2_gpio_prepare_for_idle(int off_mode);
extern void omap2_gpio_resume_after_idle(void);
extern void omap_set_gpio_debounce(int gpio, int enable);
extern void omap_set_gpio_debounce_time(int gpio, int enable);
+extern void omap2_gpio_set_edge_wakeup(void);
+extern void omap2_gpio_restore_edge_wakeup(void);
/*-------------------------------------------------------------------------*/
/* Wrappers for "new style" GPIO calls, using the new infrastructure
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 38d92b1..ed33ddf 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -56,6 +56,8 @@ struct iommu {
u32 da_end;
struct platform_device *pdev;
struct pm_qos_request_list *qos_request;
+ void *secure_ttb;
+ bool secure_mode;
};
struct cr_regs {
@@ -179,6 +181,8 @@ extern int iommu_set_isr(const char *name,
void *priv),
void *isr_priv);
+extern int iommu_set_secure(const char *name, bool enable, void *data);
+
extern void iommu_save_ctx(struct iommu *obj);
extern void iommu_restore_ctx(struct iommu *obj);
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 0a19b41..7f52a30 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -237,6 +237,11 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
struct iotlb_lock l;
struct cr_regs *cr;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return -EBUSY;
+ }
+
if (!obj || !obj->nr_tlb_entries || !e)
return -EINVAL;
@@ -297,6 +302,11 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
int i;
struct cr_regs cr;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return;
+ }
+
for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
u32 start;
size_t bytes;
@@ -616,6 +626,11 @@ int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
{
int err;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return -EBUSY;
+ }
+
flush_iotlb_page(obj, e->da);
err = iopgtable_store_entry_core(obj, e);
#ifdef PREFETCH_IOTLB
@@ -637,6 +652,11 @@ void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
{
u32 *iopgd, *iopte = NULL;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return;
+ }
+
iopgd = iopgd_offset(obj, da);
if (!*iopgd)
goto out;
@@ -706,6 +726,11 @@ size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
{
size_t bytes;
+ if (obj && obj->secure_mode) {
+ WARN_ON(1);
+ return 0;
+ }
+
spin_lock(&obj->page_table_lock);
bytes = iopgtable_clear_entry_core(obj, da);
@@ -921,6 +946,30 @@ int iommu_set_isr(const char *name,
}
EXPORT_SYMBOL_GPL(iommu_set_isr);
+int iommu_set_secure(const char *name, bool enable, void *data)
+{
+ struct device *dev;
+ struct iommu *obj;
+
+ dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
+ device_match_by_alias);
+ if (!dev)
+ return -ENODEV;
+
+ obj = to_iommu(dev);
+ mutex_lock(&obj->iommu_lock);
+ if (obj->refcount) {
+ mutex_unlock(&obj->iommu_lock);
+ return -EBUSY;
+ }
+ obj->secure_mode = enable;
+ obj->secure_ttb = data;
+ mutex_unlock(&obj->iommu_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_set_secure);
+
/*
* OMAP Device MMU(IOMMU) detection
*/
diff --git a/arch/arm/plat-omap/omap_rpmsg.c b/arch/arm/plat-omap/omap_rpmsg.c
index 44efd71..63d7eb7 100644
--- a/arch/arm/plat-omap/omap_rpmsg.c
+++ b/arch/arm/plat-omap/omap_rpmsg.c
@@ -165,8 +165,6 @@ static int omap_rpmsg_mbox_callback(struct notifier_block *this,
pr_debug("mbox msg: 0x%x\n", msg);
- rproc_last_busy(rpdev->rproc);
-
switch (msg) {
case RP_MBOX_CRASH:
pr_err("%s has just crashed !\n", rpdev->rproc_name);
diff --git a/arch/arm/plat-omap/rproc_user.c b/arch/arm/plat-omap/rproc_user.c
new file mode 100644
index 0000000..0764cfe
--- /dev/null
+++ b/arch/arm/plat-omap/rproc_user.c
@@ -0,0 +1,165 @@
+/*
+ * Secure Mode Input interface to remoteproc driver
+ *
+ * Copyright (C) 2011 Texas Instruments. All rights reserved.
+ *
+ * Authors: Suman Anna <s-anna@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <linux/remoteproc.h>
+
+
+#define RPROC_USER_NAME "rproc_user"
+#define RPROC_USER_DEVICES 1
+
+static DEFINE_MUTEX(rproc_user_mutex);
+
+struct rproc_user_device {
+ struct miscdevice mdev;
+};
+
+static struct rproc_user_device *ipu_device;
+static char *rproc_user_name = RPROC_USER_NAME;
+static bool secure_mode;
+static bool secure_attempt;
+
+
+static int rproc_user_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int rproc_user_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static ssize_t rproc_user_read(struct file *filp, char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ u8 enable;
+ int ret = 1;
+
+ if (len != 1)
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&rproc_user_mutex))
+ return -EINTR;
+ enable = secure_mode ? 1 : 0;
+ if (copy_to_user((void *)ubuf, &enable, sizeof(enable)))
+ ret = -EFAULT;
+ mutex_unlock(&rproc_user_mutex);
+
+ return ret;
+}
+
+static ssize_t rproc_user_write(struct file *filp, const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ int ret;
+ u8 enable;
+
+ if (len != 1)
+ return -EINVAL;
+
+ //enable = !(*(u8 *)ubuf == 0);
+ if (copy_from_user(&enable, (char __user *) ubuf, sizeof(enable)))
+ return -EFAULT;
+ enable = !(enable == 0);
+
+ if (mutex_lock_interruptible(&rproc_user_mutex))
+ return -EINTR;
+ if (enable && !secure_mode) {
+ ret = rproc_set_secure("ipu", enable);
+ if (!ret)
+ secure_mode = enable;
+ else
+ pr_err("rproc secure start failed, 0x%x\n", ret);
+ secure_attempt = enable;
+ } else if (!enable && secure_attempt) {
+ ret = rproc_set_secure("ipu", enable);
+ if (ret)
+ pr_err("rproc normal start failed 0x%x, urghh!!", ret);
+ secure_mode = enable;
+ secure_attempt = enable;
+ } else
+ ret = -EINVAL;
+ mutex_unlock(&rproc_user_mutex);
+
+ return ret ? ret : 1;
+}
+
+static const struct file_operations rproc_user_fops = {
+ .owner = THIS_MODULE,
+ .open = rproc_user_open,
+ .release = rproc_user_release,
+ .read = rproc_user_read,
+ .write = rproc_user_write,
+};
+
+static int __init rproc_user_init(void)
+{
+ int ret;
+
+ ipu_device = kzalloc(sizeof(struct rproc_user_device), GFP_KERNEL);
+ if (!ipu_device) {
+ pr_err("%s: memory allocation failed for ipu_device\n",
+ __func__);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ipu_device->mdev.minor = MISC_DYNAMIC_MINOR;
+ ipu_device->mdev.name = rproc_user_name;
+ ipu_device->mdev.fops = &rproc_user_fops;
+ ipu_device->mdev.parent = NULL;
+ ret = misc_register(&ipu_device->mdev);
+ if (ret) {
+ pr_err("rproc_user_init: failed to register rproc_user misc "
+ "device\n");
+ goto misc_fail;
+ }
+ return ret;
+
+misc_fail:
+ kfree(ipu_device);
+exit:
+ return ret;
+}
+module_init(rproc_user_init);
+
+static void __exit rproc_user_exit(void)
+{
+ misc_deregister(&ipu_device->mdev);
+ kfree(ipu_device);
+}
+module_exit(rproc_user_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("RemoteProc Secure Mode Interface Driver");
+MODULE_AUTHOR("Suman Anna");
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index d8f62f4..d60cb38 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -145,7 +145,7 @@ static void cpufreq_interactive_timer(unsigned long data)
delta_time = (unsigned int) cputime64_sub(pcpu->timer_run_time,
pcpu->freq_change_time);
- if (delta_idle > delta_time)
+ if ((delta_time == 0) || (delta_idle > delta_time))
load_since_change = 0;
else
load_since_change =
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index b20d3164..312d45d 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -44,6 +44,8 @@ struct gpio_regs {
u32 dataout;
u32 debounce;
u32 debounce_en;
+ u32 edge_falling;
+ u32 edge_rising;
};
struct gpio_bank {
@@ -86,6 +88,27 @@ static void omap_gpio_mod_init(struct gpio_bank *bank);
#define GPIO_INDEX(bank, gpio) (gpio % bank->width)
#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
#define GPIO_MOD_CTRL_BIT BIT(0)
+static void _set_gpio_waken(struct gpio_bank *bank, int gpio)
+{
+ if (bank->regs->wkup_set != bank->regs->wkup_clear) {
+ __raw_writel((1 << gpio), bank->base + bank->regs->wkup_set);
+ } else {
+ u32 val = __raw_readl(bank->base + bank->regs->wkup_set);
+ val |= 1 << gpio;
+ __raw_writel(val, bank->base + bank->regs->wkup_set);
+ }
+}
+static void _clear_gpio_waken(struct gpio_bank *bank, int gpio)
+{
+ if (bank->regs->wkup_set != bank->regs->wkup_clear) {
+ __raw_writel((1 << gpio), bank->base + bank->regs->wkup_clear);
+ } else {
+ u32 val = __raw_readl(bank->base + bank->regs->wkup_clear);
+ val &= ~(1 << gpio);
+ __raw_writel(val, bank->base + bank->regs->wkup_clear);
+ }
+
+}
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
{
@@ -224,11 +247,9 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
* transitions
*/
if (trigger & IRQ_TYPE_EDGE_BOTH)
- __raw_writel(1 << gpio, bank->base
- + bank->regs->wkup_set);
+ _set_gpio_waken(bank, gpio);
else
- __raw_writel(1 << gpio, bank->base
- + bank->regs->wkup_clear);
+ _clear_gpio_waken(bank, gpio);
}
}
/* This part needs to be executed always for OMAP{34xx, 44xx} */
@@ -314,11 +335,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
if (trigger)
/* Enable wake-up during idle for dynamic tick */
- __raw_writel(1 << gpio, bank->base
- + bank->regs->wkup_set);
+ _set_gpio_waken(bank, gpio);
else
- __raw_writel(1 << gpio, bank->base
- + bank->regs->wkup_clear);
+ _clear_gpio_waken(bank, gpio);
__raw_writel(l, reg);
}
@@ -553,7 +572,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
if (bank->regs->wkup_clear)
/* Disable wake-up during idle for dynamic tick */
- __raw_writel(1 << offset, bank->base + bank->regs->wkup_clear);
+ _clear_gpio_waken(bank, offset);
bank->mod_usage &= ~(1 << offset);
@@ -1366,6 +1385,51 @@ static int omap_gpio_pm_runtime_resume(struct device *dev)
}
#ifdef CONFIG_ARCH_OMAP2PLUS
+void omap2_gpio_set_edge_wakeup(void)
+{
+ struct gpio_bank *bank;
+
+ list_for_each_entry(bank, &omap_gpio_list, node) {
+ u32 level_low = 0;
+ u32 level_high = 0;
+ u32 wkup_status = 0;
+
+ level_low = __raw_readl(bank->base +
+ bank->regs->leveldetect0);
+ level_high = __raw_readl(bank->base +
+ bank->regs->leveldetect1);
+ wkup_status = __raw_readl(bank->base +
+ bank->regs->wkup_status);
+ bank->context.edge_falling = __raw_readl(bank->base +
+ bank->regs->fallingdetect);
+ bank->context.edge_rising = __raw_readl(bank->base +
+ bank->regs->risingdetect);
+
+ /*
+ * Set edge trigger for all gpio's that are
+ * expected to produce wakeup from low power.
+ * even if they are set for level detection only.
+ */
+ __raw_writel((bank->context.edge_falling | level_low) & wkup_status,
+ (bank->base + bank->regs->fallingdetect));
+ __raw_writel((bank->context.edge_rising | level_high) & wkup_status,
+ (bank->base + bank->regs->risingdetect));
+
+ }
+}
+
+void omap2_gpio_restore_edge_wakeup(void)
+{
+ struct gpio_bank *bank;
+
+ list_for_each_entry(bank, &omap_gpio_list, node) {
+ /* restore edge setting */
+ __raw_writel(bank->context.edge_falling,
+ (bank->base + bank->regs->fallingdetect));
+ __raw_writel(bank->context.edge_rising,
+ (bank->base + bank->regs->risingdetect));
+ }
+}
void omap2_gpio_prepare_for_idle(int off_mode)
{
diff --git a/drivers/gpu/pvr/pvrversion.h b/drivers/gpu/pvr/pvrversion.h
index 6d6b1ae..7d2c34a 100644
--- a/drivers/gpu/pvr/pvrversion.h
+++ b/drivers/gpu/pvr/pvrversion.h
@@ -36,7 +36,7 @@
#define PVRVERSION_FAMILY "sgxddk"
#define PVRVERSION_BRANCHNAME "1.8"
-#define PVRVERSION_BUILD 294981
+#define PVRVERSION_BUILD 295231
#define PVRVERSION_BSCONTROL "CustomerGoogle_Android_ogles1_ogles2_GPL"
#define PVRVERSION_STRING "CustomerGoogle_Android_ogles1_ogles2_GPL sgxddk 18 1.8@" PVR_STR2(PVRVERSION_BUILD)
@@ -45,7 +45,7 @@
#define COPYRIGHT_TXT "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
#define PVRVERSION_BUILD_HI 29
-#define PVRVERSION_BUILD_LO 4981
+#define PVRVERSION_BUILD_LO 5231
#define PVRVERSION_STRING_NUMERIC PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO)
#endif /* _PVRVERSION_H_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 2363da9..397492c 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c 285933 2011-09-23 21:45:31Z $
+ * $Id: dhd_linux.c 287541 2011-10-03 23:48:17Z $
*/
#include <typedefs.h>
@@ -1404,9 +1404,16 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
struct dot11_llc_snap_header *lsh;
ifp = dhd->iflist[ifidx];
+ if (ifp == NULL) {
+ DHD_ERROR(("%s: ifp is NULL. drop packet\n",
+ __FUNCTION__));
+ PKTFREE(dhdp->osh, pktbuf, TRUE);
+ continue;
+ }
/* Dropping packets before registering net device to avoid kernel panic */
- if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) {
+ if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED ||
+ !dhd->pub.up) {
DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n",
__FUNCTION__));
PKTFREE(dhdp->osh, pktbuf, TRUE);
@@ -2922,19 +2929,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret));
- /* query for 'ver' to get version info from firmware */
- memset(buf, 0, sizeof(buf));
- ptr = buf;
- bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
- DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
- else {
- bcmstrtok(&ptr, "\n", 0);
- /* Print fw version info */
- DHD_ERROR(("Firmware version = %s\n", buf));
- DHD_BLOG(buf, strlen(buf) + 1);
- DHD_BLOG(dhd_version, strlen(dhd_version) + 1);
- }
/* Set PowerSave mode */
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
@@ -2980,7 +2974,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
}
#endif /* defined(KEEP_ALIVE) */
-
/* Read event_msgs mask */
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
@@ -3077,9 +3070,24 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* PKT_FILTER_SUPPORT */
/* Force STA UP */
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0)
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0) {
DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+ /* query for 'ver' to get version info from firmware */
+ memset(buf, 0, sizeof(buf));
+ ptr = buf;
+ bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
+ DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
+ else {
+ bcmstrtok(&ptr, "\n", 0);
+ /* Print fw version info */
+ DHD_ERROR(("Firmware version = %s\n", buf));
+ DHD_BLOG(buf, strlen(buf) + 1);
+ DHD_BLOG(dhd_version, strlen(dhd_version) + 1);
+ }
done:
return ret;
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 16cb75f..a7b88f8 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -277,8 +277,8 @@ static void wl_destroy_event_handler(struct wl_priv *wl);
static s32 wl_event_handler(void *data);
static void wl_init_eq(struct wl_priv *wl);
static void wl_flush_eq(struct wl_priv *wl);
-static void wl_lock_eq(struct wl_priv *wl);
-static void wl_unlock_eq(struct wl_priv *wl);
+static unsigned long wl_lock_eq(struct wl_priv *wl);
+static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags);
static void wl_init_eq_lock(struct wl_priv *wl);
static void wl_init_event_handler(struct wl_priv *wl);
static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
@@ -330,7 +330,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
static s32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e,
void *data, s32 item);
static void *wl_read_prof(struct wl_priv *wl, s32 item);
-static void wl_init_prof(struct wl_profile *prof);
+static void wl_init_prof(struct wl_priv *wl);
/*
* cfg80211 connect utilites
@@ -2175,6 +2175,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
{
struct wl_priv *wl = wiphy_priv(wiphy);
struct ieee80211_channel *chan = sme->channel;
+ wl_extjoin_params_t *ext_join_params;
struct wl_join_params join_params;
size_t join_params_size;
s32 err = 0;
@@ -2184,6 +2185,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
u8* wpaie = 0;
u32 wpaie_len = 0;
u32 wpsie_len = 0;
+ u32 chan_cnt = 0;
u8 wpsie[IE_MAX_LEN];
WL_DBG(("In\n"));
CHECK_SYS_UP(wl);
@@ -2264,6 +2266,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
}
if (chan) {
wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
+ chan_cnt = 1;
WL_DBG(("channel (%d), center_req (%d)\n", wl->channel,
chan->center_freq));
} else
@@ -2304,6 +2307,67 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
* Join with specific BSSID and cached SSID
* If SSID is zero join based on BSSID only
*/
+ join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
+ chan_cnt * sizeof(chanspec_t);
+ ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
+ if (ext_join_params == NULL) {
+ err = -ENOMEM;
+ wl_clr_drv_status(wl, CONNECTING);
+ goto exit;
+ }
+ ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
+ memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
+ ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
+ /* Set up join scan parameters */
+ ext_join_params->scan.scan_type = DOT11_SCANTYPE_ACTIVE;
+ ext_join_params->scan.nprobes = 2;
+ /* increate dwell time to receive probe response
+ * from target AP at a noisy air
+ */
+ if (chan_cnt)
+ ext_join_params->scan.active_time = 150;
+ else
+ ext_join_params->scan.active_time = -1;
+ ext_join_params->scan.home_time = -1;
+ if (sme->bssid)
+ memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
+ else
+ memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
+ ext_join_params->assoc.chanspec_num = chan_cnt;
+ if (chan_cnt) {
+ u16 channel, band, bw, ctl_sb;
+ chanspec_t chspec;
+ channel = wl->channel;
+ band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
+ : WL_CHANSPEC_BAND_5G;
+ bw = WL_CHANSPEC_BW_20;
+ ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
+ chspec = (channel | band | bw | ctl_sb);
+ ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
+ ext_join_params->assoc.chanspec_list[0] |= chspec;
+ ext_join_params->assoc.chanspec_list[0] =
+ htodchanspec(ext_join_params->assoc.chanspec_list[0]);
+ }
+ ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
+ if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
+ ext_join_params->ssid.SSID_len));
+ }
+ wl_set_drv_status(wl, CONNECTING);
+ err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, ioctlbuf,
+ sizeof(ioctlbuf), wl_cfgp2p_find_idx(wl, dev));
+ kfree(ext_join_params);
+ if (err) {
+ wl_clr_drv_status(wl, CONNECTING);
+ if (err == BCME_UNSUPPORTED) {
+ WL_DBG(("join iovar is not supported\n"));
+ goto set_ssid;
+ } else
+ WL_ERR(("error (%d)\n", err));
+ } else
+ goto exit;
+
+set_ssid:
memset(&join_params, 0, sizeof(join_params));
join_params_size = sizeof(join_params.ssid);
@@ -2325,11 +2389,11 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
}
wl_set_drv_status(wl, CONNECTING);
err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
- if (unlikely(err)) {
+ if (err) {
WL_ERR(("error (%d)\n", err));
wl_clr_drv_status(wl, CONNECTING);
- return err;
}
+exit:
return err;
}
@@ -2798,12 +2862,12 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
sta->idle * 1000));
#endif
} else if (get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {
- if (memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID),
- ETHER_ADDR_LEN)) {
- WL_ERR(("Wrong Mac address\n"));
+ u8 *curmacp = wl_read_prof(wl, WL_PROF_BSSID);
+ if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
+ WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n",
+ MAC2STR(mac), MAC2STR(curmacp)));
return -ENOENT;
}
-
/* Report the current tx rate */
err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
if (err) {
@@ -4388,7 +4452,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
sizeof(scb_val_t), true);
cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
wl_link_down(wl);
- wl_init_prof(wl->profile);
+ wl_init_prof(wl);
} else if (wl_get_drv_status(wl, CONNECTING)) {
printk("link down, during connecting\n");
wl_bss_connect_done(wl, ndev, e, data, false);
@@ -4913,9 +4977,13 @@ static void wl_init_conf(struct wl_conf *conf)
conf->tx_power = -1;
}
-static void wl_init_prof(struct wl_profile *prof)
+static void wl_init_prof(struct wl_priv *wl)
{
- memset(prof, 0, sizeof(*prof));
+ unsigned long flags;
+
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
+ memset(wl->profile, 0, sizeof(struct wl_profile));
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
}
static void wl_init_event_handler(struct wl_priv *wl)
@@ -5498,7 +5566,7 @@ static s32 wl_init_priv(struct wl_priv *wl)
return err;
wl_init_fw(wl->fw);
wl_init_conf(wl->conf);
- wl_init_prof(wl->profile);
+ wl_init_prof(wl);
wl_link_down(wl);
return err;
@@ -5667,22 +5735,18 @@ static s32 wl_event_handler(void *data)
SMP_RD_BARRIER_DEPENDS();
if (tsk->terminated)
break;
- e = wl_deq_event(wl);
- if (unlikely(!e)) {
- WL_ERR(("equeue empty..\n"));
- DHD_OS_WAKE_UNLOCK(wl->pub);
- return 0;
- }
- WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
- netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
- if (!netdev)
- netdev = wl_to_prmry_ndev(wl);
- if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
- wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata);
- } else {
- WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
+ while ((e = wl_deq_event(wl))) {
+ WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
+ netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
+ if (!netdev)
+ netdev = wl_to_prmry_ndev(wl);
+ if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
+ wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata);
+ } else {
+ WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
+ }
+ wl_put_event(e);
}
- wl_put_event(e);
DHD_OS_WAKE_UNLOCK(wl->pub);
}
WL_DBG(("%s was terminated\n", __func__));
@@ -5718,14 +5782,15 @@ static void wl_init_eq(struct wl_priv *wl)
static void wl_flush_eq(struct wl_priv *wl)
{
struct wl_event_q *e;
+ unsigned long flags;
- wl_lock_eq(wl);
+ flags = wl_lock_eq(wl);
while (!list_empty(&wl->eq_list)) {
e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
list_del(&e->eq_list);
kfree(e);
}
- wl_unlock_eq(wl);
+ wl_unlock_eq(wl, flags);
}
/*
@@ -5735,13 +5800,14 @@ static void wl_flush_eq(struct wl_priv *wl)
static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
{
struct wl_event_q *e = NULL;
+ unsigned long flags;
- wl_lock_eq(wl);
+ flags = wl_lock_eq(wl);
if (likely(!list_empty(&wl->eq_list))) {
e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
list_del(&e->eq_list);
}
- wl_unlock_eq(wl);
+ wl_unlock_eq(wl, flags);
return e;
}
@@ -5758,12 +5824,15 @@ wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_ev
s32 err = 0;
uint32 evtq_size;
uint32 data_len;
+ unsigned long flags;
+ gfp_t aflags;
data_len = 0;
if (data)
data_len = ntoh32(msg->datalen);
evtq_size = sizeof(struct wl_event_q) + data_len;
- e = kzalloc(evtq_size, GFP_ATOMIC);
+ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
+ e = kzalloc(evtq_size, aflags);
if (unlikely(!e)) {
WL_ERR(("event alloc failed\n"));
return -ENOMEM;
@@ -5772,9 +5841,9 @@ wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_ev
memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
if (data)
memcpy(e->edata, data, data_len);
- wl_lock_eq(wl);
+ flags = wl_lock_eq(wl);
list_add_tail(&e->eq_list, &wl->eq_list);
- wl_unlock_eq(wl);
+ wl_unlock_eq(wl, flags);
return err;
}
@@ -6353,18 +6422,28 @@ static s32 wl_dongle_probecap(struct wl_priv *wl)
static void *wl_read_prof(struct wl_priv *wl, s32 item)
{
+ unsigned long flags;
+ void *rptr = NULL;
+
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
switch (item) {
case WL_PROF_SEC:
- return &wl->profile->sec;
+ rptr = &wl->profile->sec;
+ break;
case WL_PROF_ACT:
- return &wl->profile->active;
+ rptr = &wl->profile->active;
+ break;
case WL_PROF_BSSID:
- return &wl->profile->bssid;
+ rptr = &wl->profile->bssid;
+ break;
case WL_PROF_SSID:
- return &wl->profile->ssid;
+ rptr = &wl->profile->ssid;
+ break;
}
- WL_ERR(("invalid item (%d)\n", item));
- return NULL;
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
+ if (!rptr)
+ WL_ERR(("invalid item (%d)\n", item));
+ return rptr;
}
static s32
@@ -6373,7 +6452,9 @@ wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data,
{
s32 err = 0;
struct wlc_ssid *ssid;
+ unsigned long flags;
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
switch (item) {
case WL_PROF_SSID:
ssid = (wlc_ssid_t *) data;
@@ -6405,7 +6486,7 @@ wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data,
err = -EOPNOTSUPP;
break;
}
-
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
return err;
}
@@ -6505,14 +6586,17 @@ static void wl_link_down(struct wl_priv *wl)
conn_info->resp_ie_len = 0;
}
-static void wl_lock_eq(struct wl_priv *wl)
+static unsigned long wl_lock_eq(struct wl_priv *wl)
{
- spin_lock_irq(&wl->eq_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->eq_lock, flags);
+ return flags;
}
-static void wl_unlock_eq(struct wl_priv *wl)
+static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
{
- spin_unlock_irq(&wl->eq_lock);
+ spin_unlock_irqrestore(&wl->eq_lock, flags);
}
static void wl_init_eq_lock(struct wl_priv *wl)
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index 356bb38..0251d82 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_cfgp2p.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
+ * $Id: wl_cfgp2p.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 $
*
*/
#include <typedefs.h>
@@ -1309,6 +1309,7 @@ wl_cfgp2p_down(struct wl_priv *wl)
{
if (timer_pending(&wl->p2p->listen_timer))
del_timer_sync(&wl->p2p->listen_timer);
+ wl_cfgp2p_deinit_priv(wl);
return 0;
}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
index 92c4198..bb3eaea 100644
--- a/drivers/net/wireless/bcmdhd/wldev_common.c
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
+ * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 $
*/
#include <linux/module.h>
@@ -318,7 +318,8 @@ int wldev_set_country(
bzero(&scbval, sizeof(scb_val_t));
error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), 1);
if (error < 0) {
- DHD_ERROR(("%s: set country failed due to Disassoc error\n", __FUNCTION__));
+ DHD_ERROR(("%s: set country failed due to Disassoc error %d\n",
+ __FUNCTION__, error));
return error;
}
}
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index d0b8f93..72a7d60 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -246,6 +246,8 @@ static int omap_rproc_iommu_init(struct rproc *rproc,
return -ENOMEM;
iommu_set_isr(pdata->iommu_name, omap_rproc_iommu_isr, rproc);
+ iommu_set_secure(pdata->iommu_name, rproc->secure_mode,
+ rproc->secure_ttb);
iommu = iommu_get(pdata->iommu_name);
if (IS_ERR(iommu)) {
ret = PTR_ERR(iommu);
@@ -257,17 +259,23 @@ static int omap_rproc_iommu_init(struct rproc *rproc,
rpp->iommu_cb = callback;
rproc->priv = rpp;
- for (i = 0; rproc->memory_maps[i].size; i++) {
- const struct rproc_mem_entry *me = &rproc->memory_maps[i];
+ if (!rproc->secure_mode) {
+ for (i = 0; rproc->memory_maps[i].size; i++) {
+ const struct rproc_mem_entry *me =
+ &rproc->memory_maps[i];
- ret = omap_rproc_map(dev, iommu, me->da, me->pa, me->size);
- if (ret)
- goto err_map;
+ ret = omap_rproc_map(dev, iommu, me->da, me->pa,
+ me->size);
+ if (ret)
+ goto err_map;
+ }
}
return 0;
+
err_map:
iommu_put(iommu);
err_mmu:
+ iommu_set_secure(pdata->iommu_name, false, NULL);
kfree(rpp);
return ret;
}
@@ -381,7 +389,15 @@ static inline int omap_rproc_start(struct rproc *rproc, u64 bootaddr)
struct platform_device *pdev = to_platform_device(dev);
struct omap_rproc_pdata *pdata = dev->platform_data;
struct omap_rproc_timers_info *timers = pdata->timers;
- int ret, i;
+ int i;
+ int ret = 0;
+
+ if (rproc->secure_mode) {
+ pr_err("TODO: Call secure service to authenticate\n");
+ if (ret)
+ return -ENXIO;
+ }
+
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
_init_pm_flags(rproc);
#endif
diff --git a/drivers/remoteproc/remoteproc.c b/drivers/remoteproc/remoteproc.c
index 9fd4d5b..f3ec8bc 100644
--- a/drivers/remoteproc/remoteproc.c
+++ b/drivers/remoteproc/remoteproc.c
@@ -601,17 +601,17 @@ static int _event_notify(struct rproc *rproc, int type, void *data)
init_completion(&rproc->error_comp);
rproc->state = RPROC_CRASHED;
mutex_unlock(&rproc->lock);
+#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
+ pm_runtime_dont_use_autosuspend(rproc->dev);
+#endif
+ dump_remoteproc_regs(rproc->name,
+ (struct exc_regs *)rproc->cdump_buf1);
if (!rproc->halt_on_crash)
complete_remoteproc_crash(rproc);
else
pr_info("remoteproc %s: halt-on-crash enabled: " \
"deferring crash recovery\n",
rproc->name);
-#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
- pm_runtime_dont_use_autosuspend(rproc->dev);
-#endif
- dump_remoteproc_regs(rproc->name,
- (struct exc_regs *)rproc->cdump_buf1);
break;
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
case RPROC_PRE_SUSPEND:
@@ -660,7 +660,7 @@ static void rproc_start(struct rproc *rproc, u64 bootaddr)
err = rproc->ops->iommu_init(rproc, rproc_mmu_fault_isr);
if (err) {
dev_err(dev, "can't configure iommu %d\n", err);
- goto unlock_mutext;
+ goto unlock_mutex;
}
}
@@ -669,7 +669,7 @@ static void rproc_start(struct rproc *rproc, u64 bootaddr)
if (err) {
dev_err(dev, "can't configure watchdog timer %d\n",
err);
- goto unlock_mutext;
+ goto unlock_mutex;
}
}
@@ -681,7 +681,7 @@ static void rproc_start(struct rproc *rproc, u64 bootaddr)
err = rproc->ops->start(rproc, bootaddr);
if (err) {
dev_err(dev, "can't start rproc %s: %d\n", rproc->name, err);
- goto unlock_mutext;
+ goto unlock_mutex;
}
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
@@ -698,7 +698,14 @@ static void rproc_start(struct rproc *rproc, u64 bootaddr)
dev_info(dev, "remote processor %s is now up\n", rproc->name);
-unlock_mutext:
+unlock_mutex:
+ /*
+ * signal always, as we would need a notification in both the
+ * normal->secure & secure->normal mode transitions, otherwise
+ * we would have to introduce one more variable.
+ */
+ rproc->secure_ok = !err;
+ complete_all(&rproc->secure_restart);
mutex_unlock(&rproc->lock);
}
@@ -1000,6 +1007,7 @@ static int rproc_process_fw(struct rproc *rproc, struct fw_section *section,
u64 da;
int ret = 0;
void *ptr;
+ bool copy;
/* first section should be FW_RESOURCE section */
if (section->type != FW_RESOURCE) {
@@ -1013,6 +1021,7 @@ static int rproc_process_fw(struct rproc *rproc, struct fw_section *section,
da = section->da;
len = section->len;
type = section->type;
+ copy = true;
dev_dbg(dev, "section: type %d da 0x%llx len 0x%x\n",
type, da, len);
@@ -1034,26 +1043,35 @@ static int rproc_process_fw(struct rproc *rproc, struct fw_section *section,
}
}
- ret = rproc_da_to_pa(rproc->memory_maps, da, &pa);
- if (ret) {
- dev_err(dev, "rproc_da_to_pa failed: %d\n", ret);
- break;
- }
+ if (section->type <= FW_DATA) {
+ ret = rproc_da_to_pa(rproc->memory_maps, da, &pa);
+ if (ret) {
+ dev_err(dev, "rproc_da_to_pa failed:%d\n", ret);
+ break;
+ }
+ } else if (rproc->secure_mode) {
+ pa = da;
+ if (section->type == FW_MMU)
+ rproc->secure_ttb = (void *)pa;
+ } else
+ copy = false;
dev_dbg(dev, "da 0x%llx pa 0x%x len 0x%x\n", da, pa, len);
- /* ioremaping normal memory, so make sparse happy */
- ptr = (__force void *) ioremap_nocache(pa, len);
- if (!ptr) {
- dev_err(dev, "can't ioremap 0x%x\n", pa);
- ret = -ENOMEM;
- break;
- }
+ if (copy) {
+ /* ioremaping normal memory, so make sparse happy */
+ ptr = (__force void *) ioremap_nocache(pa, len);
+ if (!ptr) {
+ dev_err(dev, "can't ioremap 0x%x\n", pa);
+ ret = -ENOMEM;
+ break;
+ }
- memcpy(ptr, section->content, len);
+ memcpy(ptr, section->content, len);
- /* iounmap normal memory, so make sparse happy */
- iounmap((__force void __iomem *) ptr);
+ /* iounmap normal memory, so make sparse happy */
+ iounmap((__force void __iomem *) ptr);
+ }
section = (struct fw_section *)(section->content + len);
left -= len;
@@ -1146,6 +1164,41 @@ static int rproc_loader(struct rproc *rproc)
return 0;
}
+int rproc_set_secure(const char *name, bool enable)
+{
+ struct rproc *rproc;
+
+ rproc = __find_rproc_by_name(name);
+ if (!rproc) {
+ pr_err("can't find remote processor %s\n", name);
+ return -ENODEV;
+ }
+
+ /*
+ * set the secure_mode here, the secure_ttb will be filled up during
+ * the reload process.
+ */
+ rproc->secure_mode = enable;
+ rproc->secure_ttb = NULL;
+ rproc->secure_ok = false;
+ init_completion(&rproc->secure_restart);
+
+ /*
+ * restart the processor, the mode will dictate regular load or
+ * secure load
+ */
+ _event_notify(rproc, RPROC_ERROR, NULL);
+
+ /* block until the restart is complete */
+ if (wait_for_completion_interruptible(&rproc->secure_restart)) {
+ pr_err("error waiting restart completion\n");
+ return -EINTR;
+ }
+
+ return rproc->secure_ok ? 0 : -EACCES;
+}
+EXPORT_SYMBOL(rproc_set_secure);
+
int rproc_error_notify(struct rproc *rproc)
{
return _event_notify(rproc, RPROC_ERROR, NULL);
@@ -1637,6 +1690,10 @@ int rproc_register(struct device *dev, const char *name,
pm_qos_add_request(rproc->qos_request, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
+ rproc->secure_mode = false;
+ rproc->secure_ttb = NULL;
+ init_completion(&rproc->secure_restart);
+
spin_lock(&rprocs_lock);
list_add_tail(&rproc->next, &rprocs);
spin_unlock(&rprocs_lock);
@@ -1687,6 +1744,8 @@ int rproc_unregister(const char *name)
list_del(&rproc->next);
spin_unlock(&rprocs_lock);
+ rproc->secure_mode = false;
+ rproc->secure_ttb = NULL;
pm_qos_remove_request(rproc->qos_request);
kfree(rproc->qos_request);
kfree(rproc->last_trace_buf0);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 20a55d0..2a1e6ed 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -427,6 +427,7 @@ static void omap_dss_driver_disable(struct omap_dss_device *dssdev)
blocking_notifier_call_chain(&dssdev->state_notifiers,
OMAP_DSS_DISPLAY_DISABLED, dssdev);
dssdev->driver->disable_orig(dssdev);
+ dssdev->first_vsync = false;
}
static int omap_dss_driver_enable(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 0e7ded0..3fa7cf5 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -65,20 +65,12 @@ struct omap_dispc_isr_data {
u32 mask;
};
-struct dispc_h_coef {
- s8 hc4;
- s8 hc3;
- u8 hc2;
- s8 hc1;
- s8 hc0;
-};
-
-struct dispc_v_coef {
- s8 vc22;
- s8 vc2;
- u8 vc1;
- s8 vc0;
- s8 vc00;
+struct dispc_hv_coef {
+ s8 hc0_vc00;
+ s8 hc1_vc0;
+ u8 hc2_vc1;
+ s8 hc3_vc2;
+ s8 hc4_vc22;
};
#define REG_GET(idx, start, end) \
@@ -618,105 +610,227 @@ static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
}
-static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
- int vscaleup, int five_taps,
- enum omap_color_component color_comp)
+static const struct dispc_hv_coef *
+dispc_get_scaling_coef(u32 inc, bool five_taps)
{
- /* Coefficients for horizontal up-sampling */
- static const struct dispc_h_coef coef_hup[8] = {
- { 0, 0, 128, 0, 0 },
- { -1, 13, 124, -8, 0 },
- { -2, 30, 112, -11, -1 },
- { -5, 51, 95, -11, -2 },
- { 0, -9, 73, 73, -9 },
- { -2, -11, 95, 51, -5 },
- { -1, -11, 112, 30, -2 },
- { 0, -8, 124, 13, -1 },
+ static const struct dispc_hv_coef coef3_M8[8] = {
+ { 0, 0, 128, 0, 0 },
+ { 0, 2, 123, 3, 0 },
+ { 0, 5, 111, 12, 0 },
+ { 0, 7, 89, 32, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 32, 89, 7, 0 },
+ { 0, 12, 111, 5, 0 },
+ { 0, 3, 123, 2, 0 },
};
- /* Coefficients for vertical up-sampling */
- static const struct dispc_v_coef coef_vup_3tap[8] = {
- { 0, 0, 128, 0, 0 },
- { 0, 3, 123, 2, 0 },
- { 0, 12, 111, 5, 0 },
- { 0, 32, 89, 7, 0 },
- { 0, 0, 64, 64, 0 },
- { 0, 7, 89, 32, 0 },
- { 0, 5, 111, 12, 0 },
- { 0, 2, 123, 3, 0 },
+ static const struct dispc_hv_coef coef3_M16[8] = {
+ { 0, 36, 56, 36, 0 },
+ { 0, 31, 57, 40, 0 },
+ { 0, 27, 56, 45, 0 },
+ { 0, 23, 55, 50, 0 },
+ { 0, 55, 55, 18, 0 },
+ { 0, 50, 55, 23, 0 },
+ { 0, 45, 56, 27, 0 },
+ { 0, 40, 57, 31, 0 },
};
- static const struct dispc_v_coef coef_vup_5tap[8] = {
- { 0, 0, 128, 0, 0 },
- { -1, 13, 124, -8, 0 },
- { -2, 30, 112, -11, -1 },
- { -5, 51, 95, -11, -2 },
- { 0, -9, 73, 73, -9 },
- { -2, -11, 95, 51, -5 },
- { -1, -11, 112, 30, -2 },
- { 0, -8, 124, 13, -1 },
+ static const struct dispc_hv_coef coef_M8[8] = {
+ { 0, 0, 128, 0, 0 },
+ { 0, -8, 124, 13, -1 },
+ { -1, -11, 112, 30, -2 },
+ { -2, -11, 95, 51, -5 },
+ { -9, 73, 73, -9, 0 },
+ { -5, 51, 95, -11, -2 },
+ { -2, 30, 112, -11, -1 },
+ { -1, 13, 124, -8, 0 },
};
- /* Coefficients for horizontal down-sampling */
- static const struct dispc_h_coef coef_hdown[8] = {
- { 0, 36, 56, 36, 0 },
- { 4, 40, 55, 31, -2 },
- { 8, 44, 54, 27, -5 },
- { 12, 48, 53, 22, -7 },
- { -9, 17, 52, 51, 17 },
- { -7, 22, 53, 48, 12 },
- { -5, 27, 54, 44, 8 },
- { -2, 31, 55, 40, 4 },
+ static const struct dispc_hv_coef coef_M9[8] = {
+ { 8, -8, 128, -8, 8 },
+ { 14, -21, 126, 8, 1 },
+ { 17, -27, 117, 30, -9 },
+ { 17, -30, 103, 56, -18 },
+ { -26, 83, 83, -26, 14 },
+ { -18, 56, 103, -30, 17 },
+ { -9, 30, 117, -27, 17 },
+ { 1, 8, 126, -21, 14 },
};
- /* Coefficients for vertical down-sampling */
- static const struct dispc_v_coef coef_vdown_3tap[8] = {
- { 0, 36, 56, 36, 0 },
- { 0, 40, 57, 31, 0 },
- { 0, 45, 56, 27, 0 },
- { 0, 50, 55, 23, 0 },
- { 0, 18, 55, 55, 0 },
- { 0, 23, 55, 50, 0 },
- { 0, 27, 56, 45, 0 },
- { 0, 31, 57, 40, 0 },
+ static const struct dispc_hv_coef coef_M10[8] = {
+ { -2, 2, 128, 2, -2 },
+ { 5, -12, 125, 20, -10 },
+ { 11, -22, 116, 41, -18 },
+ { 15, -27, 102, 62, -24 },
+ { -28, 83, 83, -28, 18 },
+ { -24, 62, 102, -27, 15 },
+ { -18, 41, 116, -22, 11 },
+ { -10, 20, 125, -12, 5 },
};
- static const struct dispc_v_coef coef_vdown_5tap[8] = {
- { 0, 36, 56, 36, 0 },
- { 4, 40, 55, 31, -2 },
- { 8, 44, 54, 27, -5 },
- { 12, 48, 53, 22, -7 },
- { -9, 17, 52, 51, 17 },
- { -7, 22, 53, 48, 12 },
- { -5, 27, 54, 44, 8 },
- { -2, 31, 55, 40, 4 },
+ static const struct dispc_hv_coef coef_M11[8] = {
+ { -12, 12, 128, 12, -12 },
+ { -4, -3, 124, 30, -19 },
+ { 3, -15, 115, 49, -24 },
+ { 9, -22, 101, 67, -27 },
+ { -26, 83, 83, -26, 14 },
+ { -27, 67, 101, -22, 9 },
+ { -24, 49, 115, -15, 3 },
+ { -19, 30, 124, -3, -4 },
};
- const struct dispc_h_coef *h_coef;
- const struct dispc_v_coef *v_coef;
- int i;
+ static const struct dispc_hv_coef coef_M12[8] = {
+ { -19, 21, 124, 21, -19 },
+ { -12, 6, 120, 38, -24 },
+ { -6, -7, 112, 55, -26 },
+ { 1, -16, 98, 70, -25 },
+ { -21, 82, 82, -21, 6 },
+ { -25, 70, 98, -16, 1 },
+ { -26, 55, 112, -7, -6 },
+ { -24, 38, 120, 6, -12 },
+ };
- if (hscaleup)
- h_coef = coef_hup;
- else
- h_coef = coef_hdown;
+ static const struct dispc_hv_coef coef_M13[8] = {
+ { -22, 27, 118, 27, -22 },
+ { -18, 13, 115, 43, -25 },
+ { -12, 0, 107, 58, -25 },
+ { -6, -10, 95, 71, -22 },
+ { -17, 81, 81, -17, 0 },
+ { -22, 71, 95, -10, -6 },
+ { -25, 58, 107, 0, -12 },
+ { -25, 43, 115, 13, -18 },
+ };
- if (vscaleup)
- v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
- else
- v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
+ static const struct dispc_hv_coef coef_M14[8] = {
+ { -23, 32, 110, 32, -23 },
+ { -20, 18, 108, 46, -24 },
+ { -16, 6, 101, 59, -22 },
+ { -11, -4, 91, 70, -18 },
+ { -11, 78, 78, -11, -6 },
+ { -18, 70, 91, -4, -11 },
+ { -22, 59, 101, 6, -16 },
+ { -24, 46, 108, 18, -20 },
+ };
+
+ static const struct dispc_hv_coef coef_M16[8] = {
+ { -20, 37, 94, 37, -20 },
+ { -21, 26, 93, 48, -18 },
+ { -19, 15, 88, 58, -14 },
+ { -17, 6, 82, 66, -9 },
+ { -2, 73, 73, -2, -14 },
+ { -9, 66, 82, 6, -17 },
+ { -14, 58, 88, 15, -19 },
+ { -18, 48, 93, 26, -21 },
+ };
+
+ static const struct dispc_hv_coef coef_M19[8] = {
+ { -12, 38, 76, 38, -12 },
+ { -14, 31, 72, 47, -8 },
+ { -16, 22, 73, 53, -4 },
+ { -16, 15, 69, 59, 1 },
+ { 8, 64, 64, 8, -16 },
+ { 1, 59, 69, 15, -16 },
+ { -4, 53, 73, 22, -16 },
+ { -9, 47, 72, 31, -13 },
+ };
+
+ static const struct dispc_hv_coef coef_M22[8] = {
+ { -6, 37, 66, 37, -6 },
+ { -8, 32, 61, 44, -1 },
+ { -11, 25, 63, 48, 3 },
+ { -13, 19, 61, 53, 8 },
+ { 13, 58, 58, 13, -14 },
+ { 8, 53, 61, 19, -13 },
+ { 3, 48, 63, 25, -11 },
+ { -2, 44, 61, 32, -7 },
+ };
+
+ static const struct dispc_hv_coef coef_M26[8] = {
+ { 1, 36, 54, 36, 1 },
+ { -2, 31, 55, 40, 4 },
+ { -5, 27, 54, 44, 8 },
+ { -8, 22, 53, 48, 13 },
+ { 18, 51, 51, 18, -10 },
+ { 13, 48, 53, 22, -8 },
+ { 8, 44, 54, 27, -5 },
+ { 4, 40, 55, 31, -2 },
+ };
+
+ static const struct dispc_hv_coef coef_M32[8] = {
+ { 7, 34, 46, 34, 7 },
+ { 4, 31, 46, 37, 10 },
+ { 1, 27, 46, 39, 14 },
+ { -1, 24, 46, 42, 17 },
+ { 21, 45, 45, 21, -4 },
+ { 17, 42, 46, 24, -1 },
+ { 14, 39, 46, 28, 1 },
+ { 10, 37, 46, 31, 4 },
+ };
+
+ inc >>= 7; /* /= 128 */
+ if (five_taps) {
+ if (inc > 26)
+ return coef_M32;
+ if (inc > 22)
+ return coef_M26;
+ if (inc > 19)
+ return coef_M22;
+ if (inc > 16)
+ return coef_M19;
+ if (inc > 14)
+ return coef_M16;
+ if (inc > 13)
+ return coef_M14;
+ if (inc > 12)
+ return coef_M13;
+ if (inc > 11)
+ return coef_M12;
+ if (inc > 10)
+ return coef_M11;
+ if (inc > 9)
+ return coef_M10;
+ if (inc > 8)
+ return coef_M9;
+ /* reduce blockiness when upscaling much */
+ if (inc > 3)
+ return coef_M8;
+ if (inc > 2)
+ return coef_M11;
+ if (inc > 1)
+ return coef_M16;
+ return coef_M19;
+ } else {
+ if (inc > 14)
+ return coef3_M16;
+ /* reduce blockiness when upscaling much */
+ if (inc > 3)
+ return coef3_M8;
+ return coef3_M16;
+ }
+}
+
+static void _dispc_set_scale_coef(enum omap_plane plane, int hinc,
+ int vinc, bool five_taps,
+ enum omap_color_component color_comp)
+{
+ const struct dispc_hv_coef *h_coef;
+ const struct dispc_hv_coef *v_coef;
+ int i;
+
+ h_coef = dispc_get_scaling_coef(hinc, true);
+ v_coef = dispc_get_scaling_coef(vinc, five_taps);
for (i = 0; i < 8; i++) {
u32 h, hv;
- h = FLD_VAL(h_coef[i].hc0, 7, 0)
- | FLD_VAL(h_coef[i].hc1, 15, 8)
- | FLD_VAL(h_coef[i].hc2, 23, 16)
- | FLD_VAL(h_coef[i].hc3, 31, 24);
- hv = FLD_VAL(h_coef[i].hc4, 7, 0)
- | FLD_VAL(v_coef[i].vc0, 15, 8)
- | FLD_VAL(v_coef[i].vc1, 23, 16)
- | FLD_VAL(v_coef[i].vc2, 31, 24);
+ h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0)
+ | FLD_VAL(h_coef[i].hc1_vc0, 15, 8)
+ | FLD_VAL(h_coef[i].hc2_vc1, 23, 16)
+ | FLD_VAL(h_coef[i].hc3_vc2, 31, 24);
+ hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0)
+ | FLD_VAL(v_coef[i].hc1_vc0, 15, 8)
+ | FLD_VAL(v_coef[i].hc2_vc1, 23, 16)
+ | FLD_VAL(v_coef[i].hc3_vc2, 31, 24);
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
_dispc_write_firh_reg(plane, i, h);
@@ -725,14 +839,13 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
_dispc_write_firh2_reg(plane, i, h);
_dispc_write_firhv2_reg(plane, i, hv);
}
-
}
if (five_taps) {
for (i = 0; i < 8; i++) {
u32 v;
- v = FLD_VAL(v_coef[i].vc00, 7, 0)
- | FLD_VAL(v_coef[i].vc22, 15, 8);
+ v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0)
+ | FLD_VAL(v_coef[i].hc4_vc22, 15, 8);
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
_dispc_write_firv_reg(plane, i, v);
else
@@ -1261,8 +1374,9 @@ static void _dispc_set_scaling_common(enum omap_plane plane,
int accu0 = 0;
int accu1 = 0;
u32 l;
+ u16 y_adjust = color_mode == OMAP_DSS_COLOR_NV12 ? 2 : 0;
- _dispc_set_scale_param(plane, orig_width, orig_height,
+ _dispc_set_scale_param(plane, orig_width, orig_height - y_adjust,
out_width, out_height, five_taps,
rotation, DISPC_COLOR_COMPONENT_RGB_Y);
l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
@@ -1314,6 +1428,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
{
int scale_x = out_width != orig_width;
int scale_y = out_height != orig_height;
+ u16 y_adjust = 0;
if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
return;
@@ -1330,6 +1445,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
orig_height >>= 1;
/* UV is subsampled by 2 horz.*/
orig_width >>= 1;
+ y_adjust = 1;
break;
case OMAP_DSS_COLOR_YUV2:
case OMAP_DSS_COLOR_UYVY:
@@ -1353,7 +1469,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
if (out_height != orig_height)
scale_y = true;
- _dispc_set_scale_param(plane, orig_width, orig_height,
+ _dispc_set_scale_param(plane, orig_width, orig_height - y_adjust,
out_width, out_height, five_taps,
rotation, DISPC_COLOR_COMPONENT_UV);
@@ -1765,10 +1881,17 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
/* FIXME venc pclk? */
u64 tmp, pclk = dispc_pclk_rate(channel);
- /* do conservative guess on OMAP4 until better formula is available */
- if (cpu_is_omap44xx())
- return pclk * DIV_ROUND_UP(width, out_width) *
- DIV_ROUND_UP(height, out_height);
+ if (cpu_is_omap44xx()) {
+ /* do conservative TRM value on OMAP4 ES1.0 */
+ if (omap_rev() == OMAP4430_REV_ES1_0)
+ return pclk * DIV_ROUND_UP(width, out_width) *
+ DIV_ROUND_UP(height, out_height);
+
+ /* since 4430 ES2.0, fclk requirement only depends on width */
+ pclk *= max(width, out_width);
+ do_div(pclk, out_width);
+ return pclk;
+ }
if (height > out_height) {
/* FIXME get real display PPL */
@@ -1805,6 +1928,11 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
{
unsigned int hf, vf;
+ /* on OMAP4 three-tap and five-tap clock requirements are the same */
+ if (cpu_is_omap44xx())
+ return calc_fclk_five_taps(channel, width, height, out_width,
+ out_height, 0);
+
/*
* FIXME how to determine the 'A' factor
* for the no downscaling case ?
@@ -1940,9 +2068,6 @@ int dispc_scaling_decision(u16 width, u16 height,
else
*five_taps = true;
- /* Also use 3-tap if downscaling by 2 or less */
- *five_taps &= out_height * 2 < in_height;
-
/*
* Predecimation on OMAP4 still fetches the whole lines
* :TODO: How does it affect the required clock speed?
@@ -1957,9 +2082,6 @@ int dispc_scaling_decision(u16 width, u16 height,
in_width, x, in_height, y, out_width, out_height,
fclk, fclk5);
- /* Use 3-tap if 5-tap clock requirement is too high */
- *five_taps &= fclk5 <= fclk_max;
-
/* for now we always use 5-tap unless 3-tap is required */
if (*five_taps)
fclk = fclk5;
@@ -2794,13 +2916,23 @@ unsigned long dispc_pclk_rate(enum omap_channel channel)
unsigned long r;
u32 l;
- l = dispc_read_reg(DISPC_DIVISORo(channel));
+ if (channel == OMAP_DSS_CHANNEL_LCD ||
+ channel == OMAP_DSS_CHANNEL_LCD2) {
+ l = dispc_read_reg(DISPC_DIVISORo(channel));
- pcd = FLD_GET(l, 7, 0);
+ pcd = FLD_GET(l, 7, 0);
- r = dispc_lclk_rate(channel);
+ r = dispc_lclk_rate(channel);
- return r / pcd;
+ return r / pcd;
+ } else {
+ struct omap_overlay_manager *mgr;
+ mgr = omap_dss_get_overlay_manager(channel);
+ if (!mgr || !mgr->device)
+ return 0;
+
+ return mgr->device->panel.timings.pixel_clock * 1000;
+ }
}
void dispc_dump_clocks(struct seq_file *s)
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index e2ae27f..8b3b360 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -339,6 +339,18 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
*fifo_low = fifo_size - burst_size_bytes;
}
+void omapdss_display_get_dimensions(struct omap_dss_device *dssdev,
+ u32 *width_in_um, u32 *height_in_um)
+{
+ if (dssdev->driver->get_dimensions) {
+ dssdev->driver->get_dimensions(dssdev,
+ width_in_um, width_in_um);
+ } else {
+ *width_in_um = dssdev->panel.width_in_um;
+ *height_in_um = dssdev->panel.height_in_um;
+ }
+}
+
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
{
switch (dssdev->type) {
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 9e2cfc3..0fa5dea 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -220,6 +220,10 @@ static void hdmi_hotplug_detect_worker(struct work_struct *work)
pr_info("panel size %d by %d\n",
dssdev->panel.monspecs.max_x,
dssdev->panel.monspecs.max_y);
+ dssdev->panel.width_in_um =
+ dssdev->panel.monspecs.max_x * 10000;
+ dssdev->panel.height_in_um =
+ dssdev->panel.monspecs.max_y * 10000;
switch_set_state(&hdmi.hpd_switch, 1);
goto done;
} else if (state == HPD_STATE_EDID_TRYLAST){
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index f933996..6485eff 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -39,6 +39,7 @@
static int num_managers;
static struct list_head manager_list;
+static struct omap_overlay_manager *mgrs[MAX_DSS_MANAGERS];
static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
{
@@ -716,7 +717,7 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
}
r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
- if(!r)
+ if (!r)
mgr->device->first_vsync = true;
return r;
@@ -784,6 +785,8 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
}
r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+ if (!r)
+ mgr->device->first_vsync = true;
if (r == -ERESTARTSYS)
break;
@@ -1403,6 +1406,8 @@ static void dss_completion_irq_handler(void *data, u32 mask)
for (i = 0; i < num_mgrs; i++) {
mc = &dss_cache.manager_cache[i];
if (mask & masks[i]) {
+ if (mgrs[i] && mgrs[i]->device)
+ mgrs[i]->device->first_vsync = true;
dss_ovl_cb(&mc->cb.dispc, i, DSS_COMPLETION_DISPLAYED);
mc->cb.dispc_displayed = true;
}
@@ -1531,6 +1536,8 @@ static void dss_apply_irq_handler(void *data, u32 mask)
for (i = 0; i < num_mgrs; ++i) {
mc = &dss_cache.manager_cache[i];
if (!mgr_busy[i] && mc->shadow_dirty) {
+ if (mgrs[i] && mgrs[i]->device)
+ mgrs[i]->device->first_vsync = true;
dss_ovl_program_cb(&mc->cb, i);
mc->shadow_dirty = false;
}
@@ -2077,6 +2084,8 @@ static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
{
++num_managers;
list_add_tail(&manager->list, &manager_list);
+ if (manager->id < ARRAY_SIZE(mgrs))
+ mgrs[manager->id] = manager;
}
int dss_init_overlay_managers(struct platform_device *pdev)
diff --git a/drivers/video/omap2/dsscomp/device.c b/drivers/video/omap2/dsscomp/device.c
index 59da904..2986687 100644
--- a/drivers/video/omap2/dsscomp/device.c
+++ b/drivers/video/omap2/dsscomp/device.c
@@ -306,9 +306,8 @@ static long query_display(struct dsscomp_dev *cdev,
dis->state = dev->state;
dis->timings = dev->panel.timings;
- /* for now LCD panels don't have width and height */
- dis->width_in_mm = dev->panel.monspecs.max_x * 10;
- dis->height_in_mm = dev->panel.monspecs.max_y * 10;
+ dis->width_in_mm = DIV_ROUND_CLOSEST(dev->panel.width_in_um, 1000);
+ dis->height_in_mm = DIV_ROUND_CLOSEST(dev->panel.height_in_um, 1000);
/* find all overlays available for/owned by this display */
for (i = 0; i < cdev->num_ovls && dis->enabled; i++) {
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index cff4503..cce6a69 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -883,6 +883,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
case OMAPFB_GET_DISPLAY_INFO: {
u16 xres, yres;
+ u32 w, h;
DBG("ioctl GET_DISPLAY_INFO\n");
@@ -896,15 +897,9 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
p.display_info.xres = xres;
p.display_info.yres = yres;
- if (display->driver->get_dimensions) {
- u32 w, h;
- display->driver->get_dimensions(display, &w, &h);
- p.display_info.width = w;
- p.display_info.height = h;
- } else {
- p.display_info.width = 0;
- p.display_info.height = 0;
- }
+ omapdss_display_get_dimensions(display, &w, &h);
+ p.display_info.width = w;
+ p.display_info.height = h;
if (copy_to_user((void __user *)arg, &p.display_info,
sizeof(p.display_info)))
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 24ea1e5..d5ced95 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -667,6 +667,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
enum omap_color_mode mode = 0;
int i;
int r;
+ u32 w = 0, h = 0;
DBG("check_fb_var %d\n", ofbi->id);
@@ -704,9 +705,10 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
var->xres, var->yres,
var->xres_virtual, var->yres_virtual);
- if (display && display->driver->get_dimensions) {
- u32 w, h;
- display->driver->get_dimensions(display, &w, &h);
+ if (display)
+ omapdss_display_get_dimensions(display, &w, &h);
+
+ if (w && h) {
var->width = DIV_ROUND_CLOSEST(w, 1000);
var->height = DIV_ROUND_CLOSEST(h, 1000);
} else {
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 90348b3..8afa29d 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -82,6 +82,8 @@ enum fw_section_type {
FW_RESOURCE = 0,
FW_TEXT = 1,
FW_DATA = 2,
+ FW_MMU = 3,
+ FW_SIGNATURE = 4,
};
struct fw_resource {
@@ -210,7 +212,7 @@ enum rproc_event {
* struct rproc - a physical remote processor device
*
* @next: next rproc entry in the list
- * @name: human readable name of the rproc, cannot exceed RPROC_MAN_NAME bytes
+ * @name: human readable name of the rproc, cannot exceed RPROC_MAX_NAME bytes
* @memory_maps: table of da-to-pa memory maps (relevant if device is behind
* an iommu)
* @memory_pool: platform-specific contiguous memory pool data (relevant for
@@ -236,6 +238,10 @@ enum rproc_event {
* @mmufault_work: work in charge of notifing mmufault
* @nb_error: notify block for fatal errors
* @error_comp: completion used when an error happens
+ * @secure_ttb: private data for configuring iommu in secure mode
+ * @secure_restart: completion event notifier for the secure restart process
+ * @secure_mode: flag to dictate whether to enable secure loading
+ * @secure_ok: restart status flag to be looked up upon the event's completion
*/
struct rproc {
struct list_head next;
@@ -271,9 +277,14 @@ struct rproc {
struct mutex pm_lock;
#endif
struct pm_qos_request_list *qos_request;
+ void *secure_ttb;
+ struct completion secure_restart;
+ bool secure_mode;
+ bool secure_ok;
bool halt_on_crash;
};
+int rproc_set_secure(const char *, bool);
struct rproc *rproc_get(const char *);
void rproc_put(struct rproc *);
int rproc_event_register(struct rproc *, struct notifier_block *, int);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 27a1643..70e4872 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -563,6 +563,9 @@ struct omap_dss_device {
enum omap_panel_config config;
struct fb_monspecs monspecs;
+
+ u32 width_in_um;
+ u32 height_in_um;
} panel;
struct {
@@ -700,6 +703,9 @@ void omap_dispc_set_irq_type(int channel, enum omap_dispc_irq_type type);
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
+void omapdss_display_get_dimensions(struct omap_dss_device *dssdev,
+ u32 *width_in_um, u32 *height_in_um);
+
void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
bool enable);
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index fd5d288..d223a23 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -2385,12 +2385,12 @@ static int pp_stats_line(struct proc_print_info *ppi, int cnt_set)
"idx iface acct_tag_hex uid_tag_int cnt_set "
"rx_bytes rx_packets "
"tx_bytes tx_packets "
- "rx_tcp_packets rx_tcp_bytes "
- "rx_udp_packets rx_udp_bytes "
- "rx_other_packets rx_other_bytes "
- "tx_tcp_packets tx_tcp_bytes "
- "tx_udp_packets tx_udp_bytes "
- "tx_other_packets tx_other_bytes\n");
+ "rx_tcp_bytes rx_tcp_packets "
+ "rx_udp_bytes rx_udp_packets "
+ "rx_other_bytes rx_other_packets "
+ "tx_tcp_bytes tx_tcp_packets "
+ "tx_udp_bytes tx_udp_packets "
+ "tx_other_bytes tx_other_packets\n");
} else {
tag_t tag = ppi->ts_entry->tn.tag;
uid_t stat_uid = get_uid_from_tag(tag);