Merge branch 'sh/dmaengine'

Conflicts:
	arch/sh/drivers/dma/dma-sh.c
This commit is contained in:
Paul Mundt 2010-02-08 11:34:03 +09:00
commit 2e18e04798
70 changed files with 922 additions and 562 deletions

View file

@ -20,7 +20,7 @@ Description:
lsm: [[subj_user=] [subj_role=] [subj_type=]
[obj_user=] [obj_role=] [obj_type=]]
base: func:= [BPRM_CHECK][FILE_MMAP][INODE_PERMISSION]
base: func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK]
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
fsmagic:= hex value
uid:= decimal value
@ -40,11 +40,11 @@ Description:
measure func=BPRM_CHECK
measure func=FILE_MMAP mask=MAY_EXEC
measure func=INODE_PERM mask=MAY_READ uid=0
measure func=FILE_CHECK mask=MAY_READ uid=0
The default policy measures all executables in bprm_check,
all files mmapped executable in file_mmap, and all files
open for read by root in inode_permission.
open for read by root in do_filp_open.
Examples of LSM specific definitions:
@ -54,8 +54,8 @@ Description:
dont_measure obj_type=var_log_t
dont_measure obj_type=auditd_log_t
measure subj_user=system_u func=INODE_PERM mask=MAY_READ
measure subj_role=system_r func=INODE_PERM mask=MAY_READ
measure subj_user=system_u func=FILE_CHECK mask=MAY_READ
measure subj_role=system_r func=FILE_CHECK mask=MAY_READ
Smack:
measure subj_user=_ func=INODE_PERM mask=MAY_READ
measure subj_user=_ func=FILE_CHECK mask=MAY_READ

View file

@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 33
EXTRAVERSION = -rc6
EXTRAVERSION = -rc7
NAME = Man-Eating Seals of Antiquity
# *DOCUMENTATION*

View file

@ -52,11 +52,14 @@ static inline unsigned int get_dmte_irq(unsigned int chan)
*
* iterations to complete the transfer.
*/
static unsigned int ts_shift[] = TS_SHIFT;
static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
{
u32 chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT];
return ts_shift[cnt];
}
/*

View file

@ -64,8 +64,10 @@ static int dmte_irq_map[] __maybe_unused = {
#define ACK_L 0x00010000
#define DM_INC 0x00004000
#define DM_DEC 0x00008000
#define DM_FIX 0x0000c000
#define SM_INC 0x00001000
#define SM_DEC 0x00002000
#define SM_FIX 0x00003000
#define RS_IN 0x00000200
#define RS_OUT 0x00000300
#define TS_BLK 0x00000040
@ -83,7 +85,7 @@ static int dmte_irq_map[] __maybe_unused = {
* Define the default configuration for dual address memory-memory transfer.
* The 0x400 value represents auto-request, external->external.
*/
#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32)
#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_INDEX2VAL(XMIT_SZ_32BIT))
/* DMA base address */
static u32 dma_base_addr[] __maybe_unused = {
@ -123,10 +125,47 @@ static u32 dma_base_addr[] __maybe_unused = {
*/
#define SHDMA_MIX_IRQ (1 << 1)
#define SHDMA_DMAOR1 (1 << 2)
#define SHDMA_DMAE1 (1 << 3)
#define SHDMA_DMAE1 (1 << 3)
enum sh_dmae_slave_chan_id {
SHDMA_SLAVE_SCIF0_TX,
SHDMA_SLAVE_SCIF0_RX,
SHDMA_SLAVE_SCIF1_TX,
SHDMA_SLAVE_SCIF1_RX,
SHDMA_SLAVE_SCIF2_TX,
SHDMA_SLAVE_SCIF2_RX,
SHDMA_SLAVE_SCIF3_TX,
SHDMA_SLAVE_SCIF3_RX,
SHDMA_SLAVE_SCIF4_TX,
SHDMA_SLAVE_SCIF4_RX,
SHDMA_SLAVE_SCIF5_TX,
SHDMA_SLAVE_SCIF5_RX,
SHDMA_SLAVE_SIUA_TX,
SHDMA_SLAVE_SIUA_RX,
SHDMA_SLAVE_SIUB_TX,
SHDMA_SLAVE_SIUB_RX,
SHDMA_SLAVE_NUMBER, /* Must stay last */
};
struct sh_dmae_slave_config {
enum sh_dmae_slave_chan_id slave_id;
dma_addr_t addr;
u32 chcr;
char mid_rid;
};
struct sh_dmae_pdata {
unsigned int mode;
struct sh_dmae_slave_config *config;
int config_num;
};
struct device;
struct sh_dmae_slave {
enum sh_dmae_slave_chan_id slave_id; /* Set by the platform */
struct device *dma_dev; /* Set by the platform */
struct sh_dmae_slave_config *config; /* Set by the driver */
};
#endif /* __DMA_SH_H */

View file

@ -20,8 +20,10 @@
#define TS_32 0x00000010
#define TS_128 0x00000018
#define CHCR_TS_MASK 0x18
#define CHCR_TS_SHIFT 3
#define CHCR_TS_LOW_MASK 0x18
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0
#define DMAOR_INIT DMAOR_DME
@ -36,11 +38,13 @@ enum {
XMIT_SZ_128BIT,
};
static unsigned int ts_shift[] __maybe_unused = {
[XMIT_SZ_8BIT] = 0,
[XMIT_SZ_16BIT] = 1,
[XMIT_SZ_32BIT] = 2,
[XMIT_SZ_128BIT] = 4,
};
#define TS_SHIFT { \
[XMIT_SZ_8BIT] = 0, \
[XMIT_SZ_16BIT] = 1, \
[XMIT_SZ_32BIT] = 2, \
[XMIT_SZ_128BIT] = 4, \
}
#define TS_INDEX2VAL(i) (((i) & 3) << CHCR_TS_LOW_SHIFT)
#endif /* __ASM_CPU_SH3_DMA_H */

View file

@ -2,22 +2,38 @@
#define __ASM_SH_CPU_SH4_DMA_SH7780_H
#if defined(CONFIG_CPU_SUBTYPE_SH7343) || \
defined(CONFIG_CPU_SUBTYPE_SH7722) || \
defined(CONFIG_CPU_SUBTYPE_SH7730)
#define DMTE0_IRQ 48
#define DMTE4_IRQ 76
#define DMAE0_IRQ 78 /* DMA Error IRQ*/
#define SH_DMAC_BASE0 0xFE008020
#define SH_DMARS_BASE 0xFE009000
#define SH_DMARS_BASE0 0xFE009000
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0
#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
#define DMTE0_IRQ 48
#define DMTE4_IRQ 76
#define DMAE0_IRQ 78 /* DMA Error IRQ*/
#define SH_DMAC_BASE0 0xFE008020
#define SH_DMARS_BASE0 0xFE009000
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0x00300000
#define CHCR_TS_HIGH_SHIFT 20
#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
defined(CONFIG_CPU_SUBTYPE_SH7764)
#define DMTE0_IRQ 34
#define DMTE4_IRQ 44
#define DMAE0_IRQ 38
#define SH_DMAC_BASE0 0xFF608020
#define SH_DMARS_BASE 0xFF609000
#elif defined(CONFIG_CPU_SUBTYPE_SH7723) || \
defined(CONFIG_CPU_SUBTYPE_SH7724)
#define SH_DMARS_BASE0 0xFF609000
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0
#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
#define DMTE0_IRQ 48 /* DMAC0A*/
#define DMTE4_IRQ 76 /* DMAC0B */
#define DMTE6_IRQ 40
@ -29,7 +45,29 @@
#define DMAE1_IRQ 74 /* DMA Error IRQ*/
#define SH_DMAC_BASE0 0xFE008020
#define SH_DMAC_BASE1 0xFDC08020
#define SH_DMARS_BASE 0xFDC09000
#define SH_DMARS_BASE0 0xFDC09000
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0
#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
#define DMTE0_IRQ 48 /* DMAC0A*/
#define DMTE4_IRQ 76 /* DMAC0B */
#define DMTE6_IRQ 40
#define DMTE8_IRQ 42 /* DMAC1A */
#define DMTE9_IRQ 43
#define DMTE10_IRQ 72 /* DMAC1B */
#define DMTE11_IRQ 73
#define DMAE0_IRQ 78 /* DMA Error IRQ*/
#define DMAE1_IRQ 74 /* DMA Error IRQ*/
#define SH_DMAC_BASE0 0xFE008020
#define SH_DMAC_BASE1 0xFDC08020
#define SH_DMARS_BASE0 0xFE009000
#define SH_DMARS_BASE1 0xFDC09000
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0x00600000
#define CHCR_TS_HIGH_SHIFT 21
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
#define DMTE0_IRQ 34
#define DMTE4_IRQ 44
@ -41,7 +79,11 @@
#define DMAE0_IRQ 38 /* DMA Error IRQ */
#define SH_DMAC_BASE0 0xFC808020
#define SH_DMAC_BASE1 0xFC818020
#define SH_DMARS_BASE 0xFC809000
#define SH_DMARS_BASE0 0xFC809000
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0
#else /* SH7785 */
#define DMTE0_IRQ 33
#define DMTE4_IRQ 37
@ -54,18 +96,17 @@
#define DMAE1_IRQ 58 /* DMA Error IRQ1 */
#define SH_DMAC_BASE0 0xFC808020
#define SH_DMAC_BASE1 0xFCC08020
#define SH_DMARS_BASE 0xFC809000
#define SH_DMARS_BASE0 0xFC809000
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0
#endif
#define REQ_HE 0x000000C0
#define REQ_H 0x00000080
#define REQ_LE 0x00000040
#define TM_BURST 0x0000020
#define TS_8 0x00000000
#define TS_16 0x00000008
#define TS_32 0x00000010
#define TS_16BLK 0x00000018
#define TS_32BLK 0x00100000
#define REQ_HE 0x000000C0
#define REQ_H 0x00000080
#define REQ_LE 0x00000040
#define TM_BURST 0x00000020
/*
* The SuperH DMAC supports a number of transmit sizes, we list them here,
@ -74,22 +115,31 @@
* Defaults to a 64-bit transfer size.
*/
enum {
XMIT_SZ_8BIT,
XMIT_SZ_16BIT,
XMIT_SZ_32BIT,
XMIT_SZ_128BIT,
XMIT_SZ_256BIT,
XMIT_SZ_8BIT = 0,
XMIT_SZ_16BIT = 1,
XMIT_SZ_32BIT = 2,
XMIT_SZ_64BIT = 7,
XMIT_SZ_128BIT = 3,
XMIT_SZ_256BIT = 4,
XMIT_SZ_128BIT_BLK = 0xb,
XMIT_SZ_256BIT_BLK = 0xc,
};
/*
* The DMA count is defined as the number of bytes to transfer.
*/
static unsigned int ts_shift[] __maybe_unused = {
[XMIT_SZ_8BIT] = 0,
[XMIT_SZ_16BIT] = 1,
[XMIT_SZ_32BIT] = 2,
[XMIT_SZ_128BIT] = 4,
[XMIT_SZ_256BIT] = 5,
};
#define TS_SHIFT { \
[XMIT_SZ_8BIT] = 0, \
[XMIT_SZ_16BIT] = 1, \
[XMIT_SZ_32BIT] = 2, \
[XMIT_SZ_64BIT] = 3, \
[XMIT_SZ_128BIT] = 4, \
[XMIT_SZ_256BIT] = 5, \
[XMIT_SZ_128BIT_BLK] = 4, \
[XMIT_SZ_256BIT_BLK] = 5, \
}
#define TS_INDEX2VAL(i) ((((i) & 3) << CHCR_TS_LOW_SHIFT) | \
((((i) >> 2) & 3) << CHCR_TS_HIGH_SHIFT))
#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */

View file

@ -6,8 +6,6 @@
#ifdef CONFIG_CPU_SH4A
#define DMAOR_INIT (DMAOR_DME)
#define CHCR_TS_MASK 0x18
#define CHCR_TS_SHIFT 3
#include <cpu/dma-sh4a.h>
#else /* CONFIG_CPU_SH4A */
@ -29,8 +27,10 @@
#define TS_32 0x00000030
#define TS_64 0x00000000
#define CHCR_TS_MASK 0x70
#define CHCR_TS_SHIFT 4
#define CHCR_TS_LOW_MASK 0x70
#define CHCR_TS_LOW_SHIFT 4
#define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0
#define DMAOR_COD 0x00000008
@ -41,23 +41,26 @@
* Defaults to a 64-bit transfer size.
*/
enum {
XMIT_SZ_64BIT,
XMIT_SZ_8BIT,
XMIT_SZ_16BIT,
XMIT_SZ_32BIT,
XMIT_SZ_256BIT,
XMIT_SZ_8BIT = 1,
XMIT_SZ_16BIT = 2,
XMIT_SZ_32BIT = 3,
XMIT_SZ_64BIT = 0,
XMIT_SZ_256BIT = 4,
};
/*
* The DMA count is defined as the number of bytes to transfer.
*/
static unsigned int ts_shift[] __maybe_unused = {
[XMIT_SZ_64BIT] = 3,
[XMIT_SZ_8BIT] = 0,
[XMIT_SZ_16BIT] = 1,
[XMIT_SZ_32BIT] = 2,
[XMIT_SZ_256BIT] = 5,
};
#define TS_SHIFT { \
[XMIT_SZ_8BIT] = 0, \
[XMIT_SZ_16BIT] = 1, \
[XMIT_SZ_32BIT] = 2, \
[XMIT_SZ_64BIT] = 3, \
[XMIT_SZ_256BIT] = 5, \
}
#define TS_INDEX2VAL(i) (((i) & 7) << CHCR_TS_LOW_SHIFT)
#endif
#endif /* __ASM_CPU_SH4_DMA_H */

View file

@ -2868,6 +2868,21 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
},
.driver_data = "F.23", /* cutoff BIOS version */
},
/*
* Acer eMachines G725 has the same problem. BIOS
* V1.03 is known to be broken. V3.04 is known to
* work. Inbetween, there are V1.06, V2.06 and V3.03
* that we don't have much idea about. For now,
* blacklist anything older than V3.04.
*/
{
.ident = "G725",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
},
.driver_data = "V3.04", /* cutoff BIOS version */
},
{ } /* terminate list */
};
const struct dmi_system_id *dmi = dmi_first_match(sysids);

View file

@ -2875,7 +2875,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
* write indication (used for PIO/DMA setup), result TF is
* copied back and we don't whine too much about its failure.
*/
tf->flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
if (scmd->sc_data_direction == DMA_TO_DEVICE)
tf->flags |= ATA_TFLAG_WRITE;

View file

@ -893,6 +893,9 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
do_write);
}
if (!do_write)
flush_dcache_page(page);
qc->curbytes += qc->sect_size;
qc->cursg_ofs += qc->sect_size;

View file

@ -1951,8 +1951,10 @@ static int tty_fasync(int fd, struct file *filp, int on)
pid = task_pid(current);
type = PIDTYPE_PID;
}
retval = __f_setown(filp, pid, type, 0);
get_pid(pid);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
retval = __f_setown(filp, pid, type, 0);
put_pid(pid);
if (retval)
goto out;
} else {

View file

@ -48,23 +48,20 @@ enum sh_dmae_desc_status {
*/
#define RS_DEFAULT (RS_DUAL)
/* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)];
static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
#define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id])
static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
{
ctrl_outl(data, (SH_DMAC_CHAN_BASE(sh_dc->id) + reg));
ctrl_outl(data, SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
}
static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
{
return ctrl_inl((SH_DMAC_CHAN_BASE(sh_dc->id) + reg));
}
static void dmae_init(struct sh_dmae_chan *sh_chan)
{
u32 chcr = RS_DEFAULT; /* default is DUAL mode */
sh_dmae_writel(sh_chan, chcr, CHCR);
return ctrl_inl(SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
}
/*
@ -95,27 +92,30 @@ static int sh_dmae_rst(int id)
return 0;
}
static int dmae_is_busy(struct sh_dmae_chan *sh_chan)
static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
{
u32 chcr = sh_dmae_readl(sh_chan, CHCR);
if (chcr & CHCR_DE) {
if (!(chcr & CHCR_TE))
return -EBUSY; /* working */
}
return 0; /* waiting */
if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE)
return true; /* working */
return false; /* waiting */
}
static inline unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan)
static unsigned int ts_shift[] = TS_SHIFT;
static inline unsigned int calc_xmit_shift(u32 chcr)
{
u32 chcr = sh_dmae_readl(sh_chan, CHCR);
return ts_shift[(chcr & CHCR_TS_MASK) >> CHCR_TS_SHIFT];
int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
return ts_shift[cnt];
}
static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
{
sh_dmae_writel(sh_chan, hw->sar, SAR);
sh_dmae_writel(sh_chan, hw->dar, DAR);
sh_dmae_writel(sh_chan, hw->tcr >> calc_xmit_shift(sh_chan), TCR);
sh_dmae_writel(sh_chan, hw->tcr >> sh_chan->xmit_shift, TCR);
}
static void dmae_start(struct sh_dmae_chan *sh_chan)
@ -123,7 +123,7 @@ static void dmae_start(struct sh_dmae_chan *sh_chan)
u32 chcr = sh_dmae_readl(sh_chan, CHCR);
chcr |= CHCR_DE | CHCR_IE;
sh_dmae_writel(sh_chan, chcr, CHCR);
sh_dmae_writel(sh_chan, chcr & ~CHCR_TE, CHCR);
}
static void dmae_halt(struct sh_dmae_chan *sh_chan)
@ -134,55 +134,50 @@ static void dmae_halt(struct sh_dmae_chan *sh_chan)
sh_dmae_writel(sh_chan, chcr, CHCR);
}
static void dmae_init(struct sh_dmae_chan *sh_chan)
{
u32 chcr = RS_DEFAULT; /* default is DUAL mode */
sh_chan->xmit_shift = calc_xmit_shift(chcr);
sh_dmae_writel(sh_chan, chcr, CHCR);
}
static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
{
int ret = dmae_is_busy(sh_chan);
/* When DMA was working, can not set data to CHCR */
if (ret)
return ret;
if (dmae_is_busy(sh_chan))
return -EBUSY;
sh_chan->xmit_shift = calc_xmit_shift(val);
sh_dmae_writel(sh_chan, val, CHCR);
return 0;
}
#define DMARS1_ADDR 0x04
#define DMARS2_ADDR 0x08
#define DMARS_SHIFT 8
#define DMARS_CHAN_MSK 0x01
#define DMARS_SHIFT 8
#define DMARS_CHAN_MSK 0x01
static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
{
u32 addr;
int shift = 0;
int ret = dmae_is_busy(sh_chan);
if (ret)
return ret;
if (dmae_is_busy(sh_chan))
return -EBUSY;
if (sh_chan->id & DMARS_CHAN_MSK)
shift = DMARS_SHIFT;
switch (sh_chan->id) {
/* DMARS0 */
case 0:
case 1:
addr = SH_DMARS_BASE;
break;
/* DMARS1 */
case 2:
case 3:
addr = (SH_DMARS_BASE + DMARS1_ADDR);
break;
/* DMARS2 */
case 4:
case 5:
addr = (SH_DMARS_BASE + DMARS2_ADDR);
break;
default:
if (sh_chan->id < 6)
/* DMA0RS0 - DMA0RS2 */
addr = SH_DMARS_BASE0 + (sh_chan->id / 2) * 4;
#ifdef SH_DMARS_BASE1
else if (sh_chan->id < 12)
/* DMA1RS0 - DMA1RS2 */
addr = SH_DMARS_BASE1 + ((sh_chan->id - 6) / 2) * 4;
#endif
else
return -EINVAL;
}
ctrl_outw((val << shift) |
(ctrl_inw(addr) & (shift ? 0xFF00 : 0x00FF)),
addr);
ctrl_outw((val << shift) | (ctrl_inw(addr) & (0xFF00 >> shift)), addr);
return 0;
}
@ -250,10 +245,53 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
return NULL;
}
static struct sh_dmae_slave_config *sh_dmae_find_slave(
struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id)
{
struct dma_device *dma_dev = sh_chan->common.device;
struct sh_dmae_device *shdev = container_of(dma_dev,
struct sh_dmae_device, common);
struct sh_dmae_pdata *pdata = &shdev->pdata;
int i;
if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER)
return NULL;
for (i = 0; i < pdata->config_num; i++)
if (pdata->config[i].slave_id == slave_id)
return pdata->config + i;
return NULL;
}
static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
{
struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
struct sh_desc *desc;
struct sh_dmae_slave *param = chan->private;
/*
* This relies on the guarantee from dmaengine that alloc_chan_resources
* never runs concurrently with itself or free_chan_resources.
*/
if (param) {
struct sh_dmae_slave_config *cfg;
cfg = sh_dmae_find_slave(sh_chan, param->slave_id);
if (!cfg)
return -EINVAL;
if (test_and_set_bit(param->slave_id, sh_dmae_slave_used))
return -EBUSY;
param->config = cfg;
dmae_set_dmars(sh_chan, cfg->mid_rid);
dmae_set_chcr(sh_chan, cfg->chcr);
} else {
if ((sh_dmae_readl(sh_chan, CHCR) & 0x700) != 0x400)
dmae_set_chcr(sh_chan, RS_DEFAULT);
}
spin_lock_bh(&sh_chan->desc_lock);
while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
@ -286,10 +324,18 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
struct sh_desc *desc, *_desc;
LIST_HEAD(list);
dmae_halt(sh_chan);
/* Prepared and not submitted descriptors can still be on the queue */
if (!list_empty(&sh_chan->ld_queue))
sh_dmae_chan_ld_cleanup(sh_chan, true);
if (chan->private) {
/* The caller is holding dma_list_mutex */
struct sh_dmae_slave *param = chan->private;
clear_bit(param->slave_id, sh_dmae_slave_used);
}
spin_lock_bh(&sh_chan->desc_lock);
list_splice_init(&sh_chan->ld_free, &list);
@ -301,23 +347,97 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
kfree(desc);
}
static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
size_t len, unsigned long flags)
/**
* sh_dmae_add_desc - get, set up and return one transfer descriptor
* @sh_chan: DMA channel
* @flags: DMA transfer flags
* @dest: destination DMA address, incremented when direction equals
* DMA_FROM_DEVICE or DMA_BIDIRECTIONAL
* @src: source DMA address, incremented when direction equals
* DMA_TO_DEVICE or DMA_BIDIRECTIONAL
* @len: DMA transfer length
* @first: if NULL, set to the current descriptor and cookie set to -EBUSY
* @direction: needed for slave DMA to decide which address to keep constant,
* equals DMA_BIDIRECTIONAL for MEMCPY
* Returns 0 or an error
* Locks: called with desc_lock held
*/
static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
struct sh_desc **first, enum dma_data_direction direction)
{
struct sh_dmae_chan *sh_chan;
struct sh_desc *first = NULL, *prev = NULL, *new;
struct sh_desc *new;
size_t copy_size;
if (!*len)
return NULL;
/* Allocate the link descriptor from the free list */
new = sh_dmae_get_desc(sh_chan);
if (!new) {
dev_err(sh_chan->dev, "No free link descriptor available\n");
return NULL;
}
copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1);
new->hw.sar = *src;
new->hw.dar = *dest;
new->hw.tcr = copy_size;
if (!*first) {
/* First desc */
new->async_tx.cookie = -EBUSY;
*first = new;
} else {
/* Other desc - invisible to the user */
new->async_tx.cookie = -EINVAL;
}
dev_dbg(sh_chan->dev,
"chaining (%u/%u)@%x -> %x with %p, cookie %d, shift %d\n",
copy_size, *len, *src, *dest, &new->async_tx,
new->async_tx.cookie, sh_chan->xmit_shift);
new->mark = DESC_PREPARED;
new->async_tx.flags = flags;
new->direction = direction;
*len -= copy_size;
if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE)
*src += copy_size;
if (direction == DMA_BIDIRECTIONAL || direction == DMA_FROM_DEVICE)
*dest += copy_size;
return new;
}
/*
* sh_dmae_prep_sg - prepare transfer descriptors from an SG list
*
* Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also
* converted to scatter-gather to guarantee consistent locking and a correct
* list manipulation. For slave DMA direction carries the usual meaning, and,
* logically, the SG list is RAM and the addr variable contains slave address,
* e.g., the FIFO I/O register. For MEMCPY direction equals DMA_BIDIRECTIONAL
* and the SG list contains only one element and points at the source buffer.
*/
static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan,
struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
enum dma_data_direction direction, unsigned long flags)
{
struct scatterlist *sg;
struct sh_desc *first = NULL, *new = NULL /* compiler... */;
LIST_HEAD(tx_list);
int chunks = (len + SH_DMA_TCR_MAX) / (SH_DMA_TCR_MAX + 1);
int chunks = 0;
int i;
if (!chan)
if (!sg_len)
return NULL;
if (!len)
return NULL;
sh_chan = to_sh_chan(chan);
for_each_sg(sgl, sg, sg_len, i)
chunks += (sg_dma_len(sg) + SH_DMA_TCR_MAX) /
(SH_DMA_TCR_MAX + 1);
/* Have to lock the whole loop to protect against concurrent release */
spin_lock_bh(&sh_chan->desc_lock);
@ -333,49 +453,32 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
* only during this function, then they are immediately spliced
* back onto the free list in form of a chain
*/
do {
/* Allocate the link descriptor from the free list */
new = sh_dmae_get_desc(sh_chan);
if (!new) {
dev_err(sh_chan->dev,
"No free memory for link descriptor\n");
list_for_each_entry(new, &tx_list, node)
new->mark = DESC_IDLE;
list_splice(&tx_list, &sh_chan->ld_free);
spin_unlock_bh(&sh_chan->desc_lock);
return NULL;
}
for_each_sg(sgl, sg, sg_len, i) {
dma_addr_t sg_addr = sg_dma_address(sg);
size_t len = sg_dma_len(sg);
copy_size = min(len, (size_t)SH_DMA_TCR_MAX + 1);
if (!len)
goto err_get_desc;
new->hw.sar = dma_src;
new->hw.dar = dma_dest;
new->hw.tcr = copy_size;
if (!first) {
/* First desc */
new->async_tx.cookie = -EBUSY;
first = new;
} else {
/* Other desc - invisible to the user */
new->async_tx.cookie = -EINVAL;
}
do {
dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n",
i, sg, len, (unsigned long long)sg_addr);
dev_dbg(sh_chan->dev,
"chaining %u of %u with %p, dst %x, cookie %d\n",
copy_size, len, &new->async_tx, dma_dest,
new->async_tx.cookie);
if (direction == DMA_FROM_DEVICE)
new = sh_dmae_add_desc(sh_chan, flags,
&sg_addr, addr, &len, &first,
direction);
else
new = sh_dmae_add_desc(sh_chan, flags,
addr, &sg_addr, &len, &first,
direction);
if (!new)
goto err_get_desc;
new->mark = DESC_PREPARED;
new->async_tx.flags = flags;
new->chunks = chunks--;
prev = new;
len -= copy_size;
dma_src += copy_size;
dma_dest += copy_size;
/* Insert the link descriptor to the LD ring */
list_add_tail(&new->node, &tx_list);
} while (len);
new->chunks = chunks--;
list_add_tail(&new->node, &tx_list);
} while (len);
}
if (new != first)
new->async_tx.cookie = -ENOSPC;
@ -386,6 +489,77 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
spin_unlock_bh(&sh_chan->desc_lock);
return &first->async_tx;
err_get_desc:
list_for_each_entry(new, &tx_list, node)
new->mark = DESC_IDLE;
list_splice(&tx_list, &sh_chan->ld_free);
spin_unlock_bh(&sh_chan->desc_lock);
return NULL;
}
static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
size_t len, unsigned long flags)
{
struct sh_dmae_chan *sh_chan;
struct scatterlist sg;
if (!chan || !len)
return NULL;
chan->private = NULL;
sh_chan = to_sh_chan(chan);
sg_init_table(&sg, 1);
sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len,
offset_in_page(dma_src));
sg_dma_address(&sg) = dma_src;
sg_dma_len(&sg) = len;
return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_BIDIRECTIONAL,
flags);
}
static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
enum dma_data_direction direction, unsigned long flags)
{
struct sh_dmae_slave *param;
struct sh_dmae_chan *sh_chan;
if (!chan)
return NULL;
sh_chan = to_sh_chan(chan);
param = chan->private;
/* Someone calling slave DMA on a public channel? */
if (!param || !sg_len) {
dev_warn(sh_chan->dev, "%s: bad parameter: %p, %d, %d\n",
__func__, param, sg_len, param ? param->slave_id : -1);
return NULL;
}
/*
* if (param != NULL), this is a successfully requested slave channel,
* therefore param->config != NULL too.
*/
return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &param->config->addr,
direction, flags);
}
static void sh_dmae_terminate_all(struct dma_chan *chan)
{
struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
if (!chan)
return;
sh_dmae_chan_ld_cleanup(sh_chan, true);
}
static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
@ -419,7 +593,11 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
cookie = tx->cookie;
if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
BUG_ON(sh_chan->completed_cookie != desc->cookie - 1);
if (sh_chan->completed_cookie != desc->cookie - 1)
dev_dbg(sh_chan->dev,
"Completing cookie %d, expected %d\n",
desc->cookie,
sh_chan->completed_cookie + 1);
sh_chan->completed_cookie = desc->cookie;
}
@ -492,7 +670,7 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
return;
}
/* Find the first un-transfer desciptor */
/* Find the first not transferred desciptor */
list_for_each_entry(sd, &sh_chan->ld_queue, node)
if (sd->mark == DESC_SUBMITTED) {
/* Get the ld start address from ld_queue */
@ -559,7 +737,7 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
/* IRQ Multi */
if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
int cnt = 0;
int __maybe_unused cnt = 0;
switch (irq) {
#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
case DMTE6_IRQ:
@ -596,11 +774,14 @@ static void dmae_do_tasklet(unsigned long data)
struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
struct sh_desc *desc;
u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
spin_lock(&sh_chan->desc_lock);
list_for_each_entry(desc, &sh_chan->ld_queue, node) {
if ((desc->hw.sar + desc->hw.tcr) == sar_buf &&
desc->mark == DESC_SUBMITTED) {
if (desc->mark == DESC_SUBMITTED &&
((desc->direction == DMA_FROM_DEVICE &&
(desc->hw.dar + desc->hw.tcr) == dar_buf) ||
(desc->hw.sar + desc->hw.tcr) == sar_buf)) {
dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
desc->async_tx.cookie, &desc->async_tx,
desc->hw.dar);
@ -673,7 +854,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
}
snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
"sh-dmae%d", new_sh_chan->id);
"sh-dmae%d", new_sh_chan->id);
/* set up channel irq */
err = request_irq(irq, &sh_dmae_interrupt, irqflags,
@ -684,11 +865,6 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
goto err_no_irq;
}
/* CHCR register control function */
new_sh_chan->set_chcr = dmae_set_chcr;
/* DMARS register control function */
new_sh_chan->set_dmars = dmae_set_dmars;
shdev->chan[id] = new_sh_chan;
return 0;
@ -759,12 +935,19 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&shdev->common.channels);
dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
shdev->common.device_alloc_chan_resources
= sh_dmae_alloc_chan_resources;
shdev->common.device_free_chan_resources = sh_dmae_free_chan_resources;
shdev->common.device_prep_dma_memcpy = sh_dmae_prep_memcpy;
shdev->common.device_is_tx_complete = sh_dmae_is_complete;
shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending;
/* Compulsory for DMA_SLAVE fields */
shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
shdev->common.device_terminate_all = sh_dmae_terminate_all;
shdev->common.dev = &pdev->dev;
/* Default transfer size of 32 bytes requires 32-byte alignment */
shdev->common.copy_align = 5;

View file

@ -29,6 +29,7 @@ struct sh_desc {
struct sh_dmae_regs hw;
struct list_head node;
struct dma_async_tx_descriptor async_tx;
enum dma_data_direction direction;
dma_cookie_t cookie;
int chunks;
int mark;
@ -45,13 +46,9 @@ struct sh_dmae_chan {
struct device *dev; /* Channel device */
struct tasklet_struct tasklet; /* Tasklet */
int descs_allocated; /* desc count */
int xmit_shift; /* log_2(bytes_per_xfer) */
int id; /* Raw id of this channel */
char dev_id[16]; /* unique name per DMAC of channel */
/* Set chcr */
int (*set_chcr)(struct sh_dmae_chan *sh_chan, u32 regs);
/* Set DMA resource */
int (*set_dmars)(struct sh_dmae_chan *sh_chan, u16 res);
};
struct sh_dmae_device {

View file

@ -113,7 +113,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) {
DRM_ERROR("fail to set dma mask to 0x%Lx\n",
gart_info->table_mask);
(unsigned long long)gart_info->table_mask);
ret = 1;
goto done;
}

View file

@ -120,7 +120,7 @@ const static struct intel_device_info intel_gm45_info = {
const static struct intel_device_info intel_pineview_info = {
.is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
.has_pipe_cxsr = 1,
.need_gfx_hws = 1,
.has_hotplug = 1,
};

View file

@ -3564,6 +3564,9 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list,
uint32_t reloc_count = 0, i;
int ret = 0;
if (relocs == NULL)
return 0;
for (i = 0; i < buffer_count; i++) {
struct drm_i915_gem_relocation_entry __user *user_relocs;
int unwritten;
@ -3653,7 +3656,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct drm_gem_object *batch_obj;
struct drm_i915_gem_object *obj_priv;
struct drm_clip_rect *cliprects = NULL;
struct drm_i915_gem_relocation_entry *relocs;
struct drm_i915_gem_relocation_entry *relocs = NULL;
int ret = 0, ret2, i, pinned = 0;
uint64_t exec_offset;
uint32_t seqno, flush_domains, reloc_index;
@ -3722,6 +3725,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (object_list[i] == NULL) {
DRM_ERROR("Invalid object handle %d at index %d\n",
exec_list[i].handle, i);
/* prevent error path from reading uninitialized data */
args->buffer_count = i + 1;
ret = -EBADF;
goto err;
}
@ -3730,6 +3735,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (obj_priv->in_execbuffer) {
DRM_ERROR("Object %p appears more than once in object list\n",
object_list[i]);
/* prevent error path from reading uninitialized data */
args->buffer_count = i + 1;
ret = -EBADF;
goto err;
}
@ -3926,6 +3933,7 @@ err:
mutex_unlock(&dev->struct_mutex);
pre_mutex_err:
/* Copy the updated relocations out regardless of current error
* state. Failure to update the relocs would mean that the next
* time userland calls execbuf, it would do so with presumed offset
@ -3940,7 +3948,6 @@ err:
ret = ret2;
}
pre_mutex_err:
drm_free_large(object_list);
kfree(cliprects);

View file

@ -309,6 +309,22 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
if (de_iir & DE_GSE)
ironlake_opregion_gse_intr(dev);
if (de_iir & DE_PLANEA_FLIP_DONE)
intel_prepare_page_flip(dev, 0);
if (de_iir & DE_PLANEB_FLIP_DONE)
intel_prepare_page_flip(dev, 1);
if (de_iir & DE_PIPEA_VBLANK) {
drm_handle_vblank(dev, 0);
intel_finish_page_flip(dev, 0);
}
if (de_iir & DE_PIPEB_VBLANK) {
drm_handle_vblank(dev, 1);
intel_finish_page_flip(dev, 1);
}
/* check event from PCH */
if ((de_iir & DE_PCH_EVENT) &&
(pch_iir & SDE_HOTPLUG_MASK)) {
@ -844,11 +860,11 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
if (!(pipeconf & PIPEACONF_ENABLE))
return -EINVAL;
if (IS_IRONLAKE(dev))
return 0;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (IS_I965G(dev))
if (IS_IRONLAKE(dev))
ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
else if (IS_I965G(dev))
i915_enable_pipestat(dev_priv, pipe,
PIPE_START_VBLANK_INTERRUPT_ENABLE);
else
@ -866,13 +882,14 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags;
if (IS_IRONLAKE(dev))
return;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
i915_disable_pipestat(dev_priv, pipe,
PIPE_VBLANK_INTERRUPT_ENABLE |
PIPE_START_VBLANK_INTERRUPT_ENABLE);
if (IS_IRONLAKE(dev))
ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
else
i915_disable_pipestat(dev_priv, pipe,
PIPE_VBLANK_INTERRUPT_ENABLE |
PIPE_START_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}
@ -1015,13 +1032,14 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
/* enable kind of interrupts always enabled */
u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT;
u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
u32 render_mask = GT_USER_INTERRUPT;
u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
dev_priv->irq_mask_reg = ~display_mask;
dev_priv->de_irq_enable_reg = display_mask;
dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK;
/* should always can generate irq */
I915_WRITE(DEIIR, I915_READ(DEIIR));

View file

@ -157,6 +157,9 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
adpa = I915_READ(PCH_ADPA);
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
/* disable HPD first */
I915_WRITE(PCH_ADPA, adpa);
(void)I915_READ(PCH_ADPA);
adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
ADPA_CRT_HOTPLUG_WARMUP_10MS |

View file

@ -1638,6 +1638,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_OFF:
DRM_DEBUG_KMS("crtc %d dpms off\n", pipe);
drm_vblank_off(dev, pipe);
/* Disable display plane */
temp = I915_READ(dspcntr_reg);
if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
@ -2519,6 +2520,10 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock,
sr_entries = roundup(sr_entries / cacheline_size, 1);
DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
} else {
/* Turn off self refresh if both pipes are enabled */
I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
& ~FW_BLC_SELF_EN);
}
DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n",
@ -2562,6 +2567,10 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
srwm = 1;
srwm &= 0x3f;
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
} else {
/* Turn off self refresh if both pipes are enabled */
I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
& ~FW_BLC_SELF_EN);
}
DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
@ -2630,6 +2639,10 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
if (srwm < 0)
srwm = 1;
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
} else {
/* Turn off self refresh if both pipes are enabled */
I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
& ~FW_BLC_SELF_EN);
}
DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
@ -3984,6 +3997,12 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;
if (work == NULL || !work->pending) {
if (work && !work->pending) {
obj_priv = work->obj->driver_private;
DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n",
obj_priv,
atomic_read(&obj_priv->pending_flip));
}
spin_unlock_irqrestore(&dev->event_lock, flags);
return;
}
@ -4005,7 +4024,10 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
spin_unlock_irqrestore(&dev->event_lock, flags);
obj_priv = work->obj->driver_private;
if (atomic_dec_and_test(&obj_priv->pending_flip))
/* Initial scanout buffer will have a 0 pending flip count */
if ((atomic_read(&obj_priv->pending_flip) == 0) ||
atomic_dec_and_test(&obj_priv->pending_flip))
DRM_WAKEUP(&dev_priv->pending_flip_queue);
schedule_work(&work->work);
}
@ -4018,8 +4040,11 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
if (intel_crtc->unpin_work)
if (intel_crtc->unpin_work) {
intel_crtc->unpin_work->pending = 1;
} else {
DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
@ -4053,6 +4078,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
/* We borrow the event spin lock for protecting unpin_work */
spin_lock_irqsave(&dev->event_lock, flags);
if (intel_crtc->unpin_work) {
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(work);
mutex_unlock(&dev->struct_mutex);
@ -4066,7 +4092,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
ret = intel_pin_and_fence_fb_obj(dev, obj);
if (ret != 0) {
DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
obj->driver_private);
kfree(work);
intel_crtc->unpin_work = NULL;
mutex_unlock(&dev->struct_mutex);
return ret;
}

View file

@ -611,7 +611,7 @@ static const struct dmi_system_id bad_lid_status[] = {
{
.ident = "Samsung SX20S",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"),
DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
DMI_MATCH(DMI_BOARD_NAME, "SX20S"),
},
},
@ -622,6 +622,13 @@ static const struct dmi_system_id bad_lid_status[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"),
},
},
{
.ident = "Aspire 1810T",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1810T"),
},
},
{
.ident = "PC-81005",
.matches = {
@ -643,7 +650,7 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connect
{
enum drm_connector_status status = connector_status_connected;
if (!acpi_lid_open() && !dmi_check_system(bad_lid_status))
if (!dmi_check_system(bad_lid_status) && !acpi_lid_open())
status = connector_status_disconnected;
return status;

View file

@ -2345,6 +2345,14 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
connector->connector_type = DRM_MODE_CONNECTOR_VGA;
intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
(1 << INTEL_ANALOG_CLONE_BIT);
} else if (flags & SDVO_OUTPUT_CVBS0) {
sdvo_priv->controlled_output = SDVO_OUTPUT_CVBS0;
encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
sdvo_priv->is_tv = true;
intel_output->needs_tv_clock = true;
intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
} else if (flags & SDVO_OUTPUT_LVDS0) {
sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;

View file

@ -354,11 +354,17 @@ u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc)
return RREG32(RADEON_CRTC2_CRNT_FRAME);
}
/* Who ever call radeon_fence_emit should call ring_lock and ask
* for enough space (today caller are ib schedule and buffer move) */
void r100_fence_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence)
{
/* Who ever call radeon_fence_emit should call ring_lock and ask
* for enough space (today caller are ib schedule and buffer move) */
/* We have to make sure that caches are flushed before
* CPU might read something from VRAM. */
radeon_ring_write(rdev, PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, RADEON_RB3D_DC_FLUSH_ALL);
radeon_ring_write(rdev, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, RADEON_RB3D_ZC_FLUSH_ALL);
/* Wait until IDLE & CLEAN */
radeon_ring_write(rdev, PACKET0(0x1720, 0));
radeon_ring_write(rdev, (1 << 16) | (1 << 17));
@ -3369,7 +3375,6 @@ int r100_suspend(struct radeon_device *rdev)
void r100_fini(struct radeon_device *rdev)
{
r100_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
@ -3481,13 +3486,12 @@ int r100_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
r100_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
radeon_irq_kms_fini(rdev);
if (rdev->flags & RADEON_IS_PCI)
r100_pci_gart_fini(rdev);
radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0;

View file

@ -506,11 +506,14 @@ void r300_vram_info(struct radeon_device *rdev)
/* DDR for all card after R300 & IGP */
rdev->mc.vram_is_ddr = true;
tmp = RREG32(RADEON_MEM_CNTL);
if (tmp & R300_MEM_NUM_CHANNELS_MASK) {
rdev->mc.vram_width = 128;
} else {
rdev->mc.vram_width = 64;
tmp &= R300_MEM_NUM_CHANNELS_MASK;
switch (tmp) {
case 0: rdev->mc.vram_width = 64; break;
case 1: rdev->mc.vram_width = 128; break;
case 2: rdev->mc.vram_width = 256; break;
default: rdev->mc.vram_width = 128; break;
}
r100_vram_init_sizes(rdev);
@ -1327,7 +1330,6 @@ int r300_suspend(struct radeon_device *rdev)
void r300_fini(struct radeon_device *rdev)
{
r300_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
@ -1418,15 +1420,15 @@ int r300_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
r300_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
radeon_irq_kms_fini(rdev);
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_fini(rdev);
if (rdev->flags & RADEON_IS_PCI)
r100_pci_gart_fini(rdev);
radeon_irq_kms_fini(rdev);
radeon_agp_fini(rdev);
rdev->accel_working = false;
}
return 0;

View file

@ -389,16 +389,15 @@ int r420_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
r420_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
radeon_irq_kms_fini(rdev);
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_fini(rdev);
if (rdev->flags & RADEON_IS_PCI)
r100_pci_gart_fini(rdev);
radeon_agp_fini(rdev);
radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0;

View file

@ -294,13 +294,12 @@ int r520_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
rv515_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
radeon_irq_kms_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0;

View file

@ -1654,6 +1654,12 @@ void r600_ring_init(struct radeon_device *rdev, unsigned ring_size)
rdev->cp.align_mask = 16 - 1;
}
void r600_cp_fini(struct radeon_device *rdev)
{
r600_cp_stop(rdev);
radeon_ring_fini(rdev);
}
/*
* GPU scratch registers helpers function.
@ -1861,6 +1867,12 @@ int r600_startup(struct radeon_device *rdev)
return r;
}
r600_gpu_init(rdev);
r = r600_blit_init(rdev);
if (r) {
r600_blit_fini(rdev);
rdev->asic->copy = NULL;
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
}
/* pin copy shader into vram */
if (rdev->r600_blit.shader_obj) {
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
@ -2045,19 +2057,15 @@ int r600_init(struct radeon_device *rdev)
r = r600_pcie_gart_init(rdev);
if (r)
return r;
r = r600_blit_init(rdev);
if (r) {
r600_blit_fini(rdev);
rdev->asic->copy = NULL;
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
}
rdev->accel_working = true;
r = r600_startup(rdev);
if (r) {
r600_suspend(rdev);
dev_err(rdev->dev, "disabling GPU acceleration\n");
r600_cp_fini(rdev);
r600_wb_fini(rdev);
radeon_ring_fini(rdev);
r600_irq_fini(rdev);
radeon_irq_kms_fini(rdev);
r600_pcie_gart_fini(rdev);
rdev->accel_working = false;
}
@ -2083,20 +2091,17 @@ int r600_init(struct radeon_device *rdev)
void r600_fini(struct radeon_device *rdev)
{
/* Suspend operations */
r600_suspend(rdev);
r600_audio_fini(rdev);
r600_blit_fini(rdev);
r600_cp_fini(rdev);
r600_wb_fini(rdev);
r600_irq_fini(rdev);
radeon_irq_kms_fini(rdev);
radeon_ring_fini(rdev);
r600_wb_fini(rdev);
r600_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_clocks_fini(rdev);
radeon_agp_fini(rdev);
radeon_bo_fini(rdev);
radeon_atombios_fini(rdev);
kfree(rdev->bios);
@ -2900,3 +2905,18 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
return 0;
#endif
}
/**
* r600_ioctl_wait_idle - flush host path cache on wait idle ioctl
* rdev: radeon device structure
* bo: buffer object struct which userspace is waiting for idle
*
* Some R6XX/R7XX doesn't seems to take into account HDP flush performed
* through ring buffer, this leads to corruption in rendering, see
* http://bugzilla.kernel.org/show_bug.cgi?id=15186 to avoid this we
* directly perform HDP flush by writing register through MMIO.
*/
void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
{
WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
}

View file

@ -35,7 +35,7 @@
*/
static int r600_audio_chipset_supported(struct radeon_device *rdev)
{
return rdev->family >= CHIP_R600
return (rdev->family >= CHIP_R600 && rdev->family < CHIP_RV710)
|| rdev->family == CHIP_RS600
|| rdev->family == CHIP_RS690
|| rdev->family == CHIP_RS740;

View file

@ -661,6 +661,13 @@ struct radeon_asic {
void (*hpd_fini)(struct radeon_device *rdev);
bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
void (*hpd_set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
/* ioctl hw specific callback. Some hw might want to perform special
* operation on specific ioctl. For instance on wait idle some hw
* might want to perform and HDP flush through MMIO as it seems that
* some R6XX/R7XX hw doesn't take HDP flush into account if programmed
* through ring.
*/
void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
};
/*
@ -1143,6 +1150,7 @@ extern bool r600_card_posted(struct radeon_device *rdev);
extern void r600_cp_stop(struct radeon_device *rdev);
extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
extern int r600_cp_resume(struct radeon_device *rdev);
extern void r600_cp_fini(struct radeon_device *rdev);
extern int r600_count_pipe_bits(uint32_t val);
extern int r600_gart_clear_page(struct radeon_device *rdev, int i);
extern int r600_mc_wait_for_idle(struct radeon_device *rdev);

View file

@ -117,6 +117,7 @@ static struct radeon_asic r100_asic = {
.hpd_fini = &r100_hpd_fini,
.hpd_sense = &r100_hpd_sense,
.hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
@ -176,6 +177,7 @@ static struct radeon_asic r300_asic = {
.hpd_fini = &r100_hpd_fini,
.hpd_sense = &r100_hpd_sense,
.hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
/*
@ -219,6 +221,7 @@ static struct radeon_asic r420_asic = {
.hpd_fini = &r100_hpd_fini,
.hpd_sense = &r100_hpd_sense,
.hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
@ -267,6 +270,7 @@ static struct radeon_asic rs400_asic = {
.hpd_fini = &r100_hpd_fini,
.hpd_sense = &r100_hpd_sense,
.hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
@ -323,6 +327,7 @@ static struct radeon_asic rs600_asic = {
.hpd_fini = &rs600_hpd_fini,
.hpd_sense = &rs600_hpd_sense,
.hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
@ -370,6 +375,7 @@ static struct radeon_asic rs690_asic = {
.hpd_fini = &rs600_hpd_fini,
.hpd_sense = &rs600_hpd_sense,
.hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
@ -421,6 +427,7 @@ static struct radeon_asic rv515_asic = {
.hpd_fini = &rs600_hpd_fini,
.hpd_sense = &rs600_hpd_sense,
.hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
@ -463,6 +470,7 @@ static struct radeon_asic r520_asic = {
.hpd_fini = &rs600_hpd_fini,
.hpd_sense = &rs600_hpd_sense,
.hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL,
};
/*
@ -504,6 +512,7 @@ void r600_hpd_fini(struct radeon_device *rdev);
bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
void r600_hpd_set_polarity(struct radeon_device *rdev,
enum radeon_hpd_id hpd);
extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
static struct radeon_asic r600_asic = {
.init = &r600_init,
@ -538,6 +547,7 @@ static struct radeon_asic r600_asic = {
.hpd_fini = &r600_hpd_fini,
.hpd_sense = &r600_hpd_sense,
.hpd_set_polarity = &r600_hpd_set_polarity,
.ioctl_wait_idle = r600_ioctl_wait_idle,
};
/*
@ -582,6 +592,7 @@ static struct radeon_asic rv770_asic = {
.hpd_fini = &r600_hpd_fini,
.hpd_sense = &r600_hpd_sense,
.hpd_set_polarity = &r600_hpd_set_polarity,
.ioctl_wait_idle = r600_ioctl_wait_idle,
};
#endif

View file

@ -971,8 +971,7 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
lvds->native_mode.vdisplay);
lvds->panel_vcc_delay = RBIOS16(lcd_info + 0x2c);
if (lvds->panel_vcc_delay > 2000 || lvds->panel_vcc_delay < 0)
lvds->panel_vcc_delay = 2000;
lvds->panel_vcc_delay = min_t(u16, lvds->panel_vcc_delay, 2000);
lvds->panel_pwr_delay = RBIOS8(lcd_info + 0x24);
lvds->panel_digon_delay = RBIOS16(lcd_info + 0x38) & 0xf;

View file

@ -1343,7 +1343,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
radeon_connector->dac_load_detect = false;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
radeon_connector->dac_load_detect);
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.tv_std_property,
radeon_combios_get_tv_info(rdev));

View file

@ -308,6 +308,9 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
}
robj = gobj->driver_private;
r = radeon_bo_wait(robj, NULL, false);
/* callback hw specific functions if any */
if (robj->rdev->asic->ioctl_wait_idle)
robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);

View file

@ -223,15 +223,31 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
return 0;
}
int rs400_mc_wait_for_idle(struct radeon_device *rdev)
{
unsigned i;
uint32_t tmp;
for (i = 0; i < rdev->usec_timeout; i++) {
/* read MC_STATUS */
tmp = RREG32(0x0150);
if (tmp & (1 << 2)) {
return 0;
}
DRM_UDELAY(1);
}
return -1;
}
void rs400_gpu_init(struct radeon_device *rdev)
{
/* FIXME: HDP same place on rs400 ? */
r100_hdp_reset(rdev);
/* FIXME: is this correct ? */
r420_pipes_init(rdev);
if (r300_mc_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n");
if (rs400_mc_wait_for_idle(rdev)) {
printk(KERN_WARNING "rs400: Failed to wait MC idle while "
"programming pipes. Bad things might happen. %08x\n", RREG32(0x150));
}
}
@ -370,8 +386,8 @@ void rs400_mc_program(struct radeon_device *rdev)
r100_mc_stop(rdev, &save);
/* Wait for mc idle */
if (r300_mc_wait_for_idle(rdev))
dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
if (rs400_mc_wait_for_idle(rdev))
dev_warn(rdev->dev, "rs400: Wait MC idle timeout before updating MC.\n");
WREG32(R_000148_MC_FB_LOCATION,
S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
@ -448,7 +464,6 @@ int rs400_suspend(struct radeon_device *rdev)
void rs400_fini(struct radeon_device *rdev)
{
rs400_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
@ -527,7 +542,6 @@ int rs400_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
rs400_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);

View file

@ -610,7 +610,6 @@ int rs600_suspend(struct radeon_device *rdev)
void rs600_fini(struct radeon_device *rdev)
{
rs600_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
@ -689,7 +688,6 @@ int rs600_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
rs600_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);

View file

@ -676,7 +676,6 @@ int rs690_suspend(struct radeon_device *rdev)
void rs690_fini(struct radeon_device *rdev)
{
rs690_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
@ -756,7 +755,6 @@ int rs690_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
rs690_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);

View file

@ -537,7 +537,6 @@ void rv515_set_safe_registers(struct radeon_device *rdev)
void rv515_fini(struct radeon_device *rdev)
{
rv515_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
@ -615,13 +614,12 @@ int rv515_init(struct radeon_device *rdev)
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
rv515_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
radeon_irq_kms_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0;

View file

@ -887,6 +887,12 @@ static int rv770_startup(struct radeon_device *rdev)
return r;
}
rv770_gpu_init(rdev);
r = r600_blit_init(rdev);
if (r) {
r600_blit_fini(rdev);
rdev->asic->copy = NULL;
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
}
/* pin copy shader into vram */
if (rdev->r600_blit.shader_obj) {
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
@ -1055,19 +1061,15 @@ int rv770_init(struct radeon_device *rdev)
r = r600_pcie_gart_init(rdev);
if (r)
return r;
r = r600_blit_init(rdev);
if (r) {
r600_blit_fini(rdev);
rdev->asic->copy = NULL;
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
}
rdev->accel_working = true;
r = rv770_startup(rdev);
if (r) {
rv770_suspend(rdev);
dev_err(rdev->dev, "disabling GPU acceleration\n");
r600_cp_fini(rdev);
r600_wb_fini(rdev);
radeon_ring_fini(rdev);
r600_irq_fini(rdev);
radeon_irq_kms_fini(rdev);
rv770_pcie_gart_fini(rdev);
rdev->accel_working = false;
}
@ -1089,13 +1091,11 @@ int rv770_init(struct radeon_device *rdev)
void rv770_fini(struct radeon_device *rdev)
{
rv770_suspend(rdev);
r600_blit_fini(rdev);
r600_cp_fini(rdev);
r600_wb_fini(rdev);
r600_irq_fini(rdev);
radeon_irq_kms_fini(rdev);
radeon_ring_fini(rdev);
r600_wb_fini(rdev);
rv770_pcie_gart_fini(rdev);
radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev);

View file

@ -179,7 +179,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
*
* Some, but not all, of these voltages have low/high limits.
*/
#define ADT7462_VOLT_COUNT 12
#define ADT7462_VOLT_COUNT 13
#define ADT7462_VENDOR 0x41
#define ADT7462_DEVICE 0x62

View file

@ -851,17 +851,16 @@ static struct lm78_data *lm78_update_device(struct device *dev)
static int __init lm78_isa_found(unsigned short address)
{
int val, save, found = 0;
int port;
/* We have to request the region in two parts because some
boards declare base+4 to base+7 as a PNP device */
if (!request_region(address, 4, "lm78")) {
pr_debug("lm78: Failed to request low part of region\n");
return 0;
}
if (!request_region(address + 4, 4, "lm78")) {
pr_debug("lm78: Failed to request high part of region\n");
release_region(address, 4);
return 0;
/* Some boards declare base+0 to base+7 as a PNP device, some base+4
* to base+7 and some base+5 to base+6. So we better request each port
* individually for the probing phase. */
for (port = address; port < address + LM78_EXTENT; port++) {
if (!request_region(port, 1, "lm78")) {
pr_debug("lm78: Failed to request port 0x%x\n", port);
goto release;
}
}
#define REALLY_SLOW_IO
@ -925,8 +924,8 @@ static int __init lm78_isa_found(unsigned short address)
val & 0x80 ? "LM79" : "LM78", (int)address);
release:
release_region(address + 4, 4);
release_region(address, 4);
for (port--; port >= address; port--)
release_region(port, 1);
return found;
}

View file

@ -1793,17 +1793,17 @@ static int __init
w83781d_isa_found(unsigned short address)
{
int val, save, found = 0;
int port;
/* We have to request the region in two parts because some
boards declare base+4 to base+7 as a PNP device */
if (!request_region(address, 4, "w83781d")) {
pr_debug("w83781d: Failed to request low part of region\n");
return 0;
}
if (!request_region(address + 4, 4, "w83781d")) {
pr_debug("w83781d: Failed to request high part of region\n");
release_region(address, 4);
return 0;
/* Some boards declare base+0 to base+7 as a PNP device, some base+4
* to base+7 and some base+5 to base+6. So we better request each port
* individually for the probing phase. */
for (port = address; port < address + W83781D_EXTENT; port++) {
if (!request_region(port, 1, "w83781d")) {
pr_debug("w83781d: Failed to request port 0x%x\n",
port);
goto release;
}
}
#define REALLY_SLOW_IO
@ -1877,8 +1877,8 @@ w83781d_isa_found(unsigned short address)
val == 0x30 ? "W83782D" : "W83781D", (int)address);
release:
release_region(address + 4, 4);
release_region(address, 4);
for (port--; port >= address; port--)
release_region(port, 1);
return found;
}

View file

@ -338,6 +338,23 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
/*
* Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS
* ver. 1.33 20070103) don't set the correct ISA PCI region header info.
* BAR0 should be 8 bytes; instead, it may be set to something like 8k
* (which conflicts w/ BAR1's memory range).
*/
static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
{
if (pci_resource_len(dev, 0) != 8) {
struct resource *res = &dev->resource[0];
res->end = res->start + 8 - 1;
dev_info(&dev->dev, "CS5536 ISA bridge bug detected "
"(incorrect header); workaround applied.\n");
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
unsigned size, int nr, const char *name)
{

View file

@ -873,6 +873,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
brelse(bh);
unacquire_priv_sbp:
kfree(befs_sb->mount_opts.iocharset);
kfree(sb->s_fs_info);
unacquire_none:

View file

@ -246,7 +246,8 @@ struct super_block *freeze_bdev(struct block_device *bdev)
if (!sb)
goto out;
if (sb->s_flags & MS_RDONLY) {
deactivate_locked_super(sb);
sb->s_frozen = SB_FREEZE_TRANS;
up_write(&sb->s_umount);
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return sb;
}
@ -307,7 +308,7 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
BUG_ON(sb->s_bdev != bdev);
down_write(&sb->s_umount);
if (sb->s_flags & MS_RDONLY)
goto out_deactivate;
goto out_unfrozen;
if (sb->s_op->unfreeze_fs) {
error = sb->s_op->unfreeze_fs(sb);
@ -321,11 +322,11 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
}
}
out_unfrozen:
sb->s_frozen = SB_UNFROZEN;
smp_wmb();
wake_up(&sb->s_wait_unfrozen);
out_deactivate:
if (sb)
deactivate_locked_super(sb);
out_unlock:

View file

@ -1982,7 +1982,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,
if (!(sb->s_flags & MS_RDONLY)) {
ret = btrfs_recover_relocation(tree_root);
BUG_ON(ret);
if (ret < 0) {
printk(KERN_WARNING
"btrfs: failed to recover relocation\n");
err = -EINVAL;
goto fail_trans_kthread;
}
}
location.objectid = BTRFS_FS_TREE_OBJECTID;

View file

@ -5402,10 +5402,6 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
int ret;
while (level >= 0) {
if (path->slots[level] >=
btrfs_header_nritems(path->nodes[level]))
break;
ret = walk_down_proc(trans, root, path, wc, lookup_info);
if (ret > 0)
break;
@ -5413,6 +5409,10 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
if (level == 0)
break;
if (path->slots[level] >=
btrfs_header_nritems(path->nodes[level]))
break;
ret = do_walk_down(trans, root, path, wc, &lookup_info);
if (ret > 0) {
path->slots[level]++;

View file

@ -3165,10 +3165,9 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
spin_unlock(&tree->buffer_lock);
goto free_eb;
}
spin_unlock(&tree->buffer_lock);
/* add one reference for the tree */
atomic_inc(&eb->refs);
spin_unlock(&tree->buffer_lock);
return eb;
free_eb:

View file

@ -1133,7 +1133,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
}
mutex_lock(&dentry->d_inode->i_mutex);
out:
return ret > 0 ? EIO : ret;
return ret > 0 ? -EIO : ret;
}
static const struct vm_operations_struct btrfs_file_vm_ops = {

View file

@ -1681,24 +1681,6 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
* before we start the transaction. It limits the amount of btree
* reads required while inside the transaction.
*/
static noinline void reada_csum(struct btrfs_root *root,
struct btrfs_path *path,
struct btrfs_ordered_extent *ordered_extent)
{
struct btrfs_ordered_sum *sum;
u64 bytenr;
sum = list_entry(ordered_extent->list.next, struct btrfs_ordered_sum,
list);
bytenr = sum->sums[0].bytenr;
/*
* we don't care about the results, the point of this search is
* just to get the btree leaves into ram
*/
btrfs_lookup_csum(NULL, root->fs_info->csum_root, path, bytenr, 0);
}
/* as ordered data IO finishes, this gets called so we can finish
* an ordered extent if the range of bytes in the file it covers are
* fully written.
@ -1709,7 +1691,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
struct btrfs_trans_handle *trans;
struct btrfs_ordered_extent *ordered_extent = NULL;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct btrfs_path *path;
int compressed = 0;
int ret;
@ -1717,32 +1698,9 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
if (!ret)
return 0;
/*
* before we join the transaction, try to do some of our IO.
* This will limit the amount of IO that we have to do with
* the transaction running. We're unlikely to need to do any
* IO if the file extents are new, the disk_i_size checks
* covers the most common case.
*/
if (start < BTRFS_I(inode)->disk_i_size) {
path = btrfs_alloc_path();
if (path) {
ret = btrfs_lookup_file_extent(NULL, root, path,
inode->i_ino,
start, 0);
ordered_extent = btrfs_lookup_ordered_extent(inode,
start);
if (!list_empty(&ordered_extent->list)) {
btrfs_release_path(root, path);
reada_csum(root, path, ordered_extent);
}
btrfs_free_path(path);
}
}
if (!ordered_extent)
ordered_extent = btrfs_lookup_ordered_extent(inode, start);
ordered_extent = btrfs_lookup_ordered_extent(inode, start);
BUG_ON(!ordered_extent);
if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
BUG_ON(!list_empty(&ordered_extent->list));
ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
@ -5841,7 +5799,9 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
inode->i_ctime = CURRENT_TIME;
BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC;
if (!(mode & FALLOC_FL_KEEP_SIZE) &&
cur_offset > inode->i_size) {
(actual_len > inode->i_size) &&
(cur_offset > inode->i_size)) {
if (cur_offset > actual_len)
i_size = actual_len;
else

View file

@ -3764,7 +3764,8 @@ out:
BTRFS_DATA_RELOC_TREE_OBJECTID);
if (IS_ERR(fs_root))
err = PTR_ERR(fs_root);
btrfs_orphan_cleanup(fs_root);
else
btrfs_orphan_cleanup(fs_root);
}
return err;
}

View file

@ -199,9 +199,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
int force)
{
unsigned long flags;
write_lock_irqsave(&filp->f_owner.lock, flags);
write_lock_irq(&filp->f_owner.lock);
if (force || !filp->f_owner.pid) {
put_pid(filp->f_owner.pid);
filp->f_owner.pid = get_pid(pid);
@ -213,7 +211,7 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
filp->f_owner.euid = cred->euid;
}
}
write_unlock_irqrestore(&filp->f_owner.lock, flags);
write_unlock_irq(&filp->f_owner.lock);
}
int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,

View file

@ -253,6 +253,7 @@ void __fput(struct file *file)
if (file->f_op && file->f_op->release)
file->f_op->release(inode, file);
security_file_free(file);
ima_file_free(file);
if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
cdev_put(inode->i_cdev);
fops_put(file->f_op);

View file

@ -1736,8 +1736,7 @@ do_last:
if (nd.root.mnt)
path_put(&nd.root);
if (!IS_ERR(filp)) {
error = ima_path_check(&filp->f_path, filp->f_mode &
(MAY_READ | MAY_WRITE | MAY_EXEC));
error = ima_file_check(filp, acc_mode);
if (error) {
fput(filp);
filp = ERR_PTR(error);
@ -1797,8 +1796,7 @@ ok:
}
filp = nameidata_to_filp(&nd);
if (!IS_ERR(filp)) {
error = ima_path_check(&filp->f_path, filp->f_mode &
(MAY_READ | MAY_WRITE | MAY_EXEC));
error = ima_file_check(filp, acc_mode);
if (error) {
fput(filp);
filp = ERR_PTR(error);

View file

@ -752,6 +752,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
flags, current_cred());
if (IS_ERR(*filp))
host_err = PTR_ERR(*filp);
host_err = ima_file_check(*filp, access);
out_nfserr:
err = nfserrno(host_err);
out:
@ -2127,7 +2128,6 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
*/
path.mnt = exp->ex_path.mnt;
path.dentry = dentry;
err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
nfsd_out:
return err? nfserrno(err) : 0;
}

View file

@ -647,9 +647,9 @@ static inline int ata_id_has_large_logical_sectors(const u16 *id)
return id[ATA_ID_SECTOR_SIZE] & (1 << 13);
}
static inline u8 ata_id_logical_per_physical_sectors(const u16 *id)
static inline u16 ata_id_logical_per_physical_sectors(const u16 *id)
{
return id[ATA_ID_SECTOR_SIZE] & 0xf;
return 1 << (id[ATA_ID_SECTOR_SIZE] & 0xf);
}
static inline int ata_id_has_lba48(const u16 *id)

View file

@ -15,6 +15,7 @@
# define __acquire(x) __context__(x,1)
# define __release(x) __context__(x,-1)
# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
# define __percpu __attribute__((noderef, address_space(3)))
extern void __chk_user_ptr(const volatile void __user *);
extern void __chk_io_ptr(const volatile void __iomem *);
#else
@ -32,6 +33,7 @@ extern void __chk_io_ptr(const volatile void __iomem *);
# define __acquire(x) (void)0
# define __release(x) (void)0
# define __cond_lock(x,c) (c)
# define __percpu
#endif
#ifdef __KERNEL__

View file

@ -17,7 +17,7 @@ struct linux_binprm;
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_inode_alloc(struct inode *inode);
extern void ima_inode_free(struct inode *inode);
extern int ima_path_check(struct path *path, int mask);
extern int ima_file_check(struct file *file, int mask);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern void ima_counts_get(struct file *file);
@ -38,7 +38,7 @@ static inline void ima_inode_free(struct inode *inode)
return;
}
static inline int ima_path_check(struct path *path, int mask)
static inline int ima_file_check(struct file *file, int mask)
{
return 0;
}

View file

@ -657,9 +657,9 @@ asmlinkage void __init start_kernel(void)
proc_caches_init();
buffer_init();
key_init();
radix_tree_init();
security_init();
vfs_caches_init(totalram_pages);
radix_tree_init();
signals_init();
/* rootfs populating might need page-writeback */
page_writeback_init();

View file

@ -912,6 +912,9 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
goto out_pm;
err = -ENODEV;
if (node < 0 || node >= MAX_NUMNODES)
goto out_pm;
if (!node_state(node, N_HIGH_MEMORY))
goto out_pm;

View file

@ -65,7 +65,6 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
const char *cause, int result, int info);
/* Internal IMA function definitions */
void ima_iintcache_init(void);
int ima_init(void);
void ima_cleanup(void);
int ima_fs_init(void);
@ -131,7 +130,7 @@ void iint_free(struct kref *kref);
void iint_rcu_free(struct rcu_head *rcu);
/* IMA policy related functions */
enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK };
enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
void ima_init_policy(void);

View file

@ -95,12 +95,12 @@ err_out:
* ima_must_measure - measure decision based on policy.
* @inode: pointer to inode to measure
* @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
* @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP)
* @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
*
* The policy is defined in terms of keypairs:
* subj=, obj=, type=, func=, mask=, fsmagic=
* subj,obj, and type: are LSM specific.
* func: PATH_CHECK | BPRM_CHECK | FILE_MMAP
* func: FILE_CHECK | BPRM_CHECK | FILE_MMAP
* mask: contains the permission mask
* fsmagic: hex value
*

View file

@ -52,9 +52,6 @@ int ima_inode_alloc(struct inode *inode)
struct ima_iint_cache *iint = NULL;
int rc = 0;
if (!ima_initialized)
return 0;
iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
if (!iint)
return -ENOMEM;
@ -118,8 +115,6 @@ void ima_inode_free(struct inode *inode)
{
struct ima_iint_cache *iint;
if (!ima_initialized)
return;
spin_lock(&ima_iint_lock);
iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
spin_unlock(&ima_iint_lock);
@ -141,9 +136,11 @@ static void init_once(void *foo)
kref_set(&iint->refcount, 1);
}
void __init ima_iintcache_init(void)
static int __init ima_iintcache_init(void)
{
iint_cache =
kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
SLAB_PANIC, init_once);
return 0;
}
security_initcall(ima_iintcache_init);

View file

@ -14,7 +14,7 @@
*
* File: ima_main.c
* implements the IMA hooks: ima_bprm_check, ima_file_mmap,
* and ima_path_check.
* and ima_file_check.
*/
#include <linux/module.h>
#include <linux/file.h>
@ -84,6 +84,36 @@ out:
return found;
}
/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
*
* When opening a file for read, if the file is already open for write,
* the file could change, resulting in a file measurement error.
*
* Opening a file for write, if the file is already open for read, results
* in a time of measure, time of use (ToMToU) error.
*
* In either case invalidate the PCR.
*/
enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
static void ima_read_write_check(enum iint_pcr_error error,
struct ima_iint_cache *iint,
struct inode *inode,
const unsigned char *filename)
{
switch (error) {
case TOMTOU:
if (iint->readcount > 0)
ima_add_violation(inode, filename, "invalid_pcr",
"ToMToU");
break;
case OPEN_WRITERS:
if (iint->writecount > 0)
ima_add_violation(inode, filename, "invalid_pcr",
"open_writers");
break;
}
}
/*
* Update the counts given an fmode_t
*/
@ -98,6 +128,47 @@ static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
iint->writecount++;
}
/*
* ima_counts_get - increment file counts
*
* Maintain read/write counters for all files, but only
* invalidate the PCR for measured files:
* - Opening a file for write when already open for read,
* results in a time of measure, time of use (ToMToU) error.
* - Opening a file for read when already open for write,
* could result in a file measurement error.
*
*/
void ima_counts_get(struct file *file)
{
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
fmode_t mode = file->f_mode;
struct ima_iint_cache *iint;
int rc;
if (!ima_initialized || !S_ISREG(inode->i_mode))
return;
iint = ima_iint_find_get(inode);
if (!iint)
return;
mutex_lock(&iint->mutex);
rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
if (rc < 0)
goto out;
if (mode & FMODE_WRITE) {
ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
goto out;
}
ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name);
out:
ima_inc_counts(iint, file->f_mode);
mutex_unlock(&iint->mutex);
kref_put(&iint->refcount, iint_free);
}
/*
* Decrement ima counts
*/
@ -153,123 +224,6 @@ void ima_file_free(struct file *file)
kref_put(&iint->refcount, iint_free);
}
/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
*
* When opening a file for read, if the file is already open for write,
* the file could change, resulting in a file measurement error.
*
* Opening a file for write, if the file is already open for read, results
* in a time of measure, time of use (ToMToU) error.
*
* In either case invalidate the PCR.
*/
enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
static void ima_read_write_check(enum iint_pcr_error error,
struct ima_iint_cache *iint,
struct inode *inode,
const unsigned char *filename)
{
switch (error) {
case TOMTOU:
if (iint->readcount > 0)
ima_add_violation(inode, filename, "invalid_pcr",
"ToMToU");
break;
case OPEN_WRITERS:
if (iint->writecount > 0)
ima_add_violation(inode, filename, "invalid_pcr",
"open_writers");
break;
}
}
static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
const unsigned char *filename)
{
int rc = 0;
ima_inc_counts(iint, file->f_mode);
rc = ima_collect_measurement(iint, file);
if (!rc)
ima_store_measurement(iint, file, filename);
return rc;
}
/**
* ima_path_check - based on policy, collect/store measurement.
* @path: contains a pointer to the path to be measured
* @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
*
* Measure the file being open for readonly, based on the
* ima_must_measure() policy decision.
*
* Keep read/write counters for all files, but only
* invalidate the PCR for measured files:
* - Opening a file for write when already open for read,
* results in a time of measure, time of use (ToMToU) error.
* - Opening a file for read when already open for write,
* could result in a file measurement error.
*
* Always return 0 and audit dentry_open failures.
* (Return code will be based upon measurement appraisal.)
*/
int ima_path_check(struct path *path, int mask)
{
struct inode *inode = path->dentry->d_inode;
struct ima_iint_cache *iint;
struct file *file = NULL;
int rc;
if (!ima_initialized || !S_ISREG(inode->i_mode))
return 0;
iint = ima_iint_find_get(inode);
if (!iint)
return 0;
mutex_lock(&iint->mutex);
rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
if (rc < 0)
goto out;
if ((mask & MAY_WRITE) || (mask == 0))
ima_read_write_check(TOMTOU, iint, inode,
path->dentry->d_name.name);
if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
goto out;
ima_read_write_check(OPEN_WRITERS, iint, inode,
path->dentry->d_name.name);
if (!(iint->flags & IMA_MEASURED)) {
struct dentry *dentry = dget(path->dentry);
struct vfsmount *mnt = mntget(path->mnt);
file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE,
current_cred());
if (IS_ERR(file)) {
int audit_info = 0;
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
dentry->d_name.name,
"add_measurement",
"dentry_open failed",
1, audit_info);
file = NULL;
goto out;
}
rc = get_path_measurement(iint, file, dentry->d_name.name);
}
out:
mutex_unlock(&iint->mutex);
if (file)
fput(file);
kref_put(&iint->refcount, iint_free);
return 0;
}
EXPORT_SYMBOL_GPL(ima_path_check);
static int process_measurement(struct file *file, const unsigned char *filename,
int mask, int function)
{
@ -297,33 +251,6 @@ out:
return rc;
}
/*
* ima_counts_get - increment file counts
*
* - for IPC shm and shmat file.
* - for nfsd exported files.
*
* Increment the counts for these files to prevent unnecessary
* imbalance messages.
*/
void ima_counts_get(struct file *file)
{
struct inode *inode = file->f_dentry->d_inode;
struct ima_iint_cache *iint;
if (!ima_initialized || !S_ISREG(inode->i_mode))
return;
iint = ima_iint_find_get(inode);
if (!iint)
return;
mutex_lock(&iint->mutex);
ima_inc_counts(iint, file->f_mode);
mutex_unlock(&iint->mutex);
kref_put(&iint->refcount, iint_free);
}
EXPORT_SYMBOL_GPL(ima_counts_get);
/**
* ima_file_mmap - based on policy, collect/store measurement.
* @file: pointer to the file to be measured (May be NULL)
@ -369,11 +296,31 @@ int ima_bprm_check(struct linux_binprm *bprm)
return 0;
}
/**
* ima_path_check - based on policy, collect/store measurement.
* @file: pointer to the file to be measured
* @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
*
* Measure files based on the ima_must_measure() policy decision.
*
* Always return 0 and audit dentry_open failures.
* (Return code will be based upon measurement appraisal.)
*/
int ima_file_check(struct file *file, int mask)
{
int rc;
rc = process_measurement(file, file->f_dentry->d_name.name,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
FILE_CHECK);
return 0;
}
EXPORT_SYMBOL_GPL(ima_file_check);
static int __init init_ima(void)
{
int error;
ima_iintcache_init();
error = ima_init();
ima_initialized = 1;
return error;

View file

@ -67,7 +67,7 @@ static struct ima_measure_rule_entry default_rules[] = {
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0,
{.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0,
.flags = IMA_FUNC | IMA_MASK | IMA_UID},
};
@ -282,8 +282,11 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
break;
case Opt_func:
audit_log_format(ab, "func=%s ", args[0].from);
if (strcmp(args[0].from, "PATH_CHECK") == 0)
entry->func = PATH_CHECK;
if (strcmp(args[0].from, "FILE_CHECK") == 0)
entry->func = FILE_CHECK;
/* PATH_CHECK is for backwards compat */
else if (strcmp(args[0].from, "PATH_CHECK") == 0)
entry->func = FILE_CHECK;
else if (strcmp(args[0].from, "FILE_MMAP") == 0)
entry->func = FILE_MMAP;
else if (strcmp(args[0].from, "BPRM_CHECK") == 0)

View file

@ -666,8 +666,6 @@ int security_file_alloc(struct file *file)
void security_file_free(struct file *file)
{
security_ops->file_free_security(file);
if (file->f_dentry)
ima_file_free(file);
}
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

View file

@ -166,18 +166,7 @@ static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index)
{
struct ct_vm *vm;
void *kvirt_addr;
unsigned long phys_addr;
vm = atc->vm;
kvirt_addr = vm->get_ptp_virt(vm, index);
if (kvirt_addr == NULL)
phys_addr = (~0UL);
else
phys_addr = virt_to_phys(kvirt_addr);
return phys_addr;
return atc->vm->get_ptp_phys(atc->vm, index);
}
static unsigned int convert_format(snd_pcm_format_t snd_format)
@ -1669,7 +1658,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
}
/* Set up device virtual memory management object */
err = ct_vm_create(&atc->vm);
err = ct_vm_create(&atc->vm, pci);
if (err < 0)
goto error1;

View file

@ -138,7 +138,7 @@ ct_vm_map(struct ct_vm *vm, struct snd_pcm_substream *substream, int size)
return NULL;
}
ptp = vm->ptp[0];
ptp = (unsigned long *)vm->ptp[0].area;
pte_start = (block->addr >> CT_PAGE_SHIFT);
pages = block->size >> CT_PAGE_SHIFT;
for (i = 0; i < pages; i++) {
@ -158,25 +158,25 @@ static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block)
}
/* *
* return the host (kmalloced) addr of the @index-th device
* page talbe page on success, or NULL on failure.
* The first returned NULL indicates the termination.
* return the host physical addr of the @index-th device
* page table page on success, or ~0UL on failure.
* The first returned ~0UL indicates the termination.
* */
static void *
ct_get_ptp_virt(struct ct_vm *vm, int index)
static dma_addr_t
ct_get_ptp_phys(struct ct_vm *vm, int index)
{
void *addr;
dma_addr_t addr;
addr = (index >= CT_PTP_NUM) ? NULL : vm->ptp[index];
addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr;
return addr;
}
int ct_vm_create(struct ct_vm **rvm)
int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci)
{
struct ct_vm *vm;
struct ct_vm_block *block;
int i;
int i, err = 0;
*rvm = NULL;
@ -188,23 +188,21 @@ int ct_vm_create(struct ct_vm **rvm)
/* Allocate page table pages */
for (i = 0; i < CT_PTP_NUM; i++) {
vm->ptp[i] = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!vm->ptp[i])
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(pci),
PAGE_SIZE, &vm->ptp[i]);
if (err < 0)
break;
}
if (!i) {
if (err < 0) {
/* no page table pages are allocated */
kfree(vm);
ct_vm_destroy(vm);
return -ENOMEM;
}
vm->size = CT_ADDRS_PER_PAGE * i;
/* Initialise remaining ptps */
for (; i < CT_PTP_NUM; i++)
vm->ptp[i] = NULL;
vm->map = ct_vm_map;
vm->unmap = ct_vm_unmap;
vm->get_ptp_virt = ct_get_ptp_virt;
vm->get_ptp_phys = ct_get_ptp_phys;
INIT_LIST_HEAD(&vm->unused);
INIT_LIST_HEAD(&vm->used);
block = kzalloc(sizeof(*block), GFP_KERNEL);
@ -242,7 +240,7 @@ void ct_vm_destroy(struct ct_vm *vm)
/* free allocated page table pages */
for (i = 0; i < CT_PTP_NUM; i++)
kfree(vm->ptp[i]);
snd_dma_free_pages(&vm->ptp[i]);
vm->size = 0;

View file

@ -22,6 +22,8 @@
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <sound/memalloc.h>
/* The chip can handle the page table of 4k pages
* (emu20k1 can handle even 8k pages, but we don't use it right now)
@ -41,7 +43,7 @@ struct snd_pcm_substream;
/* Virtual memory management object for card device */
struct ct_vm {
void *ptp[CT_PTP_NUM]; /* Device page table pages */
struct snd_dma_buffer ptp[CT_PTP_NUM]; /* Device page table pages */
unsigned int size; /* Available addr space in bytes */
struct list_head unused; /* List of unused blocks */
struct list_head used; /* List of used blocks */
@ -52,10 +54,10 @@ struct ct_vm {
int size);
/* Unmap device logical addr area. */
void (*unmap)(struct ct_vm *, struct ct_vm_block *block);
void *(*get_ptp_virt)(struct ct_vm *vm, int index);
dma_addr_t (*get_ptp_phys)(struct ct_vm *vm, int index);
};
int ct_vm_create(struct ct_vm **rvm);
int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci);
void ct_vm_destroy(struct ct_vm *vm);
#endif /* CTVMEM_H */

View file

@ -426,6 +426,7 @@ struct azx {
/* flags */
int position_fix;
int poll_count;
unsigned int running :1;
unsigned int initialized :1;
unsigned int single_cmd :1;
@ -506,7 +507,7 @@ static char *driver_short_names[] __devinitdata = {
#define get_azx_dev(substream) (substream->runtime->private_data)
static int azx_acquire_irq(struct azx *chip, int do_disconnect);
static int azx_send_cmd(struct hda_bus *bus, unsigned int val);
/*
* Interface for HD codec
*/
@ -664,11 +665,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
{
struct azx *chip = bus->private_data;
unsigned long timeout;
int do_poll = 0;
again:
timeout = jiffies + msecs_to_jiffies(1000);
for (;;) {
if (chip->polling_mode) {
if (chip->polling_mode || do_poll) {
spin_lock_irq(&chip->reg_lock);
azx_update_rirb(chip);
spin_unlock_irq(&chip->reg_lock);
@ -676,6 +678,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
if (!chip->rirb.cmds[addr]) {
smp_rmb();
bus->rirb_error = 0;
if (!do_poll)
chip->poll_count = 0;
return chip->rirb.res[addr]; /* the last value */
}
if (time_after(jiffies, timeout))
@ -688,6 +693,16 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
}
}
if (!chip->polling_mode && chip->poll_count < 2) {
snd_printdd(SFX "azx_get_response timeout, "
"polling the codec once: last cmd=0x%08x\n",
chip->last_cmd[addr]);
do_poll = 1;
chip->poll_count++;
goto again;
}
if (!chip->polling_mode) {
snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x\n",
@ -2043,7 +2058,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
{
if (request_irq(chip->pci->irq, azx_interrupt,
chip->msi ? 0 : IRQF_SHARED,
"HDA Intel", chip)) {
"hda_intel", chip)) {
printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
"disabling device\n", chip->pci->irq);
if (do_disconnect)

View file

@ -703,11 +703,13 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho
{
unsigned char nvol;
if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) {
nvol = 0;
else
} else {
nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) /
WM_VOL_MAX;
nvol += 0x1b;
}
wm_put(ice, index, nvol);
wm_put_nocache(ice, index, 0x180 | nvol);
@ -778,7 +780,7 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
for (ch = 0; ch < 2; ch++) {
unsigned int vol = ucontrol->value.integer.value[ch];
if (vol > WM_VOL_MAX)
continue;
vol = WM_VOL_MAX;
vol |= spec->master[ch] & WM_VOL_MUTE;
if (vol != spec->master[ch]) {
int dac;
@ -834,8 +836,8 @@ static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *
for (i = 0; i < voices; i++) {
unsigned int vol = ucontrol->value.integer.value[i];
if (vol > WM_VOL_MAX)
continue;
vol |= spec->vol[ofs+i];
vol = WM_VOL_MAX;
vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
if (vol != spec->vol[ofs+i]) {
spec->vol[ofs+i] = vol;
idx = WM_DAC_ATTEN + ofs + i;

View file

@ -145,6 +145,7 @@ static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
};
static const struct snd_soc_dapm_route omap3pandora_out_map[] = {
{"PCM DAC", NULL, "APLL Enable"},
{"Headphone Amplifier", NULL, "PCM DAC"},
{"Line Out", NULL, "PCM DAC"},
{"Headphone Jack", NULL, "Headphone Amplifier"},