Commit 45b583b1 authored by Linus Torvalds's avatar Linus Torvalds

Merge 'akpm' patch series

* Merge akpm patch series: (122 commits)
  drivers/connector/cn_proc.c: remove unused local
  Documentation/SubmitChecklist: add RCU debug config options
  reiserfs: use hweight_long()
  reiserfs: use proper little-endian bitops
  pnpacpi: register disabled resources
  drivers/rtc/rtc-tegra.c: properly initialize spinlock
  drivers/rtc/rtc-twl.c: check return value of twl_rtc_write_u8() in twl_rtc_set_time()
  drivers/rtc: add support for Qualcomm PMIC8xxx RTC
  drivers/rtc/rtc-s3c.c: support clock gating
  drivers/rtc/rtc-mpc5121.c: add support for RTC on MPC5200
  init: skip calibration delay if previously done
  misc/eeprom: add eeprom access driver for digsy_mtc board
  misc/eeprom: add driver for microwire 93xx46 EEPROMs
  checkpatch.pl: update $logFunctions
  checkpatch: make utf-8 test --strict
  checkpatch.pl: add ability to ignore various messages
  checkpatch: add a "prefer __aligned" check
  checkpatch: validate signature styles and To: and Cc: lines
  checkpatch: add __rcu as a sparse modifier
  checkpatch: suggest using min_t or max_t
  ...

Did this as a merge because of (trivial) conflicts in
 - Documentation/feature-removal-schedule.txt
 - arch/xtensa/include/asm/uaccess.h
that were just easier to fix up in the merge than in the patch series.
parents 154dd78d f19da2ce
......@@ -14,7 +14,7 @@ Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's
A much more powerful interface, /proc/<pid>/oom_score_adj, was
introduced with the oom killer rewrite that allows users to increase or
decrease the badness() score linearly. This interface will replace
decrease the badness score linearly. This interface will replace
/proc/<pid>/oom_adj.
A warning will be emitted to the kernel log if an application uses this
......
What: /sys/bus/i2c/devices/.../device
Date: February 2011
Contact: Minkyu Kang <mk7.kang@samsung.com>
Description:
show what device is attached
NONE - no device
USB - USB device is attached
UART - UART is attached
CHARGER - Charger is attaced
JIG - JIG is attached
What: /sys/bus/i2c/devices/.../switch
Date: February 2011
Contact: Minkyu Kang <mk7.kang@samsung.com>
Description:
show or set the state of manual switch
VAUDIO - switch to VAUDIO path
UART - switch to UART path
AUDIO - switch to AUDIO path
DHOST - switch to DHOST path
AUTO - switch automatically by device
......@@ -53,8 +53,8 @@ kernel patches.
12: Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP all simultaneously
enabled.
CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_PROVE_RCU
and CONFIG_DEBUG_OBJECTS_RCU_HEAD all simultaneously enabled.
13: Has been build- and runtime tested with and without CONFIG_SMP and
CONFIG_PREEMPT.
......
......@@ -184,7 +184,7 @@ Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's
A much more powerful interface, /proc/<pid>/oom_score_adj, was
introduced with the oom killer rewrite that allows users to increase or
decrease the badness() score linearly. This interface will replace
decrease the badness score linearly. This interface will replace
/proc/<pid>/oom_adj.
A warning will be emitted to the kernel log if an application uses this
......@@ -518,22 +518,6 @@ Files: net/netfilter/xt_connlimit.c
----------------------------
What: noswapaccount kernel command line parameter
When: 3.0
Why: The original implementation of memsw feature enabled by
CONFIG_CGROUP_MEM_RES_CTLR_SWAP could be disabled by the noswapaccount
kernel parameter (introduced in 2.6.29-rc1). Later on, this decision
turned out to be not ideal because we cannot have the feature compiled
in and disabled by default and let only interested to enable it
(e.g. general distribution kernels might need it). Therefore we have
added swapaccount[=0|1] parameter (introduced in 2.6.37) which provides
the both possibilities. If we remove noswapaccount we will have
less command line parameters with the same functionality and we
can also cleanup the parameter handling a bit ().
Who: Michal Hocko <mhocko@suse.cz>
----------------------------
What: ipt_addrtype match include file
When: 2012
Why: superseded by xt_addrtype
......
......@@ -3012,7 +3012,7 @@ F: kernel/hrtimer.c
F: kernel/time/clockevents.c
F: kernel/time/tick*.*
F: kernel/time/timer_*.c
F: include/linux/clockevents.h
F: include/linux/clockchips.h
F: include/linux/hrtimer.h
HIGH-SPEED SCC DRIVER FOR AX.25
......
......@@ -200,7 +200,6 @@ show_regs(struct pt_regs *regs)
void
start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
set_fs(USER_DS);
regs->pc = pc;
regs->ps = 8;
wrusp(sp);
......
......@@ -10,16 +10,97 @@
#include <linux/amba/bus.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <plat/pincfg.h>
#include <plat/i2c.h>
#include <mach/hardware.h>
#include <mach/devices.h>
#include <mach/setup.h>
#include "pins-db5500.h"
#include "devices-db5500.h"
#include <linux/led-lm3530.h>
/*
* GPIO
*/
static pin_cfg_t u5500_pins[] = {
/* I2C */
GPIO218_I2C2_SCL | PIN_INPUT_PULLUP,
GPIO219_I2C2_SDA | PIN_INPUT_PULLUP,
/* DISPLAY_ENABLE */
GPIO226_GPIO | PIN_OUTPUT_LOW,
/* Backlight Enbale */
GPIO224_GPIO | PIN_OUTPUT_HIGH,
};
/*
* I2C
*/
#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
static struct nmk_i2c_controller u5500_i2c##id##_data = { \
/* \
* slave data setup time, which is \
* 250 ns,100ns,10ns which is 14,6,2 \
* respectively for a 48 Mhz \
* i2c clock \
*/ \
.slsu = _slsu, \
/* Tx FIFO threshold */ \
.tft = _tft, \
/* Rx FIFO threshold */ \
.rft = _rft, \
/* std. mode operation */ \
.clk_freq = clk, \
.sm = _sm, \
}
/*
* The board uses TODO <3> i2c controllers, initialize all of
* them with slave data setup time of 250 ns,
* Tx & Rx FIFO threshold values as 1 and standard
* mode of operation
*/
U5500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST);
static struct lm3530_platform_data u5500_als_platform_data = {
.mode = LM3530_BL_MODE_MANUAL,
.als_input_mode = LM3530_INPUT_ALS1,
.max_current = LM3530_FS_CURR_26mA,
.pwm_pol_hi = true,
.als_avrg_time = LM3530_ALS_AVRG_TIME_512ms,
.brt_ramp_law = 1, /* Linear */
.brt_ramp_fall = LM3530_RAMP_TIME_8s,
.brt_ramp_rise = LM3530_RAMP_TIME_8s,
.als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm,
.als2_resistor_sel = LM3530_ALS_IMPD_Z,
.als_vmin = 730, /* mV */
.als_vmax = 1020, /* mV */
.brt_val = 0x7F, /* Max brightness */
};
static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
{
/* Backlight */
I2C_BOARD_INFO("lm3530-led", 0x36),
.platform_data = &u5500_als_platform_data,
},
};
static void __init u5500_i2c_init(void)
{
db5500_add_i2c2(&u5500_i2c2_data);
i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
}
static void __init u5500_uart_init(void)
{
db5500_add_uart0(NULL);
......@@ -30,7 +111,8 @@ static void __init u5500_uart_init(void)
static void __init u5500_init_machine(void)
{
u5500_init_devices();
nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins));
u5500_i2c_init();
u5500_sdi_init();
u5500_uart_init();
}
......
......@@ -85,6 +85,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
int ret = -EINVAL;
char saved[sizeof pins];
unsigned long flags;
reg_pinmux_rw_hwprot hwprot;
reg_clkgen_rw_clk_ctrl clk_ctrl;
spin_lock_irqsave(&pinmux_lock, flags);
......@@ -93,9 +95,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
rw_clk_ctrl);
hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
switch (function) {
case pinmux_eth:
......@@ -262,6 +263,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
int ret = -EINVAL;
char saved[sizeof pins];
unsigned long flags;
reg_pinmux_rw_hwprot hwprot;
spin_lock_irqsave(&pinmux_lock, flags);
......@@ -270,7 +272,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
switch (function) {
case pinmux_eth:
......
......@@ -53,7 +53,6 @@ struct thread_struct {
*/
#define start_thread(regs, ip, usp) do { \
set_fs(USER_DS); \
regs->irp = ip; \
regs->dccr |= 1 << U_DCCR_BITNR; \
wrusp(usp); \
......
......@@ -47,7 +47,6 @@ struct thread_struct {
*/
#define start_thread(regs, ip, usp) \
do { \
set_fs(USER_DS); \
regs->erp = ip; \
regs->ccs |= 1 << (U_CCS_BITNR + CCS_SHIFT); \
wrusp(usp); \
......
......@@ -81,7 +81,6 @@ struct thread_struct {
#if defined(__H8300H__)
#define start_thread(_regs, _pc, _usp) \
do { \
set_fs(USER_DS); /* reads from user space */ \
(_regs)->pc = (_pc); \
(_regs)->ccr = 0x00; /* clear all flags */ \
(_regs)->er5 = current->mm->start_data; /* GOT base */ \
......@@ -91,7 +90,6 @@ do { \
#if defined(__H8300S__)
#define start_thread(_regs, _pc, _usp) \
do { \
set_fs(USER_DS); /* reads from user space */ \
(_regs)->pc = (_pc); \
(_regs)->ccr = 0x00; /* clear kernel flag */ \
(_regs)->exr = 0x78; /* enable all interrupts */ \
......
......@@ -106,7 +106,6 @@ struct thread_struct {
#define start_thread(regs, new_pc, new_spu) \
do { \
set_fs(USER_DS); \
regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL; \
regs->bpc = new_pc; \
regs->spu = new_spu; \
......
......@@ -105,9 +105,6 @@ struct thread_struct {
static inline void start_thread(struct pt_regs * regs, unsigned long pc,
unsigned long usp)
{
/* reads from user space */
set_fs(USER_DS);
regs->pc = pc;
regs->sr &= ~0x2000;
wrusp(usp);
......@@ -129,7 +126,6 @@ extern int handle_kernel_fault(struct pt_regs *regs);
#define start_thread(_regs, _pc, _usp) \
do { \
set_fs(USER_DS); /* reads from user space */ \
(_regs)->pc = (_pc); \
((struct switch_stack *)(_regs))[-1].a6 = 0; \
reformat(_regs); \
......
......@@ -185,7 +185,7 @@ EXPORT_SYMBOL(kernel_thread);
void flush_thread(void)
{
unsigned long zero = 0;
set_fs(USER_DS);
current->thread.fs = __USER_DS;
if (!FPU_IS_EMU)
asm volatile (".chip 68k/68881\n\t"
......
......@@ -158,7 +158,7 @@ void flush_thread(void)
#ifdef CONFIG_FPU
unsigned long zero = 0;
#endif
set_fs(USER_DS);
current->thread.fs = __USER_DS;
#ifdef CONFIG_FPU
if (!FPU_IS_EMU)
......
......@@ -24,6 +24,7 @@
#include <linux/cpumask.h>
#include <linux/memblock.h>
#include <linux/slab.h>
#include <linux/reboot.h>
#include <asm/prom.h>
#include <asm/rtas.h>
......
......@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/reboot.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
......
......@@ -41,6 +41,7 @@ config SPARC64
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_KRETPROBES
select HAVE_KPROBES
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_MEMBLOCK
select HAVE_SYSCALL_WRAPPERS
select HAVE_DYNAMIC_FTRACE
......@@ -81,10 +82,6 @@ config IOMMU_HELPER
bool
default y if SPARC64
config QUICKLIST
bool
default y if SPARC64
config STACKTRACE_SUPPORT
bool
default y if SPARC64
......
......@@ -5,7 +5,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/quicklist.h>
#include <asm/spitfire.h>
#include <asm/cpudata.h>
......@@ -14,71 +13,114 @@
/* Page table allocation/freeing. */
extern struct kmem_cache *pgtable_cache;
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
return quicklist_alloc(0, GFP_KERNEL, NULL);
return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
}
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
quicklist_free(0, NULL, pgd);
kmem_cache_free(pgtable_cache, pgd);
}
#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
return quicklist_alloc(0, GFP_KERNEL, NULL);
return kmem_cache_alloc(pgtable_cache,
GFP_KERNEL|__GFP_REPEAT);
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
quicklist_free(0, NULL, pmd);
kmem_cache_free(pgtable_cache, pmd);
}
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
return quicklist_alloc(0, GFP_KERNEL, NULL);
return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
}
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
unsigned long address)
{
struct page *page;
void *pg;
pte_t *pte;
pg = quicklist_alloc(0, GFP_KERNEL, NULL);
if (!pg)
pte = pte_alloc_one_kernel(mm, address);
if (!pte)
return NULL;
page = virt_to_page(pg);
page = virt_to_page(pte);
pgtable_page_ctor(page);
return page;
}
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
quicklist_free(0, NULL, pte);
free_page((unsigned long)pte);
}
static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
{
pgtable_page_dtor(ptepage);
quicklist_free_page(0, NULL, ptepage);
__free_page(ptepage);
}
#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
#define pmd_populate(MM,PMD,PTE_PAGE) \
pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
#define pmd_pgtable(pmd) pmd_page(pmd)
static inline void check_pgt_cache(void)
#define check_pgt_cache() do { } while (0)
static inline void pgtable_free(void *table, bool is_page)
{
if (is_page)
free_page((unsigned long)table);
else
kmem_cache_free(pgtable_cache, table);
}
#ifdef CONFIG_SMP
struct mmu_gather;
extern void tlb_remove_table(struct mmu_gather *, void *);
static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
{
unsigned long pgf = (unsigned long)table;
if (is_page)
pgf |= 0x1UL;
tlb_remove_table(tlb, (void *)pgf);
}
static inline void __tlb_remove_table(void *_table)
{
void *table = (void *)((unsigned long)_table & ~0x1UL);
bool is_page = false;
if ((unsigned long)_table & 0x1UL)
is_page = true;
pgtable_free(table, is_page);
}
#else /* CONFIG_SMP */
static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
{
quicklist_trim(0, NULL, 25, 16);
pgtable_free(table, is_page);
}
#endif /* !CONFIG_SMP */
static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage,
unsigned long address)
{
pgtable_page_dtor(ptepage);
pgtable_free_tlb(tlb, page_address(ptepage), true);
}
#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
#define __pmd_free_tlb(tlb, pmd, addr) \
pgtable_free_tlb(tlb, pmd, false)
#endif /* _SPARC64_PGALLOC_H */
......@@ -95,6 +95,10 @@
/* PTE bits which are the same in SUN4U and SUN4V format. */
#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */
#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
#define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */
/* Advertise support for _PAGE_SPECIAL */
#define __HAVE_ARCH_PTE_SPECIAL
/* SUN4U pte bits... */
#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */
......@@ -104,6 +108,7 @@
#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */
#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */
#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
#define _PAGE_SPECIAL_4U _AC(0x0200000000000000,UL) /* Special page */
#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */
#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */
#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
......@@ -133,6 +138,7 @@
#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */
#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */
#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */
#define _PAGE_SPECIAL_4V _AC(0x0200000000000000,UL) /* Special page */
#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */
#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */
#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */
......@@ -302,10 +308,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
: "=r" (mask), "=r" (tmp)
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
_PAGE_SZBITS_4U),
_PAGE_SZBITS_4U | _PAGE_SPECIAL),
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
_PAGE_SZBITS_4V));
_PAGE_SZBITS_4V | _PAGE_SPECIAL));
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
}
......@@ -502,6 +508,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
static inline pte_t pte_mkspecial(pte_t pte)
{
pte_val(pte) |= _PAGE_SPECIAL;
return pte;
}
......@@ -607,9 +614,9 @@ static inline unsigned long pte_present(pte_t pte)
return val;
}
static inline int pte_special(pte_t pte)
static inline unsigned long pte_special(pte_t pte)
{
return 0;
return pte_val(pte) & _PAGE_SPECIAL;
}
#define pmd_set(pmdp, ptep) \
......
......@@ -4,7 +4,7 @@
asflags-y := -ansi
ccflags-y := -Werror
obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o
obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o
obj-y += fault_$(BITS).o
obj-y += init_$(BITS).o
obj-$(CONFIG_SPARC32) += loadmmu.o
......
/*
* Lockless get_user_pages_fast for sparc, cribbed from powerpc
*
* Copyright (C) 2008 Nick Piggin
* Copyright (C) 2008 Novell Inc.
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/vmstat.h>
#include <linux/pagemap.h>
#include <linux/rwsem.h>
#include <asm/pgtable.h>
/*
* The performance critical leaf functions are made noinline otherwise gcc
* inlines everything into a single function which results in too much
* register pressure.
*/
static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
unsigned long mask, result;
pte_t *ptep;
if (tlb_type == hypervisor) {
result = _PAGE_PRESENT_4V|_PAGE_P_4V;
if (write)
result |= _PAGE_WRITE_4V;
} else {
result = _PAGE_PRESENT_4U|_PAGE_P_4U;
if (write)
result |= _PAGE_WRITE_4U;
}
mask = result | _PAGE_SPECIAL;
ptep = pte_offset_kernel(&pmd, addr);
do {
struct page *page, *head;
pte_t pte = *ptep;
if ((pte_val(pte) & mask) != result)
return 0;
VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
/* The hugepage case is simplified on sparc64 because
* we encode the sub-page pfn offsets into the
* hugepage PTEs. We could optimize this in the future
* use page_cache_add_speculative() for the hugepage case.
*/
page = pte_page(pte);
head = compound_head(page);
if (!page_cache_get_speculative(head))
return 0;
if (unlikely(pte_val(pte) != pte_val(*ptep))) {
put_page(head);
return 0;
}
pages[*nr] = page;
(*nr)++;
} while (ptep++, addr += PAGE_SIZE, addr != end);
return 1;
}
static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
int write, struct page **pages, int *nr)
{
unsigned long next;
pmd_t *pmdp;
pmdp = pmd_offset(&pud, addr);
do {
pmd_t pmd = *pmdp;
next = pmd_addr_end(addr, end);
if (pmd_none(pmd))
return 0;
if (!gup_pte_range(pmd, addr, next, write, pages, nr))
return 0;
} while (pmdp++, addr = next, addr != end);
return 1;
}
static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
int write, struct page **pages, int *nr)
{
unsigned long next;
pud_t *pudp;
pudp = pud_offset(&pgd, addr);
do {
pud_t pud = *pudp;
next = pud_addr_end(addr, end);
if (pud_none(pud))
return 0;
if (!gup_pmd_range(pud, addr, next, write, pages, nr))
return 0;
} while (pudp++, addr = next, addr != end);
return 1;
}
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
struct page **pages)
{
struct mm_struct *mm = current->mm;
unsigned long addr, len, end;
unsigned long next;
pgd_t *pgdp;
int nr = 0;
start &= PAGE_MASK;
addr = start;
len = (unsigned long) nr_pages << PAGE_SHIFT;
end = start + len;
/*
* XXX: batch / limit 'nr', to avoid large irq off latency
* needs some instrumenting to determine the common sizes used by
* important workloads (eg. DB2), and whether limiting the batch size
* will decrease performance.
*
* It seems like we're in the clear for the moment. Direct-IO is
* the main guy that batches up lots of get_user_pages, and even
* they are limited to 64-at-a-time which is not so many.
*/
/*
* This doesn't prevent pagetable teardown, but does prevent
* the pagetables from being freed on sparc.
*
* So long as we atomically load page table pointers versus teardown,
* we can follow the address down to the the page and take a ref on it.
*/
local_irq_disable();
pgdp = pgd_offset(mm, addr);
do {
pgd_t pgd = *pgdp;
next = pgd_addr_end(addr, end);
if (pgd_none(pgd))
goto slow;
if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
goto slow;
} while (pgdp++, addr = next, addr != end);
local_irq_enable();
VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
return nr;
{
int ret;
slow:
local_irq_enable();
/* Try to get the remaining pages with get_user_pages */
start += nr << PAGE_SHIFT;
pages += nr;
down_read(&mm->mmap_sem);
ret = get_user_pages(current, mm, start,
(end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
up_read(&mm->mmap_sem);
/* Have to be a bit careful with return values */
if (nr > 0) {
if (ret < 0)
ret = nr;
else
ret += nr;
}
return ret;
}
}
......@@ -236,6 +236,8 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
}
}
struct kmem_cache *pgtable_cache __read_mostly;
static struct kmem_cache *tsb_caches[8] __read_mostly;
static const char *tsb_cache_names[8] = {
......@@ -253,6 +255,15 @@ void __init pgtable_cache_init(void)
{
unsigned long i;
pgtable_cache = kmem_cache_create("pgtable_cache",
PAGE_SIZE, PAGE_SIZE,
0,
_clear_page);
if (!pgtable_cache) {
prom_printf("pgtable_cache_init(): Could not create!\n");
prom_halt();
}
for (i = 0; i < 8; i++) {
unsigned long size = 8192 << i;
const char *name = tsb_cache_names[i];
......
mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
source "arch/um/Kconfig.common"
menu "UML-specific options"
......
......@@ -543,11 +543,10 @@ int parse_chan_pair(char *str, struct line *line, int device,
const struct chan_opts *opts, char **error_out)
{
struct list_head *chans = &line->chan_list;
struct chan *new, *chan;
struct chan *new;
char *in, *out;
if (!list_empty(chans)) {
chan = list_entry(chans->next, struct chan, list);
free_chan(chans, 0);
INIT_LIST_HEAD(chans);
}
......
......@@ -186,7 +186,11 @@ static int absolutize(char *to, int size, char *from)
strcat(to, "/");
strcat(to, from);
}
chdir(save_cwd);
if (chdir(save_cwd)) {
cow_printf("absolutize : Can't cd to '%s' - "
"errno = %d\n", save_cwd, errno);
return -1;
}
return 0;
}
......
......@@ -32,7 +32,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
{
struct dog_data data;
int in_fds[2], out_fds[2], pid, n, err;
char pid_buf[sizeof("nnnnn\0")], c;
char pid_buf[sizeof("nnnnnnn\0")], c;
char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
NULL };
......
......@@ -176,10 +176,9 @@ void line_flush_buffer(struct tty_struct *tty)
{
struct line *line = tty->driver_data;
unsigned long flags;
int err;
spin_lock_irqsave(&line->lock, flags);
err = flush_buffer(line);
flush_buffer(line);
spin_unlock_irqrestore(&line->lock, flags);
}
......
......@@ -262,6 +262,15 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
static void uml_net_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
uml_net_interrupt(dev->irq, dev);
enable_irq(dev->irq);
}
#endif
static void uml_net_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
......@@ -364,6 +373,9 @@ static const struct net_device_ops uml_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = uml_net_change_mtu,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = uml_net_poll_controller,
#endif
};
/*
......
......@@ -228,7 +228,10 @@ static void change(char *dev, char *what, unsigned char *addr,
"buffer\n");
pid = change_tramp(argv, output, output_len);
if (pid < 0) return;
if (pid < 0) {
kfree(output);
return;
}
if (output != NULL) {
printk("%s", output);
......
......@@ -102,7 +102,7 @@ static int slip_tramp(char **argv, int fd)
"buffer\n");
os_kill_process(pid, 1);
err = -ENOMEM;
goto out_free;
goto out_close;
}
close(fds[1]);
......@@ -112,7 +112,6 @@ static int slip_tramp(char **argv, int fd)
err = helper_wait(pid);
close(fds[0]);
out_free:
kfree(output);
return err;
......
#ifndef __UM_DELAY_H
#define __UM_DELAY_H
#define MILLION 1000000
/* Undefined on purpose */
extern void __bad_udelay(void);
extern void __bad_ndelay(void);
extern void __udelay(unsigned long usecs);
extern void __ndelay(unsigned long usecs);
extern void __delay(unsigned long loops);
#define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
__bad_udelay() : __udelay(n))
/* It appears that ndelay is not used at all for UML, and has never been
* implemented. */
extern void __unimplemented_ndelay(void);
#define ndelay(n) __unimplemented_ndelay()
#define ndelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
__bad_ndelay() : __ndelay(n))
#endif
......@@ -38,7 +38,6 @@ void flush_thread(void)
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
set_fs(USER_DS);
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
}
......
......@@ -20,9 +20,8 @@ static void kill_off_processes(void)
os_kill_ptraced_process(userspace_pid[0], 1);
else {
struct task_struct *p;
int pid, me;
int pid;
me = os_getpid();
for_each_process(p) {
if (p->mm == NULL)
continue;
......
......@@ -3,10 +3,12 @@
# Licensed under the GPL
#
obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
tty.o tls.o uaccess.o umid.o util.o
......
......@@ -14,16 +14,11 @@
#include "mem_user.h"
#include <kern_constants.h>
/* Use the one from the kernel - the host may miss it, if having old headers. */
#if UM_ELF_CLASS == UM_ELFCLASS32
typedef Elf32_auxv_t elf_auxv_t;
#else
typedef Elf64_auxv_t elf_auxv_t;
#endif
/* These are initialized very early in boot and never changed */
char * elf_aux_platform;
long elf_aux_hwcap;
extern long elf_aux_hwcap;
unsigned long vsyscall_ehdr;
unsigned long vsyscall_end;
unsigned long __kernel_vsyscall;
......
......@@ -28,14 +28,14 @@ static int helper_child(void *arg)
{
struct helper_data *data = arg;
char **argv = data->argv;
int err;
int err, ret;
if (data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
err = execvp_noalloc(data->buf, argv[0], argv);
/* If the exec succeeds, we don't get here */
write(data->fd, &err, sizeof(err));
CATCH_EINTR(ret = write(data->fd, &err, sizeof(err)));
return 0;
}
......
......@@ -21,6 +21,8 @@
#define STACKSIZE (8 * 1024 * 1024)
#define THREAD_NAME_LEN (256)
long elf_aux_hwcap;
static void set_stklim(void)
{
struct rlimit lim;
......@@ -143,7 +145,9 @@ int __init main(int argc, char **argv, char **envp)
install_fatal_handler(SIGINT);
install_fatal_handler(SIGTERM);
#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
scan_elf_aux(envp);
#endif
do_uml_initcalls();
ret = linux_main(argc, argv);
......
......@@ -176,7 +176,7 @@ static int __init make_tempfile(const char *template, char **out_tempname,
find_tempdir();
if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN))
return -1;
goto out;
if (template[0] != '/')
strcpy(tempname, tempdir);
......@@ -191,13 +191,15 @@ static int __init make_tempfile(const char *template, char **out_tempname,
}
if (do_unlink && (unlink(tempname) < 0)) {
perror("unlink");
goto out;
goto close;
}
if (out_tempname) {
*out_tempname = tempname;
} else
free(tempname);
return fd;
close:
close(fd);
out:
free(tempname);
return -1;
......
......@@ -113,3 +113,8 @@ EXPORT_SYMBOL(__stack_smash_handler);
extern long __guard __attribute__((weak));
EXPORT_SYMBOL(__guard);
#ifdef _FORTIFY_SOURCE
extern int __sprintf_chk(char *str, int flag, size_t strlen, const char *format);
EXPORT_SYMBOL(__sprintf_chk);
#endif
......@@ -4,7 +4,7 @@
obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
sys_call_table.o tls.o atomic64_cx8_32.o
sys_call_table.o tls.o atomic64_cx8_32.o mem.o
obj-$(CONFIG_BINFMT_ELF) += elfcore.o
......
......@@ -105,6 +105,8 @@ extern unsigned long __kernel_vsyscall;
#define FIXADDR_USER_START VSYSCALL_BASE
#define FIXADDR_USER_END VSYSCALL_END
#define __HAVE_ARCH_GATE_AREA 1
/*
* Architecture-neutral AT_ values in 0-17, leave some room
* for more of them, start the x86-specific ones at 32.
......
/*
* Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
* Mostly copied from arch/x86/lib/delay.c
*
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <asm/param.h>
void __delay(unsigned long time)
void __delay(unsigned long loops)
{
/* Stolen from the i386 __loop_delay */
int d0;
__asm__ __volatile__(
"\tjmp 1f\n"
asm volatile(
"test %0,%0\n"
"jz 3f\n"
"jmp 1f\n"
".align 16\n"
"1:\tjmp 2f\n"
"1: jmp 2f\n"
".align 16\n"
"2:\tdecl %0\n\tjns 2b"
:"=&a" (d0)
:"0" (time));
"2: dec %0\n"
" jnz 2b\n"
"3: dec %0\n"
: /* we don't need output */
: "a" (loops)
);
}
EXPORT_SYMBOL(__delay);
void __udelay(unsigned long usecs)
inline void __const_udelay(unsigned long xloops)
{
int i, n;
int d0;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
for(i=0;i<n;i++)
cpu_relax();
xloops *= 4;
asm("mull %%edx"
: "=d" (xloops), "=&a" (d0)
: "1" (xloops), "0"
(loops_per_jiffy * (HZ/4)));
__delay(++xloops);
}
EXPORT_SYMBOL(__const_udelay);
void __udelay(unsigned long usecs)
{
__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
}
EXPORT_SYMBOL(__udelay);
void __ndelay(unsigned long nsecs)
{
__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
}
EXPORT_SYMBOL(__ndelay);
/*
* Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
*
* 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.
*/
#include <linux/mm.h>
#include <asm/page.h>
#include <asm/mman.h>
static struct vm_area_struct gate_vma;
static int __init gate_vma_init(void)
{
if (!FIXADDR_USER_START)
return 0;
gate_vma.vm_mm = NULL;
gate_vma.vm_start = FIXADDR_USER_START;
gate_vma.vm_end = FIXADDR_USER_END;
gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
gate_vma.vm_page_prot = __P101;
/*
* Make sure the vDSO gets into every core dump.
* Dumping its contents makes post-mortem fully interpretable later
* without matching up the same kernel and hardware config to see
* what PC values meant.
*/
gate_vma.vm_flags |= VM_ALWAYSDUMP;
return 0;
}
__initcall(gate_vma_init);
struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
{
return FIXADDR_USER_START ? &gate_vma : NULL;
}
int in_gate_area_no_mm(unsigned long addr)
{
if (!FIXADDR_USER_START)
return 0;
if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
return 1;
return 0;
}
int in_gate_area(struct mm_struct *mm, unsigned long addr)
{
struct vm_area_struct *vma = get_gate_vma(mm);
if (!vma)
return 0;
return (addr >= vma->vm_start) && (addr < vma->vm_end);
}
......@@ -4,10 +4,12 @@
# Licensed under the GPL
#
obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \
setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
sysrq.o ksyms.o tls.o
obj-y += vdso/
subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
lib/rwsem.o
subarch-obj-$(CONFIG_MODULES) += kernel/module.o
......
......@@ -119,4 +119,14 @@ extern long elf_aux_hwcap;
#define SET_PERSONALITY(ex) do ; while(0)
#define __HAVE_ARCH_GATE_AREA 1
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);
extern unsigned long um_vdso_addr;
#define AT_SYSINFO_EHDR 33
#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
#endif
/*
* Copyright 2003 PathScale, Inc.
* Copied from arch/x86_64
* Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
* Mostly copied from arch/x86/lib/delay.c
*
* Licensed under the GPL
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <asm/processor.h>
#include <asm/param.h>
void __delay(unsigned long loops)
{
unsigned long i;
asm volatile(
"test %0,%0\n"
"jz 3f\n"
"jmp 1f\n"
for(i = 0; i < loops; i++)
cpu_relax();
".align 16\n"
"1: jmp 2f\n"
".align 16\n"
"2: dec %0\n"
" jnz 2b\n"
"3: dec %0\n"
: /* we don't need output */
: "a" (loops)
);
}
EXPORT_SYMBOL(__delay);
void __udelay(unsigned long usecs)
inline void __const_udelay(unsigned long xloops)
{
unsigned long i, n;
int d0;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
for(i=0;i<n;i++)
cpu_relax();
xloops *= 4;
asm("mull %%edx"
: "=d" (xloops), "=&a" (d0)
: "1" (xloops), "0"
(loops_per_jiffy * (HZ/4)));
__delay(++xloops);
}
EXPORT_SYMBOL(__const_udelay);
void __udelay(unsigned long usecs)
{
__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
}
EXPORT_SYMBOL(__udelay);
void __ndelay(unsigned long nsecs)
{
__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
}
EXPORT_SYMBOL(__ndelay);
/*
* Copyright 2003 PathScale, Inc.
*
* Licensed under the GPL
*/
#include "linux/mm.h"
#include "asm/page.h"
#include "asm/mman.h"
unsigned long vm_stack_flags = __VM_STACK_FLAGS;
unsigned long vm_stack_flags32 = __VM_STACK_FLAGS;
unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS;
unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS;
unsigned long vm_force_exec32 = PROT_EXEC;
const char *arch_vma_name(struct vm_area_struct *vma)
{
if (vma->vm_mm && vma->vm_start == um_vdso_addr)
return "[vdso]";
return NULL;
}
struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
{
return NULL;
}
int in_gate_area(struct mm_struct *mm, unsigned long addr)
{
return 0;
}
int in_gate_area_no_mm(unsigned long addr)
{
return 0;
}
......@@ -7,27 +7,9 @@
#ifndef __VM_FLAGS_X86_64_H
#define __VM_FLAGS_X86_64_H
#define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \
VM_MAYEXEC)
extern unsigned long vm_stack_flags, vm_stack_flags32;
extern unsigned long vm_data_default_flags, vm_data_default_flags32;
extern unsigned long vm_force_exec32;
#ifdef TIF_IA32
#define VM_DATA_DEFAULT_FLAGS \
(test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \
vm_data_default_flags)
#define VM_STACK_DEFAULT_FLAGS \
(test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags)
#endif
#define VM_DATA_DEFAULT_FLAGS vm_data_default_flags
#define VM_STACK_DEFAULT_FLAGS vm_stack_flags
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#endif
#
# Building vDSO images for x86.
#
VDSO64-y := y
vdso-install-$(VDSO64-y) += vdso.so
# files to link into the vdso
vobjs-y := vdso-note.o um_vdso.o
# files to link into kernel
obj-$(VDSO64-y) += vdso.o vma.o
vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
$(obj)/vdso.o: $(obj)/vdso.so
targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
export CPPFLAGS_vdso.lds += -P -C
VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
$(call if_changed,vdso)
$(obj)/%.so: OBJCOPYFLAGS := -S
$(obj)/%.so: $(obj)/%.so.dbg FORCE
$(call if_changed,objcopy)
#
# Don't omit frame pointers for ease of userspace debugging, but do
# optimize sibling calls.
#
CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
$(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
-fno-omit-frame-pointer -foptimize-sibling-calls
$(vobjs): KBUILD_CFLAGS += $(CFL)
#
# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
#
CFLAGS_REMOVE_vdso-note.o = -pg
CFLAGS_REMOVE_um_vdso.o = -pg
targets += vdso-syms.lds
obj-$(VDSO64-y) += vdso-syms.lds
#
# Match symbols in the DSO that look like VDSO*; produce a file of constants.
#
sed-vdsosym := -e 's/^00*/0/' \
-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
quiet_cmd_vdsosym = VDSOSYM $@
define cmd_vdsosym
$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
endef
$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
$(call if_changed,vdsosym)
#
# The DSO images are built using a special linker script.
#
quiet_cmd_vdso = VDSO $@
cmd_vdso = $(CC) -nostdlib -o $@ \
$(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
-Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
GCOV_PROFILE := n
#
# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
#
quiet_cmd_vdso_install = INSTALL $@
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
@mkdir -p $(MODLIB)/vdso
$(call cmd,vdso_install)
PHONY += vdso_install $(vdso-install-y)
vdso_install: $(vdso-install-y)
#!/bin/sh
nm="$1"
file="$2"
$nm "$file" | grep '^ *U' > /dev/null 2>&1
if [ $? -eq 1 ]; then
exit 0
else
echo "$file: undefined symbols found" >&2
exit 1
fi
/*
* Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This vDSO turns all calls into a syscall so that UML can trap them.
*/
/* Disable profiling for userspace code */
#define DISABLE_BRANCH_PROFILING
#include <linux/time.h>
#include <linux/getcpu.h>
#include <asm/unistd.h>
int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
{
long ret;
asm("syscall" : "=a" (ret) :
"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
return ret;
}
int clock_gettime(clockid_t, struct timespec *)
__attribute__((weak, alias("__vdso_clock_gettime")));
int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
long ret;
asm("syscall" : "=a" (ret) :
"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
return ret;
}
int gettimeofday(struct timeval *, struct timezone *)
__attribute__((weak, alias("__vdso_gettimeofday")));
time_t __vdso_time(time_t *t)
{
long secs;
asm volatile("syscall"
: "=a" (secs)
: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
return secs;
}
int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
long
__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
{
/*
* UML does not support SMP, we can cheat here. :)
*/
if (cpu)
*cpu = 0;
if (node)
*node = 0;
return 0;
}
long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
__attribute__((weak, alias("__vdso_getcpu")));
/*
* Linker script for vDSO. This is an ELF shared object prelinked to
* its virtual address, and with only one read-only segment.
* This script controls its layout.
*/
SECTIONS
{
. = VDSO_PRELINK + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.note : { *(.note.*) } :text :note
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
.eh_frame : { KEEP (*(.eh_frame)) } :text
.dynamic : { *(.dynamic) } :text :dynamic
.rodata : { *(.rodata*) } :text
.data : {
*(.data*)
*(.sdata*)
*(.got.plt) *(.got)
*(.gnu.linkonce.d.*)
*(.bss*)
*(.dynbss*)
*(.gnu.linkonce.b.*)
}
.altinstructions : { *(.altinstructions) }
.altinstr_replacement : { *(.altinstr_replacement) }
/*
* Align the actual code well away from the non-instruction data.
* This is the best thing for the I-cache.
*/
. = ALIGN(0x100);
.text : { *(.text*) } :text =0x90909090
}
/*
* Very old versions of ld do not recognize this name token; use the constant.
*/
#define PT_GNU_EH_FRAME 0x6474e550
/*
* We must supply the ELF program headers explicitly to get just one
* PT_LOAD segment, and set the flags explicitly to make segments read-only.
*/
PHDRS
{
text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
note PT_NOTE FLAGS(4); /* PF_R */
eh_frame_hdr PT_GNU_EH_FRAME;
}
/*
* This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
* Here we can supply some information useful to userland.
*/
#include <linux/uts.h>
#include <linux/version.h>
#include <linux/elfnote.h>
ELFNOTE_START(Linux, 0, "a")
.long LINUX_VERSION_CODE
ELFNOTE_END
#include <linux/init.h>
__INITDATA
.globl vdso_start, vdso_end
vdso_start:
.incbin "arch/um/sys-x86_64/vdso/vdso.so"
vdso_end:
__FINIT
/*
* Linker script for 64-bit vDSO.
* We #include the file to define the layout details.
* Here we only choose the prelinked virtual address.
*
* This file defines the version script giving the user-exported symbols in
* the DSO. We can define local symbols here called VDSO* to make their
* values visible using the asm-x86/vdso.h macros from the kernel proper.
*/
#define VDSO_PRELINK 0xffffffffff700000
#include "vdso-layout.lds.S"
/*
* This controls what userland symbols we export from the vDSO.
*/
VERSION {
LINUX_2.6 {
global:
clock_gettime;
__vdso_clock_gettime;
gettimeofday;
__vdso_gettimeofday;
getcpu;
__vdso_getcpu;
time;
__vdso_time;
local: *;
};
}
VDSO64_PRELINK = VDSO_PRELINK;
/*
* Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
*
* 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.
*/
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/page.h>
#include <linux/init.h>
unsigned int __read_mostly vdso_enabled = 1;
unsigned long um_vdso_addr;
extern unsigned long task_size;
extern char vdso_start[], vdso_end[];
static struct page **vdsop;
static int __init init_vdso(void)
{
struct page *um_vdso;
BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
um_vdso_addr = task_size - PAGE_SIZE;
vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
if (!vdsop)
goto oom;
um_vdso = alloc_page(GFP_KERNEL);
if (!um_vdso) {
kfree(vdsop);
goto oom;
}
copy_page(page_address(um_vdso), vdso_start);
*vdsop = um_vdso;
return 0;
oom:
printk(KERN_ERR "Cannot allocate vdso\n");
vdso_enabled = 0;
return -ENOMEM;
}
subsys_initcall(init_vdso);
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
int err;
struct mm_struct *mm = current->mm;
if (!vdso_enabled)
return 0;
down_write(&mm->mmap_sem);
err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
VM_READ|VM_EXEC|
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
VM_ALWAYSDUMP,
vdsop);
up_write(&mm->mmap_sem);
return err;
}
......@@ -17,6 +17,7 @@
#define _XTENSA_UACCESS_H
#include <linux/errno.h>
#include <linux/prefetch.h>
#include <asm/types.h>
#define VERIFY_READ 0
......
......@@ -147,6 +147,9 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs)
elf_xtregs_t *xtregs = uregs;
int ret = 0;
if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t)))
return -EFAULT;
#if XTENSA_HAVE_COPROCESSORS
/* Flush all coprocessors before we overwrite them. */
coprocessor_flush_all(ti);
......
......@@ -1642,13 +1642,12 @@ static int sata_dwc_probe(struct platform_device *ofdev)
const struct ata_port_info *ppi[] = { &pi, NULL };
/* Allocate DWC SATA device */
hsdev = kmalloc(sizeof(*hsdev), GFP_KERNEL);
hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
if (hsdev == NULL) {
dev_err(&ofdev->dev, "kmalloc failed for hsdev\n");
err = -ENOMEM;
goto error;
}
memset(hsdev, 0, sizeof(*hsdev));
/* Ioremap SATA registers */
base = of_iomap(ofdev->dev.of_node, 0);
......
......@@ -173,7 +173,6 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
struct proc_event *ev;
struct timespec ts;
__u8 buffer[CN_PROC_MSG_SIZE];
struct task_struct *tracer;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
......
......@@ -45,13 +45,13 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
return 0;
}
static struct pci_device_id pci_eisa_pci_tbl[] = {
static struct pci_device_id __initdata pci_eisa_pci_tbl[] = {
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
{ 0, }
};
static struct pci_driver pci_eisa_driver = {
static struct pci_driver __initdata pci_eisa_driver = {
.name = "pci_eisa",
.id_table = pci_eisa_pci_tbl,
.probe = pci_eisa_init,
......
......@@ -11,6 +11,7 @@
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/sigma.h>
/* Return: 0==OK, <0==error, =1 ==no more actions */
......@@ -113,3 +114,5 @@ int process_sigma_firmware(struct i2c_client *client, const char *name)
return ret;
}
EXPORT_SYMBOL(process_sigma_firmware);
MODULE_LICENSE("GPL");
......@@ -83,30 +83,26 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
if (dev->sg)
return -EINVAL;
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
memset(entry, 0, sizeof(*entry));
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
entry->pages = pages;
entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL);
entry->pagelist = kcalloc(pages, sizeof(*entry->pagelist), GFP_KERNEL);
if (!entry->pagelist) {
kfree(entry);
return -ENOMEM;
}
memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL);
entry->busaddr = kcalloc(pages, sizeof(*entry->busaddr), GFP_KERNEL);
if (!entry->busaddr) {
kfree(entry->pagelist);
kfree(entry);
return -ENOMEM;
}
memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
if (!entry->virtual) {
......
......@@ -139,7 +139,7 @@ static int init_heap(struct mem_block **heap, int start, int size)
if (!blocks)
return -ENOMEM;
*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
*heap = kzalloc(sizeof(**heap), GFP_KERNEL);
if (!*heap) {
kfree(blocks);
return -ENOMEM;
......@@ -150,7 +150,6 @@ static int init_heap(struct mem_block **heap, int start, int size)
blocks->file_priv = NULL;
blocks->next = blocks->prev = *heap;
memset(*heap, 0, sizeof(**heap));
(*heap)->file_priv = (struct drm_file *) - 1;
(*heap)->next = (*heap)->prev = blocks;
return 0;
......
......@@ -585,11 +585,10 @@ int vmw_overlay_init(struct vmw_private *dev_priv)
return -ENOSYS;
}
overlay = kmalloc(sizeof(*overlay), GFP_KERNEL);
overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
if (!overlay)
return -ENOMEM;
memset(overlay, 0, sizeof(*overlay));
mutex_init(&overlay->mutex);
for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
overlay->stream[i].buf = NULL;
......
......@@ -612,11 +612,9 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
srf->sizes[0].height == 64 &&
srf->format == SVGA3D_A8R8G8B8) {
srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
/* clear the image */
if (srf->snooper.image) {
memset(srf->snooper.image, 0x00, 64 * 64 * 4);
} else {
/* allocate image area and clear it */
srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL);
if (!srf->snooper.image) {
DRM_ERROR("Failed to allocate cursor_image\n");
ret = -ENOMEM;
goto out_err1;
......
......@@ -1171,10 +1171,9 @@ static int vga_arb_open(struct inode *inode, struct file *file)
pr_debug("%s\n", __func__);
priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
memset(priv, 0, sizeof(*priv));
spin_lock_init(&priv->lock);
file->private_data = priv;
......
......@@ -365,6 +365,7 @@ config LEDS_NS2
config LEDS_NETXBIG
tristate "LED support for Big Network series LEDs"
depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2
depends on LEDS_CLASS
default y
help
This option enable support for LEDs found on the LaCie 2Big
......
......@@ -68,17 +68,16 @@
#define LM3530_ALS2_IMP_SHIFT (4)
/* Zone Boundary Register defaults */
#define LM3530_DEF_ZB_0 (0x33)
#define LM3530_DEF_ZB_1 (0x66)
#define LM3530_DEF_ZB_2 (0x99)
#define LM3530_DEF_ZB_3 (0xCC)
#define LM3530_ALS_ZB_MAX (4)
#define LM3530_ALS_WINDOW_mV (1000)
#define LM3530_ALS_OFFSET_mV (4)
/* Zone Target Register defaults */
#define LM3530_DEF_ZT_0 (0x19)
#define LM3530_DEF_ZT_1 (0x33)
#define LM3530_DEF_ZT_0 (0x7F)
#define LM3530_DEF_ZT_1 (0x66)
#define LM3530_DEF_ZT_2 (0x4C)
#define LM3530_DEF_ZT_3 (0x66)
#define LM3530_DEF_ZT_4 (0x7F)
#define LM3530_DEF_ZT_3 (0x33)
#define LM3530_DEF_ZT_4 (0x19)
struct lm3530_mode_map {
const char *mode;
......@@ -150,6 +149,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
u8 als_imp_sel = 0;
u8 brightness;
u8 reg_val[LM3530_REG_MAX];
u8 zones[LM3530_ALS_ZB_MAX];
u32 als_vmin, als_vmax, als_vstep;
struct lm3530_platform_data *pltfm = drvdata->pdata;
struct i2c_client *client = drvdata->client;
......@@ -161,6 +162,26 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
gen_config |= (LM3530_ENABLE_I2C);
if (drvdata->mode == LM3530_BL_MODE_ALS) {
if (pltfm->als_vmax == 0) {
pltfm->als_vmin = als_vmin = 0;
pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV;
}
als_vmin = pltfm->als_vmin;
als_vmax = pltfm->als_vmax;
if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV)
pltfm->als_vmax = als_vmax =
als_vmin + LM3530_ALS_WINDOW_mV;
/* n zone boundary makes n+1 zones */
als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1);
for (i = 0; i < LM3530_ALS_ZB_MAX; i++)
zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) +
als_vstep + (i * als_vstep)) * LED_FULL)
/ 1000;
als_config =
(pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
(LM3530_ENABLE_ALS) |
......@@ -169,6 +190,7 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
als_imp_sel =
(pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
(pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
}
if (drvdata->mode == LM3530_BL_MODE_PWM)
......@@ -190,10 +212,10 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
reg_val[3] = 0x00; /* LM3530_ALS_ZONE_REG */
reg_val[4] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */
reg_val[5] = brightness; /* LM3530_BRT_CTRL_REG */
reg_val[6] = LM3530_DEF_ZB_0; /* LM3530_ALS_ZB0_REG */
reg_val[7] = LM3530_DEF_ZB_1; /* LM3530_ALS_ZB1_REG */
reg_val[8] = LM3530_DEF_ZB_2; /* LM3530_ALS_ZB2_REG */
reg_val[9] = LM3530_DEF_ZB_3; /* LM3530_ALS_ZB3_REG */
reg_val[6] = zones[0]; /* LM3530_ALS_ZB0_REG */
reg_val[7] = zones[1]; /* LM3530_ALS_ZB1_REG */
reg_val[8] = zones[2]; /* LM3530_ALS_ZB2_REG */
reg_val[9] = zones[3]; /* LM3530_ALS_ZB3_REG */
reg_val[10] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */
reg_val[11] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */
reg_val[12] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */
......@@ -265,6 +287,24 @@ static void lm3530_brightness_set(struct led_classdev *led_cdev,
}
}
static ssize_t lm3530_mode_get(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = container_of(
dev->parent, struct i2c_client, dev);
struct lm3530_data *drvdata = i2c_get_clientdata(client);
int i, len = 0;
for (i = 0; i < ARRAY_SIZE(mode_map); i++)
if (drvdata->mode == mode_map[i].mode_val)
len += sprintf(buf + len, "[%s] ", mode_map[i].mode);
else
len += sprintf(buf + len, "%s ", mode_map[i].mode);
len += sprintf(buf + len, "\n");
return len;
}
static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
*attr, const char *buf, size_t size)
......@@ -298,8 +338,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
return sizeof(drvdata->mode);
}
static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set);
static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
static int __devinit lm3530_probe(struct i2c_client *client,
const struct i2c_device_id *id)
......
......@@ -744,7 +744,7 @@ static int __devinit lp5521_probe(struct i2c_client *client,
return ret;
}
static int lp5521_remove(struct i2c_client *client)
static int __devexit lp5521_remove(struct i2c_client *client)
{
struct lp5521_chip *chip = i2c_get_clientdata(client);
int i;
......@@ -775,7 +775,7 @@ static struct i2c_driver lp5521_driver = {
.name = "lp5521",
},
.probe = lp5521_probe,
.remove = lp5521_remove,
.remove = __devexit_p(lp5521_remove),
.id_table = lp5521_id,
};
......
......@@ -127,17 +127,19 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
struct led_type *types)
{
struct sunfire_drvdata *p;
int i, err = -EINVAL;
int i, err;
if (pdev->num_resources != 1) {
printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n",
pdev->num_resources);
err = -EINVAL;
goto out;
}
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p) {
printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n");
err = -ENOMEM;
goto out;
}
......@@ -160,14 +162,14 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
dev_set_drvdata(&pdev->dev, p);
err = 0;
out:
return err;
return 0;
out_unregister_led_cdevs:
for (i--; i >= 0; i--)
led_classdev_unregister(&p->leds[i].led_cdev);
goto out;
kfree(p);
out:
return err;
}
static int __devexit sunfire_led_generic_remove(struct platform_device *pdev)
......
......@@ -245,8 +245,7 @@ config SGI_XP
config CS5535_MFGPT
tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support"
depends on PCI
depends on X86
depends on PCI && X86 && MFD_CS5535
default n
help
This driver provides access to MFGPT functionality for other
......@@ -490,6 +489,15 @@ config PCH_PHUB
To compile this driver as a module, choose M here: the module will
be called pch_phub.
config USB_SWITCH_FSA9480
tristate "FSA9480 USB Switch"
depends on I2C
help
The FSA9480 is a USB port accessory detector and switch.
The FSA9480 is fully controlled using I2C and enables USB data,
stereo and mono audio, video, microphone and UART data to use
a common connector port.
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
......
......@@ -46,3 +46,4 @@ obj-y += ti-st/
obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
obj-y += lis3lv02d/
obj-y += carma/
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
......@@ -70,4 +70,29 @@ config EEPROM_93CX6
If unsure, say N.
config EEPROM_93XX46
tristate "Microwire EEPROM 93XX46 support"
depends on SPI && SYSFS
help
Driver for the microwire EEPROM chipsets 93xx46x. The driver
supports both read and write commands and also the command to
erase the whole EEPROM.
This driver can also be built as a module. If so, the module
will be called eeprom_93xx46.
If unsure, say N.
config EEPROM_DIGSY_MTC_CFG
bool "DigsyMTC display configuration EEPROMs device"
depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO
help
This option enables access to display configuration EEPROMs
on digsy_mtc board. You have to additionally select Microwire
EEPROM 93XX46 driver. sysfs entries will be created for that
EEPROM allowing to read/write the configuration data or to
erase the whole EEPROM.
If unsure, say N.
endmenu
......@@ -3,3 +3,5 @@ obj-$(CONFIG_EEPROM_AT25) += at25.o
obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o
obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
/*
* EEPROMs access control driver for display configuration EEPROMs
* on DigsyMTC board.
*
* (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
*
* 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.
*/
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h>
#include <linux/eeprom_93xx46.h>
#define GPIO_EEPROM_CLK 216
#define GPIO_EEPROM_CS 210
#define GPIO_EEPROM_DI 217
#define GPIO_EEPROM_DO 249
#define GPIO_EEPROM_OE 255
#define EE_SPI_BUS_NUM 1
static void digsy_mtc_op_prepare(void *p)
{
/* enable */
gpio_set_value(GPIO_EEPROM_OE, 0);
}
static void digsy_mtc_op_finish(void *p)
{
/* disable */
gpio_set_value(GPIO_EEPROM_OE, 1);
}
struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = {
.flags = EE_ADDR8,
.prepare = digsy_mtc_op_prepare,
.finish = digsy_mtc_op_finish,
};
static struct spi_gpio_platform_data eeprom_spi_gpio_data = {
.sck = GPIO_EEPROM_CLK,
.mosi = GPIO_EEPROM_DI,
.miso = GPIO_EEPROM_DO,
.num_chipselect = 1,
};
static struct platform_device digsy_mtc_eeprom = {
.name = "spi_gpio",
.id = EE_SPI_BUS_NUM,
.dev = {
.platform_data = &eeprom_spi_gpio_data,
},
};
static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = {
{
.modalias = "93xx46",
.max_speed_hz = 1000000,
.bus_num = EE_SPI_BUS_NUM,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data = (void *)GPIO_EEPROM_CS,
.platform_data = &digsy_mtc_eeprom_data,
},
};
static int __init digsy_mtc_eeprom_devices_init(void)
{
int ret;
ret = gpio_request_one(GPIO_EEPROM_OE, GPIOF_OUT_INIT_HIGH,
"93xx46 EEPROMs OE");
if (ret) {
pr_err("can't request gpio %d\n", GPIO_EEPROM_OE);
return ret;
}
spi_register_board_info(digsy_mtc_eeprom_info,
ARRAY_SIZE(digsy_mtc_eeprom_info));
return platform_device_register(&digsy_mtc_eeprom);
}
device_initcall(digsy_mtc_eeprom_devices_init);
/*
* Driver for 93xx46 EEPROMs
*
* (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
*
* 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.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/eeprom_93xx46.h>
#define OP_START 0x4
#define OP_WRITE (OP_START | 0x1)
#define OP_READ (OP_START | 0x2)
#define ADDR_EWDS 0x00
#define ADDR_ERAL 0x20
#define ADDR_EWEN 0x30
struct eeprom_93xx46_dev {
struct spi_device *spi;
struct eeprom_93xx46_platform_data *pdata;
struct bin_attribute bin;
struct mutex lock;
int addrlen;
};
static ssize_t
eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct eeprom_93xx46_dev *edev;
struct device *dev;
struct spi_message m;
struct spi_transfer t[2];
int bits, ret;
u16 cmd_addr;
dev = container_of(kobj, struct device, kobj);
edev = dev_get_drvdata(dev);
if (unlikely(off >= edev->bin.size))
return 0;
if ((off + count) > edev->bin.size)
count = edev->bin.size - off;
if (unlikely(!count))
return count;
cmd_addr = OP_READ << edev->addrlen;
if (edev->addrlen == 7) {
cmd_addr |= off & 0x7f;
bits = 10;
} else {
cmd_addr |= off & 0x3f;
bits = 9;
}
dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n",
cmd_addr, edev->spi->max_speed_hz);
spi_message_init(&m);
memset(t, 0, sizeof(t));
t[0].tx_buf = (char *)&cmd_addr;
t[0].len = 2;
t[0].bits_per_word = bits;
spi_message_add_tail(&t[0], &m);
t[1].rx_buf = buf;
t[1].len = count;
t[1].bits_per_word = 8;
spi_message_add_tail(&t[1], &m);
mutex_lock(&edev->lock);
if (edev->pdata->prepare)
edev->pdata->prepare(edev);
ret = spi_sync(edev->spi, &m);
/* have to wait at least Tcsl ns */
ndelay(250);
if (ret) {
dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n",
count, (int)off, ret);
}
if (edev->pdata->finish)
edev->pdata->finish(edev);
mutex_unlock(&edev->lock);
return ret ? : count;
}
static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
{
struct spi_message m;
struct spi_transfer t;
int bits, ret;
u16 cmd_addr;
cmd_addr = OP_START << edev->addrlen;
if (edev->addrlen == 7) {
cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1;
bits = 10;
} else {
cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS);
bits = 9;
}
dev_dbg(&edev->spi->dev, "ew cmd 0x%04x\n", cmd_addr);
spi_message_init(&m);
memset(&t, 0, sizeof(t));
t.tx_buf = &cmd_addr;
t.len = 2;
t.bits_per_word = bits;
spi_message_add_tail(&t, &m);
mutex_lock(&edev->lock);
if (edev->pdata->prepare)
edev->pdata->prepare(edev);
ret = spi_sync(edev->spi, &m);
/* have to wait at least Tcsl ns */
ndelay(250);
if (ret)
dev_err(&edev->spi->dev, "erase/write %sable error %d\n",
is_on ? "en" : "dis", ret);
if (edev->pdata->finish)
edev->pdata->finish(edev);
mutex_unlock(&edev->lock);
return ret;
}
static ssize_t
eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
const char *buf, unsigned off)
{
struct spi_message m;
struct spi_transfer t[2];
int bits, data_len, ret;
u16 cmd_addr;
cmd_addr = OP_WRITE << edev->addrlen;
if (edev->addrlen == 7) {
cmd_addr |= off & 0x7f;
bits = 10;
data_len = 1;
} else {
cmd_addr |= off & 0x3f;
bits = 9;
data_len = 2;
}
dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr);
spi_message_init(&m);
memset(t, 0, sizeof(t));
t[0].tx_buf = (char *)&cmd_addr;
t[0].len = 2;
t[0].bits_per_word = bits;
spi_message_add_tail(&t[0], &m);
t[1].tx_buf = buf;
t[1].len = data_len;
t[1].bits_per_word = 8;
spi_message_add_tail(&t[1], &m);
ret = spi_sync(edev->spi, &m);
/* have to wait program cycle time Twc ms */
mdelay(6);
return ret;
}
static ssize_t
eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct eeprom_93xx46_dev *edev;
struct device *dev;
int i, ret, step = 1;
dev = container_of(kobj, struct device, kobj);
edev = dev_get_drvdata(dev);
if (unlikely(off >= edev->bin.size))
return 0;
if ((off + count) > edev->bin.size)
count = edev->bin.size - off;
if (unlikely(!count))
return count;
/* only write even number of bytes on 16-bit devices */
if (edev->addrlen == 6) {
step = 2;
count &= ~1;
}
/* erase/write enable */
ret = eeprom_93xx46_ew(edev, 1);
if (ret)
return ret;
mutex_lock(&edev->lock);
if (edev->pdata->prepare)
edev->pdata->prepare(edev);
for (i = 0; i < count; i += step) {
ret = eeprom_93xx46_write_word(edev, &buf[i], off + i);
if (ret) {
dev_err(&edev->spi->dev, "write failed at %d: %d\n",
(int)off + i, ret);
break;
}
}
if (edev->pdata->finish)
edev->pdata->finish(edev);
mutex_unlock(&edev->lock);
/* erase/write disable */
eeprom_93xx46_ew(edev, 0);
return ret ? : count;
}
static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
{
struct eeprom_93xx46_platform_data *pd = edev->pdata;
struct spi_message m;
struct spi_transfer t;
int bits, ret;
u16 cmd_addr;
cmd_addr = OP_START << edev->addrlen;
if (edev->addrlen == 7) {
cmd_addr |= ADDR_ERAL << 1;
bits = 10;
} else {
cmd_addr |= ADDR_ERAL;
bits = 9;
}
spi_message_init(&m);
memset(&t, 0, sizeof(t));
t.tx_buf = &cmd_addr;
t.len = 2;
t.bits_per_word = bits;
spi_message_add_tail(&t, &m);
mutex_lock(&edev->lock);
if (edev->pdata->prepare)
edev->pdata->prepare(edev);
ret = spi_sync(edev->spi, &m);
if (ret)
dev_err(&edev->spi->dev, "erase error %d\n", ret);
/* have to wait erase cycle time Tec ms */
mdelay(6);
if (pd->finish)
pd->finish(edev);
mutex_unlock(&edev->lock);
return ret;
}
static ssize_t eeprom_93xx46_store_erase(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev);
int erase = 0, ret;
sscanf(buf, "%d", &erase);
if (erase) {
ret = eeprom_93xx46_ew(edev, 1);
if (ret)
return ret;
ret = eeprom_93xx46_eral(edev);
if (ret)
return ret;
ret = eeprom_93xx46_ew(edev, 0);
if (ret)
return ret;
}
return count;
}
static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
{
struct eeprom_93xx46_platform_data *pd;
struct eeprom_93xx46_dev *edev;
int err;
pd = spi->dev.platform_data;
if (!pd) {
dev_err(&spi->dev, "missing platform data\n");
return -ENODEV;
}
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev)
return -ENOMEM;
if (pd->flags & EE_ADDR8)
edev->addrlen = 7;
else if (pd->flags & EE_ADDR16)
edev->addrlen = 6;
else {
dev_err(&spi->dev, "unspecified address type\n");
err = -EINVAL;
goto fail;
}
mutex_init(&edev->lock);
edev->spi = spi_dev_get(spi);
edev->pdata = pd;
sysfs_bin_attr_init(&edev->bin);
edev->bin.attr.name = "eeprom";
edev->bin.attr.mode = S_IRUSR;
edev->bin.read = eeprom_93xx46_bin_read;
edev->bin.size = 128;
if (!(pd->flags & EE_READONLY)) {
edev->bin.write = eeprom_93xx46_bin_write;
edev->bin.attr.mode |= S_IWUSR;
}
err = sysfs_create_bin_file(&spi->dev.kobj, &edev->bin);
if (err)
goto fail;
dev_info(&spi->dev, "%d-bit eeprom %s\n",
(pd->flags & EE_ADDR8) ? 8 : 16,
(pd->flags & EE_READONLY) ? "(readonly)" : "");
if (!(pd->flags & EE_READONLY)) {
if (device_create_file(&spi->dev, &dev_attr_erase))
dev_err(&spi->dev, "can't create erase interface\n");
}
dev_set_drvdata(&spi->dev, edev);
return 0;
fail:
kfree(edev);
return err;
}
static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
{
struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
if (!(edev->pdata->flags & EE_READONLY))
device_remove_file(&spi->dev, &dev_attr_erase);
sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin);
dev_set_drvdata(&spi->dev, NULL);
kfree(edev);
return 0;
}
static struct spi_driver eeprom_93xx46_driver = {
.driver = {
.name = "93xx46",
.owner = THIS_MODULE,
},
.probe = eeprom_93xx46_probe,
.remove = __devexit_p(eeprom_93xx46_remove),
};
static int __init eeprom_93xx46_init(void)
{
return spi_register_driver(&eeprom_93xx46_driver);
}
module_init(eeprom_93xx46_init);
static void __exit eeprom_93xx46_exit(void)
{
spi_unregister_driver(&eeprom_93xx46_driver);
}
module_exit(eeprom_93xx46_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs");
MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
MODULE_ALIAS("spi:93xx46");
This diff is collapsed.
......@@ -686,6 +686,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
}
if (id->driver_data == 1) { /* EG20T PCH */
const char *board_name;
retval = sysfs_create_file(&pdev->dev.kobj,
&dev_attr_pch_mac.attr);
if (retval)
......@@ -701,7 +703,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
CLKCFG_CANCLK_MASK);
/* quirk for CM-iTC board */
if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
board_name = dmi_get_system_info(DMI_BOARD_NAME);
if (board_name && strstr(board_name, "CM-iTC"))
pch_phub_read_modify_write_reg(chip,
(unsigned int)CLKCFG_REG_OFFSET,
CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV |
......
......@@ -23,6 +23,7 @@
#include <linux/log2.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
......
......@@ -509,15 +509,15 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
struct acpi_resource_dma *p)
{
int i;
unsigned char map = 0, flags;
unsigned char map = 0, flags = 0;
if (p->channel_count == 0)
return;
flags |= IORESOURCE_DISABLED;
for (i = 0; i < p->channel_count; i++)
map |= 1 << p->channels[i];
flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
flags |= dma_flags(dev, p->type, p->bus_master, p->transfer);
pnp_register_dma_resource(dev, option_flags, map, flags);
}
......@@ -527,17 +527,17 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
{
int i;
pnp_irq_mask_t map;
unsigned char flags;
unsigned char flags = 0;
if (p->interrupt_count == 0)
return;
flags |= IORESOURCE_DISABLED;
bitmap_zero(map.bits, PNP_IRQ_NR);
for (i = 0; i < p->interrupt_count; i++)
if (p->interrupts[i])
__set_bit(p->interrupts[i], map.bits);
flags = irq_flags(p->triggering, p->polarity, p->sharable);
flags |= irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
......@@ -547,10 +547,10 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
{
int i;
pnp_irq_mask_t map;
unsigned char flags;
unsigned char flags = 0;
if (p->interrupt_count == 0)
return;
flags |= IORESOURCE_DISABLED;
bitmap_zero(map.bits, PNP_IRQ_NR);
for (i = 0; i < p->interrupt_count; i++) {
......@@ -564,7 +564,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
}
}
flags = irq_flags(p->triggering, p->polarity, p->sharable);
flags |= irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
......@@ -575,10 +575,10 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (io->address_length == 0)
return;
flags |= IORESOURCE_DISABLED;
if (io->io_decode == ACPI_DECODE_16)
flags = IORESOURCE_IO_16BIT_ADDR;
flags |= IORESOURCE_IO_16BIT_ADDR;
pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
io->alignment, io->address_length, flags);
}
......@@ -587,11 +587,13 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
unsigned int option_flags,
struct acpi_resource_fixed_io *io)
{
unsigned char flags = 0;
if (io->address_length == 0)
return;
flags |= IORESOURCE_DISABLED;
pnp_register_port_resource(dev, option_flags, io->address, io->address,
0, io->address_length, IORESOURCE_IO_FIXED);
0, io->address_length, flags | IORESOURCE_IO_FIXED);
}
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
......@@ -601,10 +603,10 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
return;
flags |= IORESOURCE_DISABLED;
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
p->alignment, p->address_length, flags);
}
......@@ -616,10 +618,10 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
return;
flags |= IORESOURCE_DISABLED;
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
p->alignment, p->address_length, flags);
}
......@@ -631,10 +633,10 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
return;
flags |= IORESOURCE_DISABLED;
if (p->write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->address, p->address,
0, p->address_length, flags);
}
......@@ -655,18 +657,18 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
}
if (p->address_length == 0)
return;
flags |= IORESOURCE_DISABLED;
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
flags);
} else if (p->resource_type == ACPI_IO_RANGE)
pnp_register_port_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
IORESOURCE_IO_FIXED);
flags | IORESOURCE_IO_FIXED);
}
static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
......@@ -677,18 +679,18 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
unsigned char flags = 0;
if (p->address_length == 0)
return;
flags |= IORESOURCE_DISABLED;
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
flags |= IORESOURCE_MEM_WRITEABLE;
pnp_register_mem_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
flags);
} else if (p->resource_type == ACPI_IO_RANGE)
pnp_register_port_resource(dev, option_flags, p->minimum,
p->minimum, 0, p->address_length,
IORESOURCE_IO_FIXED);
flags | IORESOURCE_IO_FIXED);
}
struct acpipnp_parse_option_s {
......
......@@ -1006,10 +1006,10 @@ config RTC_DRV_MC13XXX
config RTC_DRV_MPC5121
tristate "Freescale MPC5121 built-in RTC"
depends on PPC_MPC512x && RTC_CLASS
depends on PPC_MPC512x || PPC_MPC52xx
help
If you say yes here you will get support for the
built-in RTC MPC5121.
built-in RTC on MPC5121 or on MPC5200.
This driver can also be built as a module. If so, the module
will be called rtc-mpc5121.
......@@ -1034,6 +1034,16 @@ config RTC_DRV_LPC32XX
This driver can also be buillt as a module. If so, the module
will be called rtc-lpc32xx.
config RTC_DRV_PM8XXX
tristate "Qualcomm PMIC8XXX RTC"
depends on MFD_PM8XXX
help
If you say yes here you get support for the
Qualcomm PMIC8XXX RTC.
To compile this driver as a module, choose M here: the
module will be called rtc-pm8xxx.
config RTC_DRV_TEGRA
tristate "NVIDIA Tegra Internal RTC driver"
depends on RTC_CLASS && ARCH_TEGRA
......
......@@ -77,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o
obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o
obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
......
......@@ -3,6 +3,7 @@
*
* Copyright 2007, Domen Puncer <domen.puncer@telargo.com>
* Copyright 2008, Freescale Semiconductor, Inc. All rights reserved.
* Copyright 2011, Dmitry Eremin-Solenikov
*
* 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
......@@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
return 0;
}
static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
int tmp;
tm->tm_sec = in_8(&regs->second);
tm->tm_min = in_8(&regs->minute);
/* 12 hour format? */
if (in_8(&regs->hour) & 0x20)
tm->tm_hour = (in_8(&regs->hour) >> 1) +
(in_8(&regs->hour) & 1 ? 12 : 0);
else
tm->tm_hour = in_8(&regs->hour);
tmp = in_8(&regs->wday_mday);
tm->tm_mday = tmp & 0x1f;
tm->tm_mon = in_8(&regs->month) - 1;
tm->tm_year = in_be16(&regs->year) - 1900;
tm->tm_wday = (tmp >> 5) % 7;
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
tm->tm_isdst = 0;
return 0;
}
static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
mpc5121_rtc_update_smh(regs, tm);
/* date */
out_8(&regs->month_set, tm->tm_mon + 1);
out_8(&regs->weekday_set, tm->tm_wday ? tm->tm_wday : 7);
out_8(&regs->date_set, tm->tm_mday);
out_be16(&regs->year_set, tm->tm_year + 1900);
/* set date sequence */
out_8(&regs->set_date, 0x1);
out_8(&regs->set_date, 0x3);
out_8(&regs->set_date, 0x1);
out_8(&regs->set_date, 0x0);
return 0;
}
static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
......@@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = {
.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
};
static const struct rtc_class_ops mpc5200_rtc_ops = {
.read_time = mpc5200_rtc_read_time,
.set_time = mpc5200_rtc_set_time,
.read_alarm = mpc5121_rtc_read_alarm,
.set_alarm = mpc5121_rtc_set_alarm,
.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
};
static int __devinit mpc5121_rtc_probe(struct platform_device *op)
{
struct mpc5121_rtc_data *rtc;
int err = 0;
u32 ka;
rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
if (!rtc)
......@@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op)
goto out_dispose2;
}
ka = in_be32(&rtc->regs->keep_alive);
if (ka & 0x02) {
dev_warn(&op->dev,
"mpc5121-rtc: Battery or oscillator failure!\n");
out_be32(&rtc->regs->keep_alive, ka);
if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) {
u32 ka;
ka = in_be32(&rtc->regs->keep_alive);
if (ka & 0x02) {
dev_warn(&op->dev,
"mpc5121-rtc: Battery or oscillator failure!\n");
out_be32(&rtc->regs->keep_alive, ka);
}
rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
&mpc5121_rtc_ops, THIS_MODULE);
} else {
rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev,
&mpc5200_rtc_ops, THIS_MODULE);
}
rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
&mpc5121_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
goto out_free_irq;
......@@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op)
static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
{ .compatible = "fsl,mpc5121-rtc", },
{ .compatible = "fsl,mpc5200-rtc", },
{},
};
......
This diff is collapsed.
......@@ -57,11 +57,13 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
{
struct rtc_device *rdev = id;
clk_enable(rtc_clk);
rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
clk_disable(rtc_clk);
return IRQ_HANDLED;
}
......@@ -69,11 +71,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
{
struct rtc_device *rdev = id;
clk_enable(rtc_clk);
rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
clk_disable(rtc_clk);
return IRQ_HANDLED;
}
......@@ -84,12 +88,14 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
pr_debug("%s: aie=%d\n", __func__, enabled);
clk_enable(rtc_clk);
tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
if (enabled)
tmp |= S3C2410_RTCALM_ALMEN;
writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
clk_disable(rtc_clk);
return 0;
}
......@@ -103,6 +109,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
if (!is_power_of_2(freq))
return -EINVAL;
clk_enable(rtc_clk);
spin_lock_irq(&s3c_rtc_pie_lock);
if (s3c_rtc_cpu_type == TYPE_S3C2410) {
......@@ -114,6 +121,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
writel(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
clk_disable(rtc_clk);
return 0;
}
......@@ -125,6 +133,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
unsigned int have_retried = 0;
void __iomem *base = s3c_rtc_base;
clk_enable(rtc_clk);
retry_get_time:
rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);
rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
......@@ -157,6 +166,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_year += 100;
rtc_tm->tm_mon -= 1;
clk_disable(rtc_clk);
return rtc_valid_tm(rtc_tm);
}
......@@ -165,6 +175,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
void __iomem *base = s3c_rtc_base;
int year = tm->tm_year - 100;
clk_enable(rtc_clk);
pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
......@@ -182,6 +193,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
clk_disable(rtc_clk);
return 0;
}
......@@ -192,6 +204,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
void __iomem *base = s3c_rtc_base;
unsigned int alm_en;
clk_enable(rtc_clk);
alm_tm->tm_sec = readb(base + S3C2410_ALMSEC);
alm_tm->tm_min = readb(base + S3C2410_ALMMIN);
alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
......@@ -243,6 +256,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
else
alm_tm->tm_year = -1;
clk_disable(rtc_clk);
return 0;
}
......@@ -252,6 +266,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
void __iomem *base = s3c_rtc_base;
unsigned int alrm_en;
clk_enable(rtc_clk);
pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
......@@ -282,6 +297,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
s3c_rtc_setaie(dev, alrm->enabled);
clk_disable(rtc_clk);
return 0;
}
......@@ -289,6 +305,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned int ticnt;
clk_enable(rtc_clk);
if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
ticnt &= S3C64XX_RTCCON_TICEN;
......@@ -298,6 +315,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
}
seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
clk_disable(rtc_clk);
return 0;
}
......@@ -360,6 +378,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
if (s3c_rtc_base == NULL)
return;
clk_enable(rtc_clk);
if (!en) {
tmp = readw(base + S3C2410_RTCCON);
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
......@@ -399,6 +418,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
base + S3C2410_RTCCON);
}
}
clk_disable(rtc_clk);
}
static int __devexit s3c_rtc_remove(struct platform_device *dev)
......@@ -410,7 +430,6 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
s3c_rtc_setaie(&dev->dev, 0);
clk_disable(rtc_clk);
clk_put(rtc_clk);
rtc_clk = NULL;
......@@ -529,6 +548,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
s3c_rtc_setfreq(&pdev->dev, 1);
clk_disable(rtc_clk);
return 0;
err_nortc:
......@@ -554,6 +575,7 @@ static int ticnt_save, ticnt_en_save;
static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
clk_enable(rtc_clk);
/* save TICNT for anyone using periodic interrupts */
ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
......@@ -568,6 +590,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
else
dev_err(&pdev->dev, "enable_irq_wake failed\n");
}
clk_disable(rtc_clk);
return 0;
}
......@@ -576,6 +599,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
{
unsigned int tmp;
clk_enable(rtc_clk);
s3c_rtc_enable(pdev, 1);
writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
......@@ -587,6 +611,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
disable_irq_wake(s3c_rtc_alarmno);
wake_en = false;
}
clk_disable(rtc_clk);
return 0;
}
......
......@@ -343,7 +343,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
/* set context info. */
info->pdev = pdev;
info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock);
spin_lock_init(&info->tegra_rtc_lock);
platform_set_drvdata(pdev, info);
......
......@@ -275,7 +275,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
goto out;
save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
if (ret < 0)
goto out;
......
......@@ -117,6 +117,14 @@ config LCD_LD9040
If you have an LD9040 Panel, say Y to enable its
control driver.
config LCD_AMS369FG06
tristate "AMS369FG06 AMOLED LCD Driver"
depends on SPI && BACKLIGHT_CLASS_DEVICE
default n
help
If you have an AMS369FG06 AMOLED Panel, say Y to enable its
LCD control driver.
endif # LCD_CLASS_DEVICE
#
......
......@@ -13,6 +13,7 @@ obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
obj-$(CONFIG_LCD_LD9040) += ld9040.o
obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
......
......@@ -722,8 +722,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
goto out2;
}
bl->props.max_brightness =
bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
data->bl = bl;
......
This diff is collapsed.
......@@ -668,6 +668,7 @@ static int ld9040_probe(struct spi_device *spi)
struct ld9040 *lcd = NULL;
struct lcd_device *ld = NULL;
struct backlight_device *bd = NULL;
struct backlight_properties props;
lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
if (!lcd)
......@@ -699,14 +700,17 @@ static int ld9040_probe(struct spi_device *spi)
lcd->ld = ld;
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
props.max_brightness = MAX_BRIGHTNESS;
bd = backlight_device_register("ld9040-bl", &spi->dev,
lcd, &ld9040_backlight_ops, NULL);
if (IS_ERR(ld)) {
ret = PTR_ERR(ld);
goto out_free_lcd;
lcd, &ld9040_backlight_ops, &props);
if (IS_ERR(bd)) {
ret = PTR_ERR(bd);
goto out_unregister_lcd;
}
bd->props.max_brightness = MAX_BRIGHTNESS;
bd->props.brightness = MAX_BRIGHTNESS;
lcd->bd = bd;
......@@ -731,6 +735,8 @@ static int ld9040_probe(struct spi_device *spi)
dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
return 0;
out_unregister_lcd:
lcd_device_unregister(lcd->ld);
out_free_lcd:
kfree(lcd);
return ret;
......@@ -741,6 +747,7 @@ static int __devexit ld9040_remove(struct spi_device *spi)
struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
ld9040_power(lcd, FB_BLANK_POWERDOWN);
backlight_device_unregister(lcd->bd);
lcd_device_unregister(lcd->ld);
kfree(lcd);
......
......@@ -738,6 +738,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
struct s6e63m0 *lcd = NULL;
struct lcd_device *ld = NULL;
struct backlight_device *bd = NULL;
struct backlight_properties props;
lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
if (!lcd)
......@@ -769,16 +770,18 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
lcd->ld = ld;
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
props.max_brightness = MAX_BRIGHTNESS;
bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd,
&s6e63m0_backlight_ops, NULL);
&s6e63m0_backlight_ops, &props);
if (IS_ERR(bd)) {
ret = PTR_ERR(bd);
goto out_lcd_unregister;
}
bd->props.max_brightness = MAX_BRIGHTNESS;
bd->props.brightness = MAX_BRIGHTNESS;
bd->props.type = BACKLIGHT_RAW;
lcd->bd = bd;
/*
......@@ -840,7 +843,7 @@ static int __devexit s6e63m0_remove(struct spi_device *spi)
}
#if defined(CONFIG_PM)
unsigned int before_power;
static unsigned int before_power;
static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
{
......
......@@ -26,6 +26,36 @@ config XEN_SELFBALLOONING
kernel boot parameter. Note that systems without a sufficiently
large swap device should not enable self-ballooning.
config XEN_BALLOON_MEMORY_HOTPLUG
bool "Memory hotplug support for Xen balloon driver"
default n
depends on XEN_BALLOON && MEMORY_HOTPLUG
help
Memory hotplug support for Xen balloon driver allows expanding memory
available for the system above limit declared at system startup.
It is very useful on critical systems which require long
run without rebooting.
Memory could be hotplugged in following steps:
1) dom0: xl mem-max <domU> <maxmem>
where <maxmem> is >= requested memory size,
2) dom0: xl mem-set <domU> <memory>
where <memory> is requested memory size; alternatively memory
could be added by writing proper value to
/sys/devices/system/xen_memory/xen_memory0/target or
/sys/devices/system/xen_memory/xen_memory0/target_kb on dumU,
3) domU: for i in /sys/devices/system/memory/memory*/state; do \
[ "`cat "$i"`" = offline ] && echo online > "$i"; done
Memory could be onlined automatically on domU by adding following line to udev rules:
SUBSYSTEM=="memory", ACTION=="add", RUN+="/bin/sh -c '[ -f /sys$devpath/state ] && echo online > /sys$devpath/state'"
In that case step 3 should be omitted.
config XEN_SCRUB_PAGES
bool "Scrub pages before returning them to system"
depends on XEN_BALLOON
......
This diff is collapsed.
......@@ -94,7 +94,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
if (vma->vm_pgoff & ~(huge_page_mask(h) >> PAGE_SHIFT))
if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
return -EINVAL;
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
......
......@@ -1118,10 +1118,9 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
* Warn that /proc/pid/oom_adj is deprecated, see
* Documentation/feature-removal-schedule.txt.
*/
printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, "
"please use /proc/%d/oom_score_adj instead.\n",
current->comm, task_pid_nr(current),
task_pid_nr(task), task_pid_nr(task));
WARN_ONCE(1, "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
current->comm, task_pid_nr(current), task_pid_nr(task),
task_pid_nr(task));
task->signal->oom_adj = oom_adjust;
/*
* Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum
......
......@@ -214,7 +214,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
}
/* otherwise we clear all bit were set ... */
while (--i >= *beg)
reiserfs_test_and_clear_le_bit
reiserfs_clear_le_bit
(i, bh->b_data);
reiserfs_restore_prepared_buffer(s, bh);
*beg = org;
......@@ -1222,15 +1222,11 @@ void reiserfs_cache_bitmap_metadata(struct super_block *sb,
info->free_count = 0;
while (--cur >= (unsigned long *)bh->b_data) {
int i;
/* 0 and ~0 are special, we can optimize for them */
if (*cur == 0)
info->free_count += BITS_PER_LONG;
else if (*cur != ~0L) /* A mix, investigate */
for (i = BITS_PER_LONG - 1; i >= 0; i--)
if (!reiserfs_test_le_bit(i, cur))
info->free_count++;
info->free_count += BITS_PER_LONG - hweight_long(*cur);
}
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment