Backport android and MSM parts from caf
This commit is contained in:
parent
9ab858cdb2
commit
0a0f12cf99
@ -43,38 +43,19 @@ static int msm_irq_debug_mask;
|
||||
module_param_named(debug_mask, msm_irq_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
|
||||
|
||||
#define VIC_REG(off) (MSM_VIC_BASE + (off))
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
#define VIC_INT_TO_REG_ADDR(base, irq) (base + (irq / 32) * 4)
|
||||
#define VIC_INT_TO_REG_INDEX(irq) ((irq >> 5) & 3)
|
||||
#else
|
||||
#define VIC_INT_TO_REG_ADDR(base, irq) (base + ((irq & 32) ? 4 : 0))
|
||||
#define VIC_INT_TO_REG_INDEX(irq) ((irq >> 5) & 1)
|
||||
#endif
|
||||
|
||||
#define VIC_INT_SELECT0 VIC_REG(0x0000) /* 1: FIQ, 0: IRQ */
|
||||
#define VIC_INT_SELECT1 VIC_REG(0x0004) /* 1: FIQ, 0: IRQ */
|
||||
#define VIC_INT_SELECT2 VIC_REG(0x0008) /* 1: FIQ, 0: IRQ */
|
||||
#define VIC_INT_SELECT3 VIC_REG(0x000C) /* 1: FIQ, 0: IRQ */
|
||||
#define VIC_INT_EN0 VIC_REG(0x0010)
|
||||
#define VIC_INT_EN1 VIC_REG(0x0014)
|
||||
#define VIC_INT_EN2 VIC_REG(0x0018)
|
||||
#define VIC_INT_EN3 VIC_REG(0x001C)
|
||||
#define VIC_INT_ENCLEAR0 VIC_REG(0x0020)
|
||||
#define VIC_INT_ENCLEAR1 VIC_REG(0x0024)
|
||||
#define VIC_INT_ENCLEAR2 VIC_REG(0x0028)
|
||||
#define VIC_INT_ENCLEAR3 VIC_REG(0x002C)
|
||||
#define VIC_INT_ENSET0 VIC_REG(0x0030)
|
||||
#define VIC_INT_ENSET1 VIC_REG(0x0034)
|
||||
#define VIC_INT_ENSET2 VIC_REG(0x0038)
|
||||
#define VIC_INT_ENSET3 VIC_REG(0x003C)
|
||||
#define VIC_INT_TYPE0 VIC_REG(0x0040) /* 1: EDGE, 0: LEVEL */
|
||||
#define VIC_INT_TYPE1 VIC_REG(0x0044) /* 1: EDGE, 0: LEVEL */
|
||||
#define VIC_INT_TYPE2 VIC_REG(0x0048) /* 1: EDGE, 0: LEVEL */
|
||||
#define VIC_INT_TYPE3 VIC_REG(0x004C) /* 1: EDGE, 0: LEVEL */
|
||||
#define VIC_INT_POLARITY0 VIC_REG(0x0050) /* 1: NEG, 0: POS */
|
||||
#define VIC_INT_POLARITY1 VIC_REG(0x0054) /* 1: NEG, 0: POS */
|
||||
#define VIC_INT_POLARITY2 VIC_REG(0x0058) /* 1: NEG, 0: POS */
|
||||
#define VIC_INT_POLARITY3 VIC_REG(0x005C) /* 1: NEG, 0: POS */
|
||||
#define VIC_NO_PEND_VAL VIC_REG(0x0060)
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM_SCORPION)
|
||||
@ -88,24 +69,14 @@ module_param_named(debug_mask, msm_irq_debug_mask, int, S_IRUGO | S_IWUSR | S_IW
|
||||
#endif
|
||||
#define VIC_IRQ_STATUS0 VIC_REG(0x0080)
|
||||
#define VIC_IRQ_STATUS1 VIC_REG(0x0084)
|
||||
#define VIC_IRQ_STATUS2 VIC_REG(0x0088)
|
||||
#define VIC_IRQ_STATUS3 VIC_REG(0x008C)
|
||||
#define VIC_FIQ_STATUS0 VIC_REG(0x0090)
|
||||
#define VIC_FIQ_STATUS1 VIC_REG(0x0094)
|
||||
#define VIC_FIQ_STATUS2 VIC_REG(0x0098)
|
||||
#define VIC_FIQ_STATUS3 VIC_REG(0x009C)
|
||||
#define VIC_RAW_STATUS0 VIC_REG(0x00A0)
|
||||
#define VIC_RAW_STATUS1 VIC_REG(0x00A4)
|
||||
#define VIC_RAW_STATUS2 VIC_REG(0x00A8)
|
||||
#define VIC_RAW_STATUS3 VIC_REG(0x00AC)
|
||||
#define VIC_INT_CLEAR0 VIC_REG(0x00B0)
|
||||
#define VIC_INT_CLEAR1 VIC_REG(0x00B4)
|
||||
#define VIC_INT_CLEAR2 VIC_REG(0x00B8)
|
||||
#define VIC_INT_CLEAR3 VIC_REG(0x00BC)
|
||||
#define VIC_SOFTINT0 VIC_REG(0x00C0)
|
||||
#define VIC_SOFTINT1 VIC_REG(0x00C4)
|
||||
#define VIC_SOFTINT2 VIC_REG(0x00C8)
|
||||
#define VIC_SOFTINT3 VIC_REG(0x00CC)
|
||||
#define VIC_IRQ_VEC_RD VIC_REG(0x00D0) /* pending int # */
|
||||
#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4) /* pending vector addr */
|
||||
#define VIC_IRQ_VEC_WR VIC_REG(0x00D8)
|
||||
@ -129,40 +100,14 @@ module_param_named(debug_mask, msm_irq_debug_mask, int, S_IRUGO | S_IWUSR | S_IW
|
||||
#define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4))
|
||||
#define VIC_VECTADDR(n) VIC_REG(0x0400+((n) * 4))
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
#define VIC_NUM_REGS 4
|
||||
#else
|
||||
#define VIC_NUM_REGS 2
|
||||
#endif
|
||||
|
||||
#if VIC_NUM_REGS == 2
|
||||
#define DPRINT_REGS(base_reg, format, ...) \
|
||||
printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__, \
|
||||
readl(base_reg ## 0), readl(base_reg ## 1))
|
||||
#define DPRINT_ARRAY(array, format, ...) \
|
||||
printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__, \
|
||||
array[0], array[1])
|
||||
#elif VIC_NUM_REGS == 4
|
||||
#define DPRINT_REGS(base_reg, format, ...) \
|
||||
printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__, \
|
||||
readl(base_reg ## 0), readl(base_reg ## 1), \
|
||||
readl(base_reg ## 2), readl(base_reg ## 3))
|
||||
#define DPRINT_ARRAY(array, format, ...) \
|
||||
printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__, \
|
||||
array[0], array[1], \
|
||||
array[2], array[3])
|
||||
#else
|
||||
#error "VIC_NUM_REGS set to illegal value"
|
||||
#endif
|
||||
|
||||
static uint32_t msm_irq_smsm_wake_enable[2];
|
||||
static struct {
|
||||
uint32_t int_en[2];
|
||||
uint32_t int_type;
|
||||
uint32_t int_polarity;
|
||||
uint32_t int_select;
|
||||
} msm_irq_shadow_reg[VIC_NUM_REGS];
|
||||
static uint32_t msm_irq_idle_disable[VIC_NUM_REGS];
|
||||
} msm_irq_shadow_reg[2];
|
||||
static uint32_t msm_irq_idle_disable[2];
|
||||
|
||||
#if defined(CONFIG_MSM_N_WAY_SMD)
|
||||
#define INT_INFO_SMSM_ID SMEM_APPS_DEM_SLAVE_DATA
|
||||
@ -198,9 +143,7 @@ static uint8_t msm_irq_to_smsm[NR_MSM_IRQS + NR_SIRC_IRQS] = {
|
||||
[INT_UART1DM_IRQ] = 17,
|
||||
[INT_UART1DM_RX] = 18,
|
||||
[INT_KEYSENSE] = 19,
|
||||
#if !defined(CONFIG_ARCH_MSM7X30)
|
||||
[INT_AD_HSSD] = 20,
|
||||
#endif
|
||||
|
||||
[INT_NAND_WR_ER_DONE] = 21,
|
||||
[INT_NAND_OP_DONE] = 22,
|
||||
@ -226,31 +169,23 @@ static uint8_t msm_irq_to_smsm[NR_MSM_IRQS + NR_SIRC_IRQS] = {
|
||||
[INT_GP_TIMER_EXP] = SMSM_FAKE_IRQ,
|
||||
[INT_DEBUG_TIMER_EXP] = SMSM_FAKE_IRQ,
|
||||
[INT_ADSP_A11] = SMSM_FAKE_IRQ,
|
||||
#ifdef CONFIG_ARCH_QSD8X50
|
||||
#ifdef CONFIG_ARCH_MSM_SCORPION
|
||||
[INT_SIRC_0] = SMSM_FAKE_IRQ,
|
||||
[INT_SIRC_1] = SMSM_FAKE_IRQ,
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void msm_irq_write_all_regs(void __iomem *base, unsigned int val)
|
||||
{
|
||||
int i;
|
||||
/* the address must be continue */
|
||||
for (i = 0; i < VIC_NUM_REGS; i++)
|
||||
writel(val, base + (i * 4));
|
||||
}
|
||||
|
||||
static void msm_irq_ack(unsigned int irq)
|
||||
{
|
||||
void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_CLEAR0, irq);
|
||||
void __iomem *reg = VIC_INT_CLEAR0 + ((irq & 32) ? 4 : 0);
|
||||
irq = 1 << (irq & 31);
|
||||
writel(irq, reg);
|
||||
}
|
||||
|
||||
static void msm_irq_mask(unsigned int irq)
|
||||
{
|
||||
void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENCLEAR0, irq);
|
||||
unsigned index = VIC_INT_TO_REG_INDEX(irq);
|
||||
void __iomem *reg = VIC_INT_ENCLEAR0 + ((irq & 32) ? 4 : 0);
|
||||
unsigned index = (irq >> 5) & 1;
|
||||
uint32_t mask = 1UL << (irq & 31);
|
||||
int smsm_irq = msm_irq_to_smsm[irq];
|
||||
|
||||
@ -266,8 +201,8 @@ static void msm_irq_mask(unsigned int irq)
|
||||
|
||||
static void msm_irq_unmask(unsigned int irq)
|
||||
{
|
||||
void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, irq);
|
||||
unsigned index = VIC_INT_TO_REG_INDEX(irq);
|
||||
void __iomem *reg = VIC_INT_ENSET0 + ((irq & 32) ? 4 : 0);
|
||||
unsigned index = (irq >> 5) & 1;
|
||||
uint32_t mask = 1UL << (irq & 31);
|
||||
int smsm_irq = msm_irq_to_smsm[irq];
|
||||
|
||||
@ -284,7 +219,7 @@ static void msm_irq_unmask(unsigned int irq)
|
||||
|
||||
static int msm_irq_set_wake(unsigned int irq, unsigned int on)
|
||||
{
|
||||
unsigned index = VIC_INT_TO_REG_INDEX(irq);
|
||||
unsigned index = (irq >> 5) & 1;
|
||||
uint32_t mask = 1UL << (irq & 31);
|
||||
int smsm_irq = msm_irq_to_smsm[irq];
|
||||
|
||||
@ -310,9 +245,9 @@ static int msm_irq_set_wake(unsigned int irq, unsigned int on)
|
||||
|
||||
static int msm_irq_set_type(unsigned int irq, unsigned int flow_type)
|
||||
{
|
||||
void __iomem *treg = VIC_INT_TO_REG_ADDR(VIC_INT_TYPE0, irq);
|
||||
void __iomem *preg = VIC_INT_TO_REG_ADDR(VIC_INT_POLARITY0, irq);
|
||||
unsigned index = VIC_INT_TO_REG_INDEX(irq);
|
||||
void __iomem *treg = VIC_INT_TYPE0 + ((irq & 32) ? 4 : 0);
|
||||
void __iomem *preg = VIC_INT_POLARITY0 + ((irq & 32) ? 4 : 0);
|
||||
unsigned index = (irq >> 5) & 1;
|
||||
int b = 1 << (irq & 31);
|
||||
uint32_t polarity;
|
||||
uint32_t type;
|
||||
@ -341,24 +276,16 @@ static int msm_irq_set_type(unsigned int irq, unsigned int flow_type)
|
||||
|
||||
int msm_irq_pending(void)
|
||||
{
|
||||
int i, pending = 0;
|
||||
/* the address must be continue */
|
||||
for (i = 0; (i < VIC_NUM_REGS) && !pending; i++)
|
||||
pending |= readl(VIC_IRQ_STATUS0 + (i * 4));
|
||||
|
||||
return pending;
|
||||
return readl(VIC_IRQ_STATUS0) || readl(VIC_IRQ_STATUS1);
|
||||
}
|
||||
|
||||
int msm_irq_idle_sleep_allowed(void)
|
||||
{
|
||||
int i, disable = 0;
|
||||
|
||||
if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_REQUEST)
|
||||
DPRINT_ARRAY(msm_irq_idle_disable,
|
||||
"msm_irq_idle_sleep_allowed: disable");
|
||||
for (i = 0; i < VIC_NUM_REGS; i++)
|
||||
disable |= msm_irq_idle_disable[i];
|
||||
return !(disable || !smsm_int_info);
|
||||
printk(KERN_INFO "msm_irq_idle_sleep_allowed: disable %x %x\n",
|
||||
msm_irq_idle_disable[0], msm_irq_idle_disable[1]);
|
||||
return !(msm_irq_idle_disable[0] || msm_irq_idle_disable[1] ||
|
||||
!smsm_int_info);
|
||||
}
|
||||
|
||||
/* If arm9_wake is set: pass control to the other core.
|
||||
@ -374,8 +301,8 @@ void msm_irq_enter_sleep1(bool arm9_wake, int from_idle)
|
||||
|
||||
int msm_irq_enter_sleep2(bool arm9_wake, int from_idle)
|
||||
{
|
||||
int i, limit = 10;
|
||||
uint32_t pending[VIC_NUM_REGS];
|
||||
int limit = 10;
|
||||
uint32_t pending0, pending1;
|
||||
|
||||
if (from_idle && !arm9_wake)
|
||||
return 0;
|
||||
@ -384,25 +311,23 @@ int msm_irq_enter_sleep2(bool arm9_wake, int from_idle)
|
||||
WARN_ON_ONCE(!arm9_wake && !from_idle);
|
||||
|
||||
if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
|
||||
DPRINT_REGS(VIC_IRQ_STATUS, "%s change irq, pend", __func__);
|
||||
|
||||
for (i = 0; i < VIC_NUM_REGS; i++) {
|
||||
pending[i] = readl(VIC_IRQ_STATUS0 + (i * 4));
|
||||
pending[i] &= msm_irq_shadow_reg[i].int_en[!from_idle];
|
||||
}
|
||||
printk(KERN_INFO "msm_irq_enter_sleep change irq, pend %x %x\n",
|
||||
readl(VIC_IRQ_STATUS0), readl(VIC_IRQ_STATUS1));
|
||||
pending0 = readl(VIC_IRQ_STATUS0);
|
||||
pending1 = readl(VIC_IRQ_STATUS1);
|
||||
pending0 &= msm_irq_shadow_reg[0].int_en[!from_idle];
|
||||
/* Clear INT_A9_M2A_5 since requesting sleep triggers it */
|
||||
pending[0] &= ~(1U << INT_A9_M2A_5);
|
||||
|
||||
for (i = 0; i < VIC_NUM_REGS; i++) {
|
||||
if (pending[i]) {
|
||||
if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_ABORT)
|
||||
DPRINT_ARRAY(pending, "%s abort",
|
||||
__func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
pending0 &= ~(1U << INT_A9_M2A_5);
|
||||
pending1 &= msm_irq_shadow_reg[1].int_en[!from_idle];
|
||||
if (pending0 || pending1) {
|
||||
if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_ABORT)
|
||||
printk(KERN_INFO "msm_irq_enter_sleep2 abort %x %x\n",
|
||||
pending0, pending1);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
msm_irq_write_all_regs(VIC_INT_EN0, 0);
|
||||
writel(0, VIC_INT_EN0);
|
||||
writel(0, VIC_INT_EN1);
|
||||
|
||||
while (limit-- > 0) {
|
||||
int pend_irq;
|
||||
@ -420,9 +345,8 @@ int msm_irq_enter_sleep2(bool arm9_wake, int from_idle)
|
||||
msm_irq_ack(INT_A9_M2A_6);
|
||||
writel(1U << INT_A9_M2A_6, VIC_INT_ENSET0);
|
||||
} else {
|
||||
for (i = 0; i < VIC_NUM_REGS; i++)
|
||||
writel(msm_irq_shadow_reg[i].int_en[1],
|
||||
VIC_INT_ENSET0 + (i * 4));
|
||||
writel(msm_irq_shadow_reg[0].int_en[1], VIC_INT_ENSET0);
|
||||
writel(msm_irq_shadow_reg[1].int_en[1], VIC_INT_ENSET1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -433,7 +357,7 @@ void msm_irq_exit_sleep1(void)
|
||||
|
||||
msm_irq_ack(INT_A9_M2A_6);
|
||||
msm_irq_ack(INT_PWB_I2C);
|
||||
for (i = 0; i < VIC_NUM_REGS; i++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
writel(msm_irq_shadow_reg[i].int_type, VIC_INT_TYPE0 + i * 4);
|
||||
writel(msm_irq_shadow_reg[i].int_polarity, VIC_INT_POLARITY0 + i * 4);
|
||||
writel(msm_irq_shadow_reg[i].int_en[0], VIC_INT_EN0 + i * 4);
|
||||
@ -527,16 +451,20 @@ void __init msm_init_irq(void)
|
||||
unsigned n;
|
||||
|
||||
/* select level interrupts */
|
||||
msm_irq_write_all_regs(VIC_INT_TYPE0, 0);
|
||||
writel(0, VIC_INT_TYPE0);
|
||||
writel(0, VIC_INT_TYPE1);
|
||||
|
||||
/* select highlevel interrupts */
|
||||
msm_irq_write_all_regs(VIC_INT_POLARITY0, 0);
|
||||
writel(0, VIC_INT_POLARITY0);
|
||||
writel(0, VIC_INT_POLARITY1);
|
||||
|
||||
/* select IRQ for all INTs */
|
||||
msm_irq_write_all_regs(VIC_INT_SELECT0, 0);
|
||||
writel(0, VIC_INT_SELECT0);
|
||||
writel(0, VIC_INT_SELECT1);
|
||||
|
||||
/* disable all INTs */
|
||||
msm_irq_write_all_regs(VIC_INT_EN0, 0);
|
||||
writel(0, VIC_INT_EN0);
|
||||
writel(0, VIC_INT_EN1);
|
||||
|
||||
/* don't use 1136 vic */
|
||||
writel(0, VIC_CONFIG);
|
||||
@ -565,7 +493,7 @@ late_initcall(msm_init_irq_late);
|
||||
#if defined(CONFIG_MSM_FIQ_SUPPORT)
|
||||
void msm_trigger_irq(int irq)
|
||||
{
|
||||
void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_SOFTINT0, irq);
|
||||
void __iomem *reg = VIC_SOFTINT0 + ((irq & 32) ? 4 : 0);
|
||||
uint32_t mask = 1UL << (irq & 31);
|
||||
writel(mask, reg);
|
||||
}
|
||||
@ -588,8 +516,8 @@ void msm_fiq_disable(int irq)
|
||||
|
||||
static void _msm_fiq_select(int irq)
|
||||
{
|
||||
void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_SELECT0, irq);
|
||||
unsigned index = VIC_INT_TO_REG_INDEX(irq);
|
||||
void __iomem *reg = VIC_INT_SELECT0 + ((irq & 32) ? 4 : 0);
|
||||
unsigned index = (irq >> 5) & 1;
|
||||
uint32_t mask = 1UL << (irq & 31);
|
||||
unsigned long flags;
|
||||
|
||||
@ -601,8 +529,8 @@ static void _msm_fiq_select(int irq)
|
||||
|
||||
static void _msm_fiq_unselect(int irq)
|
||||
{
|
||||
void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_SELECT0, irq);
|
||||
unsigned index = VIC_INT_TO_REG_INDEX(irq);
|
||||
void __iomem *reg = VIC_INT_SELECT0 + ((irq & 32) ? 4 : 0);
|
||||
unsigned index = (irq >> 5) & 1;
|
||||
uint32_t mask = 1UL << (irq & 31);
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* arch/arm/mach-msm/proc_comm.c
|
||||
*
|
||||
* Copyright (C) 2007-2008 Google, Inc.
|
||||
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
@ -18,24 +19,24 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/system.h>
|
||||
|
||||
#include "proc_comm.h"
|
||||
#include "smd_private.h"
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
#define MSM_TRIG_A2M_INT(n) (writel(1 << n, MSM_GCC_BASE + 0x8))
|
||||
#define MSM_TRIG_A2M_PC_INT (writel(1 << 6, MSM_GCC_BASE + 0x8))
|
||||
#elif defined(CONFIG_ARCH_MSM8X60)
|
||||
#define MSM_TRIG_A2M_PC_INT (writel(1 << 5, MSM_GCC_BASE + 0x8))
|
||||
#else
|
||||
#define MSM_TRIG_A2M_PC_INT (writel(1, MSM_CSR_BASE + 0x400 + (6) * 4))
|
||||
#endif
|
||||
|
||||
#define MSM_A2M_INT(n) (MSM_CSR_BASE + 0x400 + (n) * 4)
|
||||
|
||||
static inline void notify_other_proc_comm(void)
|
||||
{
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
MSM_TRIG_A2M_INT(6);
|
||||
#else
|
||||
writel(1, MSM_A2M_INT(6));
|
||||
#endif
|
||||
MSM_TRIG_A2M_PC_INT;
|
||||
}
|
||||
|
||||
#define APP_COMMAND 0x00
|
||||
@ -50,69 +51,84 @@ static inline void notify_other_proc_comm(void)
|
||||
|
||||
static DEFINE_SPINLOCK(proc_comm_lock);
|
||||
|
||||
/* The higher level SMD support will install this to
|
||||
* provide a way to check for and handle modem restart.
|
||||
*/
|
||||
int (*msm_check_for_modem_crash)(void);
|
||||
|
||||
/* Poll for a state change, checking for possible
|
||||
* modem crashes along the way (so we don't wait
|
||||
* forever while the ARM9 is blowing up).
|
||||
* forever while the ARM9 is blowing up.
|
||||
*
|
||||
* Return an error in the event of a modem crash and
|
||||
* restart so the msm_proc_comm() routine can restart
|
||||
* the operation from the beginning.
|
||||
*/
|
||||
static int proc_comm_wait_for(void __iomem *addr, unsigned value)
|
||||
static int proc_comm_wait_for(unsigned addr, unsigned value)
|
||||
{
|
||||
for (;;) {
|
||||
while (1) {
|
||||
if (readl(addr) == value)
|
||||
return 0;
|
||||
|
||||
if (msm_check_for_modem_crash)
|
||||
if (msm_check_for_modem_crash())
|
||||
return -EAGAIN;
|
||||
if (smsm_check_for_modem_crash())
|
||||
return -EAGAIN;
|
||||
|
||||
udelay(5);
|
||||
}
|
||||
}
|
||||
|
||||
void msm_proc_comm_reset_modem_now(void)
|
||||
{
|
||||
unsigned base = (unsigned)MSM_SHARED_RAM_BASE;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&proc_comm_lock, flags);
|
||||
|
||||
again:
|
||||
if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
|
||||
goto again;
|
||||
|
||||
writel(PCOM_RESET_MODEM, base + APP_COMMAND);
|
||||
writel(0, base + APP_DATA1);
|
||||
writel(0, base + APP_DATA2);
|
||||
|
||||
spin_unlock_irqrestore(&proc_comm_lock, flags);
|
||||
|
||||
notify_other_proc_comm();
|
||||
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_proc_comm_reset_modem_now);
|
||||
|
||||
int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
|
||||
{
|
||||
void __iomem *base = MSM_SHARED_RAM_BASE;
|
||||
unsigned base = (unsigned)MSM_SHARED_RAM_BASE;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&proc_comm_lock, flags);
|
||||
|
||||
for (;;) {
|
||||
if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
|
||||
continue;
|
||||
again:
|
||||
if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
|
||||
goto again;
|
||||
|
||||
writel(cmd, base + APP_COMMAND);
|
||||
writel(data1 ? *data1 : 0, base + APP_DATA1);
|
||||
writel(data2 ? *data2 : 0, base + APP_DATA2);
|
||||
writel(cmd, base + APP_COMMAND);
|
||||
writel(data1 ? *data1 : 0, base + APP_DATA1);
|
||||
writel(data2 ? *data2 : 0, base + APP_DATA2);
|
||||
|
||||
notify_other_proc_comm();
|
||||
notify_other_proc_comm();
|
||||
|
||||
if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE))
|
||||
continue;
|
||||
if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE))
|
||||
goto again;
|
||||
|
||||
if (readl(base + APP_STATUS) != PCOM_CMD_FAIL) {
|
||||
if (data1)
|
||||
*data1 = readl(base + APP_DATA1);
|
||||
if (data2)
|
||||
*data2 = readl(base + APP_DATA2);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -EIO;
|
||||
}
|
||||
break;
|
||||
if (readl(base + APP_STATUS) == PCOM_CMD_SUCCESS) {
|
||||
if (data1)
|
||||
*data1 = readl(base + APP_DATA1);
|
||||
if (data2)
|
||||
*data2 = readl(base + APP_DATA2);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
writel(PCOM_CMD_IDLE, base + APP_COMMAND);
|
||||
|
||||
spin_unlock_irqrestore(&proc_comm_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(msm_proc_comm);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* arch/arm/mach-msm/proc_comm.h
|
||||
*
|
||||
* Copyright (c) 2007 QUALCOMM Incorporated
|
||||
* Copyright (c) 2007-2009, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@ -179,7 +179,18 @@ enum {
|
||||
PCOM_CLKCTL_RPC_RAIL_DISABLE,
|
||||
PCOM_CLKCTL_RPC_RAIL_CONTROL,
|
||||
PCOM_CLKCTL_RPC_MIN_MSMC1,
|
||||
PCOM_NUM_CMDS,
|
||||
PCOM_CLKCTL_RPC_SRC_REQUEST,
|
||||
PCOM_NPA_INIT,
|
||||
PCOM_NPA_ISSUE_REQUIRED_REQUEST,
|
||||
};
|
||||
|
||||
enum {
|
||||
PCOM_OEM_FIRST_CMD = 0x10000000,
|
||||
PCOM_OEM_TEST_CMD = PCOM_OEM_FIRST_CMD,
|
||||
|
||||
/* add OEM PROC COMM commands here */
|
||||
|
||||
PCOM_OEM_LAST = PCOM_OEM_TEST_CMD,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -199,7 +210,6 @@ enum {
|
||||
PCOM_CMD_FAIL_SMSM_NOT_INIT,
|
||||
PCOM_CMD_FAIL_PROC_COMM_BUSY,
|
||||
PCOM_CMD_FAIL_PROC_COMM_NOT_INIT,
|
||||
|
||||
};
|
||||
|
||||
/* List of VREGs that support the Pull Down Resistor setting. */
|
||||
@ -294,6 +304,7 @@ enum {
|
||||
(((pull) & 0x3) << 15) | \
|
||||
(((drvstr) & 0xF) << 17))
|
||||
|
||||
void msm_proc_comm_reset_modem_now(void);
|
||||
int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2);
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* linux/arch/arm/mach-msm/irq.c
|
||||
*
|
||||
* Copyright (c) 2009 QUALCOMM Incorporated.
|
||||
* Copyright (c) 2009-2010 Code Aurora Forum. All rights reserved.
|
||||
* Copyright (C) 2009 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
@ -189,9 +189,9 @@ static void sirc_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
reg++;
|
||||
|
||||
if (reg == ARRAY_SIZE(sirc_reg_table)) {
|
||||
printk(KERN_ERR "%s: incorrect irq %d called\n",
|
||||
__func__, irq);
|
||||
return;
|
||||
printk(KERN_ERR "%s: incorrect irq %d called\n",
|
||||
__func__, irq);
|
||||
return;
|
||||
}
|
||||
|
||||
status = readl(sirc_reg_table[reg].int_status);
|
||||
|
@ -16,12 +16,20 @@
|
||||
#ifndef _ARCH_ARM_MACH_MSM_SIRC_H
|
||||
#define _ARCH_ARM_MACH_MSM_SIRC_H
|
||||
|
||||
#ifdef CONFIG_ARCH_QSD8X50
|
||||
#ifdef CONFIG_ARCH_MSM_SCORPION
|
||||
void sirc_fiq_select(int irq, bool enable);
|
||||
void __init msm_init_sirc(void);
|
||||
#else
|
||||
static inline void sirc_fiq_select(int irq, bool enable) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_QSD8X50
|
||||
void __init msm_init_sirc(void);
|
||||
void msm_sirc_enter_sleep(void);
|
||||
void msm_sirc_exit_sleep(void);
|
||||
#else
|
||||
static inline void __init msm_init_sirc(void) {}
|
||||
static inline void msm_sirc_enter_sleep(void) { }
|
||||
static inline void msm_sirc_exit_sleep(void) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -140,16 +140,18 @@ static void handle_modem_crash(void)
|
||||
;
|
||||
}
|
||||
|
||||
extern int (*msm_check_for_modem_crash)(void);
|
||||
|
||||
uint32_t raw_smsm_get_state(enum smsm_state_item item)
|
||||
{
|
||||
return readl(smd_info.state + item * 4);
|
||||
}
|
||||
|
||||
static int check_for_modem_crash(void)
|
||||
int smsm_check_for_modem_crash(void)
|
||||
{
|
||||
if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET) {
|
||||
/* if the modem's not ready yet, we have to hope for the best */
|
||||
if (!smd_info.state)
|
||||
return 0;
|
||||
|
||||
if (raw_smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET) {
|
||||
handle_modem_crash();
|
||||
return -1;
|
||||
}
|
||||
@ -1238,8 +1240,6 @@ static int __init msm_smd_probe(struct platform_device *pdev)
|
||||
|
||||
do_smd_probe();
|
||||
|
||||
msm_check_for_modem_crash = check_for_modem_crash;
|
||||
|
||||
msm_init_last_radio_log(THIS_MODULE);
|
||||
|
||||
smd_initialized = 1;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* arch/arm/mach-msm/smd_private.h
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2007 QUALCOMM Incorporated
|
||||
* Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@ -16,6 +16,9 @@
|
||||
#ifndef _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_
|
||||
#define _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
struct smem_heap_info {
|
||||
unsigned initialized;
|
||||
unsigned free_offset;
|
||||
@ -46,12 +49,15 @@ struct smem_proc_comm {
|
||||
#define VERSION_MODEM_SBL 7
|
||||
#define VERSION_APPS 8
|
||||
#define VERSION_MODEM 9
|
||||
#define VERSION_DSPS 10
|
||||
|
||||
#define SMD_HEAP_SIZE 512
|
||||
|
||||
struct smem_shared {
|
||||
struct smem_proc_comm proc_comm[4];
|
||||
unsigned version[32];
|
||||
struct smem_heap_info heap_info;
|
||||
struct smem_heap_entry heap_toc[512];
|
||||
struct smem_heap_entry heap_toc[SMD_HEAP_SIZE];
|
||||
};
|
||||
|
||||
#define SMSM_V1_SIZE (sizeof(unsigned) * 8)
|
||||
@ -122,35 +128,37 @@ enum {
|
||||
#define ID_SHARED_STATE SMEM_SMSM_SHARED_STATE
|
||||
#define ID_CH_ALLOC_TBL SMEM_CHANNEL_ALLOC_TBL
|
||||
|
||||
#define SMSM_INIT 0x00000001
|
||||
#define SMSM_OSENTERED 0x00000002
|
||||
#define SMSM_SMDWAIT 0x00000004
|
||||
#define SMSM_SMDINIT 0x00000008
|
||||
#define SMSM_RPCWAIT 0x00000010
|
||||
#define SMSM_RPCINIT 0x00000020
|
||||
#define SMSM_RESET 0x00000040
|
||||
#define SMSM_RSA 0x00000080
|
||||
#define SMSM_RUN 0x00000100
|
||||
#define SMSM_PWRC 0x00000200
|
||||
#define SMSM_TIMEWAIT 0x00000400
|
||||
#define SMSM_TIMEINIT 0x00000800
|
||||
#define SMSM_PWRC_EARLY_EXIT 0x00001000
|
||||
#define SMSM_WFPI 0x00002000
|
||||
#define SMSM_SLEEP 0x00004000
|
||||
#define SMSM_SLEEPEXIT 0x00008000
|
||||
#define SMSM_OEMSBL_RELEASE 0x00010000
|
||||
#define SMSM_APPS_REBOOT 0x00020000
|
||||
#define SMSM_SYSTEM_POWER_DOWN 0x00040000
|
||||
#define SMSM_SYSTEM_REBOOT 0x00080000
|
||||
#define SMSM_SYSTEM_DOWNLOAD 0x00100000
|
||||
#define SMSM_PWRC_SUSPEND 0x00200000
|
||||
#define SMSM_APPS_SHUTDOWN 0x00400000
|
||||
#define SMSM_SMD_LOOPBACK 0x00800000
|
||||
#define SMSM_RUN_QUIET 0x01000000
|
||||
#define SMSM_MODEM_WAIT 0x02000000
|
||||
#define SMSM_MODEM_BREAK 0x04000000
|
||||
#define SMSM_MODEM_CONTINUE 0x08000000
|
||||
#define SMSM_UNKNOWN 0x80000000
|
||||
#define SMSM_INIT 0x00000001
|
||||
#define SMSM_OSENTERED 0x00000002
|
||||
#define SMSM_SMDWAIT 0x00000004
|
||||
#define SMSM_SMDINIT 0x00000008
|
||||
#define SMSM_RPCWAIT 0x00000010
|
||||
#define SMSM_RPCINIT 0x00000020
|
||||
#define SMSM_RESET 0x00000040
|
||||
#define SMSM_RSA 0x00000080
|
||||
#define SMSM_RUN 0x00000100
|
||||
#define SMSM_PWRC 0x00000200
|
||||
#define SMSM_TIMEWAIT 0x00000400
|
||||
#define SMSM_TIMEINIT 0x00000800
|
||||
#define SMSM_PWRC_EARLY_EXIT 0x00001000
|
||||
#define SMSM_WFPI 0x00002000
|
||||
#define SMSM_SLEEP 0x00004000
|
||||
#define SMSM_SLEEPEXIT 0x00008000
|
||||
#define SMSM_OEMSBL_RELEASE 0x00010000
|
||||
#define SMSM_APPS_REBOOT 0x00020000
|
||||
#define SMSM_SYSTEM_POWER_DOWN 0x00040000
|
||||
#define SMSM_SYSTEM_REBOOT 0x00080000
|
||||
#define SMSM_SYSTEM_DOWNLOAD 0x00100000
|
||||
#define SMSM_PWRC_SUSPEND 0x00200000
|
||||
#define SMSM_APPS_SHUTDOWN 0x00400000
|
||||
#define SMSM_SMD_LOOPBACK 0x00800000
|
||||
#define SMSM_RUN_QUIET 0x01000000
|
||||
#define SMSM_MODEM_WAIT 0x02000000
|
||||
#define SMSM_MODEM_BREAK 0x04000000
|
||||
#define SMSM_MODEM_CONTINUE 0x08000000
|
||||
#define SMSM_SYSTEM_REBOOT_USR 0x20000000
|
||||
#define SMSM_SYSTEM_PWRDWN_USR 0x40000000
|
||||
#define SMSM_UNKNOWN 0x80000000
|
||||
|
||||
#define SMSM_WKUP_REASON_RPC 0x00000001
|
||||
#define SMSM_WKUP_REASON_INT 0x00000002
|
||||
@ -278,18 +286,17 @@ typedef enum {
|
||||
} smem_mem_type;
|
||||
|
||||
|
||||
#define SMD_SS_CLOSED 0x00000000
|
||||
#define SMD_SS_OPENING 0x00000001
|
||||
#define SMD_SS_OPENED 0x00000002
|
||||
#define SMD_SS_FLUSHING 0x00000003
|
||||
#define SMD_SS_CLOSING 0x00000004
|
||||
#define SMD_SS_RESET 0x00000005
|
||||
#define SMD_SS_RESET_OPENING 0x00000006
|
||||
#define SMD_SS_CLOSED 0x00000000
|
||||
#define SMD_SS_OPENING 0x00000001
|
||||
#define SMD_SS_OPENED 0x00000002
|
||||
#define SMD_SS_FLUSHING 0x00000003
|
||||
#define SMD_SS_CLOSING 0x00000004
|
||||
#define SMD_SS_RESET 0x00000005
|
||||
#define SMD_SS_RESET_OPENING 0x00000006
|
||||
|
||||
#define SMD_BUF_SIZE 8192
|
||||
#define SMD_CHANNELS 64
|
||||
|
||||
#define SMD_HEADER_SIZE 20
|
||||
#define SMD_BUF_SIZE 8192
|
||||
#define SMD_CHANNELS 64
|
||||
#define SMD_HEADER_SIZE 20
|
||||
|
||||
#define SMD_TYPE_MASK 0x0FF
|
||||
#define SMD_TYPE_APPS_MODEM 0x000
|
||||
@ -301,6 +308,8 @@ typedef enum {
|
||||
#define SMD_KIND_STREAM 0x100
|
||||
#define SMD_KIND_PACKET 0x200
|
||||
|
||||
int smsm_check_for_modem_crash(void);
|
||||
#define msm_check_for_modem_crash smsm_check_for_modem_crash
|
||||
void *smem_find(unsigned id, unsigned size);
|
||||
void *smem_item(unsigned id, unsigned *size);
|
||||
uint32_t raw_smsm_get_state(enum smsm_state_item item);
|
||||
|
1738
drivers/misc/pmem.c
1738
drivers/misc/pmem.c
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,7 @@
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
@ -81,7 +82,6 @@ enum {
|
||||
BINDER_DEBUG_BUFFER_ALLOC = 1U << 13,
|
||||
BINDER_DEBUG_PRIORITY_CAP = 1U << 14,
|
||||
BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15,
|
||||
BINDER_DEBUG_IOCTL = 1U << 16,
|
||||
};
|
||||
static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
|
||||
BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
|
||||
@ -2615,9 +2615,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
unsigned int size = _IOC_SIZE(cmd);
|
||||
void __user *ubuf = (void __user *)arg;
|
||||
|
||||
binder_debug(BINDER_DEBUG_IOCTL,
|
||||
"binder_ioctl begin: %d:%d %x %lx\n",
|
||||
proc->pid, current->pid, cmd, arg);
|
||||
/*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
|
||||
|
||||
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
|
||||
if (ret)
|
||||
@ -2736,9 +2734,6 @@ err:
|
||||
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
|
||||
if (ret && ret != -ERESTARTSYS)
|
||||
printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
|
||||
binder_debug(BINDER_DEBUG_IOCTL,
|
||||
"binder_ioctl end: %d:%d %x %lx\n",
|
||||
proc->pid, current->pid, cmd, arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include "logger.h"
|
||||
|
||||
@ -431,7 +432,10 @@ static int logger_release(struct inode *ignored, struct file *file)
|
||||
{
|
||||
if (file->f_mode & FMODE_READ) {
|
||||
struct logger_reader *reader = file->private_data;
|
||||
struct logger_log *log = reader->log;
|
||||
mutex_lock(&log->mutex);
|
||||
list_del(&reader->list);
|
||||
mutex_unlock(&log->mutex);
|
||||
kfree(reader);
|
||||
}
|
||||
|
||||
|
@ -52,19 +52,8 @@ static size_t lowmem_minfree[6] = {
|
||||
};
|
||||
static int lowmem_minfree_size = 4;
|
||||
|
||||
static size_t lowmem_minfile[6] = {
|
||||
1536,
|
||||
2048,
|
||||
4096,
|
||||
5120,
|
||||
5632,
|
||||
6144
|
||||
};
|
||||
static int lowmem_minfile_size = 6;
|
||||
|
||||
static struct task_struct *lowmem_deathpending;
|
||||
|
||||
static uint32_t lowmem_check_filepages = 0;
|
||||
static DEFINE_SPINLOCK(lowmem_deathpending_lock);
|
||||
|
||||
#define lowmem_print(level, x...) \
|
||||
do { \
|
||||
@ -79,13 +68,25 @@ static struct notifier_block task_nb = {
|
||||
.notifier_call = task_notify_func,
|
||||
};
|
||||
|
||||
|
||||
static void task_free_fn(struct work_struct *work)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
task_free_unregister(&task_nb);
|
||||
spin_lock_irqsave(&lowmem_deathpending_lock, flags);
|
||||
lowmem_deathpending = NULL;
|
||||
spin_unlock_irqrestore(&lowmem_deathpending_lock, flags);
|
||||
}
|
||||
static DECLARE_WORK(task_free_work, task_free_fn);
|
||||
|
||||
static int
|
||||
task_notify_func(struct notifier_block *self, unsigned long val, void *data)
|
||||
{
|
||||
struct task_struct *task = data;
|
||||
|
||||
if (task == lowmem_deathpending) {
|
||||
lowmem_deathpending = NULL;
|
||||
task_free_unregister(&task_nb);
|
||||
schedule_work(&task_free_work);
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
@ -103,8 +104,7 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
|
||||
int array_size = ARRAY_SIZE(lowmem_adj);
|
||||
int other_free = global_page_state(NR_FREE_PAGES);
|
||||
int other_file = global_page_state(NR_FILE_PAGES);
|
||||
int lru_file = global_page_state(NR_ACTIVE_FILE) +
|
||||
global_page_state(NR_INACTIVE_FILE);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* If we already have a death outstanding, then
|
||||
@ -121,14 +121,9 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
|
||||
if (lowmem_minfree_size < array_size)
|
||||
array_size = lowmem_minfree_size;
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if (other_free < lowmem_minfree[i]) {
|
||||
if(other_file < lowmem_minfree[i] ||
|
||||
(lowmem_check_filepages &&
|
||||
(lru_file < lowmem_minfile[i]))) {
|
||||
|
||||
min_adj = lowmem_adj[i];
|
||||
break;
|
||||
}
|
||||
if (other_file < lowmem_minfree[i]) {
|
||||
min_adj = lowmem_adj[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nr_to_scan > 0)
|
||||
@ -181,14 +176,20 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
|
||||
lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
|
||||
p->pid, p->comm, oom_adj, tasksize);
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
|
||||
selected->pid, selected->comm,
|
||||
selected_oom_adj, selected_tasksize);
|
||||
lowmem_deathpending = selected;
|
||||
task_free_register(&task_nb);
|
||||
force_sig(SIGKILL, selected);
|
||||
rem -= selected_tasksize;
|
||||
spin_lock_irqsave(&lowmem_deathpending_lock, flags);
|
||||
if (!lowmem_deathpending) {
|
||||
lowmem_print(1,
|
||||
"send sigkill to %d (%s), adj %d, size %d\n",
|
||||
selected->pid, selected->comm,
|
||||
selected_oom_adj, selected_tasksize);
|
||||
lowmem_deathpending = selected;
|
||||
task_free_register(&task_nb);
|
||||
force_sig(SIGKILL, selected);
|
||||
rem -= selected_tasksize;
|
||||
}
|
||||
spin_unlock_irqrestore(&lowmem_deathpending_lock, flags);
|
||||
}
|
||||
lowmem_print(4, "lowmem_shrink %d, %x, return %d\n",
|
||||
nr_to_scan, gfp_mask, rem);
|
||||
@ -219,11 +220,6 @@ module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
|
||||
S_IRUGO | S_IWUSR);
|
||||
module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
|
||||
|
||||
module_param_named(check_filepages , lowmem_check_filepages, uint,
|
||||
S_IRUGO | S_IWUSR);
|
||||
module_param_array_named(minfile, lowmem_minfile, uint, &lowmem_minfile_size,
|
||||
S_IRUGO | S_IWUSR);
|
||||
|
||||
module_init(lowmem_init);
|
||||
module_exit(lowmem_exit);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
|
@ -74,6 +74,7 @@ ktime_t alarm_get_elapsed_realtime(void);
|
||||
|
||||
/* set rtc while preserving elapsed realtime */
|
||||
int alarm_set_rtc(const struct timespec ts);
|
||||
void alarm_update_timedelta(struct timespec tv, struct timespec ts);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -8,12 +8,12 @@
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef CONFIG_MSM_KGSL
|
||||
|
||||
#ifndef _ANDROID_PMEM_H_
|
||||
#define _ANDROID_PMEM_H_
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
*/
|
||||
#define PMEM_CONNECT _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
|
||||
/* Returns the total size of the pmem region it is sent to as a pmem_region
|
||||
* struct (with offset set to 0).
|
||||
* struct (with offset set to 0).
|
||||
*/
|
||||
#define PMEM_GET_TOTAL_SIZE _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
|
||||
/* Revokes gpu registers and resets the gpu. Pass a pointer to the
|
||||
@ -54,6 +54,7 @@
|
||||
#define HW3D_REVOKE_GPU _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
|
||||
#define PMEM_CACHE_FLUSH _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
|
||||
#define HW3D_GRANT_GPU _IOW(PMEM_IOCTL_MAGIC, 9, unsigned int)
|
||||
#define HW3D_WAIT_FOR_INTERRUPT _IOW(PMEM_IOCTL_MAGIC, 10, unsigned int)
|
||||
|
||||
#define PMEM_CLEAN_INV_CACHES _IOW(PMEM_IOCTL_MAGIC, 11, unsigned int)
|
||||
#define PMEM_CLEAN_CACHES _IOW(PMEM_IOCTL_MAGIC, 12, unsigned int)
|
||||
@ -85,6 +86,8 @@ struct pmem_allocation {
|
||||
#ifdef __KERNEL__
|
||||
int get_pmem_file(unsigned int fd, unsigned long *start, unsigned long *vstart,
|
||||
unsigned long *end, struct file **filp);
|
||||
int get_pmem_addr(struct file *file, unsigned long *start,
|
||||
unsigned long *vstart, unsigned long *len);
|
||||
int get_pmem_fd(int fd, unsigned long *start, unsigned long *end);
|
||||
int get_pmem_user_addr(struct file *file, unsigned long *start,
|
||||
unsigned long *end);
|
||||
@ -101,6 +104,7 @@ enum pmem_allocator_type {
|
||||
* defined
|
||||
*/
|
||||
PMEM_ALLOCATORTYPE_BITMAP = 0, /* forced to be zero here */
|
||||
PMEM_ALLOCATORTYPE_SYSTEM,
|
||||
|
||||
PMEM_ALLOCATORTYPE_ALLORNOTHING,
|
||||
PMEM_ALLOCATORTYPE_BUDDYBESTFIT,
|
||||
@ -163,104 +167,7 @@ int pmem_setup(struct android_pmem_platform_data *pdata,
|
||||
|
||||
int pmem_remap(struct pmem_region *region, struct file *file,
|
||||
unsigned operation);
|
||||
int is_pmem_file(struct file *file);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif //_ANDROID_PPP_H_
|
||||
#else
|
||||
|
||||
/* include/linux/android_pmem.h
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_PMEM_H_
|
||||
#define _ANDROID_PMEM_H_
|
||||
|
||||
#define PMEM_IOCTL_MAGIC 'p'
|
||||
#define PMEM_GET_PHYS _IOW(PMEM_IOCTL_MAGIC, 1, unsigned int)
|
||||
#define PMEM_MAP _IOW(PMEM_IOCTL_MAGIC, 2, unsigned int)
|
||||
#define PMEM_GET_SIZE _IOW(PMEM_IOCTL_MAGIC, 3, unsigned int)
|
||||
#define PMEM_UNMAP _IOW(PMEM_IOCTL_MAGIC, 4, unsigned int)
|
||||
/* This ioctl will allocate pmem space, backing the file, it will fail
|
||||
* if the file already has an allocation, pass it the len as the argument
|
||||
* to the ioctl */
|
||||
#define PMEM_ALLOCATE _IOW(PMEM_IOCTL_MAGIC, 5, unsigned int)
|
||||
/* This will connect a one pmem file to another, pass the file that is already
|
||||
* backed in memory as the argument to the ioctl
|
||||
*/
|
||||
#define PMEM_CONNECT _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
|
||||
/* Returns the total size of the pmem region it is sent to as a pmem_region
|
||||
* struct (with offset set to 0).
|
||||
*/
|
||||
#define PMEM_GET_TOTAL_SIZE _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
|
||||
#define PMEM_CACHE_FLUSH _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
|
||||
|
||||
struct android_pmem_platform_data
|
||||
{
|
||||
const char* name;
|
||||
/* starting physical address of memory region */
|
||||
unsigned long start;
|
||||
/* size of memory region */
|
||||
unsigned long size;
|
||||
/* set to indicate the region should not be managed with an allocator */
|
||||
unsigned no_allocator;
|
||||
/* set to indicate maps of this region should be cached, if a mix of
|
||||
* cached and uncached is desired, set this and open the device with
|
||||
* O_SYNC to get an uncached region */
|
||||
unsigned cached;
|
||||
/* The MSM7k has bits to enable a write buffer in the bus controller*/
|
||||
unsigned buffered;
|
||||
};
|
||||
|
||||
struct pmem_region {
|
||||
unsigned long offset;
|
||||
unsigned long len;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ANDROID_PMEM
|
||||
int is_pmem_file(struct file *file);
|
||||
int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
|
||||
unsigned long *end, struct file **filp);
|
||||
int get_pmem_user_addr(struct file *file, unsigned long *start,
|
||||
unsigned long *end);
|
||||
void put_pmem_file(struct file* file);
|
||||
void flush_pmem_file(struct file *file, unsigned long start, unsigned long len);
|
||||
int pmem_setup(struct android_pmem_platform_data *pdata,
|
||||
long (*ioctl)(struct file *, unsigned int, unsigned long),
|
||||
int (*release)(struct inode *, struct file *));
|
||||
int pmem_remap(struct pmem_region *region, struct file *file,
|
||||
unsigned operation);
|
||||
|
||||
#else
|
||||
static inline int is_pmem_file(struct file *file) { return 0; }
|
||||
static inline int get_pmem_file(int fd, unsigned long *start,
|
||||
unsigned long *vstart, unsigned long *end,
|
||||
struct file **filp) { return -ENOSYS; }
|
||||
static inline int get_pmem_user_addr(struct file *file, unsigned long *start,
|
||||
unsigned long *end) { return -ENOSYS; }
|
||||
static inline void put_pmem_file(struct file* file) { return; }
|
||||
static inline void flush_pmem_file(struct file *file, unsigned long start,
|
||||
unsigned long len) { return; }
|
||||
static inline int pmem_setup(struct android_pmem_platform_data *pdata,
|
||||
long (*ioctl)(struct file *, unsigned int, unsigned long),
|
||||
int (*release)(struct inode *, struct file *)) { return -ENOSYS; }
|
||||
|
||||
static inline int pmem_remap(struct pmem_region *region, struct file *file,
|
||||
unsigned operation) { return -ENOSYS; }
|
||||
#endif
|
||||
|
||||
#endif //_ANDROID_PPP_H_
|
||||
|
||||
#endif
|
@ -15,7 +15,7 @@ struct vm_area_struct;
|
||||
* Zone modifiers (see linux/mmzone.h - low three bits)
|
||||
*
|
||||
* Do not put any conditional on these. If necessary modify the definitions
|
||||
* without the underscores and use the consistently. The definitions here may
|
||||
* without the underscores and use them consistently. The definitions here may
|
||||
* be used in bit comparisons.
|
||||
*/
|
||||
#define __GFP_DMA ((__force gfp_t)0x01u)
|
||||
@ -30,7 +30,8 @@ struct vm_area_struct;
|
||||
* _might_ fail. This depends upon the particular VM implementation.
|
||||
*
|
||||
* __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
|
||||
* cannot handle allocation failures.
|
||||
* cannot handle allocation failures. This modifier is deprecated and no new
|
||||
* users should be added.
|
||||
*
|
||||
* __GFP_NORETRY: The VM implementation must not retry indefinitely.
|
||||
*
|
||||
@ -83,6 +84,7 @@ struct vm_area_struct;
|
||||
#define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
|
||||
__GFP_HARDWALL | __GFP_HIGHMEM | \
|
||||
__GFP_MOVABLE)
|
||||
#define GFP_IOFS (__GFP_IO | __GFP_FS)
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
#define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
|
||||
@ -99,7 +101,7 @@ struct vm_area_struct;
|
||||
__GFP_NORETRY|__GFP_NOMEMALLOC)
|
||||
|
||||
/* Control slab gfp mask during early boot */
|
||||
#define GFP_BOOT_MASK __GFP_BITS_MASK & ~(__GFP_WAIT|__GFP_IO|__GFP_FS)
|
||||
#define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_WAIT|__GFP_IO|__GFP_FS))
|
||||
|
||||
/* Control allocation constraints */
|
||||
#define GFP_CONSTRAINT_MASK (__GFP_HARDWALL|__GFP_THISNODE)
|
||||
@ -150,12 +152,12 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags)
|
||||
* GFP_ZONE_TABLE is a word size bitstring that is used for looking up the
|
||||
* zone to use given the lowest 4 bits of gfp_t. Entries are ZONE_SHIFT long
|
||||
* and there are 16 of them to cover all possible combinations of
|
||||
* __GFP_DMA, __GFP_DMA32, __GFP_MOVABLE and __GFP_HIGHMEM
|
||||
* __GFP_DMA, __GFP_DMA32, __GFP_MOVABLE and __GFP_HIGHMEM.
|
||||
*
|
||||
* The zone fallback order is MOVABLE=>HIGHMEM=>NORMAL=>DMA32=>DMA.
|
||||
* But GFP_MOVABLE is not only a zone specifier but also an allocation
|
||||
* policy. Therefore __GFP_MOVABLE plus another zone selector is valid.
|
||||
* Only 1bit of the lowest 3 bit (DMA,DMA32,HIGHMEM) can be set to "1".
|
||||
* Only 1 bit of the lowest 3 bits (DMA,DMA32,HIGHMEM) can be set to "1".
|
||||
*
|
||||
* bit result
|
||||
* =================
|
||||
@ -185,7 +187,7 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags)
|
||||
|
||||
#define GFP_ZONE_TABLE ( \
|
||||
(ZONE_NORMAL << 0 * ZONES_SHIFT) \
|
||||
| (OPT_ZONE_DMA << __GFP_DMA * ZONES_SHIFT) \
|
||||
| (OPT_ZONE_DMA << __GFP_DMA * ZONES_SHIFT) \
|
||||
| (OPT_ZONE_HIGHMEM << __GFP_HIGHMEM * ZONES_SHIFT) \
|
||||
| (OPT_ZONE_DMA32 << __GFP_DMA32 * ZONES_SHIFT) \
|
||||
| (ZONE_NORMAL << __GFP_MOVABLE * ZONES_SHIFT) \
|
||||
@ -195,7 +197,7 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags)
|
||||
)
|
||||
|
||||
/*
|
||||
* GFP_ZONE_BAD is a bitmap for all combination of __GFP_DMA, __GFP_DMA32
|
||||
* GFP_ZONE_BAD is a bitmap for all combinations of __GFP_DMA, __GFP_DMA32
|
||||
* __GFP_HIGHMEM and __GFP_MOVABLE that are not permitted. One flag per
|
||||
* entry starting with bit 0. Bit is set if the combination is not
|
||||
* allowed.
|
||||
@ -318,10 +320,10 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask);
|
||||
void free_pages_exact(void *virt, size_t size);
|
||||
|
||||
#define __get_free_page(gfp_mask) \
|
||||
__get_free_pages((gfp_mask),0)
|
||||
__get_free_pages((gfp_mask), 0)
|
||||
|
||||
#define __get_dma_pages(gfp_mask, order) \
|
||||
__get_free_pages((gfp_mask) | GFP_DMA,(order))
|
||||
__get_free_pages((gfp_mask) | GFP_DMA, (order))
|
||||
|
||||
extern void __free_pages(struct page *page, unsigned int order);
|
||||
extern void free_pages(unsigned long addr, unsigned int order);
|
||||
|
@ -1,4 +1,3 @@
|
||||
#ifdef CONFIG_MSM_KGSL
|
||||
/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -464,355 +463,3 @@ int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
|
||||
#endif
|
||||
#endif
|
||||
#endif /* _MSM_KGSL_H */
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* (C) Copyright Advanced Micro Devices, Inc. 2002, 2007
|
||||
* Copyright (c) 2008-2009 QUALCOMM USA, INC.
|
||||
*
|
||||
* All source code in this file is licensed under the following license
|
||||
*
|
||||
* 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, you can find it at http://www.fsf.org
|
||||
*/
|
||||
#ifndef _MSM_KGSL_H
|
||||
#define _MSM_KGSL_H
|
||||
|
||||
/*context flags */
|
||||
#define KGSL_CONTEXT_SAVE_GMEM 1
|
||||
#define KGSL_CONTEXT_NO_GMEM_ALLOC 2
|
||||
|
||||
/* generic flag values */
|
||||
#define KGSL_FLAGS_NORMALMODE 0x00000000
|
||||
#define KGSL_FLAGS_SAFEMODE 0x00000001
|
||||
#define KGSL_FLAGS_INITIALIZED0 0x00000002
|
||||
#define KGSL_FLAGS_INITIALIZED 0x00000004
|
||||
#define KGSL_FLAGS_STARTED 0x00000008
|
||||
#define KGSL_FLAGS_ACTIVE 0x00000010
|
||||
#define KGSL_FLAGS_RESERVED0 0x00000020
|
||||
#define KGSL_FLAGS_RESERVED1 0x00000040
|
||||
#define KGSL_FLAGS_RESERVED2 0x00000080
|
||||
|
||||
/* device id */
|
||||
enum kgsl_deviceid {
|
||||
KGSL_DEVICE_ANY = 0x00000000,
|
||||
KGSL_DEVICE_YAMATO = 0x00000001,
|
||||
KGSL_DEVICE_G12 = 0x00000002,
|
||||
KGSL_DEVICE_MAX = 0x00000002
|
||||
};
|
||||
|
||||
struct kgsl_devinfo {
|
||||
|
||||
unsigned int device_id;
|
||||
/* chip revision id
|
||||
* coreid:8 majorrev:8 minorrev:8 patch:8
|
||||
*/
|
||||
unsigned int chip_id;
|
||||
unsigned int mmu_enabled;
|
||||
unsigned int gmem_gpubaseaddr;
|
||||
/* if gmem_hostbaseaddr is NULL, we would know its not mapped into
|
||||
* mmio space */
|
||||
unsigned int gmem_hostbaseaddr;
|
||||
unsigned int gmem_sizebytes;
|
||||
};
|
||||
|
||||
/* this structure defines the region of memory that can be mmap()ed from this
|
||||
driver. The timestamp fields are volatile because they are written by the
|
||||
GPU
|
||||
*/
|
||||
struct kgsl_devmemstore {
|
||||
volatile unsigned int soptimestamp;
|
||||
unsigned int sbz;
|
||||
volatile unsigned int eoptimestamp;
|
||||
unsigned int sbz2;
|
||||
volatile unsigned int ts_cmp_enable;
|
||||
unsigned int sbz3;
|
||||
volatile unsigned int ref_wait_ts;
|
||||
unsigned int sbz4;
|
||||
};
|
||||
|
||||
#define KGSL_DEVICE_MEMSTORE_OFFSET(field) \
|
||||
offsetof(struct kgsl_devmemstore, field)
|
||||
|
||||
|
||||
/* timestamp id*/
|
||||
enum kgsl_timestamp_type {
|
||||
KGSL_TIMESTAMP_CONSUMED = 0x00000001, /* start-of-pipeline timestamp */
|
||||
KGSL_TIMESTAMP_RETIRED = 0x00000002, /* end-of-pipeline timestamp*/
|
||||
KGSL_TIMESTAMP_MAX = 0x00000002,
|
||||
};
|
||||
|
||||
/* property types - used with kgsl_device_getproperty */
|
||||
enum kgsl_property_type {
|
||||
KGSL_PROP_DEVICE_INFO = 0x00000001,
|
||||
KGSL_PROP_DEVICE_SHADOW = 0x00000002,
|
||||
KGSL_PROP_DEVICE_POWER = 0x00000003,
|
||||
KGSL_PROP_SHMEM = 0x00000004,
|
||||
KGSL_PROP_SHMEM_APERTURES = 0x00000005,
|
||||
KGSL_PROP_MMU_ENABLE = 0x00000006,
|
||||
KGSL_PROP_INTERRUPT_WAITS = 0x00000007,
|
||||
};
|
||||
|
||||
struct kgsl_shadowprop {
|
||||
unsigned int gpuaddr;
|
||||
unsigned int size;
|
||||
unsigned int flags; /* contains KGSL_FLAGS_ values */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
struct kgsl_platform_data {
|
||||
unsigned int high_axi_2d;
|
||||
unsigned int high_axi_3d;
|
||||
unsigned int max_grp2d_freq;
|
||||
unsigned int min_grp2d_freq;
|
||||
int (*set_grp2d_async)(void);
|
||||
unsigned int max_grp3d_freq;
|
||||
unsigned int min_grp3d_freq;
|
||||
int (*set_grp3d_async)(void);
|
||||
};
|
||||
#endif
|
||||
/* ioctls */
|
||||
#define KGSL_IOC_TYPE 0x09
|
||||
|
||||
/* get misc info about the GPU
|
||||
type should be a value from enum kgsl_property_type
|
||||
value points to a structure that varies based on type
|
||||
sizebytes is sizeof() that structure
|
||||
for KGSL_PROP_DEVICE_INFO, use struct kgsl_devinfo
|
||||
this structure contaings hardware versioning info.
|
||||
for KGSL_PROP_DEVICE_SHADOW, use struct kgsl_shadowprop
|
||||
this is used to find mmap() offset and sizes for mapping
|
||||
struct kgsl_memstore into userspace.
|
||||
*/
|
||||
struct kgsl_device_getproperty {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int type;
|
||||
void *value;
|
||||
unsigned int sizebytes;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DEVICE_GETPROPERTY \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x2, struct kgsl_device_getproperty)
|
||||
|
||||
|
||||
/* read a GPU register.
|
||||
offsetwords it the 32 bit word offset from the beginning of the
|
||||
GPU register space.
|
||||
*/
|
||||
struct kgsl_device_regread {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int offsetwords;
|
||||
unsigned int value; /* output param */
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DEVICE_REGREAD \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x3, struct kgsl_device_regread)
|
||||
|
||||
|
||||
/* block until the GPU has executed past a given timestamp
|
||||
* timeout is in milliseconds.
|
||||
*/
|
||||
struct kgsl_device_waittimestamp {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int timestamp;
|
||||
unsigned int timeout;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DEVICE_WAITTIMESTAMP \
|
||||
_IOW(KGSL_IOC_TYPE, 0x6, struct kgsl_device_waittimestamp)
|
||||
|
||||
|
||||
/* issue indirect commands to the GPU.
|
||||
* drawctxt_id must have been created with IOCTL_KGSL_DRAWCTXT_CREATE
|
||||
* ibaddr and sizedwords must specify a subset of a buffer created
|
||||
* with IOCTL_KGSL_SHAREDMEM_FROM_PMEM
|
||||
* flags may be a mask of KGSL_CONTEXT_ values
|
||||
* timestamp is a returned counter value which can be passed to
|
||||
* other ioctls to determine when the commands have been executed by
|
||||
* the GPU.
|
||||
*/
|
||||
struct kgsl_ringbuffer_issueibcmds {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int drawctxt_id;
|
||||
unsigned int ibaddr;
|
||||
unsigned int sizedwords;
|
||||
unsigned int timestamp; /*output param */
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x10, struct kgsl_ringbuffer_issueibcmds)
|
||||
|
||||
/* read the most recently executed timestamp value
|
||||
* type should be a value from enum kgsl_timestamp_type
|
||||
*/
|
||||
struct kgsl_cmdstream_readtimestamp {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int type;
|
||||
unsigned int timestamp; /*output param */
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_CMDSTREAM_READTIMESTAMP \
|
||||
_IOR(KGSL_IOC_TYPE, 0x11, struct kgsl_cmdstream_readtimestamp)
|
||||
|
||||
/* free memory when the GPU reaches a given timestamp.
|
||||
* gpuaddr specify a memory region created by a
|
||||
* IOCTL_KGSL_SHAREDMEM_FROM_PMEM call
|
||||
* type should be a value from enum kgsl_timestamp_type
|
||||
*/
|
||||
struct kgsl_cmdstream_freememontimestamp {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int gpuaddr;
|
||||
unsigned int type;
|
||||
unsigned int timestamp;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP \
|
||||
_IOR(KGSL_IOC_TYPE, 0x12, struct kgsl_cmdstream_freememontimestamp)
|
||||
|
||||
/* create a draw context, which is used to preserve GPU state.
|
||||
* The flags field may contain a mask KGSL_CONTEXT_* values
|
||||
*/
|
||||
struct kgsl_drawctxt_create {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int flags;
|
||||
unsigned int drawctxt_id; /*output param */
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DRAWCTXT_CREATE \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create)
|
||||
|
||||
/* destroy a draw context */
|
||||
struct kgsl_drawctxt_destroy {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int drawctxt_id;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DRAWCTXT_DESTROY \
|
||||
_IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy)
|
||||
|
||||
/* add a block of pmem or fb into the GPU address space */
|
||||
struct kgsl_sharedmem_from_pmem {
|
||||
int pmem_fd;
|
||||
unsigned int gpuaddr; /*output param */
|
||||
unsigned int len;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_SHAREDMEM_FROM_PMEM \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x20, struct kgsl_sharedmem_from_pmem)
|
||||
|
||||
/* remove memory from the GPU's address space */
|
||||
struct kgsl_sharedmem_free {
|
||||
unsigned int gpuaddr;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_SHAREDMEM_FREE \
|
||||
_IOW(KGSL_IOC_TYPE, 0x21, struct kgsl_sharedmem_free)
|
||||
|
||||
struct kgsl_gmem_desc {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int pitch;
|
||||
};
|
||||
|
||||
struct kgsl_buffer_desc {
|
||||
void *hostptr;
|
||||
unsigned int gpuaddr;
|
||||
int size;
|
||||
unsigned int format;
|
||||
unsigned int pitch;
|
||||
unsigned int enabled;
|
||||
};
|
||||
|
||||
struct kgsl_bind_gmem_shadow {
|
||||
unsigned int drawctxt_id;
|
||||
struct kgsl_gmem_desc gmem_desc;
|
||||
unsigned int shadow_x;
|
||||
unsigned int shadow_y;
|
||||
struct kgsl_buffer_desc shadow_buffer;
|
||||
unsigned int buffer_id;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW \
|
||||
_IOW(KGSL_IOC_TYPE, 0x22, struct kgsl_bind_gmem_shadow)
|
||||
|
||||
/* add a block of memory into the GPU address space */
|
||||
struct kgsl_sharedmem_from_vmalloc {
|
||||
unsigned int gpuaddr; /*output param */
|
||||
unsigned int hostptr;
|
||||
/* If set from user space then will attempt to
|
||||
* allocate even if low watermark is crossed */
|
||||
int force_no_low_watermark;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x23, struct kgsl_sharedmem_from_vmalloc)
|
||||
|
||||
#define IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE \
|
||||
_IOW(KGSL_IOC_TYPE, 0x24, struct kgsl_sharedmem_free)
|
||||
|
||||
struct kgsl_drawctxt_set_bin_base_offset {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
unsigned int drawctxt_id;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DRAWCTXT_SET_BIN_BASE_OFFSET \
|
||||
_IOW(KGSL_IOC_TYPE, 0x25, struct kgsl_drawctxt_set_bin_base_offset)
|
||||
|
||||
enum kgsl_cmdwindow_type {
|
||||
KGSL_CMDWINDOW_MIN = 0x00000000,
|
||||
KGSL_CMDWINDOW_2D = 0x00000000,
|
||||
KGSL_CMDWINDOW_3D = 0x00000001, /* legacy */
|
||||
KGSL_CMDWINDOW_MMU = 0x00000002,
|
||||
KGSL_CMDWINDOW_ARBITER = 0x000000FF,
|
||||
KGSL_CMDWINDOW_MAX = 0x000000FF,
|
||||
};
|
||||
|
||||
/* write to the command window */
|
||||
struct kgsl_cmdwindow_write {
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
unsigned int device_id;
|
||||
#endif
|
||||
enum kgsl_cmdwindow_type target;
|
||||
unsigned int addr;
|
||||
unsigned int data;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_CMDWINDOW_WRITE \
|
||||
_IOW(KGSL_IOC_TYPE, 0x2e, struct kgsl_cmdwindow_write)
|
||||
|
||||
#endif /* _MSM_KGSL_H */
|
||||
#endif
|
||||
|
159
mm/ashmem.c
159
mm/ashmem.c
@ -29,6 +29,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/shmem_fs.h>
|
||||
#include <linux/ashmem.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#define ASHMEM_NAME_PREFIX "dev/ashmem/"
|
||||
#define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1)
|
||||
@ -45,6 +46,8 @@ struct ashmem_area {
|
||||
struct list_head unpinned_list; /* list of all ashmem areas */
|
||||
struct file *file; /* the shmem-based backing file */
|
||||
size_t size; /* size of the mapping, in bytes */
|
||||
unsigned long vm_start; /* Start address of vm_area
|
||||
* which maps this ashmem */
|
||||
unsigned long prot_mask; /* allowed prot bits, as vm_flags */
|
||||
};
|
||||
|
||||
@ -178,7 +181,7 @@ static int ashmem_open(struct inode *inode, struct file *file)
|
||||
struct ashmem_area *asma;
|
||||
int ret;
|
||||
|
||||
ret = nonseekable_open(inode, file);
|
||||
ret = generic_file_open(inode, file);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
@ -211,6 +214,75 @@ static int ashmem_release(struct inode *ignored, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ashmem_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct ashmem_area *asma = file->private_data;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&ashmem_mutex);
|
||||
|
||||
/* If size is not set, or set to 0, always return EOF. */
|
||||
if (asma->size == 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!asma->file) {
|
||||
ret = -EBADF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = asma->file->f_op->read(asma->file, buf, len, pos);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/** Update backing file pos, since f_ops->read() doesn't */
|
||||
asma->file->f_pos = *pos;
|
||||
|
||||
out:
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static loff_t ashmem_llseek(struct file *file, loff_t offset, int origin)
|
||||
{
|
||||
struct ashmem_area *asma = file->private_data;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ashmem_mutex);
|
||||
|
||||
if (asma->size == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!asma->file) {
|
||||
ret = -EBADF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = asma->file->f_op->llseek(asma->file, offset, origin);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/** Copy f_pos from backing file, since f_ops->llseek() sets it */
|
||||
file->f_pos = asma->file->f_pos;
|
||||
|
||||
out:
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
calc_vm_may_flags(unsigned long prot)
|
||||
{
|
||||
return _calc_vm_trans(prot, PROT_READ, VM_MAYREAD ) |
|
||||
_calc_vm_trans(prot, PROT_WRITE, VM_MAYWRITE) |
|
||||
_calc_vm_trans(prot, PROT_EXEC, VM_MAYEXEC);
|
||||
}
|
||||
|
||||
static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct ashmem_area *asma = file->private_data;
|
||||
@ -225,10 +297,12 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
}
|
||||
|
||||
/* requested protection bits must match our allowed protection mask */
|
||||
if (unlikely((vma->vm_flags & ~asma->prot_mask) & PROT_MASK)) {
|
||||
if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask)) &
|
||||
calc_vm_prot_bits(PROT_MASK))) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
vma->vm_flags &= ~calc_vm_may_flags(~asma->prot_mask);
|
||||
|
||||
if (!asma->file) {
|
||||
char *name = ASHMEM_NAME_DEF;
|
||||
@ -255,6 +329,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
vma->vm_file = asma->file;
|
||||
}
|
||||
vma->vm_flags |= VM_CAN_NONLINEAR;
|
||||
asma->vm_start = vma->vm_start;
|
||||
|
||||
out:
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
@ -286,11 +361,7 @@ static int ashmem_shrink(struct shrinker *s, int nr_to_scan, gfp_t gfp_mask)
|
||||
if (!nr_to_scan)
|
||||
return lru_count;
|
||||
|
||||
/* If our mutex is held, we are recursing into ourselves, so bail out */
|
||||
if (!mutex_trylock(&ashmem_mutex)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock(&ashmem_mutex);
|
||||
list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
|
||||
struct inode *inode = range->asma->file->f_dentry->d_inode;
|
||||
loff_t start = range->pgstart * PAGE_SIZE;
|
||||
@ -559,6 +630,69 @@ static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OUTER_CACHE
|
||||
static unsigned int virtaddr_to_physaddr(unsigned int virtaddr)
|
||||
{
|
||||
unsigned int physaddr = 0;
|
||||
pgd_t *pgd_ptr = NULL;
|
||||
pmd_t *pmd_ptr = NULL;
|
||||
pte_t *pte_ptr = NULL, pte;
|
||||
|
||||
spin_lock(¤t->mm->page_table_lock);
|
||||
pgd_ptr = pgd_offset(current->mm, virtaddr);
|
||||
if (pgd_none(*pgd) || pgd_bad(*pgd)) {
|
||||
pr_err("Failed to convert virtaddr %x to pgd_ptr\n",
|
||||
virtaddr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pmd_ptr = pmd_offset(pgd_ptr, virtaddr);
|
||||
if (pmd_none(*pmd_ptr) || pmd_bad(*pmd_ptr)) {
|
||||
pr_err("Failed to convert pgd_ptr %p to pmd_ptr\n",
|
||||
(void *)pgd_ptr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pte_ptr = pte_offset_map(pmd_ptr, virtaddr);
|
||||
if (!pte_ptr) {
|
||||
pr_err("Failed to convert pmd_ptr %p to pte_ptr\n",
|
||||
(void *)pmd_ptr);
|
||||
goto done;
|
||||
}
|
||||
pte = *pte_ptr;
|
||||
physaddr = pte_pfn(pte);
|
||||
pte_unmap(pte_ptr);
|
||||
done:
|
||||
spin_unlock(¤t->mm->page_table_lock);
|
||||
physaddr <<= PAGE_SHIFT;
|
||||
return physaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ashmem_cache_op(struct ashmem_area *asma,
|
||||
void (*cache_func)(unsigned long vstart, unsigned long length,
|
||||
unsigned long pstart))
|
||||
{
|
||||
#ifdef CONFIG_OUTER_CACHE
|
||||
unsigned long vaddr;
|
||||
#endif
|
||||
mutex_lock(&ashmem_mutex);
|
||||
#ifndef CONFIG_OUTER_CACHE
|
||||
cache_func(asma->vm_start, asma->size, 0);
|
||||
#else
|
||||
for (vaddr = asma->vm_start; vaddr < asma->vm_start + asma->size;
|
||||
vaddr += PAGE_SIZE) {
|
||||
unsigned long physaddr;
|
||||
physaddr = virtaddr_to_physaddr(vaddr);
|
||||
if (!physaddr)
|
||||
return -EINVAL;
|
||||
cache_func(vaddr, PAGE_SIZE, physaddr);
|
||||
}
|
||||
#endif
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct ashmem_area *asma = file->private_data;
|
||||
@ -599,6 +733,15 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
ashmem_shrink(&ashmem_shrinker, ret, GFP_KERNEL);
|
||||
}
|
||||
break;
|
||||
case ASHMEM_CACHE_FLUSH_RANGE:
|
||||
ret = ashmem_cache_op(asma, &clean_and_invalidate_caches);
|
||||
break;
|
||||
case ASHMEM_CACHE_CLEAN_RANGE:
|
||||
ret = ashmem_cache_op(asma, &clean_caches);
|
||||
break;
|
||||
case ASHMEM_CACHE_INV_RANGE:
|
||||
ret = ashmem_cache_op(asma, &invalidate_caches);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -661,6 +804,8 @@ static struct file_operations ashmem_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ashmem_open,
|
||||
.release = ashmem_release,
|
||||
.read = ashmem_read,
|
||||
.llseek = ashmem_llseek,
|
||||
.mmap = ashmem_mmap,
|
||||
.unlocked_ioctl = ashmem_ioctl,
|
||||
.compat_ioctl = ashmem_ioctl,
|
||||
|
Loading…
Reference in New Issue
Block a user