diff options
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, ðer_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); |