mount options "ro,noload" can be used to prevent
writes to the filesystem.
+journal_checksum Enable checksumming of the journal transactions.
+ This will allow the recovery code in e2fsck and the
+ kernel to detect corruption in the kernel. It is a
+ compatible change and will be ignored by older kernels.
+
journal_async_commit Commit block can be written to disk without waiting
for descriptor blocks. If enabled older kernels cannot
- mount the device.
+ mount the device. This will enable 'journal_checksum'
+ internally.
journal=update Update the ext4 file system's journal to the current
format.
pcm_devs - Number of PCM devices assigned to each card
(default = 1, up to 4)
pcm_substreams - Number of PCM substreams assigned to each PCM
- (default = 8, up to 16)
+ (default = 8, up to 128)
hrtimer - Use hrtimer (=1, default) or system timer (=0)
fake_buffer - Fake buffer allocations (default = 1)
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <string.h>
#define _STR(x) #x
#define STR(x) _STR(x)
return NULL;
}
+ strcat(debugfs, "/tracing/");
debugfs_found = 1;
return debugfs;
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 32
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
NAME = Man-Eating Seals of Antiquity
# *DOCUMENTATION*
static inline void __flush_icache_all(void)
{
+#ifdef CONFIG_ARM_ERRATA_411920
+ extern void v6_icache_inval_all(void);
+ v6_icache_inval_all();
+#else
asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n"
:
: "r" (0));
+#endif
}
#define ARCH_HAS_FLUSH_ANON_PAGE
/*
* linux/arch/arm/kernel/signal.c
*
- * Copyright (C) 1995-2002 Russell King
+ * Copyright (C) 1995-2009 Russell King
*
* 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
*/
#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
+#define SWI_SYS_RESTART (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE)
/*
* With EABI, the syscall number has to be loaded into r7.
MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
};
+/*
+ * Either we support OABI only, or we have EABI with the OABI
+ * compat layer enabled. In the later case we don't know if
+ * user space is EABI or not, and if not we must not clobber r7.
+ * Always using the OABI syscall solves that issue and works for
+ * all those cases.
+ */
+const unsigned long syscall_restart_code[2] = {
+ SWI_SYS_RESTART, /* swi __NR_restart_syscall */
+ 0xe49df004, /* ldr pc, [sp], #4 */
+};
+
/*
* atomically swap in the new signal mask, and wait for a signal.
*/
regs->ARM_pc -= 4;
#else
u32 __user *usp;
- u32 swival = __NR_restart_syscall;
- regs->ARM_sp -= 12;
+ regs->ARM_sp -= 4;
usp = (u32 __user *)regs->ARM_sp;
- /*
- * Either we supports OABI only, or we have
- * EABI with the OABI compat layer enabled.
- * In the later case we don't know if user
- * space is EABI or not, and if not we must
- * not clobber r7. Always using the OABI
- * syscall solves that issue and works for
- * all those cases.
- */
- swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE;
-
- put_user(regs->ARM_pc, &usp[0]);
- /* swi __NR_restart_syscall */
- put_user(0xef000000 | swival, &usp[1]);
- /* ldr pc, [sp], #12 */
- put_user(0xe49df00c, &usp[2]);
-
- flush_icache_range((unsigned long)usp,
- (unsigned long)(usp + 3));
-
- regs->ARM_pc = regs->ARM_sp + 4;
+ put_user(regs->ARM_pc, usp);
+ regs->ARM_pc = KERN_RESTART_CODE;
#endif
}
}
/*
* linux/arch/arm/kernel/signal.h
*
- * Copyright (C) 2005 Russell King.
+ * Copyright (C) 2005-2009 Russell King.
*
* 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.
*/
#define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500)
+#define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
extern const unsigned long sigreturn_codes[7];
+extern const unsigned long syscall_restart_code[2];
/*
* linux/arch/arm/kernel/traps.c
*
- * Copyright (C) 1995-2002 Russell King
+ * Copyright (C) 1995-2009 Russell King
* Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
*
* This program is free software; you can redistribute it and/or modify
*/
memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
sizeof(sigreturn_codes));
+ memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
+ sizeof(syscall_restart_code));
flush_icache_range(vectors, vectors + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
* http://infocenter.arm.com/help/topic/com.arm.doc.subset.swdev.abi/index.html
*/
+#if !defined (__ARM_EABI__)
+#warning Your compiler does not have EABI support.
+#warning ARM unwind is known to compile only with EABI compilers.
+#warning Change compiler or disable ARM_UNWIND option.
+#elif (__GNUC__ == 4 && __GNUC_MINOR__ <= 2)
+#warning Your compiler is too buggy; it is known to not compile ARM unwind support.
+#warning Change compiler or disable ARM_UNWIND option.
+#endif
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#define ARCH_ID_AT91SAM9G20 0x019905a0
#define ARCH_ID_AT91SAM9RL64 0x019b03a0
#define ARCH_ID_AT91SAM9G45 0x819b05a0
+#define ARCH_ID_AT91SAM9G45MRL 0x819b05a2 /* aka 9G45-ES2 & non ES lots */
+#define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */
#define ARCH_ID_AT91CAP9 0x039A03A0
#define ARCH_ID_AT91SAM9XE128 0x329973a0
return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
}
+static inline unsigned long at91_cpu_fully_identify(void)
+{
+ return at91_sys_read(AT91_DBGU_CIDR);
+}
+
#define ARCH_EXID_AT91SAM9M11 0x00000001
#define ARCH_EXID_AT91SAM9M10 0x00000002
#define ARCH_EXID_AT91SAM9G45 0x00000004
#ifdef CONFIG_ARCH_AT91SAM9G45
#define cpu_is_at91sam9g45() (at91_cpu_identify() == ARCH_ID_AT91SAM9G45)
+#define cpu_is_at91sam9g45es() (at91_cpu_fully_identify() == ARCH_ID_AT91SAM9G45ES)
#else
#define cpu_is_at91sam9g45() (0)
+#define cpu_is_at91sam9g45es() (0)
#endif
#ifdef CONFIG_ARCH_AT91CAP9
#define BUS_OFFSET UL(0x80000000)
#define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET)
#define __bus_to_virt(x) ((x) - BUS_OFFSET + PAGE_OFFSET)
+#define __pfn_to_bus(x) (((x) << PAGE_SHIFT) + BUS_OFFSET)
#endif
extern int realview_flash_register(struct resource *res, u32 num);
extern int realview_eth_register(const char *name, struct resource *res);
extern int realview_usb_register(struct resource *res);
-
+extern void (*realview_reset)(char);
#endif
#define REALVIEW_PB1176_GIC_DIST_BASE 0x10041000 /* GIC distributor, on FPGA */
#define REALVIEW_PB1176_L220_BASE 0x10110000 /* L220 registers */
+/*
+ * Control register SYS_RESETCTL is set to 1 to force a soft reset
+ */
+#define REALVIEW_PB1176_SYS_LOCKVAL_RSTCTL 0x0100
+
#endif /* __ASM_ARCH_BOARD_PB1176_H */
#define REALVIEW_TC11MP_GIC_DIST_BASE 0x1F001000 /* Test chip interrupt controller distributor */
#define REALVIEW_TC11MP_L220_BASE 0x1F002000 /* L220 registers */
+ /*
+ * Values for REALVIEW_SYS_RESET_CTRL
+ */
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_CONFIGCLR 0x01
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_CONFIGINIT 0x02
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_DLLRESET 0x03
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_PLLRESET 0x04
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_POR 0x05
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_DoC 0x06
+
+#define REALVIEW_PB11MP_SYS_CTRL_LED (1 << 0)
+
#endif /* __ASM_ARCH_BOARD_PB11MP_H */
#define REALVIEW_SYS_TEST_OSC3 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC3_OFFSET)
#define REALVIEW_SYS_TEST_OSC4 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC4_OFFSET)
-/*
- * Values for REALVIEW_SYS_RESET_CTRL
- */
-#define REALVIEW_SYS_CTRL_RESET_CONFIGCLR 0x01
-#define REALVIEW_SYS_CTRL_RESET_CONFIGINIT 0x02
-#define REALVIEW_SYS_CTRL_RESET_DLLRESET 0x03
-#define REALVIEW_SYS_CTRL_RESET_PLLRESET 0x04
-#define REALVIEW_SYS_CTRL_RESET_POR 0x05
-#define REALVIEW_SYS_CTRL_RESET_DoC 0x06
-
-#define REALVIEW_SYS_CTRL_LED (1 << 0)
-
-
/* ------------------------------------------------------------------------
* RealView control registers
* ------------------------------------------------------------------------
* SYS_CLD, SYS_BOOTCS
*/
#define REALVIEW_SYS_LOCK_LOCKED (1 << 16)
-#define REALVIEW_SYS_LOCKVAL_MASK 0xFFFF /* write 0xA05F to enable write access */
+#define REALVIEW_SYS_LOCKVAL_MASK 0xA05F /* Enable write access */
/*
* REALVIEW_SYS_FLASH
#include <mach/hardware.h>
#include <mach/platform.h>
+void (*realview_reset)(char mode);
+
static inline void arch_idle(void)
{
/*
static inline void arch_reset(char mode, const char *cmd)
{
- void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_RESETCTL_OFFSET;
- unsigned int val;
-
/*
* To reset, we hit the on-board reset register
* in the system FPGA
*/
- val = __raw_readl(hdr_ctrl);
- val |= REALVIEW_SYS_CTRL_RESET_CONFIGCLR;
- __raw_writel(val, hdr_ctrl);
+ if (realview_reset)
+ realview_reset(mode);
}
#endif
.init = realview_pb1176_timer_init,
};
+static void realview_pb1176_reset(char mode)
+{
+ void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) +
+ REALVIEW_SYS_RESETCTL_OFFSET;
+ void __iomem *rst_hdr_ctrl = __io_address(REALVIEW_SYS_BASE) +
+ REALVIEW_SYS_LOCK_OFFSET;
+ __raw_writel(REALVIEW_SYS_LOCKVAL_MASK, rst_hdr_ctrl);
+ __raw_writel(REALVIEW_PB1176_SYS_LOCKVAL_RSTCTL, hdr_ctrl);
+}
+
static void __init realview_pb1176_init(void)
{
int i;
#ifdef CONFIG_LEDS
leds_event = realview_leds_event;
#endif
+ realview_reset = realview_pb1176_reset;
}
MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
.init = realview_pb11mp_timer_init,
};
+static void realview_pb11mp_reset(char mode)
+{
+ void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) +
+ REALVIEW_SYS_RESETCTL_OFFSET;
+ unsigned int val;
+
+ /*
+ * To reset, we hit the on-board reset register
+ * in the system FPGA
+ */
+ val = __raw_readl(hdr_ctrl);
+ val |= REALVIEW_PB11MP_SYS_CTRL_RESET_CONFIGCLR;
+ __raw_writel(val, hdr_ctrl);
+}
+
static void __init realview_pb11mp_init(void)
{
int i;
#ifdef CONFIG_LEDS
leds_event = realview_leds_event;
#endif
+ realview_reset = realview_pb11mp_reset;
}
MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
#include <linux/io.h>
#include <mach/hardware.h>
+#include <mach/gpio-fns.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
* waiting for reloads */
#define S3C2410_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */
+#define S3C2410_DMAF_CIRCULAR (1 << 2) /* no circular dma support */
+
/* dma buffer */
struct s3c2410_dma_buf;
typedef unsigned long dma_device_t;
+static inline bool s3c_dma_has_circular(void)
+{
+ return false;
+}
+
#endif /* __ASM_ARCH_DMA_H */
select LEDS_TRIGGER_BACKLIGHT
select SND_S3C24XX_SOC_S3C24XX_UDA134X
select S3C_DEV_NAND
+ select S3C_DEV_USB_HOST
help
Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
available via various sources. It can come with a 3.5" or 7" touch LCD.
.type = (S3C2410_LCDCON1_TFT16BPP |\
S3C2410_LCDCON1_TFT)
-struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
+static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
[0] = { /* mini2440 + 3.5" TFT + touchscreen */
_LCD_DECLARE(
7, /* The 3.5 is quite fast */
#define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
#define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
-struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
+static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
.displays = &mini2440_lcd_cfg[0], /* not constant! see init */
.num_displays = 1,
.default_display = 0,
#define S3C2410_DMAF_CIRCULAR (1 << 0)
+static inline bool s3c_dma_has_circular(void)
+{
+ return false;
+}
+
#include <plat/dma.h>
#endif /* __ASM_ARCH_IRQ_H */
isb();
flush_tlb_all();
if (icache_is_vivt_asid_tagged()) {
- asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n"
- "mcr p15, 0, %0, c7, c5, 6 @ flush BTAC/BTB\n"
- :
- : "r" (0));
+ __flush_icache_all();
dsb();
}
}
order = get_order(size);
- if (mask != 0xffffffff)
+ if (mask < 0xffffffffULL)
gfp |= GFP_DMA;
page = alloc_pages(gfp, order);
if (!mask)
goto error;
- if (mask != 0xffffffff)
+ if (mask < 0xffffffffULL)
gfp |= GFP_DMA;
virt = kmalloc(size, gfp);
if (!virt)
#include "mm.h"
-#ifdef CONFIG_ARM_ERRATA_411920
-extern void v6_icache_inval_all(void);
-#endif
-
#ifdef CONFIG_CPU_CACHE_VIPT
#define ALIAS_FLUSH_START 0xffff4000
flush_tlb_kernel_page(to);
asm( "mcrr p15, 0, %1, %0, c14\n"
- " mcr p15, 0, %2, c7, c10, 4\n"
-#ifndef CONFIG_ARM_ERRATA_411920
- " mcr p15, 0, %2, c7, c5, 0\n"
-#endif
+ " mcr p15, 0, %2, c7, c10, 4"
:
: "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
: "cc");
-#ifdef CONFIG_ARM_ERRATA_411920
- v6_icache_inval_all();
-#endif
+ __flush_icache_all();
}
void flush_cache_mm(struct mm_struct *mm)
if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n"
- " mcr p15, 0, %0, c7, c10, 4\n"
-#ifndef CONFIG_ARM_ERRATA_411920
- " mcr p15, 0, %0, c7, c5, 0\n"
-#endif
+ " mcr p15, 0, %0, c7, c10, 4"
:
: "r" (0)
: "cc");
-#ifdef CONFIG_ARM_ERRATA_411920
- v6_icache_inval_all();
-#endif
+ __flush_icache_all();
}
}
if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n"
- " mcr p15, 0, %0, c7, c10, 4\n"
-#ifndef CONFIG_ARM_ERRATA_411920
- " mcr p15, 0, %0, c7, c5, 0\n"
-#endif
+ " mcr p15, 0, %0, c7, c10, 4"
:
: "r" (0)
: "cc");
-#ifdef CONFIG_ARM_ERRATA_411920
- v6_icache_inval_all();
-#endif
+ __flush_icache_all();
}
}
struct membank *bank = &mi->bank[i];
if (!bank->highmem)
free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
- memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
}
/*
return 0;
}
EXPORT_SYMBOL(pfn_valid);
+
+static void arm_memory_present(struct meminfo *mi, int node)
+{
+}
+#else
+static void arm_memory_present(struct meminfo *mi, int node)
+{
+ int i;
+ for_each_nodebank(i, mi, node) {
+ struct membank *bank = &mi->bank[i];
+ memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
+ }
+}
#endif
static int __init meminfo_cmp(const void *_a, const void *_b)
*/
if (node == initrd_node)
bootmem_reserve_initrd(node);
+
+ /*
+ * Sparsemem tries to allocate bootmem in memory_present(),
+ * so must be done after the fixed reservations
+ */
+ arm_memory_present(mi, node);
}
/*
}
if (i == ARRAY_SIZE(cache_policies))
printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
+ /*
+ * This restriction is partly to do with the way we boot; it is
+ * unpredictable to have memory mapped using two different sets of
+ * memory attributes (shared, type, and cache attribs). We can not
+ * change these attributes once the initial assembly has setup the
+ * page tables.
+ */
if (cpu_architecture() >= CPU_ARCH_ARMv6) {
printk(KERN_WARNING "Only cachepolicy=writeback supported on ARMv6 and later\n");
cachepolicy = CPOLICY_WRITEBACK;
#ifndef CONFIG_SMP
#define TTB_FLAGS TTB_RGN_WBWA
+#define PMD_FLAGS PMD_SECT_WB
#else
#define TTB_FLAGS TTB_RGN_WBWA|TTB_S
+#define PMD_FLAGS PMD_SECT_WBWA|PMD_SECT_S
#endif
ENTRY(cpu_v6_proc_init)
.long 0x0007b000
.long 0x0007f000
.long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
+ PMD_SECT_AP_READ | \
+ PMD_FLAGS
.long PMD_TYPE_SECT | \
PMD_SECT_XN | \
PMD_SECT_AP_WRITE | \
#ifndef CONFIG_SMP
/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
#define TTB_FLAGS TTB_IRGN_WB|TTB_RGN_OC_WB
+#define PMD_FLAGS PMD_SECT_WB
#else
/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
#define TTB_FLAGS TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
+#define PMD_FLAGS PMD_SECT_WBWA|PMD_SECT_S
#endif
ENTRY(cpu_v7_proc_init)
.long 0x000f0000 @ Required ID value
.long 0x000f0000 @ Mask for ID
.long PMD_TYPE_SECT | \
- PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | \
PMD_SECT_AP_WRITE | \
- PMD_SECT_AP_READ
+ PMD_SECT_AP_READ | \
+ PMD_FLAGS
.long PMD_TYPE_SECT | \
PMD_SECT_XN | \
PMD_SECT_AP_WRITE | \
err:
return ret;
}
-EXPORT_SYMBOL_GPL(s3c_adc_convert);
+EXPORT_SYMBOL_GPL(s3c_adc_read);
static void s3c_adc_default_select(struct s3c_adc_client *client,
unsigned select)
static const char name_s3c2412[] = "S3C2412";
static const char name_s3c2440[] = "S3C2440";
static const char name_s3c2442[] = "S3C2442";
+static const char name_s3c2442b[] = "S3C2442B";
static const char name_s3c2443[] = "S3C2443";
static const char name_s3c2410a[] = "S3C2410A";
static const char name_s3c2440a[] = "S3C2440A";
.init = s3c2442_init,
.name = name_s3c2442
},
+ {
+ .idcode = 0x32440aab,
+ .idmask = 0xffffffff,
+ .map_io = s3c244x_map_io,
+ .init_clocks = s3c244x_init_clocks,
+ .init_uarts = s3c244x_init_uarts,
+ .init = s3c2442_init,
+ .name = name_s3c2442b
+ },
{
.idcode = 0x32412001,
.idmask = 0xffffffff,
{
unsigned long reload;
- pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
- buf, (unsigned long)buf->data, buf->size);
-
if (buf == NULL) {
dmawarn("buffer is NULL\n");
return -EINVAL;
}
+ pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+ buf, (unsigned long)buf->data, buf->size);
+
/* check the state of the channel before we do anything */
if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
#include <linux/io.h>
#include <mach/hardware.h>
+#include <mach/gpio-fns.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
/* S3C2410 and compatible exported functions */
extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
+extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
+#ifdef CONFIG_S3C2410_IOTIMING
extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *iot);
extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *iot);
-
-extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
+#else
+#define s3c2410_iotiming_calc NULL
+#define s3c2410_iotiming_get NULL
+#define s3c2410_iotiming_set NULL
+#endif /* CONFIG_S3C2410_IOTIMING */
/* S3C2412 compatible routines */
#define s3c2410_init_uarts NULL
#define s3c2410_map_io NULL
#define s3c2410_init NULL
+#define s3c2410a_init NULL
#endif
extern int s3c2410_baseclk_add(void);
#define S3C6400_CLKDIV0_HCLK_SHIFT (8)
#define S3C6400_CLKDIV0_MPLL_MASK (0x1 << 4)
#define S3C6400_CLKDIV0_MPLL_SHIFT (4)
-#define S3C6400_CLKDIV0_ARM_MASK (0x3 << 0)
-#define S3C6410_CLKDIV0_ARM_MASK (0x7 << 0)
+#define S3C6400_CLKDIV0_ARM_MASK (0x7 << 0)
+#define S3C6410_CLKDIV0_ARM_MASK (0xf << 0)
#define S3C6400_CLKDIV0_ARM_SHIFT (0)
/* CLKDIV1 */
printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+ /* For now assume the mux always selects the crystal */
+ clk_ext_xtal_mux.parent = xtal_clk;
+
epll = s3c6400_get_epll(xtal);
mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
#define cpu_is_at91sam9263() (0)
#define cpu_is_at91sam9rl() (0)
#define cpu_is_at91cap9() (0)
+#define cpu_is_at91sam9g10() (0)
+#define cpu_is_at91sam9g45() (0)
+#define cpu_is_at91sam9g45es() (0)
#endif /* __ASM_ARCH_CPU_H */
* by atomically noting the tail and incrementing it by one (thus adding
* ourself to the queue and noting our position), then waiting until the head
* becomes equal to the the initial value of the tail.
+ * The pad bits in the middle are used to prevent the next_ticket number
+ * overflowing into the now_serving number.
*
- * 63 32 31 0
+ * 31 17 16 15 14 0
* +----------------------------------------------------+
- * | next_ticket_number | now_serving |
+ * | now_serving | padding | next_ticket |
* +----------------------------------------------------+
*/
-#define TICKET_SHIFT 32
+#define TICKET_SHIFT 17
+#define TICKET_BITS 15
+#define TICKET_MASK ((1 << TICKET_BITS) - 1)
static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
{
- int *p = (int *)&lock->lock, turn, now_serving;
+ int *p = (int *)&lock->lock, ticket, serve;
- now_serving = *p;
- turn = ia64_fetchadd(1, p+1, acq);
+ ticket = ia64_fetchadd(1, p, acq);
- if (turn == now_serving)
+ if (!(((ticket >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
return;
- do {
+ ia64_invala();
+
+ for (;;) {
+ asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(p) : "memory");
+
+ if (!(((serve >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
+ return;
cpu_relax();
- } while (ACCESS_ONCE(*p) != turn);
+ }
}
static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
{
- long tmp = ACCESS_ONCE(lock->lock), try;
-
- if (!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1L << TICKET_SHIFT) - 1))) {
- try = tmp + (1L << TICKET_SHIFT);
+ int tmp = ACCESS_ONCE(lock->lock);
- return ia64_cmpxchg(acq, &lock->lock, tmp, try, sizeof (tmp)) == tmp;
- }
+ if (!(((tmp >> TICKET_SHIFT) ^ tmp) & TICKET_MASK))
+ return ia64_cmpxchg(acq, &lock->lock, tmp, tmp + 1, sizeof (tmp)) == tmp;
return 0;
}
static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
{
- int *p = (int *)&lock->lock;
+ unsigned short *p = (unsigned short *)&lock->lock + 1, tmp;
- (void)ia64_fetchadd(1, p, rel);
+ asm volatile ("ld2.bias %0=[%1]" : "=r"(tmp) : "r"(p));
+ ACCESS_ONCE(*p) = (tmp + 2) & ~1;
+}
+
+static __always_inline void __ticket_spin_unlock_wait(raw_spinlock_t *lock)
+{
+ int *p = (int *)&lock->lock, ticket;
+
+ ia64_invala();
+
+ for (;;) {
+ asm volatile ("ld4.c.nc %0=[%1]" : "=r"(ticket) : "r"(p) : "memory");
+ if (!(((ticket >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
+ return;
+ cpu_relax();
+ }
}
static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
{
long tmp = ACCESS_ONCE(lock->lock);
- return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1L << TICKET_SHIFT) - 1));
+ return !!(((tmp >> TICKET_SHIFT) ^ tmp) & TICKET_MASK);
}
static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
{
long tmp = ACCESS_ONCE(lock->lock);
- return (((tmp >> TICKET_SHIFT) - tmp) & ((1L << TICKET_SHIFT) - 1)) > 1;
+ return ((tmp - (tmp >> TICKET_SHIFT)) & TICKET_MASK) > 1;
}
static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
{
- while (__raw_spin_is_locked(lock))
- cpu_relax();
+ __ticket_spin_unlock_wait(lock);
}
#define __raw_read_can_lock(rw) (*(volatile int *)(rw) >= 0)
#endif
typedef struct {
- volatile unsigned long lock;
+ volatile unsigned int lock;
} raw_spinlock_t;
#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
memcpy(current->comm, comm, sizeof(current->comm));
}
+static void
+finish_pt_regs(struct pt_regs *regs, const pal_min_state_area_t *ms,
+ unsigned long *nat)
+{
+ const u64 *bank;
+
+ /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
+ * pmsa_{xip,xpsr,xfs}
+ */
+ if (ia64_psr(regs)->ic) {
+ regs->cr_iip = ms->pmsa_iip;
+ regs->cr_ipsr = ms->pmsa_ipsr;
+ regs->cr_ifs = ms->pmsa_ifs;
+ } else {
+ regs->cr_iip = ms->pmsa_xip;
+ regs->cr_ipsr = ms->pmsa_xpsr;
+ regs->cr_ifs = ms->pmsa_xfs;
+ }
+ regs->pr = ms->pmsa_pr;
+ regs->b0 = ms->pmsa_br0;
+ regs->ar_rsc = ms->pmsa_rsc;
+ copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, ®s->r1, nat);
+ copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, ®s->r2, nat);
+ copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, ®s->r3, nat);
+ copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, ®s->r8, nat);
+ copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, ®s->r9, nat);
+ copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, ®s->r10, nat);
+ copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, ®s->r11, nat);
+ copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, ®s->r12, nat);
+ copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, ®s->r13, nat);
+ copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, ®s->r14, nat);
+ copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, ®s->r15, nat);
+ if (ia64_psr(regs)->bn)
+ bank = ms->pmsa_bank1_gr;
+ else
+ bank = ms->pmsa_bank0_gr;
+ copy_reg(&bank[16-16], ms->pmsa_nat_bits, ®s->r16, nat);
+ copy_reg(&bank[17-16], ms->pmsa_nat_bits, ®s->r17, nat);
+ copy_reg(&bank[18-16], ms->pmsa_nat_bits, ®s->r18, nat);
+ copy_reg(&bank[19-16], ms->pmsa_nat_bits, ®s->r19, nat);
+ copy_reg(&bank[20-16], ms->pmsa_nat_bits, ®s->r20, nat);
+ copy_reg(&bank[21-16], ms->pmsa_nat_bits, ®s->r21, nat);
+ copy_reg(&bank[22-16], ms->pmsa_nat_bits, ®s->r22, nat);
+ copy_reg(&bank[23-16], ms->pmsa_nat_bits, ®s->r23, nat);
+ copy_reg(&bank[24-16], ms->pmsa_nat_bits, ®s->r24, nat);
+ copy_reg(&bank[25-16], ms->pmsa_nat_bits, ®s->r25, nat);
+ copy_reg(&bank[26-16], ms->pmsa_nat_bits, ®s->r26, nat);
+ copy_reg(&bank[27-16], ms->pmsa_nat_bits, ®s->r27, nat);
+ copy_reg(&bank[28-16], ms->pmsa_nat_bits, ®s->r28, nat);
+ copy_reg(&bank[29-16], ms->pmsa_nat_bits, ®s->r29, nat);
+ copy_reg(&bank[30-16], ms->pmsa_nat_bits, ®s->r30, nat);
+ copy_reg(&bank[31-16], ms->pmsa_nat_bits, ®s->r31, nat);
+}
+
/* On entry to this routine, we are running on the per cpu stack, see
* mca_asm.h. The original stack has not been touched by this event. Some of
* the original stack's registers will be in the RBS on this stack. This stack
u64 r12 = ms->pmsa_gr[12-1], r13 = ms->pmsa_gr[13-1];
u64 ar_bspstore = regs->ar_bspstore;
u64 ar_bsp = regs->ar_bspstore + (loadrs >> 16);
- const u64 *bank;
const char *msg;
int cpu = smp_processor_id();
p = (char *)r12 - sizeof(*regs);
old_regs = (struct pt_regs *)p;
memcpy(old_regs, regs, sizeof(*regs));
- /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
- * pmsa_{xip,xpsr,xfs}
- */
- if (ia64_psr(regs)->ic) {
- old_regs->cr_iip = ms->pmsa_iip;
- old_regs->cr_ipsr = ms->pmsa_ipsr;
- old_regs->cr_ifs = ms->pmsa_ifs;
- } else {
- old_regs->cr_iip = ms->pmsa_xip;
- old_regs->cr_ipsr = ms->pmsa_xpsr;
- old_regs->cr_ifs = ms->pmsa_xfs;
- }
- old_regs->pr = ms->pmsa_pr;
- old_regs->b0 = ms->pmsa_br0;
old_regs->loadrs = loadrs;
- old_regs->ar_rsc = ms->pmsa_rsc;
old_unat = old_regs->ar_unat;
- copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, &old_regs->r1, &old_unat);
- copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, &old_regs->r2, &old_unat);
- copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, &old_regs->r3, &old_unat);
- copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, &old_regs->r8, &old_unat);
- copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, &old_regs->r9, &old_unat);
- copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, &old_regs->r10, &old_unat);
- copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, &old_regs->r11, &old_unat);
- copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, &old_regs->r12, &old_unat);
- copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, &old_regs->r13, &old_unat);
- copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, &old_regs->r14, &old_unat);
- copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, &old_regs->r15, &old_unat);
- if (ia64_psr(old_regs)->bn)
- bank = ms->pmsa_bank1_gr;
- else
- bank = ms->pmsa_bank0_gr;
- copy_reg(&bank[16-16], ms->pmsa_nat_bits, &old_regs->r16, &old_unat);
- copy_reg(&bank[17-16], ms->pmsa_nat_bits, &old_regs->r17, &old_unat);
- copy_reg(&bank[18-16], ms->pmsa_nat_bits, &old_regs->r18, &old_unat);
- copy_reg(&bank[19-16], ms->pmsa_nat_bits, &old_regs->r19, &old_unat);
- copy_reg(&bank[20-16], ms->pmsa_nat_bits, &old_regs->r20, &old_unat);
- copy_reg(&bank[21-16], ms->pmsa_nat_bits, &old_regs->r21, &old_unat);
- copy_reg(&bank[22-16], ms->pmsa_nat_bits, &old_regs->r22, &old_unat);
- copy_reg(&bank[23-16], ms->pmsa_nat_bits, &old_regs->r23, &old_unat);
- copy_reg(&bank[24-16], ms->pmsa_nat_bits, &old_regs->r24, &old_unat);
- copy_reg(&bank[25-16], ms->pmsa_nat_bits, &old_regs->r25, &old_unat);
- copy_reg(&bank[26-16], ms->pmsa_nat_bits, &old_regs->r26, &old_unat);
- copy_reg(&bank[27-16], ms->pmsa_nat_bits, &old_regs->r27, &old_unat);
- copy_reg(&bank[28-16], ms->pmsa_nat_bits, &old_regs->r28, &old_unat);
- copy_reg(&bank[29-16], ms->pmsa_nat_bits, &old_regs->r29, &old_unat);
- copy_reg(&bank[30-16], ms->pmsa_nat_bits, &old_regs->r30, &old_unat);
- copy_reg(&bank[31-16], ms->pmsa_nat_bits, &old_regs->r31, &old_unat);
+ finish_pt_regs(old_regs, ms, &old_unat);
/* Next stack a struct switch_stack. mca_asm.S built a partial
* switch_stack, copy it and fill in the blanks using pt_regs and
no_mod:
mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
smp_processor_id(), type, msg);
+ old_unat = regs->ar_unat;
+ finish_pt_regs(regs, ms, &old_unat);
return previous_current;
}
*/
int no_unaligned_warning;
int unaligned_dump_stack;
-static int noprint_warning;
/*
* For M-unit:
/* watch for command names containing %s */
printk(KERN_WARNING "%s", buf);
} else {
- if (no_unaligned_warning && !noprint_warning) {
- noprint_warning = 1;
- printk(KERN_WARNING "%s(%d) encountered an "
+ if (no_unaligned_warning) {
+ printk_once(KERN_WARNING "%s(%d) encountered an "
"unaligned exception which required\n"
"kernel assistance, which degrades "
"the performance of the application.\n"
* this primitive it can be moved up to a spinaphore.h header.
*/
struct spinaphore {
- atomic_t cur;
+ unsigned long ticket;
+ unsigned long serve;
};
static inline void spinaphore_init(struct spinaphore *ss, int val)
{
- atomic_set(&ss->cur, val);
+ ss->ticket = 0;
+ ss->serve = val;
}
static inline void down_spin(struct spinaphore *ss)
{
- while (unlikely(!atomic_add_unless(&ss->cur, -1, 0)))
- while (atomic_read(&ss->cur) == 0)
- cpu_relax();
+ unsigned long t = ia64_fetchadd(1, &ss->ticket, acq), serve;
+
+ if (time_before(t, ss->serve))
+ return;
+
+ ia64_invala();
+
+ for (;;) {
+ asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
+ if (time_before(t, serve))
+ return;
+ cpu_relax();
+ }
}
static inline void up_spin(struct spinaphore *ss)
{
- atomic_add(1, &ss->cur);
+ ia64_fetchadd(1, &ss->serve, rel);
}
static struct spinaphore ptcg_sem;
if ((seg | reg) <= 255) {
addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
mode = 0;
- } else {
+ } else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
mode = 1;
+ } else {
+ return -EINVAL;
}
+
result = ia64_sal_pci_config_read(addr, mode, len, &data);
if (result != 0)
return -EINVAL;
if ((seg | reg) <= 255) {
addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
mode = 0;
- } else {
+ } else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
mode = 1;
+ } else {
+ return -EINVAL;
}
result = ia64_sal_pci_config_write(addr, mode, len, value);
if (result != 0)
* Additionally note that the struct sn_flush_device_war also has to be
* removed from arch/ia64/sn/include/xtalk/hubdev.h
*/
-static u8 war_implemented = 0;
static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
struct sn_flush_device_common *common)
struct sn_flush_device_war *dev_entry;
struct ia64_sal_retval isrv = {0,0,0,0};
- if (!war_implemented) {
- printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
- "PROM flush WAR\n");
- war_implemented = 1;
- }
+ printk_once(KERN_WARNING
+ "PROM version < 4.50 -- implementing old PROM flush WAR\n");
war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
BUG_ON(!war_list);
break;
case SN_HWPERF_GET_OBJ_NODE:
- if (a.sz != sizeof(u64) || a.arg < 0) {
+ i = a.arg;
+ if (a.sz != sizeof(u64) || i < 0) {
r = -EINVAL;
goto error;
}
if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
- if (a.arg >= nobj) {
+ if (i >= nobj) {
r = -EINVAL;
vfree(objs);
goto error;
}
- if (objs[(i = a.arg)].id != a.arg) {
+ if (objs[i].id != a.arg) {
for (i = 0; i < nobj; i++) {
if (objs[i].id == a.arg)
break;
config MIPS_L1_CACHE_SHIFT
int
- default "4" if MACH_DECSTATION || MIKROTIK_RB532
+ default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL
+ default "6" if MIPS_CPU_SCACHE
default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
- default "4" if PMC_MSP4200_EVAL
default "5"
config HAVE_STD_PC_SERIAL_PORT
au_sync();
}
+static void au1x_ic0_maskack(unsigned int irq_nr)
+{
+ unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+
+ au_writel(1 << bit, IC0_WAKECLR);
+ au_writel(1 << bit, IC0_MASKCLR);
+ au_writel(1 << bit, IC0_RISINGCLR);
+ au_writel(1 << bit, IC0_FALLINGCLR);
+ au_sync();
+}
+
+static void au1x_ic1_maskack(unsigned int irq_nr)
+{
+ unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+
+ au_writel(1 << bit, IC1_WAKECLR);
+ au_writel(1 << bit, IC1_MASKCLR);
+ au_writel(1 << bit, IC1_RISINGCLR);
+ au_writel(1 << bit, IC1_FALLINGCLR);
+ au_sync();
+}
+
static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
{
unsigned int bit = irq - AU1000_INTC1_INT_BASE;
/*
* irq_chips for both ICs; this way the mask handlers can be
* as short as possible.
- *
- * NOTE: the ->ack() callback is used by the handle_edge_irq
- * flowhandler only, the ->mask_ack() one by handle_level_irq,
- * so no need for an irq_chip for each type of irq (level/edge).
*/
static struct irq_chip au1x_ic0_chip = {
.name = "Alchemy-IC0",
- .ack = au1x_ic0_ack, /* edge */
+ .ack = au1x_ic0_ack,
.mask = au1x_ic0_mask,
- .mask_ack = au1x_ic0_mask, /* level */
+ .mask_ack = au1x_ic0_maskack,
.unmask = au1x_ic0_unmask,
.set_type = au1x_ic_settype,
};
static struct irq_chip au1x_ic1_chip = {
.name = "Alchemy-IC1",
- .ack = au1x_ic1_ack, /* edge */
+ .ack = au1x_ic1_ack,
.mask = au1x_ic1_mask,
- .mask_ack = au1x_ic1_mask, /* level */
+ .mask_ack = au1x_ic1_maskack,
.unmask = au1x_ic1_unmask,
.set_type = au1x_ic_settype,
.set_wake = au1x_ic1_setwake,
#else
au_writel(0xf, Au1500_PCI_CFG);
#endif
+ board_pci_idsel = mtx1_pci_idsel;
#endif
/* Initialize sys_pinfunc */
alchemy_gpio_direction_output(211, 1); /* green on */
alchemy_gpio_direction_output(212, 0); /* red off */
- board_pci_idsel = mtx1_pci_idsel;
-
printk(KERN_INFO "4G Systems MTX-1 Board\n");
}
{
u16 chip_id;
int res;
+ u32 *bootcr, val;
#ifdef CONFIG_SERIAL_8250
static struct uart_port uart_port[2];
ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
- res = platform_device_register(&ar7_wdt);
+ bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+ val = *bootcr;
+ iounmap(bootcr);
+
+ /* Register watchdog only if enabled in hardware */
+ if (val & AR7_WDT_HW_ENA)
+ res = platform_device_register(&ar7_wdt);
return res;
}
obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
- dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o
+ dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_dsp.h>
#include <bcm63xx_dev_pcmcia.h>
-#include <bcm63xx_dev_uart.h>
#include <board_bcm963xx.h>
#define PFX "board_bcm963xx: "
{
u32 val;
- bcm63xx_uart_register();
-
if (board.has_pccard)
bcm63xx_pcmcia_register();
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpu.h>
+#include <asm/cpu-info.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
{
unsigned int tmp, expected_cpu_id;
struct cpuinfo_mips *c = ¤t_cpu_data;
+ unsigned int cpu = smp_processor_id();
/* soc registers location depends on cpu type */
expected_cpu_id = 0;
* BCM6338 as the same PrId as BCM3302 see arch/mips/kernel/cpu-probe.c
*/
case CPU_BCM3302:
+ __cpu_name[cpu] = "Broadcom BCM6338";
expected_cpu_id = BCM6338_CPU_ID;
bcm63xx_regs_base = bcm96338_regs_base;
bcm63xx_irqs = bcm96338_irqs;
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <bcm63xx_cpu.h>
-#include <bcm63xx_dev_uart.h>
static struct resource uart_resources[] = {
{
uart_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
return platform_device_register(&bcm63xx_uart_device);
}
+arch_initcall(bcm63xx_uart_register);
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <bcm63xx_cpu.h>
+
+static struct resource wdt_resources[] = {
+ {
+ .start = -1, /* filled at runtime */
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device bcm63xx_wdt_device = {
+ .name = "bcm63xx-wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(wdt_resources),
+ .resource = wdt_resources,
+};
+
+int __init bcm63xx_wdt_register(void)
+{
+ wdt_resources[0].start = bcm63xx_regset_address(RSET_WDT);
+ wdt_resources[0].end = wdt_resources[0].start;
+ wdt_resources[0].end += RSET_WDT_SIZE - 1;
+
+ return platform_device_register(&bcm63xx_wdt_device);
+}
+arch_initcall(bcm63xx_wdt_register);
bcm6348_a1_reboot();
printk(KERN_INFO "triggering watchdog soft-reset...\n");
- bcm_perf_writel(SYS_PLL_SOFT_RESET, PERF_SYS_PLL_CTL_REG);
+ reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
+ reg |= SYS_PLL_SOFT_RESET;
+ bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
while (1)
;
}
DEFINE_RWLOCK(octeon_irq_ciu1_rwlock);
DEFINE_SPINLOCK(octeon_irq_msi_lock);
+static int octeon_coreid_for_cpu(int cpu)
+{
+#ifdef CONFIG_SMP
+ return cpu_logical_map(cpu);
+#else
+ return cvmx_get_core_num();
+#endif
+}
+
static void octeon_irq_core_ack(unsigned int irq)
{
unsigned int bit = irq - OCTEON_IRQ_SW0;
int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
unsigned long flags;
uint64_t en0;
-#ifdef CONFIG_SMP
int cpu;
write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
for_each_online_cpu(cpu) {
- int coreid = cpu_logical_map(cpu);
+ int coreid = octeon_coreid_for_cpu(cpu);
en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
en0 &= ~(1ull << bit);
cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
*/
cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
-#else
- int coreid = cvmx_get_core_num();
- local_irq_save(flags);
- en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
- en0 &= ~(1ull << bit);
- cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
- cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
- local_irq_restore(flags);
-#endif
+}
+
+/*
+ * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_enable_v2(unsigned int irq)
+{
+ int index = cvmx_get_core_num() * 2;
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+
+ cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+}
+
+/*
+ * Disable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_disable_v2(unsigned int irq)
+{
+ int index = cvmx_get_core_num() * 2;
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+
+ cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+}
+
+/*
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_disable_all_v2(unsigned int irq)
+{
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+ int index;
+ int cpu;
+ for_each_online_cpu(cpu) {
+ index = octeon_coreid_for_cpu(cpu) * 2;
+ cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+ }
}
#ifdef CONFIG_SMP
static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
{
int cpu;
+ unsigned long flags;
int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
- write_lock(&octeon_irq_ciu0_rwlock);
+ write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
for_each_online_cpu(cpu) {
- int coreid = cpu_logical_map(cpu);
+ int coreid = octeon_coreid_for_cpu(cpu);
uint64_t en0 =
cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
if (cpumask_test_cpu(cpu, dest))
* of them are done.
*/
cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
- write_unlock(&octeon_irq_ciu0_rwlock);
+ write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
return 0;
}
+
+/*
+ * Set affinity for the irq for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq,
+ const struct cpumask *dest)
+{
+ int cpu;
+ int index;
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+ for_each_online_cpu(cpu) {
+ index = octeon_coreid_for_cpu(cpu) * 2;
+ if (cpumask_test_cpu(cpu, dest))
+ cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+ else
+ cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+ }
+ return 0;
+}
+#endif
+
+/*
+ * Newer octeon chips have support for lockless CIU operation.
+ */
+static struct irq_chip octeon_irq_chip_ciu0_v2 = {
+ .name = "CIU0",
+ .enable = octeon_irq_ciu0_enable_v2,
+ .disable = octeon_irq_ciu0_disable_all_v2,
+ .ack = octeon_irq_ciu0_disable_v2,
+ .eoi = octeon_irq_ciu0_enable_v2,
+#ifdef CONFIG_SMP
+ .set_affinity = octeon_irq_ciu0_set_affinity_v2,
#endif
+};
static struct irq_chip octeon_irq_chip_ciu0 = {
.name = "CIU0",
int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
unsigned long flags;
uint64_t en1;
-#ifdef CONFIG_SMP
int cpu;
write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
for_each_online_cpu(cpu) {
- int coreid = cpu_logical_map(cpu);
+ int coreid = octeon_coreid_for_cpu(cpu);
en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
en1 &= ~(1ull << bit);
cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
*/
cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
-#else
- int coreid = cvmx_get_core_num();
- local_irq_save(flags);
- en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
- en1 &= ~(1ull << bit);
- cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
- cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
- local_irq_restore(flags);
-#endif
+}
+
+/*
+ * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_enable_v2(unsigned int irq)
+{
+ int index = cvmx_get_core_num() * 2 + 1;
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+
+ cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+}
+
+/*
+ * Disable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_disable_v2(unsigned int irq)
+{
+ int index = cvmx_get_core_num() * 2 + 1;
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+
+ cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+}
+
+/*
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_disable_all_v2(unsigned int irq)
+{
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+ int index;
+ int cpu;
+ for_each_online_cpu(cpu) {
+ index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+ cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+ }
}
#ifdef CONFIG_SMP
-static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu1_set_affinity(unsigned int irq,
+ const struct cpumask *dest)
{
int cpu;
+ unsigned long flags;
int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
- write_lock(&octeon_irq_ciu1_rwlock);
+ write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
for_each_online_cpu(cpu) {
- int coreid = cpu_logical_map(cpu);
+ int coreid = octeon_coreid_for_cpu(cpu);
uint64_t en1 =
cvmx_read_csr(CVMX_CIU_INTX_EN1
(coreid * 2 + 1));
* of them are done.
*/
cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
- write_unlock(&octeon_irq_ciu1_rwlock);
+ write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
+
+ return 0;
+}
+/*
+ * Set affinity for the irq for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq,
+ const struct cpumask *dest)
+{
+ int cpu;
+ int index;
+ u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+ for_each_online_cpu(cpu) {
+ index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+ if (cpumask_test_cpu(cpu, dest))
+ cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+ else
+ cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+ }
return 0;
}
#endif
+/*
+ * Newer octeon chips have support for lockless CIU operation.
+ */
+static struct irq_chip octeon_irq_chip_ciu1_v2 = {
+ .name = "CIU0",
+ .enable = octeon_irq_ciu1_enable_v2,
+ .disable = octeon_irq_ciu1_disable_all_v2,
+ .ack = octeon_irq_ciu1_disable_v2,
+ .eoi = octeon_irq_ciu1_enable_v2,
+#ifdef CONFIG_SMP
+ .set_affinity = octeon_irq_ciu1_set_affinity_v2,
+#endif
+};
+
static struct irq_chip octeon_irq_chip_ciu1 = {
.name = "CIU1",
.enable = octeon_irq_ciu1_enable,
void __init arch_init_irq(void)
{
int irq;
+ struct irq_chip *chip0;
+ struct irq_chip *chip1;
#ifdef CONFIG_SMP
/* Set the default affinity to the boot cpu. */
if (NR_IRQS < OCTEON_IRQ_LAST)
pr_err("octeon_irq_init: NR_IRQS is set too low\n");
+ if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
+ OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
+ OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
+ chip0 = &octeon_irq_chip_ciu0_v2;
+ chip1 = &octeon_irq_chip_ciu1_v2;
+ } else {
+ chip0 = &octeon_irq_chip_ciu0;
+ chip1 = &octeon_irq_chip_ciu1;
+ }
+
/* 0 - 15 reserved for i8259 master and slave controller. */
/* 17 - 23 Mips internal */
/* 24 - 87 CIU_INT_SUM0 */
for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
- set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu0,
- handle_percpu_irq);
+ set_irq_chip_and_handler(irq, chip0, handle_percpu_irq);
}
/* 88 - 151 CIU_INT_SUM1 */
for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_RESERVED151; irq++) {
- set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu1,
- handle_percpu_irq);
+ set_irq_chip_and_handler(irq, chip1, handle_percpu_irq);
}
#ifdef CONFIG_PCI_MSI
#ifdef CONFIG_HOTPLUG_CPU
static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu)
{
- unsigned int isset;
-#ifdef CONFIG_SMP
- int coreid = cpu_logical_map(cpu);
-#else
- int coreid = cvmx_get_core_num();
-#endif
+ unsigned int isset;
+ int coreid = octeon_coreid_for_cpu(cpu);
int bit = (irq < OCTEON_IRQ_WDOG0) ?
- irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0;
+ irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0;
if (irq < 64) {
isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) &
(1ull << bit)) >> bit;
cvmx_write_csr(CVMX_CIU_MBOX_SETX(coreid), action);
}
-static inline void octeon_send_ipi_mask(cpumask_t mask, unsigned int action)
+static inline void octeon_send_ipi_mask(const struct cpumask *mask,
+ unsigned int action)
{
unsigned int i;
- for_each_cpu_mask(i, mask)
+ for_each_cpu_mask(i, *mask)
octeon_send_ipi_single(i, action);
}
#define FIX_N_COLOURS 8
FIX_CMAP_BEGIN,
#ifdef CONFIG_MIPS_MT_SMTC
- FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS),
+ FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS * 2),
#else
- FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS,
+ FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * 2),
#endif
#ifdef CONFIG_HIGHMEM
/* reserved pte's for temporary kernel mappings */
#define GCMP_GDB_OFS 0x8000 /* Global Debug Block */
/* Offsets to individual GCMP registers from GCMP base */
-#define GCMPOFS(block, tag, reg) (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
+#define GCMPOFS(block, tag, reg) \
+ (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
+#define GCMPOFSn(block, tag, reg, n) \
+ (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS(n))
#define GCMPGCBOFS(reg) GCMPOFS(GCB, GCB, reg)
+#define GCMPGCBOFSn(reg, n) GCMPOFSn(GCB, GCB, reg, n)
#define GCMPCLCBOFS(reg) GCMPOFS(CLCB, CCB, reg)
#define GCMPCOCBOFS(reg) GCMPOFS(COCB, CCB, reg)
#define GCMPGDBOFS(reg) GCMPOFS(GDB, GDB, reg)
/* GCMP register access */
#define GCMPGCB(reg) REGP(_gcmp_base, GCMPGCBOFS(reg))
+#define GCMPGCBn(reg, n) REGP(_gcmp_base, GCMPGCBOFSn(reg, n))
#define GCMPCLCB(reg) REGP(_gcmp_base, GCMPCLCBOFS(reg))
#define GCMPCOCB(reg) REGP(_gcmp_base, GCMPCOCBOFS(reg))
#define GCMPGDB(reg) REGP(_gcmp_base, GCMPGDBOFS(reg))
#define GCMP_GCB_GCMPB_GCMPBASE_MSK GCMPGCBMSK(GCMPB_GCMPBASE, 17)
#define GCMP_GCB_GCMPB_CMDEFTGT_SHF 0
#define GCMP_GCB_GCMPB_CMDEFTGT_MSK GCMPGCBMSK(GCMPB_CMDEFTGT, 2)
-#define GCMP_GCB_GCMPB_CMDEFTGT_MEM 0
-#define GCMP_GCB_GCMPB_CMDEFTGT_MEM1 1
-#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU1 2
-#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU2 3
+#define GCMP_GCB_GCMPB_CMDEFTGT_DISABLED 0
+#define GCMP_GCB_GCMPB_CMDEFTGT_MEM 1
+#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU1 2
+#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU2 3
#define GCMP_GCB_CCMC_OFS 0x0010 /* Global CM Control */
#define GCMP_GCB_GCSRAP_OFS 0x0020 /* Global CSR Access Privilege */
#define GCMP_GCB_GCSRAP_CMACCESS_SHF 0
#define GCMP_CCB_DBGGROUP_OFS 0x0100 /* DebugBreak Group */
extern int __init gcmp_probe(unsigned long, unsigned long);
-
+extern int __init gcmp_niocu(void);
+extern void __init gcmp_setregion(int, unsigned long, unsigned long, int);
#endif /* _ASM_GCMPREGS_H */
#define _ASM_GICREGS_H
#undef GICISBYTELITTLEENDIAN
-#define GICISWORDLITTLEENDIAN
/* Constants */
#define GIC_POL_POS 1
#define GIC_TRIG_EDGE 1
#define GIC_TRIG_LEVEL 0
-#ifdef CONFIG_SMP
#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
-#else
-#define GIC_NUM_INTRS 32
-#endif
#define MSK(n) ((1 << (n)) - 1)
#define REG32(addr) (*(volatile unsigned int *) (addr))
#define USM_VISIBLE_SECTION_SIZE 0x10000
/* Register Map for Shared Section */
-#if defined(CONFIG_CPU_LITTLE_ENDIAN) || defined(GICISWORDLITTLEENDIAN)
#define GIC_SH_CONFIG_OFS 0x0000
/* Shared Global Counter */
#define GIC_SH_COUNTER_31_00_OFS 0x0010
#define GIC_SH_COUNTER_63_32_OFS 0x0014
+#define GIC_SH_REVISIONID_OFS 0x0020
/* Interrupt Polarity */
#define GIC_SH_POL_31_0_OFS 0x0100
(GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + (((vpe) / 32) * 4))
#define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
+/* Convert an interrupt number to a byte offset/bit for multi-word registers */
+#define GIC_INTR_OFS(intr) (((intr) / 32)*4)
+#define GIC_INTR_BIT(intr) ((intr) % 32)
+
/* Polarity : Reset Value is always 0 */
#define GIC_SH_SET_POLARITY_OFS 0x0100
#define GIC_SET_POLARITY(intr, pol) \
- GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + (((intr) / 32) * 4)), (pol) << ((intr) % 32))
+ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
+ GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr))
/* Triggering : Reset Value is always 0 */
#define GIC_SH_SET_TRIGGER_OFS 0x0180
#define GIC_SET_TRIGGER(intr, trig) \
- GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + (((intr) / 32) * 4)), (trig) << ((intr) % 32))
+ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
+ GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr))
/* Mask manipulation */
#define GIC_SH_SMASK_OFS 0x0380
-#define GIC_SET_INTR_MASK(intr, val) \
- GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
-
+#define GIC_SET_INTR_MASK(intr) \
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + \
+ GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
#define GIC_SH_RMASK_OFS 0x0300
-#define GIC_CLR_INTR_MASK(intr, val) \
- GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
+#define GIC_CLR_INTR_MASK(intr) \
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + \
+ GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
/* Register Map for Local Section */
#define GIC_VPE_CTL_OFS 0x0000
#define GIC_UMV_SH_COUNTER_31_00_OFS 0x0000
#define GIC_UMV_SH_COUNTER_63_32_OFS 0x0004
-#else /* CONFIG_CPU_BIG_ENDIAN */
-
-#define GIC_SH_CONFIG_OFS 0x0000
-
-/* Shared Global Counter */
-#define GIC_SH_COUNTER_31_00_OFS 0x0014
-#define GIC_SH_COUNTER_63_32_OFS 0x0010
-
-/* Interrupt Polarity */
-#define GIC_SH_POL_31_0_OFS 0x0104
-#define GIC_SH_POL_63_32_OFS 0x0100
-#define GIC_SH_POL_95_64_OFS 0x010c
-#define GIC_SH_POL_127_96_OFS 0x0108
-#define GIC_SH_POL_159_128_OFS 0x0114
-#define GIC_SH_POL_191_160_OFS 0x0110
-#define GIC_SH_POL_223_192_OFS 0x011c
-#define GIC_SH_POL_255_224_OFS 0x0118
-
-/* Edge/Level Triggering */
-#define GIC_SH_TRIG_31_0_OFS 0x0184
-#define GIC_SH_TRIG_63_32_OFS 0x0180
-#define GIC_SH_TRIG_95_64_OFS 0x018c
-#define GIC_SH_TRIG_127_96_OFS 0x0188
-#define GIC_SH_TRIG_159_128_OFS 0x0194
-#define GIC_SH_TRIG_191_160_OFS 0x0190
-#define GIC_SH_TRIG_223_192_OFS 0x019c
-#define GIC_SH_TRIG_255_224_OFS 0x0198
-
-/* Dual Edge Triggering */
-#define GIC_SH_DUAL_31_0_OFS 0x0204
-#define GIC_SH_DUAL_63_32_OFS 0x0200
-#define GIC_SH_DUAL_95_64_OFS 0x020c
-#define GIC_SH_DUAL_127_96_OFS 0x0208
-#define GIC_SH_DUAL_159_128_OFS 0x0214
-#define GIC_SH_DUAL_191_160_OFS 0x0210
-#define GIC_SH_DUAL_223_192_OFS 0x021c
-#define GIC_SH_DUAL_255_224_OFS 0x0218
-
-/* Set/Clear corresponding bit in Edge Detect Register */
-#define GIC_SH_WEDGE_OFS 0x0280
-
-/* Reset Mask - Disables Interrupt */
-#define GIC_SH_RMASK_31_0_OFS 0x0304
-#define GIC_SH_RMASK_63_32_OFS 0x0300
-#define GIC_SH_RMASK_95_64_OFS 0x030c
-#define GIC_SH_RMASK_127_96_OFS 0x0308
-#define GIC_SH_RMASK_159_128_OFS 0x0314
-#define GIC_SH_RMASK_191_160_OFS 0x0310
-#define GIC_SH_RMASK_223_192_OFS 0x031c
-#define GIC_SH_RMASK_255_224_OFS 0x0318
-
-/* Set Mask (WO) - Enables Interrupt */
-#define GIC_SH_SMASK_31_0_OFS 0x0384
-#define GIC_SH_SMASK_63_32_OFS 0x0380
-#define GIC_SH_SMASK_95_64_OFS 0x038c
-#define GIC_SH_SMASK_127_96_OFS 0x0388
-#define GIC_SH_SMASK_159_128_OFS 0x0394
-#define GIC_SH_SMASK_191_160_OFS 0x0390
-#define GIC_SH_SMASK_223_192_OFS 0x039c
-#define GIC_SH_SMASK_255_224_OFS 0x0398
-
-/* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */
-#define GIC_SH_MASK_31_0_OFS 0x0404
-#define GIC_SH_MASK_63_32_OFS 0x0400
-#define GIC_SH_MASK_95_64_OFS 0x040c
-#define GIC_SH_MASK_127_96_OFS 0x0408
-#define GIC_SH_MASK_159_128_OFS 0x0414
-#define GIC_SH_MASK_191_160_OFS 0x0410
-#define GIC_SH_MASK_223_192_OFS 0x041c
-#define GIC_SH_MASK_255_224_OFS 0x0418
-
-/* Pending Global Interrupts (RO) */
-#define GIC_SH_PEND_31_0_OFS 0x0484
-#define GIC_SH_PEND_63_32_OFS 0x0480
-#define GIC_SH_PEND_95_64_OFS 0x048c
-#define GIC_SH_PEND_127_96_OFS 0x0488
-#define GIC_SH_PEND_159_128_OFS 0x0494
-#define GIC_SH_PEND_191_160_OFS 0x0490
-#define GIC_SH_PEND_223_192_OFS 0x049c
-#define GIC_SH_PEND_255_224_OFS 0x0498
-
-#define GIC_SH_INTR_MAP_TO_PIN_BASE_OFS 0x0500
-
-/* Maps Interrupt X to a Pin */
-#define GIC_SH_MAP_TO_PIN(intr) \
- (GIC_SH_INTR_MAP_TO_PIN_BASE_OFS + (4 * intr))
-
-#define GIC_SH_INTR_MAP_TO_VPE_BASE_OFS 0x2004
-
-/*
- * Maps Interrupt X to a VPE. This is more complex than the LE case, as
- * odd and even registers need to be transposed. It does work - trust me!
- */
-#define GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe) \
- (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + \
- (((((vpe) / 32) ^ 1) - 1) * 4))
-#define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
-
-/* Polarity */
-#define GIC_SH_SET_POLARITY_OFS 0x0100
-#define GIC_SET_POLARITY(intr, pol) \
- GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (pol) << ((intr) % 32))
-
-/* Triggering */
-#define GIC_SH_SET_TRIGGER_OFS 0x0180
-#define GIC_SET_TRIGGER(intr, trig) \
- GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (trig) << ((intr) % 32))
-
-/* Mask manipulation */
-#define GIC_SH_SMASK_OFS 0x0380
-#define GIC_SET_INTR_MASK(intr, val) \
- GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)))
-
-#define GIC_SH_RMASK_OFS 0x0300
-#define GIC_CLR_INTR_MASK(intr, val) \
- GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)))
-
-/* Register Map for Local Section */
-#define GIC_VPE_CTL_OFS 0x0000
-#define GIC_VPE_PEND_OFS 0x0004
-#define GIC_VPE_MASK_OFS 0x0008
-#define GIC_VPE_RMASK_OFS 0x000c
-#define GIC_VPE_SMASK_OFS 0x0010
-#define GIC_VPE_WD_MAP_OFS 0x0040
-#define GIC_VPE_COMPARE_MAP_OFS 0x0044
-#define GIC_VPE_TIMER_MAP_OFS 0x0048
-#define GIC_VPE_PERFCTR_MAP_OFS 0x0050
-#define GIC_VPE_SWINT0_MAP_OFS 0x0054
-#define GIC_VPE_SWINT1_MAP_OFS 0x0058
-#define GIC_VPE_OTHER_ADDR_OFS 0x0080
-#define GIC_VPE_WD_CONFIG0_OFS 0x0090
-#define GIC_VPE_WD_COUNT0_OFS 0x0094
-#define GIC_VPE_WD_INITIAL0_OFS 0x0098
-#define GIC_VPE_COMPARE_LO_OFS 0x00a4
-#define GIC_VPE_COMPARE_HI_OFS 0x00a0
-
-#define GIC_VPE_EIC_SHADOW_SET_BASE 0x0100
-#define GIC_VPE_EIC_SS(intr) \
- (GIC_EIC_SHADOW_SET_BASE + (4 * intr))
-
-#define GIC_VPE_EIC_VEC_BASE 0x0800
-#define GIC_VPE_EIC_VEC(intr) \
- (GIC_VPE_EIC_VEC_BASE + (4 * intr))
-
-#define GIC_VPE_TENABLE_NMI_OFS 0x1000
-#define GIC_VPE_TENABLE_YQ_OFS 0x1004
-#define GIC_VPE_TENABLE_INT_31_0_OFS 0x1080
-#define GIC_VPE_TENABLE_INT_63_32_OFS 0x1084
-
-/* User Mode Visible Section Register Map */
-#define GIC_UMV_SH_COUNTER_31_00_OFS 0x0004
-#define GIC_UMV_SH_COUNTER_63_32_OFS 0x0000
-
-#endif /* !LE */
-
/* Masks */
#define GIC_SH_CONFIG_COUNTSTOP_SHF 28
#define GIC_SH_CONFIG_COUNTSTOP_MSK (MSK(1) << GIC_SH_CONFIG_COUNTSTOP_SHF)
* in building ipi_map.
*/
struct gic_intr_map {
- unsigned int intrnum; /* Ext Intr Num */
unsigned int cpunum; /* Directed to this CPU */
unsigned int pin; /* Directed to this Pin */
unsigned int polarity; /* Polarity : +/- */
unsigned int trigtype; /* Trigger : Edge/Levl */
- unsigned int ipiflag; /* Is used for IPI ? */
+ unsigned int flags; /* Misc flags */
+#define GIC_FLAG_IPI 0x01
+#define GIC_FLAG_TRANSPARENT 0x02
};
extern void gic_init(unsigned long gic_base_addr,
#define AR7_REF_CLOCK 25000000
#define AR7_XTAL_CLOCK 24000000
+/* DCL */
+#define AR7_WDT_HW_ENA 0x10
+
struct plat_cpmac_data {
int reset_bit;
int power_bit;
if ((gpio >= 8) && (gpio <= 15))
return MAKE_IRQ(0, 29); /* shared GPIO208_215 */
+
+ return -ENXIO;
}
#ifdef CONFIG_SOC_AU1100
+++ /dev/null
-#ifndef BCM63XX_DEV_UART_H_
-#define BCM63XX_DEV_UART_H_
-
-int bcm63xx_uart_register(void);
-
-#endif /* BCM63XX_DEV_UART_H_ */
.busy_factor = 32, \
.imbalance_pct = 125, \
.cache_nice_tries = 1, \
- .flags = SD_LOAD_BALANCE \
- | SD_BALANCE_EXEC \
+ .flags = SD_LOAD_BALANCE | \
+ SD_BALANCE_EXEC, \
.last_balance = jiffies, \
.balance_interval = 1, \
.nr_balance_failed = 0, \
#define cpu_has_cache_cdex_p 0
#define cpu_has_cache_cdex_s 0
#define cpu_has_counter 1
-#define cpu_has_dc_aliases 1
+#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
#define cpu_has_divec 0
#define cpu_has_dsp 0
#define cpu_has_ejtag 0
#define cpu_has_vce 0
#define cpu_has_vtag_icache 0
#define cpu_has_watch 1
-#define cpu_icache_snoops_remote_store 1
#endif /* __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H */
#include <linux/smp.h>
#include <linux/slab.h>
#include <asm/cacheflush.h>
+#include <asm/hazards.h>
#include <asm/tlbflush.h>
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#ifdef CONFIG_32BIT
#define TLBMISS_HANDLER_SETUP() \
write_c0_context((unsigned long) smp_processor_id() << 25); \
+ back_to_back_c0_hazard(); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
#endif
#ifdef CONFIG_64BIT
#define TLBMISS_HANDLER_SETUP() \
write_c0_context((unsigned long) smp_processor_id() << 26); \
+ back_to_back_c0_hazard(); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
#endif
* having ASID_MASK smaller than the hardware maximum,
* make sure no "soft" bits become "hard"...
*/
- write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
- | (cpu_context(cpu, next) & ASID_MASK));
+ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
+ cpu_asid(cpu, next));
ehb(); /* Make sure it propagates to TCStatus */
evpe(mtflags);
#else
- write_c0_entryhi(cpu_context(cpu, next));
+ write_c0_entryhi(cpu_asid(cpu, next));
#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
}
/* See comments for similar code above */
write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
- (cpu_context(cpu, next) & ASID_MASK));
+ cpu_asid(cpu, next));
ehb(); /* Make sure it propagates to TCStatus */
evpe(mtflags);
#else
- write_c0_entryhi(cpu_context(cpu, next));
+ write_c0_entryhi(cpu_asid(cpu, next));
#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
#ifndef _MIPS_SETUP_H
#define _MIPS_SETUP_H
-#define COMMAND_LINE_SIZE 256
+#define COMMAND_LINE_SIZE 4096
#ifdef __KERNEL__
extern void setup_early_printk(void);
spinlock_t lock;
struct smtc_ipi *tail;
int depth;
+ int resched_flag; /* reschedule already queued */
};
static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
--- /dev/null
+#ifndef _MIPS_SPRAM_H
+#define _MIPS_SPRAM_H
+
+#ifdef CONFIG_CPU_MIPSR2
+extern __init void spram_config(void);
+#else
+static inline void spram_config(void) { };
+#endif /* CONFIG_CPU_MIPSR2 */
+
+#endif /* _MIPS_SPRAM_H */
#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) \
-({ \
- struct thread_info *ret; \
- \
- ret = kzalloc(THREAD_SIZE, GFP_KERNEL); \
- \
- ret; \
-})
+#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
#else
#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
#endif
static struct irqaction r4030_timer_irqaction = {
.handler = r4030_timer_interrupt,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_DISABLED | IRQF_TIMER,
.name = "R4030 timer",
};
bcm1480_unmask_irq(cpu, irq);
action->handler = sibyte_counter_handler;
- action->flags = IRQF_DISABLED | IRQF_PERCPU;
+ action->flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER;
action->name = name;
action->dev_id = cd;
static struct irqaction ds1287_irqaction = {
.handler = ds1287_interrupt,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
.name = "ds1287",
};
static struct irqaction gt641xx_timer0_irqaction = {
.handler = gt641xx_timer0_interrupt,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
.name = "gt641xx_timer0",
};
struct irqaction c0_compare_irqaction = {
.handler = c0_compare_interrupt,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
.name = "timer",
};
sb1250_unmask_irq(cpu, irq);
action->handler = sibyte_counter_handler;
- action->flags = IRQF_DISABLED | IRQF_PERCPU;
+ action->flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER;
action->name = name;
action->dev_id = cd;
static struct irqaction txx9tmr_irq = {
.handler = txx9tmr_interrupt,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
.name = "txx9tmr",
.dev_id = &txx9_clock_event_device,
};
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/watch.h>
-
+#include <asm/spram.h>
/*
* Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
* the implementation of the "wait" feature differs between CPU families. This
mips_probe_watch_registers(c);
}
-#ifdef CONFIG_CPU_MIPSR2
-extern void spram_config(void);
-#else
-static inline void spram_config(void) {}
-#endif
-
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
/* Set the SP after an empty pt_regs. */
PTR_LI sp, _THREAD_SIZE - 32 - PT_SIZE
PTR_ADDU sp, $28
+ back_to_back_c0_hazard
set_saved_sp sp, t0, t1
PTR_SUBU sp, 4 * SZREG # init stack pointer
static struct irqaction irq0 = {
.handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+ .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
.name = "timer"
};
static unsigned long _gic_base;
-static unsigned int _irqbase, _mapsize, numvpes, numintrs;
-static struct gic_intr_map *_intrmap;
+static unsigned int _irqbase;
+static unsigned int gic_irq_flags[GIC_NUM_INTRS];
+#define GIC_IRQ_FLAG_EDGE 0x0001
-static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
+struct gic_pcpu_mask pcpu_masks[NR_CPUS];
static struct gic_pending_regs pending_regs[NR_CPUS];
static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
-#define gic_wedgeb2bok 0 /*
- * Can GIC handle b2b writes to wedge register?
- */
-#if gic_wedgeb2bok == 0
-static DEFINE_SPINLOCK(gic_wedgeb2b_lock);
-#endif
-
void gic_send_ipi(unsigned int intr)
{
-#if gic_wedgeb2bok == 0
- unsigned long flags;
-#endif
pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
read_c0_status());
- if (!gic_wedgeb2bok)
- spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
- if (!gic_wedgeb2bok) {
- (void) GIC_REG(SHARED, GIC_SH_CONFIG);
- spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
- }
}
/* This is Malta specific and needs to be exported */
-static void vpe_local_setup(unsigned int numvpes)
+static void __init vpe_local_setup(unsigned int numvpes)
{
int i;
unsigned long timer_interrupt = 5, perf_interrupt = 5;
static unsigned int gic_irq_startup(unsigned int irq)
{
- pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
irq -= _irqbase;
- GIC_SET_INTR_MASK(irq, 1);
+ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+ GIC_SET_INTR_MASK(irq);
return 0;
}
static void gic_irq_ack(unsigned int irq)
{
-#if gic_wedgeb2bok == 0
- unsigned long flags;
-#endif
- pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
irq -= _irqbase;
- GIC_CLR_INTR_MASK(irq, 1);
+ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+ GIC_CLR_INTR_MASK(irq);
- if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
- if (!gic_wedgeb2bok)
- spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
+ if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE)
GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
- if (!gic_wedgeb2bok) {
- (void) GIC_REG(SHARED, GIC_SH_CONFIG);
- spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
- }
- }
}
static void gic_mask_irq(unsigned int irq)
{
- pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
irq -= _irqbase;
- GIC_CLR_INTR_MASK(irq, 1);
+ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+ GIC_CLR_INTR_MASK(irq);
}
static void gic_unmask_irq(unsigned int irq)
{
- pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
irq -= _irqbase;
- GIC_SET_INTR_MASK(irq, 1);
+ pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+ GIC_SET_INTR_MASK(irq);
}
#ifdef CONFIG_SMP
unsigned long flags;
int i;
- pr_debug(KERN_DEBUG "%s called\n", __func__);
irq -= _irqbase;
-
+ pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq);
cpumask_and(&tmp, cpumask, cpu_online_mask);
if (cpus_empty(tmp))
return -1;
/* Re-route this IRQ */
GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));
- /*
- * FIXME: assumption that _intrmap is ordered and has no holes
- */
-
- /* Update the intr_map */
- _intrmap[irq].cpunum = first_cpu(tmp);
-
/* Update the pcpu_masks */
for (i = 0; i < NR_CPUS; i++)
clear_bit(irq, pcpu_masks[i].pcpu_mask);
#endif
};
-static void __init setup_intr(unsigned int intr, unsigned int cpu,
- unsigned int pin, unsigned int polarity, unsigned int trigtype)
+static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
+ unsigned int pin, unsigned int polarity, unsigned int trigtype,
+ unsigned int flags)
{
/* Setup Intr to Pin mapping */
if (pin & GIC_MAP_TO_NMI_MSK) {
GIC_SET_TRIGGER(intr, trigtype);
/* Init Intr Masks */
- GIC_SET_INTR_MASK(intr, 0);
+ GIC_CLR_INTR_MASK(intr);
+ /* Initialise per-cpu Interrupt software masks */
+ if (flags & GIC_FLAG_IPI)
+ set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+ if (flags & GIC_FLAG_TRANSPARENT)
+ GIC_SET_INTR_MASK(intr);
+ if (trigtype == GIC_TRIG_EDGE)
+ gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE;
}
-static void __init gic_basic_init(void)
+static void __init gic_basic_init(int numintrs, int numvpes,
+ struct gic_intr_map *intrmap, int mapsize)
{
unsigned int i, cpu;
/* Setup defaults */
- for (i = 0; i < GIC_NUM_INTRS; i++) {
+ for (i = 0; i < numintrs; i++) {
GIC_SET_POLARITY(i, GIC_POL_POS);
GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
- GIC_SET_INTR_MASK(i, 0);
+ GIC_CLR_INTR_MASK(i);
+ if (i < GIC_NUM_INTRS)
+ gic_irq_flags[i] = 0;
}
/* Setup specifics */
- for (i = 0; i < _mapsize; i++) {
- cpu = _intrmap[i].cpunum;
+ for (i = 0; i < mapsize; i++) {
+ cpu = intrmap[i].cpunum;
if (cpu == X)
continue;
-
- if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 &&
- _intrmap[i].ipiflag == 0)
+ if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
continue;
-
- setup_intr(_intrmap[i].intrnum,
- _intrmap[i].cpunum,
- _intrmap[i].pin,
- _intrmap[i].polarity,
- _intrmap[i].trigtype);
- /* Initialise per-cpu Interrupt software masks */
- if (_intrmap[i].ipiflag)
- set_bit(_intrmap[i].intrnum, pcpu_masks[cpu].pcpu_mask);
+ gic_setup_intr(i,
+ intrmap[i].cpunum,
+ intrmap[i].pin,
+ intrmap[i].polarity,
+ intrmap[i].trigtype,
+ intrmap[i].flags);
}
vpe_local_setup(numvpes);
unsigned int irqbase)
{
unsigned int gicconfig;
+ int numvpes, numintrs;
_gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
gic_addrspace_size);
_irqbase = irqbase;
- _intrmap = intr_map;
- _mapsize = intr_map_size;
GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
pr_debug("%s called\n", __func__);
- gic_basic_init();
+ gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
}
return do_fork(clone_flags, newsp, ®s, 0,
parent_tidptr, child_tidptr);
}
+
+asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf,
+ size_t len)
+{
+ return sys_lookup_dcookie(merge_64(a0, a1), buf, len);
+}
PTR sys_io_submit
PTR sys_io_cancel /* 4245 */
PTR sys_exit_group
- PTR sys_lookup_dcookie
+ PTR sys32_lookup_dcookie
PTR sys_epoll_create
PTR sys_epoll_ctl
PTR sys_epoll_wait /* 4250 */
PTR sys_fchmodat
PTR sys_faccessat /* 4300 */
PTR compat_sys_pselect6
- PTR sys_ppoll
+ PTR compat_sys_ppoll
PTR sys_unshare
PTR sys_splice
PTR sys32_sync_file_range /* 4305 */
asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
-
/*
* Number of InterProcessor Interrupt (IPI) message buffers to allocate
*/
IPIQ[i].head = IPIQ[i].tail = NULL;
spin_lock_init(&IPIQ[i].lock);
IPIQ[i].depth = 0;
+ IPIQ[i].resched_flag = 0; /* No reschedules queued initially */
}
/* cpu_data index starts at zero */
static void smtc_ipi_qdump(void)
{
int i;
+ struct smtc_ipi *temp;
for (i = 0; i < NR_CPUS ;i++) {
- printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
+ pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
IPIQ[i].depth);
+ temp = IPIQ[i].head;
+
+ while (temp != IPIQ[i].tail) {
+ pr_debug("%d %d %d: ", temp->type, temp->dest,
+ (int)temp->arg);
+#ifdef SMTC_IPI_DEBUG
+ pr_debug("%u %lu\n", temp->sender, temp->stamp);
+#else
+ pr_debug("\n");
+#endif
+ temp = temp->flink;
+ }
}
}
int mtflags;
unsigned long tcrestart;
extern void r4k_wait_irqoff(void), __pastwait(void);
+ int set_resched_flag = (type == LINUX_SMP_IPI &&
+ action == SMP_RESCHEDULE_YOURSELF);
if (cpu == smp_processor_id()) {
printk("Cannot Send IPI to self!\n");
return;
}
+ if (set_resched_flag && IPIQ[cpu].resched_flag != 0)
+ return; /* There is a reschedule queued already */
+
/* Set up a descriptor, to be delivered either promptly or queued */
pipi = smtc_ipi_dq(&freeIPIq);
if (pipi == NULL) {
pipi->dest = cpu;
if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
/* If not on same VPE, enqueue and send cross-VPE interrupt */
+ IPIQ[cpu].resched_flag |= set_resched_flag;
smtc_ipi_nq(&IPIQ[cpu], pipi);
LOCK_CORE_PRA();
settc(cpu_data[cpu].tc_id);
*/
write_tc_c0_tchalt(0);
UNLOCK_CORE_PRA();
+ IPIQ[cpu].resched_flag |= set_resched_flag;
smtc_ipi_nq(&IPIQ[cpu], pipi);
} else {
postdirect:
* already enabled.
*/
local_irq_save(flags);
-
spin_lock(&q->lock);
pipi = __smtc_ipi_dq(q);
spin_unlock(&q->lock);
- if (pipi != NULL)
+ if (pipi != NULL) {
+ if (pipi->type == LINUX_SMP_IPI &&
+ (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
+ IPIQ[cpu].resched_flag = 0;
ipi_decode(pipi);
+ }
/*
* The use of the __raw_local restore isn't
* as obviously necessary here as in smtc_ipi_replay(),
* with interrupts off
*/
local_irq_save(flags);
+ if (pipi->type == LINUX_SMP_IPI &&
+ (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
+ IPIQ[cpu].resched_flag = 0;
ipi_decode(pipi);
local_irq_restore(flags);
}
#include <linux/ptrace.h>
#include <linux/stddef.h>
-#include <asm/cpu.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
offset += 2 * SPRAM_TAG_STRIDE;
}
}
-
-__cpuinit void spram_config(void)
+void __cpuinit spram_config(void)
{
struct cpuinfo_mips *c = ¤t_cpu_data;
unsigned int config0;
case CPU_24K:
case CPU_34K:
case CPU_74K:
+ case CPU_1004K:
config0 = read_c0_config();
/* FIXME: addresses are Malta specific */
if (config0 & (1<<24)) {
v->shared_ptr = NULL;
v->__start = 0;
- unlock_kernel();
-
return 0;
}
* int-handler is not on bootstrap
*/
clear_c0_status(ST0_IM | ST0_BEV);
- local_irq_disable();
/* setting irq trigger mode */
set_irq_trigger_mode();
return ieee754dp_nanxcpt(y, "neg");
}
- if (ieee754dp_isnan(x)) /* but not infinity */
- return ieee754dp_nanxcpt(x, "neg", x);
return x;
}
CLEARCX;
FLUSHXDP;
+ /* Clear sign ALWAYS, irrespective of NaN */
+ DPSIGN(x) = 0;
+
if (xc == IEEE754_CLASS_SNAN) {
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "neg");
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "abs");
}
- if (ieee754dp_isnan(x)) /* but not infinity */
- return ieee754dp_nanxcpt(x, "abs", x);
-
- /* quick fix up */
- DPSIGN(x) = 0;
return x;
}
return ieee754sp_nanxcpt(y, "neg");
}
- if (ieee754sp_isnan(x)) /* but not infinity */
- return ieee754sp_nanxcpt(x, "neg", x);
return x;
}
CLEARCX;
FLUSHXSP;
+ /* Clear sign ALWAYS, irrespective of NaN */
+ SPSIGN(x) = 0;
+
if (xc == IEEE754_CLASS_SNAN) {
- SETCX(IEEE754_INVALID_OPERATION);
return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
}
- if (ieee754sp_isnan(x)) /* but not infinity */
- return ieee754sp_nanxcpt(x, "abs", x);
-
- /* quick fix up */
- SPSIGN(x) = 0;
return x;
}
#include <linux/swap.h>
#include <linux/proc_fs.h>
#include <linux/pfn.h>
+#include <linux/hardirq.h>
#include <asm/asm-offsets.h>
#include <asm/bootinfo.h>
inc_preempt_count();
idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
#ifdef CONFIG_MIPS_MT_SMTC
- idx += FIX_N_COLOURS * smp_processor_id();
+ idx += FIX_N_COLOURS * smp_processor_id() +
+ (in_interrupt() ? (FIX_N_COLOURS * NR_CPUS) : 0);
+#else
+ idx += in_interrupt() ? FIX_N_COLOURS : 0;
#endif
vaddr = __fix_to_virt(FIX_CMAP_END - idx);
pte = mk_pte(page, PAGE_KERNEL);
launch->sp = sp;
launch->a0 = a0;
- /* Make sure target sees parameters before the go bit */
- smp_mb();
-
+ smp_wmb(); /* Target must see parameters before go */
launch->flags |= LAUNCH_FGO;
+ smp_wmb(); /* Target must see go before we poll */
+
while ((launch->flags & LAUNCH_FGONE) == 0)
;
+ smp_rmb(); /* Target will be updating flags soon */
pr_debug("launch: cpu%d gone!\n", cpu);
}
dummy = BONITO_PCIMAP_CFG;
iob(); /* sync */
- irq = readl((u32 *)_pcictrl_bonito_pcicfg);
+ irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
iob(); /* sync */
irq &= 0xff;
BONITO_PCIMAP_CFG = 0;
static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
-#if defined(CONFIG_MIPS_MT_SMP)
/*
* This GIC specific tabular array defines the association between External
* Interrupts and CPUs/Core Interrupts. The nature of the External
* Interrupts is also defined here - polarity/trigger.
*/
+
+#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
- { GIC_EXT_INTR(0), X, X, X, X, 0 },
- { GIC_EXT_INTR(1), X, X, X, X, 0 },
- { GIC_EXT_INTR(2), X, X, X, X, 0 },
- { GIC_EXT_INTR(3), 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(4), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(5), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(6), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(7), 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(8), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(9), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(10), X, X, X, X, 0 },
- { GIC_EXT_INTR(11), X, X, X, X, 0 },
- { GIC_EXT_INTR(12), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(13), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(14), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 },
- { GIC_EXT_INTR(15), X, X, X, X, 0 },
-/* This is the end of the general interrupts now we do IPI ones */
+ { X, X, X, X, 0 },
+ { X, X, X, X, 0 },
+ { X, X, X, X, 0 },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { X, X, X, X, 0 },
+ { X, X, X, X, 0 },
+ { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { X, X, X, X, 0 },
+ /* The remainder of this table is initialised by fill_ipi_map */
};
-#endif
/*
* GCMP needs to be detected before any SMP initialisation
*/
int __init gcmp_probe(unsigned long addr, unsigned long size)
{
+ if (mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) {
+ gcmp_present = 0;
+ return gcmp_present;
+ }
+
if (gcmp_present >= 0)
return gcmp_present;
gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
if (gcmp_present)
- printk(KERN_DEBUG "GCMP present\n");
+ pr_debug("GCMP present\n");
return gcmp_present;
}
+/* Return the number of IOCU's present */
+int __init gcmp_niocu(void)
+{
+ return gcmp_present ?
+ (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF :
+ 0;
+}
+
+/* Set GCMP region attributes */
+void __init gcmp_setregion(int region, unsigned long base,
+ unsigned long mask, int type)
+{
+ GCMPGCBn(CMxBASE, region) = base;
+ GCMPGCBn(CMxMASK, region) = mask | type;
+}
+
#if defined(CONFIG_MIPS_MT_SMP)
static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
{
int intr = baseintr + cpu;
- gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr);
gic_intr_map[intr].cpunum = cpu;
gic_intr_map[intr].pin = cpupin;
gic_intr_map[intr].polarity = GIC_POL_POS;
gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
- gic_intr_map[intr].ipiflag = 1;
+ gic_intr_map[intr].flags = GIC_FLAG_IPI;
ipi_map[cpu] |= (1 << (cpupin + 2));
}
}
#endif
+void __init arch_init_ipiirq(int irq, struct irqaction *action)
+{
+ setup_irq(irq, action);
+ set_irq_handler(irq, handle_percpu_irq);
+}
+
void __init arch_init_irq(void)
{
init_i8259_irqs();
GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
gic_present = 1;
} else {
- _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
- gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
- MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF;
+ if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) {
+ _msc01_biu_base = (unsigned long)
+ ioremap_nocache(MSC01_BIU_REG_BASE,
+ MSC01_BIU_ADDRSPACE_SZ);
+ gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
+ MSC01_SC_CFG_GICPRES_MSK) >>
+ MSC01_SC_CFG_GICPRES_SHF;
+ }
}
if (gic_present)
- printk(KERN_DEBUG "GIC present\n");
+ pr_debug("GIC present\n");
switch (mips_revision_sconid) {
case MIPS_REVISION_SCON_SOCIT:
&corehi_irqaction);
}
-#if defined(CONFIG_MIPS_MT_SMP)
if (gic_present) {
/* FIXME */
int i;
-
+#if defined(CONFIG_MIPS_MT_SMP)
gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
gic_resched_int_base = gic_call_int_base - NR_CPUS;
-
fill_ipi_map();
- gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
+#endif
+ gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
+ ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
if (!gcmp_present) {
/* Enable the GIC */
i = REG(_msc01_biu_base, MSC01_SC_CFG);
(i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
pr_debug("GIC Enabled\n");
}
-
+#if defined(CONFIG_MIPS_MT_SMP)
/* set up ipi interrupts */
if (cpu_has_vint) {
set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
write_c0_status(0x1100dc00);
printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
for (i = 0; i < NR_CPUS; i++) {
- setup_irq(MIPS_GIC_IRQ_BASE +
- GIC_RESCHED_INT(i), &irq_resched);
- setup_irq(MIPS_GIC_IRQ_BASE +
- GIC_CALL_INT(i), &irq_call);
- set_irq_handler(MIPS_GIC_IRQ_BASE +
- GIC_RESCHED_INT(i), handle_percpu_irq);
- set_irq_handler(MIPS_GIC_IRQ_BASE +
- GIC_CALL_INT(i), handle_percpu_irq);
+ arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
+ GIC_RESCHED_INT(i), &irq_resched);
+ arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
+ GIC_CALL_INT(i), &irq_call);
}
+#endif
} else {
+#if defined(CONFIG_MIPS_MT_SMP)
/* set up ipi interrupts */
if (cpu_has_veic) {
set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
}
-
- setup_irq(cpu_ipi_resched_irq, &irq_resched);
- setup_irq(cpu_ipi_call_irq, &irq_call);
-
- set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
- set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
- }
+ arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
+ arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
#endif
+ }
}
void malta_be_init(void)
#include <linux/init.h>
#include <asm/gt64120.h>
-
+#include <asm/gcmpregs.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/bonito64.h>
#include <asm/mips-boards/msc01_pci.h>
msc_mem_resource.start = start & mask;
msc_mem_resource.end = (start & mask) | ~mask;
msc_controller.mem_offset = (start & mask) - (map & mask);
-
+#ifdef CONFIG_MIPS_CMP
+ if (gcmp_niocu())
+ gcmp_setregion(0, start, mask,
+ GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
+#endif
MSC_READ(MSC01_PCI_SC2PIOBASL, start);
MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
msc_io_resource.end = (map & mask) | ~mask;
msc_controller.io_offset = 0;
ioport_resource.end = ~mask;
-
+#ifdef CONFIG_MIPS_CMP
+ if (gcmp_niocu())
+ gcmp_setregion(1, start, mask,
+ GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
+#endif
/* If ranges overlap I/O takes precedence. */
start = start & mask;
end = start | ~mask;
register_pci_controller(controller);
}
+
+/* Enable PCI 2.1 compatibility in PIIX4 */
+static void __init quirk_dlcsetup(struct pci_dev *dev)
+{
+ u8 odlc, ndlc;
+ (void) pci_read_config_byte(dev, 0x82, &odlc);
+ /* Enable passive releases and delayed transaction */
+ ndlc = odlc | 7;
+ (void) pci_write_config_byte(dev, 0x82, ndlc);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+ quirk_dlcsetup);
static struct irqaction timer_action = {
.handler = no_action,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_DISABLED | IRQF_TIMER,
.name = "Timer",
};
static struct irqaction pnx8xxx_timer_irq = {
.handler = pnx8xxx_timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
.name = "pnx8xxx_timer",
};
static struct irqaction monotonic_irqaction = {
.handler = monotonic_interrupt,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_DISABLED | IRQF_TIMER,
.name = "Monotonic timer",
};
* otherwise, the oprofile tool will not recognize this and complain about
* "cpu_type 'unset' is not valid".
*/
-#define LOONGSON2_CPU_TYPE "mips/godson2"
+#define LOONGSON2_CPU_TYPE "mips/loongson2"
#define LOONGSON2_COUNTER1_EVENT(event) ((event & 0x0f) << 5)
#define LOONGSON2_COUNTER2_EVENT(event) ((event & 0x0f) << 9)
struct irqaction hub_rt_irqaction = {
.handler = hub_rt_counter_handler,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
.name = "hub-rt",
};
static struct irqaction a20r_irqaction = {
.handler = a20r_interrupt,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
.name = "a20r-timer",
};
struct clk *clk_get(struct device *dev, const char *id)
{
if (!strcmp(id, "spi-baseclk"))
- return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 4);
+ return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 2);
if (!strcmp(id, "imbus_clk"))
return (struct clk *)((unsigned long)txx9_gbus_clock / 2);
return ERR_PTR(-ENOENT);
out_pdev:
platform_device_put(pdev);
out_gpio:
- gpio_remove(&iocled->chip);
+ if (gpiochip_remove(&iocled->chip))
+ return;
out_unmap:
iounmap(iocled->mmioaddr);
out_free:
If unsure, say Y. Only embedded should say N here.
-config CC_STACKPROTECTOR_ALL
- bool
-
config CC_STACKPROTECTOR
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
- select CC_STACKPROTECTOR_ALL
---help---
This option turns on the -fstack-protector GCC feature. This
feature puts, at the beginning of functions, a canary value on
config X86_CMPXCHG64
def_bool y
- depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM
+ depends on !M386 && !M486
# this should be set for all -march=.. options where the compiler
# generates cmov.
cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh
ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(biarch)),y)
stackp-y := -fstack-protector
- stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += -fstack-protector-all
KBUILD_CFLAGS += $(stackp-y)
else
$(warning stack protector enabled but no compiler support)
movl RDI-ARGOFFSET(%rsp),%r8d /* reload 5th syscall arg */
.endm
- .macro auditsys_exit exit,ebpsave=RBP
+ .macro auditsys_exit exit
testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
jnz ia32_ret_from_sys_call
TRACE_IRQS_ON
call audit_syscall_exit
GET_THREAD_INFO(%r10)
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall return value */
- movl \ebpsave-ARGOFFSET(%rsp),%ebp /* reload user register value */
movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
cli
TRACE_IRQS_OFF
jmp cstar_dispatch
sysretl_audit:
- auditsys_exit sysretl_from_sys_call, RCX /* user %ebp in RCX slot */
+ auditsys_exit sysretl_from_sys_call
#endif
cstar_tracesys:
/* Stores the physical address of elf header of crash image. */
unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+static inline bool is_crashed_pfn_valid(unsigned long pfn)
+{
+#ifndef CONFIG_X86_PAE
+ /*
+ * non-PAE kdump kernel executed from a PAE one will crop high pte
+ * bits and poke unwanted space counting again from address 0, we
+ * don't want that. pte must fit into unsigned long. In fact the
+ * test checks high 12 bits for being zero (pfn will be shifted left
+ * by PAGE_SHIFT).
+ */
+ return pte_pfn(pfn_pte(pfn, __pgprot(0))) == pfn;
+#else
+ return true;
+#endif
+}
+
/**
* copy_oldmem_page - copy one page from "oldmem"
* @pfn: page frame number to be copied
if (!csize)
return 0;
+ if (!is_crashed_pfn_valid(pfn))
+ return -EFAULT;
+
vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
if (!userbuf) {
if (add_efi_memmap)
do_add_efi_memmap();
+#ifdef CONFIG_X86_32
x86_platform.get_wallclock = efi_get_time;
x86_platform.set_wallclock = efi_set_rtc_mmss;
+#endif
/* Setup for EFI runtime service */
reboot_type = BOOT_EFI;
CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */
CFQ_CFQQ_FLAG_sync, /* synchronous queue */
CFQ_CFQQ_FLAG_coop, /* has done a coop jump of the queue */
+ CFQ_CFQQ_FLAG_coop_preempt, /* coop preempt */
};
#define CFQ_CFQQ_FNS(name) \
CFQ_CFQQ_FNS(slice_new);
CFQ_CFQQ_FNS(sync);
CFQ_CFQQ_FNS(coop);
+CFQ_CFQQ_FNS(coop_preempt);
#undef CFQ_CFQQ_FNS
#define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \
{
if (!cfqq) {
cfqq = cfq_get_next_queue(cfqd);
- if (cfqq)
+ if (cfqq && !cfq_cfqq_coop_preempt(cfqq))
cfq_clear_cfqq_coop(cfqq);
}
+ if (cfqq)
+ cfq_clear_cfqq_coop_preempt(cfqq);
+
__cfq_set_active_queue(cfqd, cfqq);
return cfqq;
}
* it's a metadata request and the current queue is doing regular IO.
*/
if (rq_is_meta(rq) && !cfqq->meta_pending)
- return false;
+ return true;
/*
* Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice.
* if this request is as-good as one we would expect from the
* current cfqq, let it preempt
*/
- if (cfq_rq_close(cfqd, rq))
+ if (cfq_rq_close(cfqd, rq) && (!cfq_cfqq_coop(new_cfqq) ||
+ cfqd->busy_queues == 1)) {
+ /*
+ * Mark new queue coop_preempt, so its coop flag will not be
+ * cleared when new queue gets scheduled at the very first time
+ */
+ cfq_mark_cfqq_coop_preempt(new_cfqq);
+ cfq_mark_cfqq_coop(new_cfqq);
return true;
+ }
return false;
}
},
.driver_data = "20071026", /* yyyymmdd */
},
+ /*
+ * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
+ * support 64bit DMA.
+ *
+ * BIOS versions earlier than 1.5 had the Manufacturer DMI
+ * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
+ * This spelling mistake was fixed in BIOS version 1.5, so
+ * 1.5 and later have the Manufacturer as
+ * "MICRO-STAR INTERNATIONAL CO.,LTD".
+ * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
+ *
+ * BIOS versions earlier than 1.9 had a Board Product Name
+ * DMI field of "MS-7376". This was changed to be
+ * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
+ * match on DMI_BOARD_NAME of "MS-7376".
+ */
+ {
+ .ident = "MSI K9A2 Platinum",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR,
+ "MICRO-STAR INTER"),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
+ },
+ },
{ }
};
const struct dmi_system_id *match;
!match)
return false;
+ if (!match->driver_data)
+ goto enable_64bit;
+
dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
- if (strcmp(buf, match->driver_data) >= 0) {
- dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
- match->ident);
- return true;
- } else {
+ if (strcmp(buf, match->driver_data) >= 0)
+ goto enable_64bit;
+ else {
dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
"forcing 32bit DMA, update BIOS\n", match->ident);
return false;
}
+
+enable_64bit:
+ dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
+ match->ident);
+ return true;
}
static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
*/
void ata_qc_free(struct ata_queued_cmd *qc)
{
- struct ata_port *ap = qc->ap;
+ struct ata_port *ap;
unsigned int tag;
WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ ap = qc->ap;
qc->flags = 0;
tag = qc->tag;
void __ata_qc_complete(struct ata_queued_cmd *qc)
{
- struct ata_port *ap = qc->ap;
- struct ata_link *link = qc->dev->link;
+ struct ata_port *ap;
+ struct ata_link *link;
WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE));
+ ap = qc->ap;
+ link = qc->dev->link;
if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
ata_sg_clean(qc);
{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
{ PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
{ PCI_VDEVICE(VIA, 0x9000), vt8251 },
- { PCI_VDEVICE(VIA, 0x9040), vt8251 },
{ } /* terminate list */
};
INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
+ transition_started = false;
while (!list_empty(&dpm_list)) {
struct device *dev = to_device(dpm_list.prev);
{
int retval = 0;
- dev_dbg(dev, "__pm_runtime_idle()!\n");
-
if (dev->power.runtime_error)
retval = -EINVAL;
else if (dev->power.idle_notification)
wake_up_all(&dev->power.wait_queue);
out:
- dev_dbg(dev, "__pm_runtime_idle() returns %d!\n", retval);
-
return retval;
}
goto out;
/* Try to set up FBC with a reasonable compressed buffer size */
- if (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev) || IS_GM45(dev)) &&
- i915_powersave) {
+ if (I915_HAS_FBC(dev) && i915_powersave) {
int cfb_size;
/* Try to get an 8M buffer... */
pci_set_power_state(dev->pdev, PCI_D3hot);
}
- dev_priv->suspended = 1;
+ /* Modeset on resume, not lid events */
+ dev_priv->modeset_on_lid = 0;
return 0;
}
drm_helper_resume_force_mode(dev);
}
- dev_priv->suspended = 0;
+ dev_priv->modeset_on_lid = 0;
return ret;
}
struct drm_i915_display_funcs display;
/* Register state */
- bool suspended;
+ bool modeset_on_lid;
u8 saveLBB;
u32 saveDSPACNTR;
u32 saveDSPBCNTR;
u32 saveVBLANK_A;
u32 saveVSYNC_A;
u32 saveBCLRPAT_A;
+ u32 saveTRANS_HTOTAL_A;
+ u32 saveTRANS_HBLANK_A;
+ u32 saveTRANS_HSYNC_A;
+ u32 saveTRANS_VTOTAL_A;
+ u32 saveTRANS_VBLANK_A;
+ u32 saveTRANS_VSYNC_A;
u32 savePIPEASTAT;
u32 saveDSPASTRIDE;
u32 saveDSPASIZE;
u32 saveDSPASURF;
u32 saveDSPATILEOFF;
u32 savePFIT_PGM_RATIOS;
+ u32 saveBLC_HIST_CTL;
u32 saveBLC_PWM_CTL;
u32 saveBLC_PWM_CTL2;
+ u32 saveBLC_CPU_PWM_CTL;
+ u32 saveBLC_CPU_PWM_CTL2;
u32 saveFPB0;
u32 saveFPB1;
u32 saveDPLL_B;
u32 saveVBLANK_B;
u32 saveVSYNC_B;
u32 saveBCLRPAT_B;
+ u32 saveTRANS_HTOTAL_B;
+ u32 saveTRANS_HBLANK_B;
+ u32 saveTRANS_HSYNC_B;
+ u32 saveTRANS_VTOTAL_B;
+ u32 saveTRANS_VBLANK_B;
+ u32 saveTRANS_VSYNC_B;
u32 savePIPEBSTAT;
u32 saveDSPBSTRIDE;
u32 saveDSPBSIZE;
u32 savePFIT_CONTROL;
u32 save_palette_a[256];
u32 save_palette_b[256];
+ u32 saveDPFC_CB_BASE;
u32 saveFBC_CFB_BASE;
u32 saveFBC_LL_BASE;
u32 saveFBC_CONTROL;
u32 saveIER;
u32 saveIIR;
u32 saveIMR;
+ u32 saveDEIER;
+ u32 saveDEIMR;
+ u32 saveGTIER;
+ u32 saveGTIMR;
+ u32 saveFDI_RXA_IMR;
+ u32 saveFDI_RXB_IMR;
u32 saveCACHE_MODE_0;
u32 saveD_STATE;
u32 saveDSPCLK_GATE_D;
u32 savePIPEB_DP_LINK_M;
u32 savePIPEA_DP_LINK_N;
u32 savePIPEB_DP_LINK_N;
+ u32 saveFDI_RXA_CTL;
+ u32 saveFDI_TXA_CTL;
+ u32 saveFDI_RXB_CTL;
+ u32 saveFDI_TXB_CTL;
+ u32 savePFA_CTL_1;
+ u32 savePFB_CTL_1;
+ u32 savePFA_WIN_SZ;
+ u32 savePFB_WIN_SZ;
+ u32 savePFA_WIN_POS;
+ u32 savePFB_WIN_POS;
struct {
struct drm_mm gtt_space;
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
} mm;
struct sdvo_device_mapping sdvo_mappings[2];
+ /* indicate whether the LVDS_BORDER should be enabled or not */
+ unsigned int lvds_border_bits;
/* Reclocking support */
bool render_reclock_avail;
#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev))
#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev))
-#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev)))
+#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \
+ (IS_I9XX(dev) || IS_GM45(dev)) && \
+ !IS_IGD(dev) && \
+ !IS_IGDNG(dev))
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
#define LVDS_PORT_EN (1 << 31)
/* Selects pipe B for LVDS data. Must be set on pre-965. */
#define LVDS_PIPEB_SELECT (1 << 30)
+/* Enable border for unscaled (or aspect-scaled) display */
+#define LVDS_BORDER_ENABLE (1 << 15)
/*
* Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
* pixel.
#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
+#define BLC_HIST_CTL 0x61260
+
/* TV port control */
#define TV_CTL 0x68000
/** Enables the TV encoder */
#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1)
#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0)
+#define PIPE_BPC_MASK (7 << 5) /* Ironlake */
+#define PIPE_8BPC (0 << 5)
+#define PIPE_10BPC (1 << 5)
+#define PIPE_6BPC (2 << 5)
+#define PIPE_12BPC (3 << 5)
#define DSPARB 0x70030
#define DSPARB_CSTART_MASK (0x7f << 7)
#define DSPARB_AEND_SHIFT 0
#define DSPFW1 0x70034
+#define DSPFW_SR_SHIFT 23
+#define DSPFW_CURSORB_SHIFT 16
+#define DSPFW_PLANEB_SHIFT 8
#define DSPFW2 0x70038
+#define DSPFW_CURSORA_MASK 0x00003f00
+#define DSPFW_CURSORA_SHIFT 16
#define DSPFW3 0x7003c
+#define DSPFW_HPLL_SR_EN (1<<31)
+#define DSPFW_CURSOR_SR_SHIFT 24
#define IGD_SELF_REFRESH_EN (1<<30)
/* FIFO watermark sizes etc */
+#define G4X_FIFO_LINE_SIZE 64
#define I915_FIFO_LINE_SIZE 64
#define I830_FIFO_LINE_SIZE 32
+
+#define G4X_FIFO_SIZE 127
#define I945_FIFO_SIZE 127 /* 945 & 965 */
#define I915_FIFO_SIZE 95
#define I855GM_FIFO_SIZE 127 /* In cachelines */
#define I830_FIFO_SIZE 95
+
+#define G4X_MAX_WM 0x3f
#define I915_MAX_WM 0x3f
#define IGD_DISPLAY_FIFO 512 /* in 64byte unit */
#define PFA_CTL_1 0x68080
#define PFB_CTL_1 0x68880
#define PF_ENABLE (1<<31)
+#define PF_FILTER_MASK (3<<23)
+#define PF_FILTER_PROGRAMMED (0<<23)
+#define PF_FILTER_MED_3x3 (1<<23)
+#define PF_FILTER_EDGE_ENHANCE (2<<23)
+#define PF_FILTER_EDGE_SOFTEN (3<<23)
#define PFA_WIN_SZ 0x68074
#define PFB_WIN_SZ 0x68874
#define PFA_WIN_POS 0x68070
#define DREF_CPU_SOURCE_OUTPUT_MASK (3<<13)
#define DREF_SSC_SOURCE_DISABLE (0<<11)
#define DREF_SSC_SOURCE_ENABLE (2<<11)
-#define DREF_SSC_SOURCE_MASK (2<<11)
+#define DREF_SSC_SOURCE_MASK (3<<11)
#define DREF_NONSPREAD_SOURCE_DISABLE (0<<9)
#define DREF_NONSPREAD_CK505_ENABLE (1<<9)
#define DREF_NONSPREAD_SOURCE_ENABLE (2<<9)
-#define DREF_NONSPREAD_SOURCE_MASK (2<<9)
+#define DREF_NONSPREAD_SOURCE_MASK (3<<9)
#define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7)
#define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7)
#define DREF_SSC4_DOWNSPREAD (0<<6)
static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 dpll_reg;
- if (pipe == PIPE_A)
- return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
- else
- return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
+ if (IS_IGDNG(dev)) {
+ dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B;
+ } else {
+ dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B;
+ }
+
+ return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE);
}
static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
if (!i915_pipe_enabled(dev, pipe))
return;
+ if (IS_IGDNG(dev))
+ reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+
if (pipe == PIPE_A)
array = dev_priv->save_palette_a;
else
if (!i915_pipe_enabled(dev, pipe))
return;
+ if (IS_IGDNG(dev))
+ reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+
if (pipe == PIPE_A)
array = dev_priv->save_palette_a;
else
/* Pipe & plane A info */
dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
- dev_priv->saveFPA0 = I915_READ(FPA0);
- dev_priv->saveFPA1 = I915_READ(FPA1);
- dev_priv->saveDPLL_A = I915_READ(DPLL_A);
- if (IS_I965G(dev))
+ if (IS_IGDNG(dev)) {
+ dev_priv->saveFPA0 = I915_READ(PCH_FPA0);
+ dev_priv->saveFPA1 = I915_READ(PCH_FPA1);
+ dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A);
+ } else {
+ dev_priv->saveFPA0 = I915_READ(FPA0);
+ dev_priv->saveFPA1 = I915_READ(FPA1);
+ dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+ }
+ if (IS_I965G(dev) && !IS_IGDNG(dev))
dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
- dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+ if (!IS_IGDNG(dev))
+ dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+ if (IS_IGDNG(dev)) {
+ dev_priv->saveFDI_TXA_CTL = I915_READ(FDI_TXA_CTL);
+ dev_priv->saveFDI_RXA_CTL = I915_READ(FDI_RXA_CTL);
+
+ dev_priv->savePFA_CTL_1 = I915_READ(PFA_CTL_1);
+ dev_priv->savePFA_WIN_SZ = I915_READ(PFA_WIN_SZ);
+ dev_priv->savePFA_WIN_POS = I915_READ(PFA_WIN_POS);
+
+ dev_priv->saveTRANS_HTOTAL_A = I915_READ(TRANS_HTOTAL_A);
+ dev_priv->saveTRANS_HBLANK_A = I915_READ(TRANS_HBLANK_A);
+ dev_priv->saveTRANS_HSYNC_A = I915_READ(TRANS_HSYNC_A);
+ dev_priv->saveTRANS_VTOTAL_A = I915_READ(TRANS_VTOTAL_A);
+ dev_priv->saveTRANS_VBLANK_A = I915_READ(TRANS_VBLANK_A);
+ dev_priv->saveTRANS_VSYNC_A = I915_READ(TRANS_VSYNC_A);
+ }
dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
/* Pipe & plane B info */
dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
- dev_priv->saveFPB0 = I915_READ(FPB0);
- dev_priv->saveFPB1 = I915_READ(FPB1);
- dev_priv->saveDPLL_B = I915_READ(DPLL_B);
- if (IS_I965G(dev))
+ if (IS_IGDNG(dev)) {
+ dev_priv->saveFPB0 = I915_READ(PCH_FPB0);
+ dev_priv->saveFPB1 = I915_READ(PCH_FPB1);
+ dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B);
+ } else {
+ dev_priv->saveFPB0 = I915_READ(FPB0);
+ dev_priv->saveFPB1 = I915_READ(FPB1);
+ dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+ }
+ if (IS_I965G(dev) && !IS_IGDNG(dev))
dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
- dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+ if (!IS_IGDNG(dev))
+ dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B);
+
+ if (IS_IGDNG(dev)) {
+ dev_priv->saveFDI_TXB_CTL = I915_READ(FDI_TXB_CTL);
+ dev_priv->saveFDI_RXB_CTL = I915_READ(FDI_RXB_CTL);
+
+ dev_priv->savePFB_CTL_1 = I915_READ(PFB_CTL_1);
+ dev_priv->savePFB_WIN_SZ = I915_READ(PFB_WIN_SZ);
+ dev_priv->savePFB_WIN_POS = I915_READ(PFB_WIN_POS);
+
+ dev_priv->saveTRANS_HTOTAL_B = I915_READ(TRANS_HTOTAL_B);
+ dev_priv->saveTRANS_HBLANK_B = I915_READ(TRANS_HBLANK_B);
+ dev_priv->saveTRANS_HSYNC_B = I915_READ(TRANS_HSYNC_B);
+ dev_priv->saveTRANS_VTOTAL_B = I915_READ(TRANS_VTOTAL_B);
+ dev_priv->saveTRANS_VBLANK_B = I915_READ(TRANS_VBLANK_B);
+ dev_priv->saveTRANS_VSYNC_B = I915_READ(TRANS_VSYNC_B);
+ }
dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
static void i915_restore_modeset_reg(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ int dpll_a_reg, fpa0_reg, fpa1_reg;
+ int dpll_b_reg, fpb0_reg, fpb1_reg;
if (drm_core_check_feature(dev, DRIVER_MODESET))
return;
+ if (IS_IGDNG(dev)) {
+ dpll_a_reg = PCH_DPLL_A;
+ dpll_b_reg = PCH_DPLL_B;
+ fpa0_reg = PCH_FPA0;
+ fpb0_reg = PCH_FPB0;
+ fpa1_reg = PCH_FPA1;
+ fpb1_reg = PCH_FPB1;
+ } else {
+ dpll_a_reg = DPLL_A;
+ dpll_b_reg = DPLL_B;
+ fpa0_reg = FPA0;
+ fpb0_reg = FPB0;
+ fpa1_reg = FPA1;
+ fpb1_reg = FPB1;
+ }
+
/* Pipe & plane A info */
/* Prime the clock */
if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
- I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+ I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A &
~DPLL_VCO_ENABLE);
DRM_UDELAY(150);
}
- I915_WRITE(FPA0, dev_priv->saveFPA0);
- I915_WRITE(FPA1, dev_priv->saveFPA1);
+ I915_WRITE(fpa0_reg, dev_priv->saveFPA0);
+ I915_WRITE(fpa1_reg, dev_priv->saveFPA1);
/* Actually enable it */
- I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+ I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
DRM_UDELAY(150);
- if (IS_I965G(dev))
+ if (IS_I965G(dev) && !IS_IGDNG(dev))
I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
DRM_UDELAY(150);
I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
- I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+ if (!IS_IGDNG(dev))
+ I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+ if (IS_IGDNG(dev)) {
+ I915_WRITE(FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
+ I915_WRITE(FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
+
+ I915_WRITE(PFA_CTL_1, dev_priv->savePFA_CTL_1);
+ I915_WRITE(PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
+ I915_WRITE(PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
+
+ I915_WRITE(TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
+ I915_WRITE(TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
+ I915_WRITE(TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
+ I915_WRITE(TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
+ I915_WRITE(TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
+ I915_WRITE(TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A);
+ }
/* Restore plane info */
I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
/* Pipe & plane B info */
if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
- I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+ I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B &
~DPLL_VCO_ENABLE);
DRM_UDELAY(150);
}
- I915_WRITE(FPB0, dev_priv->saveFPB0);
- I915_WRITE(FPB1, dev_priv->saveFPB1);
+ I915_WRITE(fpb0_reg, dev_priv->saveFPB0);
+ I915_WRITE(fpb1_reg, dev_priv->saveFPB1);
/* Actually enable it */
- I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+ I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
DRM_UDELAY(150);
if (IS_I965G(dev))
I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
- I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+ if (!IS_IGDNG(dev))
+ I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+ if (IS_IGDNG(dev)) {
+ I915_WRITE(FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
+ I915_WRITE(FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
+
+ I915_WRITE(PFB_CTL_1, dev_priv->savePFB_CTL_1);
+ I915_WRITE(PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
+ I915_WRITE(PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
+
+ I915_WRITE(TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
+ I915_WRITE(TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
+ I915_WRITE(TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
+ I915_WRITE(TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
+ I915_WRITE(TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
+ I915_WRITE(TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B);
+ }
/* Restore plane info */
I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
dev_priv->saveCURSIZE = I915_READ(CURSIZE);
/* CRT state */
- dev_priv->saveADPA = I915_READ(ADPA);
+ if (IS_IGDNG(dev)) {
+ dev_priv->saveADPA = I915_READ(PCH_ADPA);
+ } else {
+ dev_priv->saveADPA = I915_READ(ADPA);
+ }
/* LVDS state */
- dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
- dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
- dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
- if (IS_I965G(dev))
- dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
- if (IS_MOBILE(dev) && !IS_I830(dev))
- dev_priv->saveLVDS = I915_READ(LVDS);
- if (!IS_I830(dev) && !IS_845G(dev))
+ if (IS_IGDNG(dev)) {
+ dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
+ dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
+ dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
+ dev_priv->saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
+ dev_priv->saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
+ dev_priv->saveLVDS = I915_READ(PCH_LVDS);
+ } else {
+ dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
+ dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
+ dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+ dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
+ if (IS_I965G(dev))
+ dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+ if (IS_MOBILE(dev) && !IS_I830(dev))
+ dev_priv->saveLVDS = I915_READ(LVDS);
+ }
+
+ if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev))
dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
- dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
- dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
- dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
+
+ if (IS_IGDNG(dev)) {
+ dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
+ dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
+ dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
+ } else {
+ dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
+ dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
+ dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
+ }
/* Display Port state */
if (SUPPORTS_INTEGRATED_DP(dev)) {
/* FIXME: save TV & SDVO state */
/* FBC state */
- dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
- dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
- dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
- dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+ if (IS_GM45(dev)) {
+ dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
+ } else {
+ dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
+ dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
+ dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
+ dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+ }
/* VGA state */
dev_priv->saveVGA0 = I915_READ(VGA0);
dev_priv->saveVGA1 = I915_READ(VGA1);
dev_priv->saveVGA_PD = I915_READ(VGA_PD);
- dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+ if (IS_IGDNG(dev))
+ dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL);
+ else
+ dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
i915_save_vga(dev);
}
I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
/* CRT state */
- I915_WRITE(ADPA, dev_priv->saveADPA);
+ if (IS_IGDNG(dev))
+ I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
+ else
+ I915_WRITE(ADPA, dev_priv->saveADPA);
/* LVDS state */
- if (IS_I965G(dev))
+ if (IS_I965G(dev) && !IS_IGDNG(dev))
I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
- if (IS_MOBILE(dev) && !IS_I830(dev))
+
+ if (IS_IGDNG(dev)) {
+ I915_WRITE(PCH_LVDS, dev_priv->saveLVDS);
+ } else if (IS_MOBILE(dev) && !IS_I830(dev))
I915_WRITE(LVDS, dev_priv->saveLVDS);
- if (!IS_I830(dev) && !IS_845G(dev))
+
+ if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev))
I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
- I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
- I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
- I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
- I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
- I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
- I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+ if (IS_IGDNG(dev)) {
+ I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL);
+ I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2);
+ I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
+ I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->saveBLC_CPU_PWM_CTL2);
+ I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
+ I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
+ I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
+ I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
+ } else {
+ I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
+ I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+ I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL);
+ I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
+ I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
+ I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
+ I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+ }
/* Display Port state */
if (SUPPORTS_INTEGRATED_DP(dev)) {
/* FIXME: restore TV & SDVO state */
/* FBC info */
- I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
- I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
- I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
- I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+ if (IS_GM45(dev)) {
+ g4x_disable_fbc(dev);
+ I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
+ } else {
+ i8xx_disable_fbc(dev);
+ I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
+ I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
+ I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
+ I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+ }
/* VGA state */
- I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+ if (IS_IGDNG(dev))
+ I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
+ else
+ I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
I915_WRITE(VGA0, dev_priv->saveVGA0);
I915_WRITE(VGA1, dev_priv->saveVGA1);
I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
i915_save_display(dev);
/* Interrupt state */
- dev_priv->saveIER = I915_READ(IER);
- dev_priv->saveIMR = I915_READ(IMR);
+ if (IS_IGDNG(dev)) {
+ dev_priv->saveDEIER = I915_READ(DEIER);
+ dev_priv->saveDEIMR = I915_READ(DEIMR);
+ dev_priv->saveGTIER = I915_READ(GTIER);
+ dev_priv->saveGTIMR = I915_READ(GTIMR);
+ dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
+ dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
+ } else {
+ dev_priv->saveIER = I915_READ(IER);
+ dev_priv->saveIMR = I915_READ(IMR);
+ }
/* Clock gating state */
dev_priv->saveD_STATE = I915_READ(D_STATE);
i915_restore_display(dev);
/* Interrupt state */
- I915_WRITE (IER, dev_priv->saveIER);
- I915_WRITE (IMR, dev_priv->saveIMR);
+ if (IS_IGDNG(dev)) {
+ I915_WRITE(DEIER, dev_priv->saveDEIER);
+ I915_WRITE(DEIMR, dev_priv->saveDEIMR);
+ I915_WRITE(GTIER, dev_priv->saveGTIER);
+ I915_WRITE(GTIMR, dev_priv->saveGTIMR);
+ I915_WRITE(FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
+ I915_WRITE(FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
+ } else {
+ I915_WRITE (IER, dev_priv->saveIER);
+ I915_WRITE (IMR, dev_priv->saveIMR);
+ }
/* Clock gating state */
I915_WRITE (D_STATE, dev_priv->saveD_STATE);
struct drm_device *dev = dev_priv->dev;
struct bdb_driver_features *driver;
- /* set default for chips without eDP */
- if (!SUPPORTS_EDP(dev)) {
- dev_priv->edp_support = 0;
- return;
- }
-
driver = find_section(bdb, BDB_DRIVER_FEATURES);
if (!driver)
return;
- if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
+ if (driver && SUPPORTS_EDP(dev) &&
+ driver->lvds_config == BDB_DRIVER_FEATURE_EDP) {
dev_priv->edp_support = 1;
+ } else {
+ dev_priv->edp_support = 0;
+ }
- if (driver->dual_frequency)
+ if (driver && driver->dual_frequency)
dev_priv->render_reclock_avail = true;
}
clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2);
clock.p = (clock.p1 * clock.p2);
clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p;
+ clock.vco = 0;
memcpy(best_clock, &clock, sizeof(intel_clock_t));
return true;
}
return ret;
}
- /* Pre-i965 needs to install a fence for tiled scan-out */
- if (!IS_I965G(dev) &&
- obj_priv->fence_reg == I915_FENCE_REG_NONE &&
+ /* Install a fence for tiled scan-out. Pre-i965 always needs a fence,
+ * whereas 965+ only requires a fence if using framebuffer compression.
+ * For simplicity, we always install a fence as the cost is not that onerous.
+ */
+ if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
if (ret != 0) {
/* Enable panel fitting for LVDS */
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
temp = I915_READ(pf_ctl_reg);
- I915_WRITE(pf_ctl_reg, temp | PF_ENABLE);
+ I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3);
/* currently full aspect */
I915_WRITE(pf_win_pos, 0);
case DRM_MODE_DPMS_ON:
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
+ intel_update_watermarks(dev);
+
/* Enable the DPLL */
temp = I915_READ(dpll_reg);
if ((temp & DPLL_VCO_ENABLE) == 0) {
/* Give the overlay scaler a chance to enable if it's on this pipe */
//intel_crtc_dpms_video(crtc, true); TODO
- intel_update_watermarks(dev);
break;
case DRM_MODE_DPMS_OFF:
intel_update_watermarks(dev);
#define LINK_N 0x80000
static void
-igdng_compute_m_n(int bytes_per_pixel, int nlanes,
+igdng_compute_m_n(int bits_per_pixel, int nlanes,
int pixel_clock, int link_clock,
struct fdi_m_n *m_n)
{
temp = (u64) DATA_N * pixel_clock;
temp = div_u64(temp, link_clock);
- m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes);
+ m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes);
+ m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */
m_n->gmch_n = DATA_N;
fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
IGD_CURSOR_GUARD_WM,
IGD_FIFO_LINE_SIZE
};
+static struct intel_watermark_params g4x_wm_info = {
+ G4X_FIFO_SIZE,
+ G4X_MAX_WM,
+ G4X_MAX_WM,
+ 2,
+ G4X_FIFO_LINE_SIZE,
+};
static struct intel_watermark_params i945_wm_info = {
I945_FIFO_SIZE,
I915_MAX_WM,
return size;
}
-static void g4x_update_wm(struct drm_device *dev, int unused, int unused2,
- int unused3, int unused4)
+static void g4x_update_wm(struct drm_device *dev, int planea_clock,
+ int planeb_clock, int sr_hdisplay, int pixel_size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 fw_blc_self = I915_READ(FW_BLC_SELF);
+ int total_size, cacheline_size;
+ int planea_wm, planeb_wm, cursora_wm, cursorb_wm, cursor_sr;
+ struct intel_watermark_params planea_params, planeb_params;
+ unsigned long line_time_us;
+ int sr_clock, sr_entries = 0, entries_required;
- if (i915_powersave)
- fw_blc_self |= FW_BLC_SELF_EN;
- else
- fw_blc_self &= ~FW_BLC_SELF_EN;
- I915_WRITE(FW_BLC_SELF, fw_blc_self);
+ /* Create copies of the base settings for each pipe */
+ planea_params = planeb_params = g4x_wm_info;
+
+ /* Grab a couple of global values before we overwrite them */
+ total_size = planea_params.fifo_size;
+ cacheline_size = planea_params.cacheline_size;
+
+ /*
+ * Note: we need to make sure we don't overflow for various clock &
+ * latency values.
+ * clocks go from a few thousand to several hundred thousand.
+ * latency is usually a few thousand
+ */
+ entries_required = ((planea_clock / 1000) * pixel_size * latency_ns) /
+ 1000;
+ entries_required /= G4X_FIFO_LINE_SIZE;
+ planea_wm = entries_required + planea_params.guard_size;
+
+ entries_required = ((planeb_clock / 1000) * pixel_size * latency_ns) /
+ 1000;
+ entries_required /= G4X_FIFO_LINE_SIZE;
+ planeb_wm = entries_required + planeb_params.guard_size;
+
+ cursora_wm = cursorb_wm = 16;
+ cursor_sr = 32;
+
+ DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+
+ /* Calc sr entries for one plane configs */
+ if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+ /* self-refresh has much higher latency */
+ const static int sr_latency_ns = 12000;
+
+ sr_clock = planea_clock ? planea_clock : planeb_clock;
+ line_time_us = ((sr_hdisplay * 1000) / sr_clock);
+
+ /* Use ns/us then divide to preserve precision */
+ sr_entries = (((sr_latency_ns / line_time_us) + 1) *
+ pixel_size * sr_hdisplay) / 1000;
+ 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);
+ }
+
+ DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n",
+ planea_wm, planeb_wm, sr_entries);
+
+ planea_wm &= 0x3f;
+ planeb_wm &= 0x3f;
+
+ I915_WRITE(DSPFW1, (sr_entries << DSPFW_SR_SHIFT) |
+ (cursorb_wm << DSPFW_CURSORB_SHIFT) |
+ (planeb_wm << DSPFW_PLANEB_SHIFT) | planea_wm);
+ I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
+ (cursora_wm << DSPFW_CURSORA_SHIFT));
+ /* HPLL off in SR has some issues on G4x... disable it */
+ I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) |
+ (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
}
static void i965_update_wm(struct drm_device *dev, int unused, int unused2,
unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
int enabled = 0, pixel_size = 0;
+ if (!dev_priv->display.update_wm)
+ return;
+
/* Get the clock config from both planes */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
intel_crtc = to_intel_crtc(crtc);
/* FDI link */
if (IS_IGDNG(dev)) {
- int lane, link_bw;
+ int lane, link_bw, bpp;
/* eDP doesn't require FDI link, so just set DP M/N
according to current link config */
if (is_edp) {
lane = 4;
link_bw = 270000;
}
- igdng_compute_m_n(3, lane, target_clock,
+
+ /* determine panel color depth */
+ temp = I915_READ(pipeconf_reg);
+
+ switch (temp & PIPE_BPC_MASK) {
+ case PIPE_8BPC:
+ bpp = 24;
+ break;
+ case PIPE_10BPC:
+ bpp = 30;
+ break;
+ case PIPE_6BPC:
+ bpp = 18;
+ break;
+ case PIPE_12BPC:
+ bpp = 36;
+ break;
+ default:
+ DRM_ERROR("unknown pipe bpc value\n");
+ bpp = 24;
+ }
+
+ igdng_compute_m_n(bpp, lane, target_clock,
link_bw, &m_n);
}
+ /* Ironlake: try to setup display ref clock before DPLL
+ * enabling. This is only under driver's control after
+ * PCH B stepping, previous chipset stepping should be
+ * ignoring this setting.
+ */
+ if (IS_IGDNG(dev)) {
+ temp = I915_READ(PCH_DREF_CONTROL);
+ /* Always enable nonspread source */
+ temp &= ~DREF_NONSPREAD_SOURCE_MASK;
+ temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+
+ temp &= ~DREF_SSC_SOURCE_MASK;
+ temp |= DREF_SSC_SOURCE_ENABLE;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+
+ udelay(200);
+
+ if (is_edp) {
+ if (dev_priv->lvds_use_ssc) {
+ temp |= DREF_SSC1_ENABLE;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+
+ udelay(200);
+
+ temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+ temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ } else {
+ temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ }
+ }
+ }
+
if (IS_IGD(dev)) {
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
if (has_reduced_clock)
lvds = I915_READ(lvds_reg);
lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
+ /* set the corresponsding LVDS_BORDER bit */
+ lvds |= dev_priv->lvds_border_bits;
/* Set the B0-B3 data pairs corresponding to whether we're going to
* set the DPLLs for dual-channel mode or not.
*/
* Disable clock gating reported to work incorrectly according to the
* specs, but enable as much else as we can.
*/
- if (IS_G4X(dev)) {
+ if (IS_IGDNG(dev)) {
+ return;
+ } else if (IS_G4X(dev)) {
uint32_t dspclk_gate;
I915_WRITE(RENCLK_GATE_D1, 0);
I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
i830_get_display_clock_speed;
/* For FIFO watermark updates */
- if (IS_G4X(dev))
+ if (IS_IGDNG(dev))
+ dev_priv->display.update_wm = NULL;
+ else if (IS_G4X(dev))
dev_priv->display.update_wm = g4x_update_wm;
else if (IS_I965G(dev))
dev_priv->display.update_wm = i965_update_wm;
{
struct intel_dp_priv *dp_priv = intel_output->dev_priv;
- DRM_ERROR("i2c_init %s\n", name);
+ DRM_DEBUG_KMS("i2c_init %s\n", name);
dp_priv->algo.running = false;
dp_priv->algo.address = 0;
dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch;
adjusted_mode->crtc_vblank_start + vsync_pos;
/* keep the vsync width constant */
adjusted_mode->crtc_vsync_end =
- adjusted_mode->crtc_vblank_start + vsync_width;
+ adjusted_mode->crtc_vsync_start + vsync_width;
border = 1;
break;
case DRM_MODE_SCALE_ASPECT:
out:
lvds_priv->pfit_control = pfit_control;
lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
+ /*
+ * When there exists the border, it means that the LVDS_BORDR
+ * should be enabled.
+ */
+ if (border)
+ dev_priv->lvds_border_bits |= LVDS_BORDER_ENABLE;
+ else
+ dev_priv->lvds_border_bits &= ~(LVDS_BORDER_ENABLE);
/*
* XXX: It would be nice to support lower refresh rates on the
* panels to reduce power consumption, and perhaps match the
return 0;
}
+/*
+ * Lid events. Note the use of 'modeset_on_lid':
+ * - we set it on lid close, and reset it on open
+ * - we use it as a "only once" bit (ie we ignore
+ * duplicate events where it was already properly
+ * set/reset)
+ * - the suspend/resume paths will also set it to
+ * zero, since they restore the mode ("lid open").
+ */
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
void *unused)
{
container_of(nb, struct drm_i915_private, lid_notifier);
struct drm_device *dev = dev_priv->dev;
- if (acpi_lid_open() && !dev_priv->suspended) {
- mutex_lock(&dev->mode_config.mutex);
- drm_helper_resume_force_mode(dev);
- mutex_unlock(&dev->mode_config.mutex);
+ if (!acpi_lid_open()) {
+ dev_priv->modeset_on_lid = 1;
+ return NOTIFY_OK;
}
- drm_sysfs_hotplug_event(dev_priv->dev);
+ if (!dev_priv->modeset_on_lid)
+ return NOTIFY_OK;
+
+ dev_priv->modeset_on_lid = 0;
+
+ mutex_lock(&dev->mode_config.mutex);
+ drm_helper_resume_force_mode(dev);
+ mutex_unlock(&dev->mode_config.mutex);
return NOTIFY_OK;
}
wait_queue_head_t queue;
unsigned long i2csr;
unsigned int disable_delay;
+ int stopped;
+ unsigned int ifdr; /* IMX_I2C_IFDR */
};
/** Functions for IMX I2C adapter driver ***************************************
*******************************************************************************/
-static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
{
unsigned long orig_jiffies = jiffies;
+ unsigned int temp;
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- /* wait for bus not busy */
- while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) {
+ while (1) {
+ temp = readb(i2c_imx->base + IMX_I2C_I2SR);
+ if (for_busy && (temp & I2SR_IBB))
+ break;
+ if (!for_busy && !(temp & I2SR_IBB))
+ break;
if (signal_pending(current)) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C Interrupted\n", __func__);
return 0;
}
-static void i2c_imx_start(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
{
unsigned int temp = 0;
+ int result;
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+ clk_enable(i2c_imx->clk);
+ writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR);
/* Enable I2C controller */
+ writeb(0, i2c_imx->base + IMX_I2C_I2SR);
writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
+
+ /* Wait controller to be stable */
+ udelay(50);
+
/* Start I2C transaction */
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
temp |= I2CR_MSTA;
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ result = i2c_imx_bus_busy(i2c_imx, 1);
+ if (result)
+ return result;
+ i2c_imx->stopped = 0;
+
temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ return result;
}
static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
{
unsigned int temp = 0;
- /* Stop I2C transaction */
- dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- temp = readb(i2c_imx->base + IMX_I2C_I2CR);
- temp &= ~I2CR_MSTA;
- writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
- /* setup chip registers to defaults */
- writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
- writeb(0, i2c_imx->base + IMX_I2C_I2SR);
- /*
- * This delay caused by an i.MXL hardware bug.
- * If no (or too short) delay, no "STOP" bit will be generated.
- */
- udelay(i2c_imx->disable_delay);
+ if (!i2c_imx->stopped) {
+ /* Stop I2C transaction */
+ dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+ temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
+ writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ i2c_imx->stopped = 1;
+ }
+ if (cpu_is_mx1()) {
+ /*
+ * This delay caused by an i.MXL hardware bug.
+ * If no (or too short) delay, no "STOP" bit will be generated.
+ */
+ udelay(i2c_imx->disable_delay);
+ }
+
+ if (!i2c_imx->stopped)
+ i2c_imx_bus_busy(i2c_imx, 0);
+
/* Disable I2C controller */
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
+ clk_disable(i2c_imx->clk);
}
static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
else
for (i = 0; i2c_clk_div[i][0] < div; i++);
- /* Write divider value to register */
- writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR);
+ /* Store divider value */
+ i2c_imx->ifdr = i2c_clk_div[i][1];
/*
* There dummy delay is calculated.
if (result)
return result;
if (i == (msgs->len - 1)) {
+ /* It must generate STOP before read I2DR to prevent
+ controller from generating another clock cycle */
dev_dbg(&i2c_imx->adapter.dev,
"<%s> clear MSTA\n", __func__);
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
- temp &= ~I2CR_MSTA;
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ i2c_imx_bus_busy(i2c_imx, 0);
+ i2c_imx->stopped = 1;
} else if (i == (msgs->len - 2)) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> set TXAK\n", __func__);
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- /* Check if i2c bus is not busy */
- result = i2c_imx_bus_busy(i2c_imx);
+ /* Start I2C transfer */
+ result = i2c_imx_start(i2c_imx);
if (result)
goto fail0;
- /* Start I2C transfer */
- i2c_imx_start(i2c_imx);
-
/* read/write data */
for (i = 0; i < num; i++) {
if (i) {
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
temp |= I2CR_RSTA;
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ result = i2c_imx_bus_busy(i2c_imx, 1);
+ if (result)
+ goto fail0;
}
dev_dbg(&i2c_imx->adapter.dev,
"<%s> transfer message: %d\n", __func__, i);
dev_err(&pdev->dev, "can't get I2C clock\n");
goto fail3;
}
- clk_enable(i2c_imx->clk);
/* Request IRQ */
ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx);
fail5:
free_irq(i2c_imx->irq, i2c_imx);
fail4:
- clk_disable(i2c_imx->clk);
clk_put(i2c_imx->clk);
fail3:
release_mem_region(i2c_imx->res->start, resource_size(res));
if (pdata && pdata->exit)
pdata->exit(&pdev->dev);
- /* Disable I2C clock */
- clk_disable(i2c_imx->clk);
clk_put(i2c_imx->clk);
release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res));
unsigned timeout = i2c->adap.timeout;
u32 flags = restart ? CCR_RSTA : 0;
- /* Start with MEN */
- if (!restart)
- writeccr(i2c, CCR_MEN);
/* Start as master */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target byte */
int i, result;
u32 flags = restart ? CCR_RSTA : 0;
- /* Start with MEN */
- if (!restart)
- writeccr(i2c, CCR_MEN);
/* Switch to read - restart */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target address byte - this time with the read flag set */
/* Generate txack on next to last byte */
if (i == length - 2)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
- /* Generate stop on last byte */
+ /* Do not generate stop on last byte */
if (i == length - 1)
- writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX);
data[i] = readb(i2c->base + MPC_I2C_DR);
}
*/
static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
static void *atkbd_platform_fixup_data;
+static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int);
static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *));
input_event(dev, EV_MSC, MSC_RAW, code);
+ if (atkbd_platform_scancode_fixup)
+ code = atkbd_platform_scancode_fixup(atkbd, code);
+
if (atkbd->translated) {
if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
0xae, 0xb0, -1U
};
+/*
+ * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas
+ * they should be generating e4-e6 (0x80 | code).
+ */
+static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd,
+ unsigned int code)
+{
+ if (atkbd->translated && atkbd->emul == 1 &&
+ (code == 0x64 || code == 0x65 || code == 0x66)) {
+ atkbd->emul = 0;
+ code |= 0x80;
+ }
+
+ return code;
+}
+
/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
return 0;
}
+static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
+{
+ atkbd_platform_scancode_fixup = id->driver_data;
+
+ return 0;
+}
+
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
{
.ident = "Dell Laptop",
.callback = atkbd_setup_forced_release,
.driver_data = atkdb_soltech_ta12_forced_release_keys,
},
+ {
+ .ident = "OQO Model 01+",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+ },
+ .callback = atkbd_setup_scancode_fixup,
+ .driver_data = atkbd_oqo_01plus_scancode_fixup,
+ },
{ }
};
}
error = request_irq(irq, gpio_keys_isr,
+ IRQF_SHARED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
bdata);
depends on X86 && PNP
select NEW_LEDS
select LEDS_CLASS
+ select LEDS_TRIGGERS
select BITREVERSE
help
Say Y here if you want to use the IR remote functionality found
static int i8042_controller_init(void)
{
unsigned long flags;
+ int n = 0;
+ unsigned char ctr[2];
/*
- * Save the CTR for restoral on unload / reboot.
+ * Save the CTR for restore on unload / reboot.
*/
- if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
- printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
- return -EIO;
- }
+ do {
+ if (n >= 10) {
+ printk(KERN_ERR
+ "i8042.c: Unable to get stable CTR read.\n");
+ return -EIO;
+ }
+
+ if (n != 0)
+ udelay(50);
+
+ if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
+ printk(KERN_ERR
+ "i8042.c: Can't read CTR while initializing i8042.\n");
+ return -EIO;
+ }
- i8042_initial_ctr = i8042_ctr;
+ } while (n < 2 || ctr[0] != ctr[1]);
+
+ i8042_initial_ctr = i8042_ctr = ctr[0];
/*
* Disable the keyboard interface and interrupt.
return -EIO;
}
+/*
+ * Flush whatever accumulated while we were disabling keyboard port.
+ */
+
+ i8042_flush();
+
return 0;
}
i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS;
i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
- if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR))
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n");
/*
} else
DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
- /* Isolate all the PHY ids */
- for (addr = 0; addr < 32; addr++)
- mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
- /* Select the discovered PHY */
- bmcr &= ~BMCR_ISOLATE;
- mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
-
/* Get phy ID */
id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
nic->phy = (u32)id_hi << 16 | (u32)id_lo;
DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);
+ /* Select the phy and isolate the rest */
+ for (addr = 0; addr < 32; addr++) {
+ if (addr != nic->mii.phy_id) {
+ mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
+ } else if (nic->phy != phy_82552_v) {
+ bmcr = mdio_read(netdev, addr, MII_BMCR);
+ mdio_write(netdev, addr, MII_BMCR,
+ bmcr & ~BMCR_ISOLATE);
+ }
+ }
+ /*
+ * Workaround for 82552:
+ * Clear the ISOLATE bit on selected phy_id last (mirrored on all
+ * other phy_id's) using bmcr value from addr discovery loop above.
+ */
+ if (nic->phy == phy_82552_v)
+ mdio_write(netdev, nic->mii.phy_id, MII_BMCR,
+ bmcr & ~BMCR_ISOLATE);
+
/* Handle National tx phys */
#define NCS_PHY_MODEL_MASK 0xFFF0FFFF
if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
/* Extended Device Control */
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
/* Extended Configuration Control and Size */
#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */
#define HV_TNCRS_LOWER PHY_REG(778, 30)
+/* BM PHY Copper Specific Status */
+#define BM_CS_STATUS 17
+#define BM_CS_STATUS_LINK_UP 0x0400
+#define BM_CS_STATUS_RESOLVED 0x0800
+#define BM_CS_STATUS_SPEED_MASK 0xC000
+#define BM_CS_STATUS_SPEED_1000 0x8000
+
+/* 82577 Mobile Phy Status Register */
+#define HV_M_STATUS 26
+#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000
+#define HV_M_STATUS_SPEED_MASK 0x0300
+#define HV_M_STATUS_SPEED_1000 0x0200
+#define HV_M_STATUS_LINK_UP 0x0040
+
enum e1000_boards {
board_82571,
board_82572,
struct e1000_dev_spec_ich8lan {
bool kmrn_lock_loss_workaround_enabled;
struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
+ bool nvm_k1_enabled;
};
struct e1000_hw {
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */
+/* SMBus Address Phy Register */
+#define HV_SMB_ADDR PHY_REG(768, 26)
+#define HV_SMB_ADDR_PEC_EN 0x0200
+#define HV_SMB_ADDR_VALID 0x0080
+
+/* Strapping Option Register - RO */
+#define E1000_STRAP 0x0000C
+#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
+#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+
/* OEM Bits Phy Register */
#define HV_OEM_BITS PHY_REG(768, 25)
#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */
+#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */
#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
+#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
+#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
+
/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
/* Offset 04h HSFSTS */
union ich8_hws_flash_status {
static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
+static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
+static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
+static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
{
goto out;
}
- if (hw->mac.type == e1000_pchlan) {
- ret_val = e1000e_write_kmrn_reg(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- E1000_KMRNCTRLSTA_K1_ENABLE);
- if (ret_val)
- goto out;
- }
-
/*
* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
if (ret_val)
goto out;
+ if (hw->mac.type == e1000_pchlan) {
+ ret_val = e1000_k1_gig_workaround_hv(hw, link);
+ if (ret_val)
+ goto out;
+ }
+
if (!link)
goto out; /* No link detected */
return 0;
}
+/**
+ * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
+ * @hw: pointer to the HW structure
+ *
+ * SW should configure the LCD from the NVM extended configuration region
+ * as a workaround for certain parts.
+ **/
+static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
+ s32 ret_val;
+ u16 word_addr, reg_data, reg_addr, phy_page = 0;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
+ /*
+ * Initialize the PHY from the NVM on ICH platforms. This
+ * is needed due to an issue where the NVM configuration is
+ * not properly autoloaded after power transitions.
+ * Therefore, after each PHY reset, we will load the
+ * configuration data out of the NVM manually.
+ */
+ if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) ||
+ (hw->mac.type == e1000_pchlan)) {
+ struct e1000_adapter *adapter = hw->adapter;
+
+ /* Check if SW needs to configure the PHY */
+ if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
+ (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
+ (hw->mac.type == e1000_pchlan))
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
+ else
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
+
+ data = er32(FEXTNVM);
+ if (!(data & sw_cfg_mask))
+ goto out;
+
+ /* Wait for basic configuration completes before proceeding */
+ e1000_lan_init_done_ich8lan(hw);
+
+ /*
+ * Make sure HW does not configure LCD from PHY
+ * extended configuration before SW configuration
+ */
+ data = er32(EXTCNF_CTRL);
+ if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+ goto out;
+
+ cnf_size = er32(EXTCNF_SIZE);
+ cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
+ cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
+ if (!cnf_size)
+ goto out;
+
+ cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
+ cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
+
+ if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
+ (hw->mac.type == e1000_pchlan)) {
+ /*
+ * HW configures the SMBus address and LEDs when the
+ * OEM and LCD Write Enable bits are set in the NVM.
+ * When both NVM bits are cleared, SW will configure
+ * them instead.
+ */
+ data = er32(STRAP);
+ data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
+ reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
+ reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+ ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
+ reg_data);
+ if (ret_val)
+ goto out;
+
+ data = er32(LEDCTL);
+ ret_val = e1000_write_phy_reg_hv_locked(hw,
+ HV_LED_CONFIG,
+ (u16)data);
+ if (ret_val)
+ goto out;
+ }
+ /* Configure LCD from extended configuration region. */
+
+ /* cnf_base_addr is in DWORD */
+ word_addr = (u16)(cnf_base_addr << 1);
+
+ for (i = 0; i < cnf_size; i++) {
+ ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
+ ®_data);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
+ 1, ®_addr);
+ if (ret_val)
+ goto out;
+
+ /* Save off the PHY page for future writes. */
+ if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
+ phy_page = reg_data;
+ continue;
+ }
+
+ reg_addr &= PHY_REG_MASK;
+ reg_addr |= phy_page;
+
+ ret_val = phy->ops.write_phy_reg_locked(hw,
+ (u32)reg_addr,
+ reg_data);
+ if (ret_val)
+ goto out;
+ }
+ }
+
+out:
+ hw->phy.ops.release_phy(hw);
+ return ret_val;
+}
+
+/**
+ * e1000_k1_gig_workaround_hv - K1 Si workaround
+ * @hw: pointer to the HW structure
+ * @link: link up bool flag
+ *
+ * If K1 is enabled for 1Gbps, the MAC might stall when transitioning
+ * from a lower speed. This workaround disables K1 whenever link is at 1Gig
+ * If link is down, the function will restore the default K1 setting located
+ * in the NVM.
+ **/
+static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
+{
+ s32 ret_val = 0;
+ u16 status_reg = 0;
+ bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;
+
+ if (hw->mac.type != e1000_pchlan)
+ goto out;
+
+ /* Wrap the whole flow with the sw flag */
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ goto out;
+
+ /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
+ if (link) {
+ if (hw->phy.type == e1000_phy_82578) {
+ ret_val = hw->phy.ops.read_phy_reg_locked(hw,
+ BM_CS_STATUS,
+ &status_reg);
+ if (ret_val)
+ goto release;
+
+ status_reg &= BM_CS_STATUS_LINK_UP |
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_MASK;
+
+ if (status_reg == (BM_CS_STATUS_LINK_UP |
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_1000))
+ k1_enable = false;
+ }
+
+ if (hw->phy.type == e1000_phy_82577) {
+ ret_val = hw->phy.ops.read_phy_reg_locked(hw,
+ HV_M_STATUS,
+ &status_reg);
+ if (ret_val)
+ goto release;
+
+ status_reg &= HV_M_STATUS_LINK_UP |
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_MASK;
+
+ if (status_reg == (HV_M_STATUS_LINK_UP |
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_1000))
+ k1_enable = false;
+ }
+
+ /* Link stall fix for link up */
+ ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
+ 0x0100);
+ if (ret_val)
+ goto release;
+
+ } else {
+ /* Link stall fix for link down */
+ ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
+ 0x4100);
+ if (ret_val)
+ goto release;
+ }
+
+ ret_val = e1000_configure_k1_ich8lan(hw, k1_enable);
+
+release:
+ hw->phy.ops.release_phy(hw);
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_configure_k1_ich8lan - Configure K1 power state
+ * @hw: pointer to the HW structure
+ * @enable: K1 state to configure
+ *
+ * Configure the K1 power state based on the provided parameter.
+ * Assumes semaphore already acquired.
+ *
+ * Success returns 0, Failure returns -E1000_ERR_PHY (-2)
+ **/
+static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
+{
+ s32 ret_val = 0;
+ u32 ctrl_reg = 0;
+ u32 ctrl_ext = 0;
+ u32 reg = 0;
+ u16 kmrn_reg = 0;
+
+ ret_val = e1000e_read_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ &kmrn_reg);
+ if (ret_val)
+ goto out;
+
+ if (k1_enable)
+ kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
+ else
+ kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;
+
+ ret_val = e1000e_write_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ kmrn_reg);
+ if (ret_val)
+ goto out;
+
+ udelay(20);
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_reg = er32(CTRL);
+
+ reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+ reg |= E1000_CTRL_FRCSPD;
+ ew32(CTRL, reg);
+
+ ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
+ udelay(20);
+ ew32(CTRL, ctrl_reg);
+ ew32(CTRL_EXT, ctrl_ext);
+ udelay(20);
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration
+ * @hw: pointer to the HW structure
+ * @d0_state: boolean if entering d0 or d3 device state
+ *
+ * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
+ * collectively called OEM bits. The OEM Write Enable bit and SW Config bit
+ * in NVM determines whether HW should configure LPLU and Gbe Disable.
+ **/
+static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
+{
+ s32 ret_val = 0;
+ u32 mac_reg;
+ u16 oem_reg;
+
+ if (hw->mac.type != e1000_pchlan)
+ return ret_val;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
+ mac_reg = er32(EXTCNF_CTRL);
+ if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
+ goto out;
+
+ mac_reg = er32(FEXTNVM);
+ if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
+ goto out;
+
+ mac_reg = er32(PHY_CTRL);
+
+ ret_val = hw->phy.ops.read_phy_reg_locked(hw, HV_OEM_BITS, &oem_reg);
+ if (ret_val)
+ goto out;
+
+ oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
+
+ if (d0_state) {
+ if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE)
+ oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+ if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ } else {
+ if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
+ oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+ if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ }
+ /* Restart auto-neg to activate the bits */
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
+ ret_val = hw->phy.ops.write_phy_reg_locked(hw, HV_OEM_BITS, oem_reg);
+
+out:
+ hw->phy.ops.release_phy(hw);
+
+ return ret_val;
+}
+
+
/**
* e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
* done after every PHY reset.
ret_val = hw->phy.ops.acquire_phy(hw);
if (ret_val)
return ret_val;
+
hw->phy.addr = 1;
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+ ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+ if (ret_val)
+ goto out;
hw->phy.ops.release_phy(hw);
+ /*
+ * Configure the K1 Si workaround during phy reset assuming there is
+ * link so that it disables K1 if link is in 1Gbps.
+ */
+ ret_val = e1000_k1_gig_workaround_hv(hw, true);
+
+out:
return ret_val;
}
**/
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
{
- struct e1000_phy_info *phy = &hw->phy;
- u32 i;
- u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;
- s32 ret_val;
- u16 reg, word_addr, reg_data, reg_addr, phy_page = 0;
+ s32 ret_val = 0;
+ u16 reg;
ret_val = e1000e_phy_hw_reset_generic(hw);
if (ret_val)
if (hw->mac.type == e1000_pchlan)
e1e_rphy(hw, BM_WUC, ®);
- /*
- * Initialize the PHY from the NVM on ICH platforms. This
- * is needed due to an issue where the NVM configuration is
- * not properly autoloaded after power transitions.
- * Therefore, after each PHY reset, we will load the
- * configuration data out of the NVM manually.
- */
- if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) {
- struct e1000_adapter *adapter = hw->adapter;
-
- /* Check if SW needs configure the PHY */
- if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
- (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M))
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
- else
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
-
- data = er32(FEXTNVM);
- if (!(data & sw_cfg_mask))
- return 0;
-
- /* Wait for basic configuration completes before proceeding */
- e1000_lan_init_done_ich8lan(hw);
-
- /*
- * Make sure HW does not configure LCD from PHY
- * extended configuration before SW configuration
- */
- data = er32(EXTCNF_CTRL);
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- return 0;
-
- cnf_size = er32(EXTCNF_SIZE);
- cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
- cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
- if (!cnf_size)
- return 0;
-
- cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
- cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
-
- /* Configure LCD from extended configuration region. */
-
- /* cnf_base_addr is in DWORD */
- word_addr = (u16)(cnf_base_addr << 1);
-
- for (i = 0; i < cnf_size; i++) {
- ret_val = e1000_read_nvm(hw,
- (word_addr + i * 2),
- 1,
- ®_data);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_nvm(hw,
- (word_addr + i * 2 + 1),
- 1,
- ®_addr);
- if (ret_val)
- return ret_val;
-
- /* Save off the PHY page for future writes. */
- if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
- phy_page = reg_data;
- continue;
- }
-
- reg_addr |= phy_page;
+ /* Configure the LCD with the extended configuration region in NVM */
+ ret_val = e1000_sw_lcd_config_ich8lan(hw);
+ if (ret_val)
+ goto out;
- ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data);
- if (ret_val)
- return ret_val;
- }
- }
+ /* Configure the LCD with the OEM bits in NVM */
+ if (hw->mac.type == e1000_pchlan)
+ ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+out:
return 0;
}
**/
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u16 reg;
u32 ctrl, icr, kab;
s32 ret_val;
ew32(PBS, E1000_PBS_16K);
}
+ if (hw->mac.type == e1000_pchlan) {
+ /* Save the NVM K1 bit setting*/
+ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®);
+ if (ret_val)
+ return ret_val;
+
+ if (reg & E1000_NVM_K1_ENABLE)
+ dev_spec->nvm_k1_enabled = true;
+ else
+ dev_spec->nvm_k1_enabled = false;
+ }
+
ctrl = er32(CTRL);
if (!e1000_check_reset_block(hw)) {
if (hw->mac.type == e1000_pchlan)
e1e_rphy(hw, BM_WUC, ®);
+ ret_val = e1000_sw_lcd_config_ich8lan(hw);
+ if (ret_val)
+ goto out;
+
+ if (hw->mac.type == e1000_pchlan) {
+ ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+ if (ret_val)
+ goto out;
+ }
/*
* For PCH, this write will make sure that any noise
* will be detected as a CRC error and be dropped rather than show up
if (hw->mac.type == e1000_pchlan)
ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
+out:
return ret_val;
}
if (ret_val)
return ret_val;
- if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
- ret_val = e1000e_write_kmrn_reg(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- E1000_KMRNCTRLSTA_K1_DISABLE);
- if (ret_val)
- return ret_val;
- }
-
if ((hw->mac.type == e1000_ich8lan) &&
(hw->phy.type == e1000_phy_igp_3) &&
(*speed == SPEED_1000)) {
/* BM PHY Copper Specific Control 1 */
#define BM_CS_CTRL1 16
-/* BM PHY Copper Specific Status */
-#define BM_CS_STATUS 17
-#define BM_CS_STATUS_LINK_UP 0x0400
-#define BM_CS_STATUS_RESOLVED 0x0800
-#define BM_CS_STATUS_SPEED_MASK 0xC000
-#define BM_CS_STATUS_SPEED_1000 0x8000
-
#define HV_MUX_DATA_CTRL PHY_REG(776, 16)
#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400
#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004
}
/**
- * e1000_read_kmrn_reg_locked - Read kumeran register
+ * e1000e_read_kmrn_reg_locked - Read kumeran register
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
* information retrieved is stored in data.
* Assumes semaphore already acquired.
**/
-s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
{
return __e1000_read_kmrn_reg(hw, offset, data, true);
}
}
/**
- * e1000_write_kmrn_reg_locked - Write kumeran register
+ * e1000e_write_kmrn_reg_locked - Write kumeran register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
* Write the data to PHY register at the offset using the kumeran interface.
* Assumes semaphore already acquired.
**/
-s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
{
return __e1000_write_kmrn_reg(hw, offset, data, true);
}
PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
{
/* Low hurts. Let's disable the filtering. */
- RTL_W16(RxMaxSize, rx_buf_sz);
+ RTL_W16(RxMaxSize, rx_buf_sz + 1);
}
static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
goto err_out_free_netdev;
}
+ netif_carrier_off(dev);
+
netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
err = request_irq(pdev->irq, sky2_intr,
} else {
char **prphase = printphase;
char **prerror = printerror;
+ int pnr = err / 16 - 1;
+ int enr = err % 16 - 1;
DPRINTK("TR Adapter misc open failure, error code = ");
- printk("0x%x, Phase: %s, Error: %s\n",
- err, prphase[err/16 -1], prerror[err%16 -1]);
+ if (pnr < 0 || pnr >= ARRAY_SIZE(printphase) ||
+ enr < 0 ||
+ enr >= ARRAY_SIZE(printerror))
+ printk("0x%x, invalid Phase/Error.", err);
+ else
+ printk("0x%x, Phase: %s, Error: %s\n", err,
+ prphase[pnr], prerror[enr]);
printk(" retrying after %ds delay...\n",
TR_RETRY_INTERVAL/HZ);
}
return rate;
if (rate_table->info[rate].valid_single_stream &&
- !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG));
+ !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
return rate;
/* This should not happen */
}
static int dma_tx_fragment(struct b43_dmaring *ring,
- struct sk_buff *skb)
+ struct sk_buff **in_skb)
{
+ struct sk_buff *skb = *in_skb;
const struct b43_dma_ops *ops = ring->ops;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *header;
}
memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+ memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
+ bounce_skb->dev = skb->dev;
+ skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
+ info = IEEE80211_SKB_CB(bounce_skb);
+
dev_kfree_skb_any(skb);
skb = bounce_skb;
+ *in_skb = bounce_skb;
meta->skb = skb;
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
* static, so we don't need to store it per frame. */
ring->queue_prio = skb_get_queue_mapping(skb);
- err = dma_tx_fragment(ring, skb);
+ /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
+ * into the skb data or cb now. */
+ hdr = NULL;
+ info = NULL;
+ err = dma_tx_fragment(ring, &skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */
fail:
if (dev) {
- if (registered)
+ if (registered) {
+ unregister_ieee80211(priv->ieee);
unregister_netdev(dev);
+ }
ipw2100_hw_stop_adapter(priv);
/* Unregister the device first - this results in close()
* being called if the device is open. If we free storage
* first, then close() will crash. */
+ unregister_ieee80211(priv->ieee);
unregister_netdev(dev);
/* ipw2100_down will ensure that there is no more pending work
if (err) {
IPW_ERROR("Failed to register promiscuous network "
"device (error %d).\n", err);
+ unregister_ieee80211(priv->ieee);
unregister_netdev(priv->net_dev);
goto out_remove_sysfs;
}
mutex_unlock(&priv->mutex);
+ unregister_ieee80211(priv->ieee);
unregister_netdev(priv->net_dev);
if (priv->rxq) {
/* ieee80211.c */
extern void free_ieee80211(struct net_device *dev, int monitor);
extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
+extern void unregister_ieee80211(struct libipw_device *ieee);
extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
extern void libipw_networks_age(struct libipw_device *ieee,
libipw_networks_free(ieee);
/* free cfg80211 resources */
- if (!monitor) {
- wiphy_unregister(ieee->wdev.wiphy);
- kfree(ieee->a_band.channels);
- kfree(ieee->bg_band.channels);
+ if (!monitor)
wiphy_free(ieee->wdev.wiphy);
- }
free_netdev(dev);
}
+void unregister_ieee80211(struct libipw_device *ieee)
+{
+ wiphy_unregister(ieee->wdev.wiphy);
+ kfree(ieee->a_band.channels);
+ kfree(ieee->bg_band.channels);
+}
+
#ifdef CONFIG_LIBIPW_DEBUG
static int debug = 0;
EXPORT_SYMBOL(alloc_ieee80211);
EXPORT_SYMBOL(free_ieee80211);
+EXPORT_SYMBOL(unregister_ieee80211);
/* Fill the receive configuration URB and initialise the Rx call back */
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
- (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),
+ skb->data + IPFIELD_ALIGN_OFFSET,
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
cardp);
{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
/* MSI */
+ { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+ /* Ovislink */
+ { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
/* Ralink */
{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
/* Planex */
{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+ /* WideTell */
+ { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
/* Zcom */
{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
/* ZyXEL */
* These functions check for the appropriate struct pcmcia_soket arrays,
* and pass them to the low-level functions pcmcia_{suspend,resume}_socket
*/
+static int socket_early_resume(struct pcmcia_socket *skt);
+static int socket_late_resume(struct pcmcia_socket *skt);
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);
-int pcmcia_socket_dev_suspend(struct device *dev)
+static void pcmcia_socket_dev_run(struct device *dev,
+ int (*cb)(struct pcmcia_socket *))
{
struct pcmcia_socket *socket;
if (socket->dev.parent != dev)
continue;
mutex_lock(&socket->skt_mutex);
- socket_suspend(socket);
+ cb(socket);
mutex_unlock(&socket->skt_mutex);
}
up_read(&pcmcia_socket_list_rwsem);
+}
+int pcmcia_socket_dev_suspend(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_suspend);
return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
-int pcmcia_socket_dev_resume(struct device *dev)
+void pcmcia_socket_dev_early_resume(struct device *dev)
{
- struct pcmcia_socket *socket;
+ pcmcia_socket_dev_run(dev, socket_early_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
- if (socket->dev.parent != dev)
- continue;
- mutex_lock(&socket->skt_mutex);
- socket_resume(socket);
- mutex_unlock(&socket->skt_mutex);
- }
- up_read(&pcmcia_socket_list_rwsem);
+void pcmcia_socket_dev_late_resume(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_late_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);
+int pcmcia_socket_dev_resume(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_resume);
return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_resume);
return 0;
}
-/*
- * Resume a socket. If a card is present, verify its CIS against
- * our cached copy. If they are different, the card has been
- * replaced, and we need to tell the drivers.
- */
-static int socket_resume(struct pcmcia_socket *skt)
+static int socket_early_resume(struct pcmcia_socket *skt)
{
- int ret;
-
- if (!(skt->state & SOCKET_SUSPEND))
- return -EBUSY;
-
skt->socket = dead_socket;
skt->ops->init(skt);
skt->ops->set_socket(skt, &skt->socket);
+ if (skt->state & SOCKET_PRESENT)
+ skt->resume_status = socket_setup(skt, resume_delay);
+ return 0;
+}
+static int socket_late_resume(struct pcmcia_socket *skt)
+{
if (!(skt->state & SOCKET_PRESENT)) {
skt->state &= ~SOCKET_SUSPEND;
return socket_insert(skt);
}
- ret = socket_setup(skt, resume_delay);
- if (ret == 0) {
+ if (skt->resume_status == 0) {
/*
* FIXME: need a better check here for cardbus cards.
*/
return 0;
}
+/*
+ * Resume a socket. If a card is present, verify its CIS against
+ * our cached copy. If they are different, the card has been
+ * replaced, and we need to tell the drivers.
+ */
+static int socket_resume(struct pcmcia_socket *skt)
+{
+ if (!(skt->state & SOCKET_SUSPEND))
+ return -EBUSY;
+
+ socket_early_resume(skt);
+ return socket_late_resume(skt);
+}
+
static void socket_remove(struct pcmcia_socket *skt)
{
dev_printk(KERN_NOTICE, &skt->dev,
if (socket->type && socket->type->restore_state)
socket->type->restore_state(socket);
- return pcmcia_socket_dev_resume(dev);
+ pcmcia_socket_dev_early_resume(dev);
+ return 0;
+}
+
+static int yenta_dev_resume(struct device *dev)
+{
+ pcmcia_socket_dev_late_resume(dev);
+ return 0;
}
static struct dev_pm_ops yenta_pm_ops = {
.suspend_noirq = yenta_dev_suspend_noirq,
.resume_noirq = yenta_dev_resume_noirq,
+ .resume = yenta_dev_resume,
.freeze_noirq = yenta_dev_suspend_noirq,
.thaw_noirq = yenta_dev_resume_noirq,
+ .thaw = yenta_dev_resume,
.poweroff_noirq = yenta_dev_suspend_noirq,
.restore_noirq = yenta_dev_resume_noirq,
+ .restore = yenta_dev_resume,
};
#define YENTA_PM_OPS (¥ta_pm_ops)
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
fw-shipped-$(CONFIG_MYRI_SBUS) += myricom/lanai.bin
fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis cis/PCMLM28.cis \
cis/DP83903.cis cis/NE2K.cis \
- cis/tamarack.cis
+ cis/tamarack.cis cis/PE-200.cis
fw-shipped-$(CONFIG_PCMCIA_3C589) += cis/3CXEM556.cis
fw-shipped-$(CONFIG_PCMCIA_3C574) += cis/3CCFEM556.cis
fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis \
- cis/COMpad2.cis cis/COMpad4.cis
+ cis/COMpad2.cis cis/COMpad4.cis \
+ cis/SW_555_SER.cis cis/SW_7xx_SER.cis \
+ cis/SW_8xx_SER.cis
fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin
fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
advansys/3550.bin advansys/38C0800.bin
cis/DP83903.cis
cis/NE2K.cis
cis/tamarack.cis
+ cis/PE-200.cis
Licence: GPL
cis/RS-COM-2P.cis
cis/COMpad2.cis
cis/COMpad4.cis
+ cis/SW_555_SER.cis
+ cis/SW_7xx_SER.cis
+ cis/SW_8xx_SER.cis
Licence: GPL
--- /dev/null
+:1000000001030000FF151E0401504D582020200060
+:1000100050452D3230300045544845524E4554002D
+:1000200052303100FF210206031A050101000101CF
+:100030001B0EC181190155E051000F100F30FFFF59
+:040040001400FF00A9
+:00000001FF
+#
+# Replacement CIS for PE-200 ethernet card
+#
--- /dev/null
+:100000000101FF17034100FF20043F0110072102F7
+:100010000200152A070053696572726120576972E0
+:10002000656C657373004169724361726420353594
+:1000300035004135353500526576203100FF1A050F
+:1000400001030007731B0BE00118A360F8030730DE
+:10005000BC3F1B08A10108A360F802071B08A2010E
+:1000600008A360E803071B08A30108A360E80207D0
+:0A0070001B04A40108231400FF0084
+:00000001FF
+#
+# Replacement CIS for AC555 provided by Sierra Wireless
+#
--- /dev/null
+:100000000101FF17034100FF2004920110072102A4
+:1000100002001537070053696572726120576972D3
+:10002000656C6573730041433731302F4143373579
+:10003000300047505253204E6574776F726B2041E9
+:1000400064617074657200523100FF1A050103008B
+:1000500007731B10E00119784D555D25A360F80367
+:100060000730BC861B08A10108A360F802071B0823
+:10007000A20108A360E803071B08A30108A360E826
+:0C00800002071B04A40108231400FF0069
+:00000001FF
+#
+# Replacement CIS for AC7xx provided by Sierra Wireless
+#
--- /dev/null
+:100000000101FF17034100FF2004920110072102A4
+:100010000200152F070053696572726120576972DB
+:10002000656C657373004143383530003347204EAB
+:100030006574776F726B20416461707465720052F1
+:100040003100FF1A0501030007731B10E001197846
+:100050004D555D25A360F8480730BC861B08A101FB
+:1000600008A360F847071B08A20108A360E8480737
+:100070001B08A30108A360E847071B04A401082389
+:040080001400FF0069
+:00000001FF
+#
+# Replacement CIS for AC8xx provided by Sierra Wireless
+#
#include "v9fs_vfs.h"
#include "fid.h"
+/**
+ * struct p9_rdir - readdir accounting
+ * @mutex: mutex protecting readdir
+ * @head: start offset of current dirread buffer
+ * @tail: end offset of current dirread buffer
+ * @buf: dirread buffer
+ *
+ * private structure for keeping track of readdir
+ * allocated on demand
+ */
+
+struct p9_rdir {
+ struct mutex mutex;
+ int head;
+ int tail;
+ uint8_t *buf;
+};
+
/**
* dt_type - return file type
* @mistat: mistat structure
{
int over;
struct p9_wstat st;
- int err;
+ int err = 0;
struct p9_fid *fid;
int buflen;
- char *statbuf;
- int n, i = 0;
+ int reclen = 0;
+ struct p9_rdir *rdir;
P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
fid = filp->private_data;
buflen = fid->clnt->msize - P9_IOHDRSZ;
- statbuf = kmalloc(buflen, GFP_KERNEL);
- if (!statbuf)
- return -ENOMEM;
-
- while (1) {
- err = v9fs_file_readn(filp, statbuf, NULL, buflen,
- fid->rdir_fpos);
- if (err <= 0)
- break;
-
- n = err;
- while (i < n) {
- err = p9stat_read(statbuf + i, buflen-i, &st,
- fid->clnt->dotu);
+
+ /* allocate rdir on demand */
+ if (!fid->rdir) {
+ rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
+
+ if (rdir == NULL) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ spin_lock(&filp->f_dentry->d_lock);
+ if (!fid->rdir) {
+ rdir->buf = (uint8_t *)rdir + sizeof(struct p9_rdir);
+ mutex_init(&rdir->mutex);
+ rdir->head = rdir->tail = 0;
+ fid->rdir = (void *) rdir;
+ rdir = NULL;
+ }
+ spin_unlock(&filp->f_dentry->d_lock);
+ kfree(rdir);
+ }
+ rdir = (struct p9_rdir *) fid->rdir;
+
+ err = mutex_lock_interruptible(&rdir->mutex);
+ while (err == 0) {
+ if (rdir->tail == rdir->head) {
+ err = v9fs_file_readn(filp, rdir->buf, NULL,
+ buflen, filp->f_pos);
+ if (err <= 0)
+ goto unlock_and_exit;
+
+ rdir->head = 0;
+ rdir->tail = err;
+ }
+
+ while (rdir->head < rdir->tail) {
+ err = p9stat_read(rdir->buf + rdir->head,
+ buflen - rdir->head, &st,
+ fid->clnt->dotu);
if (err) {
P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err);
err = -EIO;
p9stat_free(&st);
- goto free_and_exit;
+ goto unlock_and_exit;
}
-
- i += st.size+2;
- fid->rdir_fpos += st.size+2;
+ reclen = st.size+2;
over = filldir(dirent, st.name, strlen(st.name),
filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st));
- filp->f_pos += st.size+2;
-
p9stat_free(&st);
if (over) {
err = 0;
- goto free_and_exit;
+ goto unlock_and_exit;
}
+ rdir->head += reclen;
+ filp->f_pos += reclen;
}
}
-free_and_exit:
- kfree(statbuf);
+unlock_and_exit:
+ mutex_unlock(&rdir->mutex);
+exit:
return err;
}
P9_DPRINTK(P9_DEBUG_VFS,
"%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
- retval = buflen;
-
+ retval = strnlen(buffer, buflen);
done:
kfree(st);
return retval;
__putname(link);
link = ERR_PTR(len);
} else
- link[len] = 0;
+ link[min(len, PATH_MAX-1)] = 0;
}
nd_set_link(nd, link);
* @gfp_mask: allocation mask to use
* @nr_iovecs: number of iovecs
*
- * Allocate a new bio with @nr_iovecs bvecs. If @gfp_mask
- * contains __GFP_WAIT, the allocation is guaranteed to succeed.
+ * bio_alloc will allocate a bio and associated bio_vec array that can hold
+ * at least @nr_iovecs entries. Allocations will be done from the
+ * fs_bio_set. Also see @bio_alloc_bioset and @bio_kmalloc.
+ *
+ * If %__GFP_WAIT is set, then bio_alloc will always be able to allocate
+ * a bio. This is due to the mempool guarantees. To make this work, callers
+ * must never allocate more than 1 bio at a time from this pool. Callers
+ * that need to allocate more than 1 bio must always submit the previously
+ * allocated bio for IO before attempting to allocate a new one. Failure to
+ * do so can cause livelocks under memory pressure.
*
* RETURNS:
* Pointer to new bio on success, NULL on failure.
}
/**
- * bio_alloc - allocate a bio for I/O
+ * bio_kmalloc - allocate a bio for I/O using kmalloc()
* @gfp_mask: the GFP_ mask given to the slab allocator
* @nr_iovecs: number of iovecs to pre-allocate
*
* Description:
- * bio_alloc will allocate a bio and associated bio_vec array that can hold
- * at least @nr_iovecs entries. Allocations will be done from the
- * fs_bio_set. Also see @bio_alloc_bioset.
- *
- * If %__GFP_WAIT is set, then bio_alloc will always be able to allocate
- * a bio. This is due to the mempool guarantees. To make this work, callers
- * must never allocate more than 1 bio at a time from this pool. Callers
- * that need to allocate more than 1 bio must always submit the previously
- * allocated bio for IO before attempting to allocate a new one. Failure to
- * do so can cause livelocks under memory pressure.
+ * Allocate a new bio with @nr_iovecs bvecs. If @gfp_mask contains
+ * %__GFP_WAIT, the allocation is guaranteed to succeed.
*
**/
struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs)
*
* Description:
* Put a reference to a &struct bio, either one you have gotten with
- * bio_alloc or bio_get. The last put of a bio will free it.
+ * bio_alloc, bio_get or bio_clone. The last put of a bio will free it.
**/
void bio_put(struct bio *bio)
{
#define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */
#define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
#define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
+#define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */
#define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */
#define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */
#define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */
*journal_devnum = option;
break;
case Opt_journal_checksum:
- break; /* Kept for backwards compatibility */
+ set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+ break;
case Opt_journal_async_commit:
set_opt(sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT);
+ set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
break;
case Opt_noload:
set_opt(sbi->s_mount_opt, NOLOAD);
goto failed_mount4;
}
- jbd2_journal_set_features(sbi->s_journal,
- JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
- if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
- jbd2_journal_set_features(sbi->s_journal, 0, 0,
+ if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
+ jbd2_journal_set_features(sbi->s_journal,
+ JBD2_FEATURE_COMPAT_CHECKSUM, 0,
JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
- else
+ } else if (test_opt(sb, JOURNAL_CHECKSUM)) {
+ jbd2_journal_set_features(sbi->s_journal,
+ JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
jbd2_journal_clear_features(sbi->s_journal, 0, 0,
JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+ } else {
+ jbd2_journal_clear_features(sbi->s_journal,
+ JBD2_FEATURE_COMPAT_CHECKSUM, 0,
+ JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+ }
/* We have now updated the journal if required, so we can
* validate the data journaling mode. */
brelse(bh);
BUG();
}
+ memset(bh->b_data, 0, 1 << inode->i_blkbits);
bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
bh->b_blocknr = blocknr;
set_buffer_mapped(bh);
"invalid oldkey %lld (newkey=%lld)",
(unsigned long long)oldkey,
(unsigned long long)newkey);
- if (!test_set_buffer_dirty(obh) && TestSetPageDirty(opage))
- BUG();
+ nilfs_btnode_mark_dirty(obh);
spin_lock_irq(&btnc->tree_lock);
radix_tree_delete(&btnc->page_tree, oldkey);
/* Clear requests (even when the construction failed) */
spin_lock(&sci->sc_state_lock);
- sci->sc_state &= ~NILFS_SEGCTOR_COMMIT;
-
if (req->mode == SC_LSEG_SR) {
+ sci->sc_state &= ~NILFS_SEGCTOR_COMMIT;
sci->sc_seq_done = req->seq_accepted;
nilfs_segctor_wakeup(sci, req->sc_err ? : req->sb_err);
sci->sc_flush_request = 0;
- } else if (req->mode == SC_FLUSH_FILE)
- sci->sc_flush_request &= ~FLUSH_FILE_BIT;
- else if (req->mode == SC_FLUSH_DAT)
- sci->sc_flush_request &= ~FLUSH_DAT_BIT;
+ } else {
+ if (req->mode == SC_FLUSH_FILE)
+ sci->sc_flush_request &= ~FLUSH_FILE_BIT;
+ else if (req->mode == SC_FLUSH_DAT)
+ sci->sc_flush_request &= ~FLUSH_DAT_BIT;
+ /* re-enable timer if checkpoint creation was not done */
+ if (sci->sc_timer && (sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
+ time_before(jiffies, sci->sc_timer->expires))
+ add_timer(sci->sc_timer);
+ }
spin_unlock(&sci->sc_state_lock);
}
unsigned long event_base;
int idx;
};
- union { /* software */
- atomic64_t count;
+ struct { /* software */
+ s64 remaining;
struct hrtimer hrtimer;
};
};
ipvs_property:1,
peeked:1,
nf_trace:1;
+ __be16 protocol:16;
kmemcheck_bitfield_end(flags1);
- __be16 protocol;
void (*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#endif
int iif;
- __u16 queue_mapping;
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
#endif
kmemcheck_bitfield_begin(flags2);
+ __u16 queue_mapping:16;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8 ndisc_nodetype:2;
#endif
int to_offset,
int size);
extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
+extern void skb_free_datagram_locked(struct sock *sk,
+ struct sk_buff *skb);
extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
unsigned int flags);
extern __wsum skb_checksum(const struct sk_buff *skb, int offset,
/*
* Trace sequences are used to allow a function to call several other functions
- * to create a string of data to use (up to a max of PAGE_SIZE.
+ * to create a string of data to use (up to a max of PAGE_SIZE).
*/
struct trace_seq {
* @qid: the &p9_qid server identifier this handle points to
* @iounit: the server reported maximum transaction size for this file
* @uid: the numeric uid of the local user who owns this handle
- * @aux: transport specific information (unused?)
- * @rdir_fpos: tracks offset of file position when reading directory contents
+ * @rdir: readdir accounting structure (allocated on demand)
* @flist: per-client-instance fid tracking
* @dlist: per-dentry fid tracking
*
struct p9_qid qid;
u32 iounit;
uid_t uid;
- void *aux;
- int rdir_fpos;
+ void *rdir;
+
struct list_head flist;
struct list_head dlist; /* list of all fids attached to a dentry */
};
extern const struct nla_policy rtm_ipv4_policy[];
extern void ip_fib_init(void);
extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
- struct net_device *dev, __be32 *spec_dst, u32 *itag);
+ struct net_device *dev, __be32 *spec_dst,
+ u32 *itag, u32 mark);
extern void fib_select_default(struct net *net, const struct flowi *flp,
struct fib_result *res);
struct device dev;
/* data internal to the socket driver */
void *driver_data;
+ /* status of the card during resume from a system sleep state */
+ int resume_status;
};
/* socket drivers are expected to use these callbacks in their .drv struct */
extern int pcmcia_socket_dev_suspend(struct device *dev);
+extern void pcmcia_socket_dev_early_resume(struct device *dev);
+extern void pcmcia_socket_dev_late_resume(struct device *dev);
extern int pcmcia_socket_dev_resume(struct device *dev);
/* socket drivers use this callback in their IRQ handler */
int cpu;
int total = 0;
- for_each_online_cpu(cpu)
+ for_each_possible_cpu(cpu)
total += per_cpu(process_counts, cpu);
return total;
plist_del(&q->list, &q->list.plist);
/* Handle spurious wakeups gracefully */
- ret = -EAGAIN;
+ ret = -EWOULDBLOCK;
if (timeout && !timeout->task)
ret = -ETIMEDOUT;
else if (signal_pending(current))
debug_rt_mutex_init_waiter(&rt_waiter);
rt_waiter.task = NULL;
-retry:
key2 = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
if (unlikely(ret != 0))
out_key2:
put_futex_key(fshared, &key2);
- /* Spurious wakeup ? */
- if (ret == -EAGAIN)
- goto retry;
out:
if (to) {
hrtimer_cancel(&to->timer);
regs = task_pt_regs(current);
if (regs) {
- if (perf_event_overflow(event, 0, &data, regs))
- ret = HRTIMER_NORESTART;
+ if (!(event->attr.exclude_idle && current->pid == 0))
+ if (perf_event_overflow(event, 0, &data, regs))
+ ret = HRTIMER_NORESTART;
}
period = max_t(u64, 10000, event->hw.sample_period);
return ret;
}
+static void perf_swevent_start_hrtimer(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ hwc->hrtimer.function = perf_swevent_hrtimer;
+ if (hwc->sample_period) {
+ u64 period;
+
+ if (hwc->remaining) {
+ if (hwc->remaining < 0)
+ period = 10000;
+ else
+ period = hwc->remaining;
+ hwc->remaining = 0;
+ } else {
+ period = max_t(u64, 10000, hwc->sample_period);
+ }
+ __hrtimer_start_range_ns(&hwc->hrtimer,
+ ns_to_ktime(period), 0,
+ HRTIMER_MODE_REL, 0);
+ }
+}
+
+static void perf_swevent_cancel_hrtimer(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (hwc->sample_period) {
+ ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
+ hwc->remaining = ktime_to_ns(remaining);
+
+ hrtimer_cancel(&hwc->hrtimer);
+ }
+}
+
/*
* Software event: cpu wall time clock
*/
int cpu = raw_smp_processor_id();
atomic64_set(&hwc->prev_count, cpu_clock(cpu));
- hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hwc->hrtimer.function = perf_swevent_hrtimer;
- if (hwc->sample_period) {
- u64 period = max_t(u64, 10000, hwc->sample_period);
- __hrtimer_start_range_ns(&hwc->hrtimer,
- ns_to_ktime(period), 0,
- HRTIMER_MODE_REL, 0);
- }
+ perf_swevent_start_hrtimer(event);
return 0;
}
static void cpu_clock_perf_event_disable(struct perf_event *event)
{
- if (event->hw.sample_period)
- hrtimer_cancel(&event->hw.hrtimer);
+ perf_swevent_cancel_hrtimer(event);
cpu_clock_perf_event_update(event);
}
now = event->ctx->time;
atomic64_set(&hwc->prev_count, now);
- hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hwc->hrtimer.function = perf_swevent_hrtimer;
- if (hwc->sample_period) {
- u64 period = max_t(u64, 10000, hwc->sample_period);
- __hrtimer_start_range_ns(&hwc->hrtimer,
- ns_to_ktime(period), 0,
- HRTIMER_MODE_REL, 0);
- }
+
+ perf_swevent_start_hrtimer(event);
return 0;
}
static void task_clock_perf_event_disable(struct perf_event *event)
{
- if (event->hw.sample_period)
- hrtimer_cancel(&event->hw.hrtimer);
+ perf_swevent_cancel_hrtimer(event);
task_clock_perf_event_update(event, event->ctx->time);
}
/* The snapshot device should not be opened while we're running */
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
error = -EBUSY;
+ swsusp_close(FMODE_READ);
goto Unlock;
}
pm_prepare_console();
error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
if (error)
- goto Finish;
+ goto close_finish;
error = usermodehelper_disable();
if (error)
- goto Finish;
+ goto close_finish;
error = create_basic_memory_bitmaps();
if (error)
- goto Finish;
+ goto close_finish;
pr_debug("PM: Preparing processes for restore.\n");
error = prepare_processes();
pr_debug("PM: Reading hibernation image.\n");
error = swsusp_read(&flags);
+ swsusp_close(FMODE_READ);
if (!error)
hibernation_restore(flags & SF_PLATFORM_MODE);
mutex_unlock(&pm_mutex);
pr_debug("PM: Resume from disk failed.\n");
return error;
+close_finish:
+ swsusp_close(FMODE_READ);
+ goto Finish;
}
late_initcall(software_resume);
{
unsigned int m;
int ret;
- int error = 0;
int nr_pages;
int err2;
struct bio *bio;
nr_pages = 0;
bio = NULL;
do_gettimeofday(&start);
- do {
+ while (1) {
ret = snapshot_read_next(snapshot, PAGE_SIZE);
- if (ret > 0) {
- error = swap_write_page(handle, data_of(*snapshot),
- &bio);
- if (error)
- break;
- if (!(nr_pages % m))
- printk("\b\b\b\b%3d%%", nr_pages / m);
- nr_pages++;
- }
- } while (ret > 0);
+ if (ret <= 0)
+ break;
+ ret = swap_write_page(handle, data_of(*snapshot), &bio);
+ if (ret)
+ break;
+ if (!(nr_pages % m))
+ printk("\b\b\b\b%3d%%", nr_pages / m);
+ nr_pages++;
+ }
err2 = wait_on_bio_chain(&bio);
do_gettimeofday(&stop);
- if (!error)
- error = err2;
- if (!error)
+ if (!ret)
+ ret = err2;
+ if (!ret)
printk("\b\b\b\bdone\n");
+ else
+ printk("\n");
swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
- return error;
+ return ret;
}
/**
snapshot_write_finalize(snapshot);
if (!snapshot_image_loaded(snapshot))
error = -ENODATA;
- }
+ } else
+ printk("\n");
swsusp_show_speed(&start, &stop, nr_to_read, "Read");
return error;
}
error = load_image(&handle, &snapshot, header->pages - 1);
release_swap_reader(&handle);
- blkdev_put(resume_bdev, FMODE_READ);
-
if (!error)
pr_debug("PM: Image successfully loaded\n");
else
error = bio_read_page(swsusp_resume_block,
swsusp_header, NULL);
if (error)
- return error;
+ goto put;
if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
error = bio_write_page(swsusp_resume_block,
swsusp_header, NULL);
} else {
- return -EINVAL;
+ error = -EINVAL;
}
+
+put:
if (error)
blkdev_put(resume_bdev, FMODE_READ);
else
out:
mutex_unlock(&ftrace_profile_lock);
- filp->f_pos += cnt;
+ *ppos += cnt;
return cnt;
}
/* Up this if you want to test the TIME_EXTENTS and normalization */
#define DEBUG_SHIFT 0
-static inline u64 rb_time_stamp(struct ring_buffer *buffer, int cpu)
+static inline u64 rb_time_stamp(struct ring_buffer *buffer)
{
/* shift to debug/test normalization and TIME_EXTENTS */
return buffer->clock() << DEBUG_SHIFT;
u64 time;
preempt_disable_notrace();
- time = rb_time_stamp(buffer, cpu);
+ time = rb_time_stamp(buffer);
preempt_enable_no_resched_notrace();
return time;
}
/*
- * rb_is_head_page - test if the give page is the head page
+ * rb_is_head_page - test if the given page is the head page
*
* Because the reader may move the head_page pointer, we can
* not trust what the head page is (it may be pointing to
* Nested commits always have zero deltas, so
* just reread the time stamp
*/
- *ts = rb_time_stamp(buffer, cpu_buffer->cpu);
+ *ts = rb_time_stamp(buffer);
next_page->page->time_stamp = *ts;
}
if (RB_WARN_ON(cpu_buffer, ++nr_loops > 1000))
goto out_fail;
- ts = rb_time_stamp(cpu_buffer->buffer, cpu_buffer->cpu);
+ ts = rb_time_stamp(cpu_buffer->buffer);
/*
* Only the first commit can update the timestamp.
EXPORT_SYMBOL_GPL(ring_buffer_entries);
/**
- * ring_buffer_overrun_cpu - get the number of overruns in buffer
+ * ring_buffer_overruns - get the number of overruns in buffer
* @buffer: The ring buffer
*
* Returns the total number of overruns in the ring buffer
return ret;
}
- filp->f_pos += cnt;
+ *ppos += cnt;
return cnt;
}
}
mutex_unlock(&trace_types_lock);
- filp->f_pos += cnt;
+ *ppos += cnt;
return cnt;
}
if (err)
return err;
- filp->f_pos += ret;
+ *ppos += ret;
return ret;
}
}
}
- filp->f_pos += cnt;
+ *ppos += cnt;
/* If check pages failed, return ENOMEM */
if (tracing_disabled)
* @s: trace sequence descriptor
* @fmt: printf format string
*
+ * It returns 0 if the trace oversizes the buffer's free
+ * space, 1 otherwise.
+ *
* The tracer may use either sequence operations or its own
* copy to user routines. To simplify formating of a trace
* trace_seq_printf is used to store strings into a special
s->len += ret;
- return len;
+ return 1;
}
EXPORT_SYMBOL_GPL(trace_seq_printf);
void bdi_unregister(struct backing_dev_info *bdi)
{
if (bdi->dev) {
+ bdi_prune_sb(bdi);
+
if (!bdi_cap_flush_forker(bdi))
bdi_wb_shutdown(bdi);
bdi_debug_unregister(bdi);
spin_unlock(&inode_lock);
}
- bdi_prune_sb(bdi);
bdi_unregister(bdi);
for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
} else
retval = unuse_mm(mm, entry, page);
- if (set_start_mm &&
- swap_count(*swap_map) < swcount) {
+ if (set_start_mm && *swap_map < swcount) {
mmput(new_start_mm);
atomic_inc(&mm->mm_users);
new_start_mm = mm;
memset(&fid->qid, 0, sizeof(struct p9_qid));
fid->mode = -1;
- fid->rdir_fpos = 0;
fid->uid = current_fsuid();
fid->clnt = clnt;
- fid->aux = NULL;
-
+ fid->rdir = NULL;
spin_lock_irqsave(&clnt->lock, flags);
list_add(&fid->flist, &clnt->fidlist);
spin_unlock_irqrestore(&clnt->lock, flags);
spin_lock_irqsave(&clnt->lock, flags);
list_del(&fid->flist);
spin_unlock_irqrestore(&clnt->lock, flags);
+ kfree(fid->rdir);
kfree(fid);
}
consume_skb(skb);
sk_mem_reclaim_partial(sk);
}
+EXPORT_SYMBOL(skb_free_datagram);
+
+void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb)
+{
+ lock_sock(sk);
+ skb_free_datagram(sk, skb);
+ release_sock(sk);
+}
+EXPORT_SYMBOL(skb_free_datagram_locked);
/**
* skb_kill_datagram - Free a datagram skbuff forcibly
EXPORT_SYMBOL(datagram_poll);
EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
EXPORT_SYMBOL(skb_copy_datagram_iovec);
-EXPORT_SYMBOL(skb_free_datagram);
EXPORT_SYMBOL(skb_recv_datagram);
*/
int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
- struct net_device *dev, __be32 *spec_dst, u32 *itag)
+ struct net_device *dev, __be32 *spec_dst,
+ u32 *itag, u32 mark)
{
struct in_device *in_dev;
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = src,
.saddr = dst,
.tos = tos } },
+ .mark = mark,
.iif = oif };
+
struct fib_result res;
int no_addr, rpf;
int ret;
ether_setup(dev);
- dev->netdev_ops = &ipgre_netdev_ops;
+ dev->netdev_ops = &ipgre_tap_netdev_ops;
dev->destructor = free_netdev;
dev->iflink = 0;
if (t->dev != dev)
return -EEXIST;
} else {
- unsigned nflags = 0;
-
t = nt;
- if (ipv4_is_multicast(p.iph.daddr))
- nflags = IFF_BROADCAST;
- else if (p.iph.daddr)
- nflags = IFF_POINTOPOINT;
+ if (dev->type != ARPHRD_ETHER) {
+ unsigned nflags = 0;
- if ((dev->flags ^ nflags) &
- (IFF_POINTOPOINT | IFF_BROADCAST))
- return -EINVAL;
+ if (ipv4_is_multicast(p.iph.daddr))
+ nflags = IFF_BROADCAST;
+ else if (p.iph.daddr)
+ nflags = IFF_POINTOPOINT;
+
+ if ((dev->flags ^ nflags) &
+ (IFF_POINTOPOINT | IFF_BROADCAST))
+ return -EINVAL;
+ }
ipgre_tunnel_unlink(ign, t);
t->parms.iph.saddr = p.iph.saddr;
t->parms.iph.daddr = p.iph.daddr;
t->parms.i_key = p.i_key;
- memcpy(dev->dev_addr, &p.iph.saddr, 4);
- memcpy(dev->broadcast, &p.iph.daddr, 4);
+ if (dev->type != ARPHRD_ETHER) {
+ memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ memcpy(dev->broadcast, &p.iph.daddr, 4);
+ }
ipgre_tunnel_link(ign, t);
netdev_state_change(dev);
}
goto e_inval;
spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
} else if (fib_validate_source(saddr, 0, tos, 0,
- dev, &spec_dst, &itag) < 0)
+ dev, &spec_dst, &itag, 0) < 0)
goto e_inval;
rth = dst_alloc(&ipv4_dst_ops);
err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res),
- in_dev->dev, &spec_dst, &itag);
+ in_dev->dev, &spec_dst, &itag, skb->mark);
if (err < 0) {
ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
saddr);
int result;
result = fib_validate_source(saddr, daddr, tos,
net->loopback_dev->ifindex,
- dev, &spec_dst, &itag);
+ dev, &spec_dst, &itag, skb->mark);
if (result < 0)
goto martian_source;
if (result)
spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
else {
err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
- &itag);
+ &itag, skb->mark);
if (err < 0)
goto martian_source;
if (err)
err = ulen;
out_free:
- lock_sock(sk);
- skb_free_datagram(sk, skb);
- release_sock(sk);
+ skb_free_datagram_locked(sk, skb);
out:
return err;
err = ulen;
out_free:
- lock_sock(sk);
- skb_free_datagram(sk, skb);
- release_sock(sk);
+ skb_free_datagram_locked(sk, skb);
out:
return err;
state = &sta->ampdu_mlme.tid_state_tx[tid];
+ del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+
spin_lock_bh(&sta->lock);
- if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
- spin_unlock_bh(&sta->lock);
- return;
- }
+ if (!(*state & HT_ADDBA_REQUESTED_MSK))
+ goto timer_still_needed;
if (mgmt->u.action.u.addba_resp.dialog_token !=
sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
- spin_unlock_bh(&sta->lock);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
- return;
+ goto timer_still_needed;
}
- del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
+
if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
== WLAN_STATUS_SUCCESS) {
u8 curstate = *state;
} else {
___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
}
+
+ goto out;
+
+ timer_still_needed:
+ add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+ out:
spin_unlock_bh(&sta->lock);
}
struct ieee80211_sub_if_data *sdata;
int ret;
+ if (netif_running(dev))
+ return -EBUSY;
+
if (!nl80211_type_check(type))
return -EINVAL;
if (ret)
return ret;
- if (netif_running(sdata->dev))
- return -EBUSY;
-
if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
ieee80211_sdata_set_mesh_id(sdata,
params->mesh_id_len,
if (net_ratelimit())
printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n",
mgmt->sa, initiator ? "initiator" : "recipient", tid,
- mgmt->u.action.u.delba.reason_code);
+ le16_to_cpu(mgmt->u.action.u.delba.reason_code));
#endif /* CONFIG_MAC80211_HT_DEBUG */
if (initiator == WLAN_BACK_INITIATOR)
struct ieee80211_mgmt *mgmt;
u8 *pos;
struct ieee80211_supported_band *sband;
+ struct cfg80211_bss *bss;
u32 bss_change;
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
- cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
- mgmt, skb->len, 0, GFP_KERNEL);
+ bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
+ mgmt, skb->len, 0, GFP_KERNEL);
+ cfg80211_put_bss(bss);
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
}
rqstp->rq_xprt_ctxt = NULL;
dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
- skb_free_datagram(svsk->sk_sk, skb);
+ skb_free_datagram_locked(svsk->sk_sk, skb);
}
}
"svc: received unknown control message %d/%d; "
"dropping RPC reply datagram\n",
cmh->cmsg_level, cmh->cmsg_type);
- skb_free_datagram(svsk->sk_sk, skb);
+ skb_free_datagram_locked(svsk->sk_sk, skb);
return 0;
}
if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) {
local_bh_enable();
/* checksum error */
- skb_free_datagram(svsk->sk_sk, skb);
+ skb_free_datagram_locked(svsk->sk_sk, skb);
return 0;
}
local_bh_enable();
- skb_free_datagram(svsk->sk_sk, skb);
+ skb_free_datagram_locked(svsk->sk_sk, skb);
} else {
/* we can use it in-place */
rqstp->rq_arg.head[0].iov_base = skb->data +
sizeof(struct udphdr);
rqstp->rq_arg.head[0].iov_len = len;
if (skb_checksum_complete(skb)) {
- skb_free_datagram(svsk->sk_sk, skb);
+ skb_free_datagram_locked(svsk->sk_sk, skb);
return 0;
}
rqstp->rq_xprt_ctxt = skb;
struct cfg80211_registered_device *rdev =
container_of(work, struct cfg80211_registered_device, conn_work);
struct wireless_dev *wdev;
- u8 bssid[ETH_ALEN];
+ u8 bssid_buf[ETH_ALEN], *bssid = NULL;
rtnl_lock();
cfg80211_lock_rdev(rdev);
wdev_unlock(wdev);
continue;
}
- memcpy(bssid, wdev->conn->params.bssid, ETH_ALEN);
+ if (wdev->conn->params.bssid) {
+ memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN);
+ bssid = bssid_buf;
+ }
if (cfg80211_conn_do_work(wdev))
__cfg80211_connect_result(
wdev->netdev, bssid,
struct snd_pcm_substream *substream;
struct snd_pcm_notify *notify;
char str[16];
- struct snd_pcm *pcm = device->device_data;
+ struct snd_pcm *pcm;
struct device *dev;
- if (snd_BUG_ON(!pcm || !device))
+ if (snd_BUG_ON(!device || !device->device_data))
return -ENXIO;
+ pcm = device->device_data;
mutex_lock(®ister_mutex);
err = snd_pcm_add(pcm);
if (err) {
module_param_array(pcm_devs, int, NULL, 0444);
MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
module_param_array(pcm_substreams, int, NULL, 0444);
-MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
+MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");
//module_param_array(midi_devs, int, NULL, 0444);
//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
module_param(fake_buffer, bool, 0444);
unsigned int idx;
int err;
- if (snd_BUG_ON(!dummy))
- return -EINVAL;
spin_lock_init(&dummy->mixer_lock);
strcpy(card->mixername, "Dummy Mixer");
/* write the port and returns the next expire time in ns;
* called at the trigger-start and in hrtimer callback
*/
-static unsigned long pcsp_timer_update(struct hrtimer *handle)
+static u64 pcsp_timer_update(struct snd_pcsp *chip)
{
unsigned char timer_cnt, val;
u64 ns;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
- struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
unsigned long flags;
if (chip->thalf) {
outb(chip->val61, 0x61);
chip->thalf = 0;
- if (!atomic_read(&chip->timer_active))
- return 0;
return chip->ns_rem;
}
- if (!atomic_read(&chip->timer_active))
- return 0;
substream = chip->playback_substream;
if (!substream)
return 0;
return ns;
}
-enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
+static void pcsp_pointer_update(struct snd_pcsp *chip)
{
- struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
struct snd_pcm_substream *substream;
- int periods_elapsed, pointer_update;
size_t period_bytes, buffer_bytes;
- unsigned long ns;
+ int periods_elapsed;
unsigned long flags;
- pointer_update = !chip->thalf;
- ns = pcsp_timer_update(handle);
- if (!ns)
- return HRTIMER_NORESTART;
-
/* update the playback position */
substream = chip->playback_substream;
if (!substream)
- return HRTIMER_NORESTART;
+ return;
period_bytes = snd_pcm_lib_period_bytes(substream);
buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
if (periods_elapsed)
tasklet_schedule(&pcsp_pcm_tasklet);
+}
+
+enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
+{
+ struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
+ int pointer_update;
+ u64 ns;
+
+ if (!atomic_read(&chip->timer_active) || !chip->playback_substream)
+ return HRTIMER_NORESTART;
+
+ pointer_update = !chip->thalf;
+ ns = pcsp_timer_update(chip);
+ if (!ns) {
+ printk(KERN_WARNING "PCSP: unexpected stop\n");
+ return HRTIMER_NORESTART;
+ }
+
+ if (pointer_update)
+ pcsp_pointer_update(chip);
hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns));
static int pcsp_start_playing(struct snd_pcsp *chip)
{
- unsigned long ns;
-
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: start_playing called\n");
#endif
atomic_set(&chip->timer_active, 1);
chip->thalf = 0;
- ns = pcsp_timer_update(&pcsp_chip.timer);
- if (!ns)
- return -EIO;
-
- hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL);
+ hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
return 0;
}
static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+ pcsp_sync_stop(chip);
+ chip->playback_ptr = 0;
+ chip->period_ptr = 0;
+ chip->fmt_size =
+ snd_pcm_format_physical_width(substream->runtime->format) >> 3;
+ chip->is_signed = snd_pcm_format_signed(substream->runtime->format);
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: prepare called, "
- "size=%zi psize=%zi f=%zi f1=%i\n",
+ "size=%zi psize=%zi f=%zi f1=%i fsize=%i\n",
snd_pcm_lib_buffer_bytes(substream),
snd_pcm_lib_period_bytes(substream),
snd_pcm_lib_buffer_bytes(substream) /
snd_pcm_lib_period_bytes(substream),
- substream->runtime->periods);
+ substream->runtime->periods,
+ chip->fmt_size);
#endif
- pcsp_sync_stop(chip);
- chip->playback_ptr = 0;
- chip->period_ptr = 0;
- chip->fmt_size =
- snd_pcm_format_physical_width(substream->runtime->format) >> 3;
- chip->is_signed = snd_pcm_format_signed(substream->runtime->format);
return 0;
}
if (treble != chip->treble) {
chip->treble = treble;
#if PCSP_DEBUG
- printk(KERN_INFO "PCSP: rate set to %i\n", PCSP_RATE());
+ printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE());
#endif
changed = 1;
}
struct snd_pcm *pcm;
int err;
+ if (snd_BUG_ON(!h))
+ return -EINVAL;
+
harmony_disable_interrupts(h);
err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm);
static int __devinit
snd_harmony_mixer_init(struct snd_harmony *h)
{
- struct snd_card *card = h->card;
+ struct snd_card *card;
int idx, err;
if (snd_BUG_ON(!h))
return -EINVAL;
+ card = h->card;
strcpy(card->mixername, "Harmony Gain control interface");
for (idx = 0; idx < HARMONY_CONTROLS; idx++) {
config SND_CS5535AUDIO
tristate "CS5535/CS5536 Audio"
- depends on X86 && !X86_64
select SND_PCM
select SND_AC97_CODEC
help
void *private_data;
snd_ali_printk("free_voice: channel=%d\n",pvoice->number);
- if (pvoice == NULL || !pvoice->use)
+ if (!pvoice->use)
return;
snd_ali_clear_voices(codec, pvoice->number, pvoice->number);
spin_lock_irq(&codec->voice_alloc);
{ PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
+ { PCI_DEVICE(0x10de, 0x0590), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
unsigned int nid = spec->autocfg.hp_pins[0];
int i;
+ if (!nid)
+ return;
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
ALC268_ACER_ASPIRE_ONE),
SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
- SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron Mini9", ALC268_DELL),
+ SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
+ "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
/* almost compatible with toshiba but with optional digital outs;
* auto-probing seems working fine
*/
/* create playback/capture controls for input pins */
#define alc662_auto_create_input_ctls \
- alc880_auto_create_input_ctls
+ alc882_auto_create_input_ctls
static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid, int pin_type,
struct snd_pcm *pcms[2];
struct snd_rawmidi *rmidi;
+ struct snd_kcontrol *dxs_controls[4];
struct snd_ac97_bus *ac97_bus;
struct snd_ac97 *ac97;
/*
- * open callback for playback on via686 and via823x DSX
+ * open callback for playback on via686
*/
-static int snd_via82xx_playback_open(struct snd_pcm_substream *substream)
+static int snd_via686_playback_open(struct snd_pcm_substream *substream)
{
struct via82xx *chip = snd_pcm_substream_chip(substream);
struct viadev *viadev = &chip->devs[chip->playback_devno + substream->number];
return 0;
}
+/*
+ * open callback for playback on via823x DXS
+ */
+static int snd_via8233_playback_open(struct snd_pcm_substream *substream)
+{
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev;
+ unsigned int stream;
+ int err;
+
+ viadev = &chip->devs[chip->playback_devno + substream->number];
+ if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0)
+ return err;
+ stream = viadev->reg_offset / 0x10;
+ if (chip->dxs_controls[stream]) {
+ chip->playback_volume[stream][0] = 0;
+ chip->playback_volume[stream][1] = 0;
+ chip->dxs_controls[stream]->vd[0].access &=
+ ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
+ SNDRV_CTL_EVENT_MASK_INFO,
+ &chip->dxs_controls[stream]->id);
+ }
+ return 0;
+}
+
/*
* open callback for playback on via823x multi-channel
*/
return 0;
}
+static int snd_via8233_playback_close(struct snd_pcm_substream *substream)
+{
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
+ unsigned int stream;
+
+ stream = viadev->reg_offset / 0x10;
+ if (chip->dxs_controls[stream]) {
+ chip->dxs_controls[stream]->vd[0].access |=
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO,
+ &chip->dxs_controls[stream]->id);
+ }
+ return snd_via82xx_pcm_close(substream);
+}
+
/* via686 playback callbacks */
static struct snd_pcm_ops snd_via686_playback_ops = {
- .open = snd_via82xx_playback_open,
+ .open = snd_via686_playback_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_via82xx_hw_params,
/* via823x DSX playback callbacks */
static struct snd_pcm_ops snd_via8233_playback_ops = {
- .open = snd_via82xx_playback_open,
- .close = snd_via82xx_pcm_close,
+ .open = snd_via8233_playback_open,
+ .close = snd_via8233_playback_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_via82xx_hw_params,
.hw_free = snd_via82xx_hw_free,
.device = 0,
/* .subdevice set later */
.name = "PCM Playback Volume",
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.info = snd_via8233_dxs_volume_info,
.get = snd_via8233_dxs_volume_get,
.put = snd_via8233_dxs_volume_put,
err = snd_ctl_add(chip->card, kctl);
if (err < 0)
return err;
+ chip->dxs_controls[i] = kctl;
}
}
}
* configuration callback
*/
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-
static int pdacf_config(struct pcmcia_device *link)
{
struct snd_pdacf *pdacf = link->priv;
- int last_fn, last_ret;
+ int ret;
snd_printdd(KERN_DEBUG "pdacf_config called\n");
link->conf.ConfigIndex = 0x5;
- CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+ ret = pcmcia_request_io(link, &link->io);
+ if (ret)
+ goto failed;
+
+ ret = pcmcia_request_irq(link, &link->irq);
+ if (ret)
+ goto failed;
+
+ ret = pcmcia_request_configuration(link, &link->conf);
+ if (ret)
+ goto failed;
if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
link->dev_node = &pdacf->node;
return 0;
-cs_failed:
- cs_error(link, last_fn, last_ret);
failed:
pcmcia_disable_device(link);
return -ENODEV;
* configuration callback
*/
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-
static int vxpocket_config(struct pcmcia_device *link)
{
struct vx_core *chip = link->priv;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
- int last_fn, last_ret;
+ int ret;
snd_printdd(KERN_DEBUG "vxpocket_config called\n");
strcpy(chip->card->driver, vxp440_hw.name);
}
- CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+ ret = pcmcia_request_io(link, &link->io);
+ if (ret)
+ goto failed;
+
+ ret = pcmcia_request_irq(link, &link->irq);
+ if (ret)
+ goto failed;
+
+ ret = pcmcia_request_configuration(link, &link->conf);
+ if (ret)
+ goto failed;
chip->dev = &handle_to_dev(link);
snd_card_set_dev(chip->card, chip->dev);
link->dev_node = &vxp->node;
return 0;
-cs_failed:
- cs_error(link, last_fn, last_ret);
failed:
pcmcia_disable_device(link);
return -ENODEV;
select SND_OMAP_SOC_MCBSP
select SND_SOC_CX20442
help
- Say Y if you want to add support for SoC audio on Amstrad Delta.
+ Say Y if you want to add support for SoC audio device connected to
+ a handset and a speakerphone found on Amstrad E3 (Delta) videophone.
+
+ Note that in order to get those devices fully supported, you have to
+ build the kernel with standard serial port driver included and
+ configured for at least 4 ports. Then, from userspace, you must load
+ a line discipline #19 on the modem (ttyS3) serial line. The simplest
+ way to achieve this is to install util-linux-ng and use the included
+ ldattach utility. This can be started automatically from udev,
+ a simple rule like this one should do the trick (it does for me):
+ ACTION=="add", KERNEL=="controlC0", \
+ RUN+="/usr/sbin/ldattach 19 /dev/ttyS3"
config SND_OMAP_SOC_OSK5912
tristate "SoC Audio support for omap osk5912"
{
struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
dma_addr_t pos = prtd->dma_pos;
+ unsigned int limit;
int ret;
pr_debug("Entered %s\n", __func__);
- while (prtd->dma_loaded < prtd->dma_limit) {
+ if (s3c_dma_has_circular()) {
+ limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
+ } else
+ limit = prtd->dma_limit;
+
+ pr_debug("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit);
+
+ while (prtd->dma_loaded < limit) {
unsigned long len = prtd->dma_period;
pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
snd_pcm_period_elapsed(substream);
spin_lock(&prtd->lock);
- if (prtd->state & ST_RUNNING) {
+ if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
prtd->dma_loaded--;
s3c24xx_pcm_enqueue(substream);
}
printk(KERN_ERR "failed to get dma channel\n");
return ret;
}
+
+ /* use the circular buffering if we have it available. */
+ if (s3c_dma_has_circular())
+ s3c2410_dma_setflags(prtd->params->channel,
+ S3C2410_DMAF_CIRCULAR);
}
s3c2410_dma_set_buffdone_fn(prtd->params->channel,
#define soc_resume NULL
#endif
+static struct snd_soc_dai_ops null_dai_ops = {
+};
+
static void snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct platform_device *pdev = container_of(card->dev,
ac97 = 1;
}
+ for (i = 0; i < card->num_links; i++) {
+ if (!card->dai_link[i].codec_dai->ops)
+ card->dai_link[i].codec_dai->ops = &null_dai_ops;
+ }
+
/* If we have AC97 in the system then don't wait for the
* codec. This will need revisiting if we have to handle
* systems with mixed AC97 and non-AC97 parts. Only check for
return 0;
}
-static struct snd_soc_dai_ops null_dai_ops = {
-};
-
/**
* snd_soc_register_dai - Register a DAI with the ASoC core
*
}
}
}
- mutex_unlock(&codec->mutex);
dapm_power_widgets(codec, event);
+ mutex_unlock(&codec->mutex);
dump_dapm(codec, __func__);
return 0;
}
activate_substream(struct snd_usb_caiaqdev *dev,
struct snd_pcm_substream *sub)
{
+ spin_lock(&dev->spinlock);
+
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
dev->sub_playback[sub->number] = sub;
else
dev->sub_capture[sub->number] = sub;
+
+ spin_unlock(&dev->spinlock);
}
static void
{
int index = sub->number;
struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+ snd_pcm_uframes_t ptr;
+
+ spin_lock(&dev->spinlock);
if (dev->input_panic || dev->output_panic)
- return SNDRV_PCM_POS_XRUN;
+ ptr = SNDRV_PCM_POS_XRUN;
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
- return bytes_to_frames(sub->runtime,
+ ptr = bytes_to_frames(sub->runtime,
dev->audio_out_buf_pos[index]);
else
- return bytes_to_frames(sub->runtime,
+ ptr = bytes_to_frames(sub->runtime,
dev->audio_in_buf_pos[index]);
+
+ spin_unlock(&dev->spinlock);
+ return ptr;
}
/* operators for both playback and capture */
#include "input.h"
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.19");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.20");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, RigKontrol3},"
# Include saner warnings here, which can catch bugs:
#
-EXTRA_WARNINGS := -Wcast-align
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat
+EXTRA_WARNINGS := -Wformat
EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security
EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k
EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
PTHREAD_LIBS =
endif
-ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+ ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+ BASIC_CFLAGS += -DLIBELF_NO_MMAP
+ endif
+else
msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
endif
if (fd < 0)
goto out;
- elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL)
goto out_close;
Elf *elf;
int nr = 0, kernel = !strcmp("[kernel]", self->name);
- elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
if (v)
fprintf(stderr, "%s: cannot read %s ELF file.\n",
if (fd < 0)
goto out;
- elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
if (v)
fprintf(stderr, "%s: cannot read %s ELF file.\n",
#endif
#endif
+/*
+ * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
+ * for newer versions we can use mmap to reduce memory usage:
+ */
+#ifdef LIBELF_NO_MMAP
+# define PERF_ELF_C_READ_MMAP ELF_C_READ
+#else
+# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
+#endif
+
#ifndef DMGL_PARAMS
#define DMGL_PARAMS (1 << 0) /* Include function args */
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */