Backport android and MSM parts from caf

This commit is contained in:
Shantanu Gupta 2012-05-12 16:56:17 +05:30 committed by milaq
parent 9ab858cdb2
commit 0a0f12cf99
17 changed files with 664 additions and 2208 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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(&current->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(&current->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,