Merge branch 'perf/urgent' into perf/core

Merge reason: We want to apply a dependent patch.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Ingo Molnar 2010-12-16 11:22:25 +01:00
commit 006b20fe4c
63 changed files with 906 additions and 221 deletions

View file

@ -47,6 +47,20 @@ Date: January 2007
KernelVersion: 2.6.20 KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net> Contact: "Corentin Chary" <corentincj@iksaif.net>
Description: Description:
Control the bluetooth device. 1 means on, 0 means off. Control the wlan device. 1 means on, 0 means off.
This may control the led, the device or both. This may control the led, the device or both.
Users: Lapsus Users: Lapsus
What: /sys/devices/platform/asus_laptop/wimax
Date: October 2010
KernelVersion: 2.6.37
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the wimax device. 1 means on, 0 means off.
What: /sys/devices/platform/asus_laptop/wwan
Date: October 2010
KernelVersion: 2.6.37
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the wwan (3G) device. 1 means on, 0 means off.

View file

@ -0,0 +1,10 @@
What: /sys/devices/platform/eeepc-wmi/cpufv
Date: Oct 2010
KernelVersion: 2.6.37
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Change CPU clock configuration (write-only).
There are three available clock configuration:
* 0 -> Super Performance Mode
* 1 -> High Performance Mode
* 2 -> Power Saving Mode

View file

@ -16,7 +16,7 @@ config CPU_S3C2412
config CPU_S3C2412_ONLY config CPU_S3C2412_ONLY
bool bool
depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \ depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
!CPU_2416 && !CPU_S3C2440 && !CPU_S3C2442 && \ !CPU_S3C2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
!CPU_S3C2443 && CPU_S3C2412 !CPU_S3C2443 && CPU_S3C2412
default y if CPU_S3C2412 default y if CPU_S3C2412

View file

@ -35,9 +35,12 @@ menu "S3C2416 Machines"
config MACH_SMDK2416 config MACH_SMDK2416
bool "SMDK2416" bool "SMDK2416"
select CPU_S3C2416 select CPU_S3C2416
select MACH_SMDK
select S3C_DEV_FB select S3C_DEV_FB
select S3C_DEV_HSMMC select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC1
select S3C_DEV_NAND
select S3C_DEV_USB_HOST
select S3C2416_PM if PM select S3C2416_PM if PM
help help
Say Y here if you are using an SMDK2416 Say Y here if you are using an SMDK2416

View file

@ -18,6 +18,7 @@ config CPU_S3C2440
config CPU_S3C2442 config CPU_S3C2442
bool bool
select CPU_ARM920T select CPU_ARM920T
select S3C_GPIO_PULL_DOWN
select S3C2410_CLOCK select S3C2410_CLOCK
select S3C2410_GPIO select S3C2410_GPIO
select S3C2410_PM if PM select S3C2410_PM if PM
@ -178,6 +179,9 @@ config MACH_MINI2440
bool "MINI2440 development board" bool "MINI2440 development board"
select CPU_S3C2440 select CPU_S3C2440
select EEPROM_AT24 select EEPROM_AT24
select NEW_LEDS
select LEDS_CLASS
select LEDS_TRIGGER
select LEDS_TRIGGER_BACKLIGHT select LEDS_TRIGGER_BACKLIGHT
select S3C_DEV_NAND select S3C_DEV_NAND
select S3C_DEV_USB_HOST select S3C_DEV_USB_HOST

View file

@ -46,9 +46,6 @@ int __init s3c2440_init(void)
{ {
printk("S3C2440: Initialising architecture\n"); printk("S3C2440: Initialising architecture\n");
s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
/* change irq for watchdog */ /* change irq for watchdog */
s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT; s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
@ -58,3 +55,11 @@ int __init s3c2440_init(void)
return sysdev_register(&s3c2440_sysdev); return sysdev_register(&s3c2440_sysdev);
} }
void __init s3c2440_map_io(void)
{
s3c244x_map_io();
s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
}

View file

@ -32,6 +32,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/gpio.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
@ -43,6 +44,11 @@
#include <plat/clock.h> #include <plat/clock.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/s3c244x.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
/* S3C2442 extended clock support */ /* S3C2442 extended clock support */
@ -163,3 +169,11 @@ int __init s3c2442_init(void)
return sysdev_register(&s3c2442_sysdev); return sysdev_register(&s3c2442_sysdev);
} }
void __init s3c2442_map_io(void)
{
s3c244x_map_io();
s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down;
s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down;
}

View file

@ -5,6 +5,7 @@
config CPU_S3C2443 config CPU_S3C2443
bool bool
depends on ARCH_S3C2410 depends on ARCH_S3C2410
select CPU_ARM920T
select S3C2443_DMA if S3C2410_DMA select S3C2443_DMA if S3C2410_DMA
select CPU_LLSERIAL_S3C2440 select CPU_LLSERIAL_S3C2440
select SAMSUNG_CLKSRC select SAMSUNG_CLKSRC

View file

@ -88,7 +88,7 @@ static struct cpu_table cpu_ids[] __initdata = {
{ {
.idcode = 0x32440000, .idcode = 0x32440000,
.idmask = 0xffffffff, .idmask = 0xffffffff,
.map_io = s3c244x_map_io, .map_io = s3c2440_map_io,
.init_clocks = s3c244x_init_clocks, .init_clocks = s3c244x_init_clocks,
.init_uarts = s3c244x_init_uarts, .init_uarts = s3c244x_init_uarts,
.init = s3c2440_init, .init = s3c2440_init,
@ -97,7 +97,7 @@ static struct cpu_table cpu_ids[] __initdata = {
{ {
.idcode = 0x32440001, .idcode = 0x32440001,
.idmask = 0xffffffff, .idmask = 0xffffffff,
.map_io = s3c244x_map_io, .map_io = s3c2440_map_io,
.init_clocks = s3c244x_init_clocks, .init_clocks = s3c244x_init_clocks,
.init_uarts = s3c244x_init_uarts, .init_uarts = s3c244x_init_uarts,
.init = s3c2440_init, .init = s3c2440_init,
@ -106,7 +106,7 @@ static struct cpu_table cpu_ids[] __initdata = {
{ {
.idcode = 0x32440aaa, .idcode = 0x32440aaa,
.idmask = 0xffffffff, .idmask = 0xffffffff,
.map_io = s3c244x_map_io, .map_io = s3c2442_map_io,
.init_clocks = s3c244x_init_clocks, .init_clocks = s3c244x_init_clocks,
.init_uarts = s3c244x_init_uarts, .init_uarts = s3c244x_init_uarts,
.init = s3c2442_init, .init = s3c2442_init,
@ -115,7 +115,7 @@ static struct cpu_table cpu_ids[] __initdata = {
{ {
.idcode = 0x32440aab, .idcode = 0x32440aab,
.idmask = 0xffffffff, .idmask = 0xffffffff,
.map_io = s3c244x_map_io, .map_io = s3c2442_map_io,
.init_clocks = s3c244x_init_clocks, .init_clocks = s3c244x_init_clocks,
.init_uarts = s3c244x_init_uarts, .init_uarts = s3c244x_init_uarts,
.init = s3c2442_init, .init = s3c2442_init,

View file

@ -82,8 +82,6 @@ static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
struct s3c_gpio_cfg s3c24xx_gpiocfg_default = { struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
.set_config = s3c_gpio_setcfg_s3c24xx, .set_config = s3c_gpio_setcfg_s3c24xx,
.get_config = s3c_gpio_getcfg_s3c24xx, .get_config = s3c_gpio_getcfg_s3c24xx,
.set_pull = s3c_gpio_setpull_1up,
.get_pull = s3c_gpio_getpull_1up,
}; };
struct s3c_gpio_chip s3c24xx_gpios[] = { struct s3c_gpio_chip s3c24xx_gpios[] = {

View file

@ -21,17 +21,22 @@ extern void s3c244x_init_clocks(int xtal);
#else #else
#define s3c244x_init_clocks NULL #define s3c244x_init_clocks NULL
#define s3c244x_init_uarts NULL #define s3c244x_init_uarts NULL
#define s3c244x_map_io NULL
#endif #endif
#ifdef CONFIG_CPU_S3C2440 #ifdef CONFIG_CPU_S3C2440
extern int s3c2440_init(void); extern int s3c2440_init(void);
extern void s3c2440_map_io(void);
#else #else
#define s3c2440_init NULL #define s3c2440_init NULL
#define s3c2440_map_io NULL
#endif #endif
#ifdef CONFIG_CPU_S3C2442 #ifdef CONFIG_CPU_S3C2442
extern int s3c2442_init(void); extern int s3c2442_init(void);
extern void s3c2442_map_io(void);
#else #else
#define s3c2442_init NULL #define s3c2442_init NULL
#define s3c2442_map_io NULL
#endif #endif

View file

@ -280,18 +280,17 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
} }
#endif #endif
#ifdef CONFIG_S3C_GPIO_PULL_UP #if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
unsigned int off, s3c_gpio_pull_t pull) unsigned int off, s3c_gpio_pull_t pull,
s3c_gpio_pull_t updown)
{ {
void __iomem *reg = chip->base + 0x08; void __iomem *reg = chip->base + 0x08;
u32 pup = __raw_readl(reg); u32 pup = __raw_readl(reg);
pup = __raw_readl(reg); if (pull == updown)
if (pup == S3C_GPIO_PULL_UP)
pup &= ~(1 << off); pup &= ~(1 << off);
else if (pup == S3C_GPIO_PULL_NONE) else if (pull == S3C_GPIO_PULL_NONE)
pup |= (1 << off); pup |= (1 << off);
else else
return -EINVAL; return -EINVAL;
@ -300,17 +299,45 @@ int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
return 0; return 0;
} }
s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
unsigned int off) unsigned int off, s3c_gpio_pull_t updown)
{ {
void __iomem *reg = chip->base + 0x08; void __iomem *reg = chip->base + 0x08;
u32 pup = __raw_readl(reg); u32 pup = __raw_readl(reg);
pup &= (1 << off); pup &= (1 << off);
return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP; return pup ? S3C_GPIO_PULL_NONE : updown;
}
#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
#ifdef CONFIG_S3C_GPIO_PULL_UP
s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
unsigned int off)
{
return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
}
int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
unsigned int off, s3c_gpio_pull_t pull)
{
return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
} }
#endif /* CONFIG_S3C_GPIO_PULL_UP */ #endif /* CONFIG_S3C_GPIO_PULL_UP */
#ifdef CONFIG_S3C_GPIO_PULL_DOWN
s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
unsigned int off)
{
return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
}
int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
unsigned int off, s3c_gpio_pull_t pull)
{
return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
}
#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
#ifdef CONFIG_S5P_GPIO_DRVSTR #ifdef CONFIG_S5P_GPIO_DRVSTR
s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
{ {

View file

@ -209,6 +209,17 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
unsigned int off); unsigned int off);
/**
* s3c_gpio_getpull_1down() - Get configuration for choice of down or none
* @chip: The gpio chip that the GPIO pin belongs to
* @off: The offset to the pin to get the configuration of.
*
* This helper function reads the state of the pull-down resistor for the
* given GPIO in the same case as s3c_gpio_setpull_1down.
*/
extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
unsigned int off);
/** /**
* s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443. * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
* @chip: The gpio chip that is being configured. * @chip: The gpio chip that is being configured.

View file

@ -73,7 +73,8 @@ void gdbstub_io_init(void)
GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI; GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
/* permit level 0 IRQs to take place */ /* permit level 0 IRQs to take place */
local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); arch_local_change_intr_mask_level(
NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
} }
/* /*

View file

@ -87,7 +87,8 @@ void __init gdbstub_io_init(void)
tmp = *gdbstub_port->_control; tmp = *gdbstub_port->_control;
/* permit level 0 IRQs only */ /* permit level 0 IRQs only */
local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); arch_local_change_intr_mask_level(
NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
} }
/* /*

View file

@ -1194,7 +1194,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
asm volatile("mov mdr,%0" : "=d"(mdr)); asm volatile("mov mdr,%0" : "=d"(mdr));
local_save_flags(epsw); local_save_flags(epsw);
local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1)); arch_local_change_intr_mask_level(
NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
gdbstub_store_fpu(); gdbstub_store_fpu();

View file

@ -19,6 +19,7 @@
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/posix-timers.h> #include <linux/posix-timers.h>
#include <linux/cpu.h>
#include <asm/s390_ext.h> #include <asm/s390_ext.h>
#include <asm/timer.h> #include <asm/timer.h>
@ -566,6 +567,23 @@ void init_cpu_vtimer(void)
__ctl_set_bit(0,10); __ctl_set_bit(0,10);
} }
static int __cpuinit s390_nohz_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
struct s390_idle_data *idle;
long cpu = (long) hcpu;
idle = &per_cpu(s390_idle, cpu);
switch (action) {
case CPU_DYING:
case CPU_DYING_FROZEN:
idle->nohz_delay = 0;
default:
break;
}
return NOTIFY_OK;
}
void __init vtime_init(void) void __init vtime_init(void)
{ {
/* request the cpu timer external interrupt */ /* request the cpu timer external interrupt */
@ -574,5 +592,6 @@ void __init vtime_init(void)
/* Enable cpu timer interrupts on the boot cpu. */ /* Enable cpu timer interrupts on the boot cpu. */
init_cpu_vtimer(); init_cpu_vtimer();
cpu_notifier(s390_nohz_notify, 0);
} }

View file

@ -11,6 +11,7 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
void pvclock_read_wallclock(struct pvclock_wall_clock *wall, void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
struct pvclock_vcpu_time_info *vcpu, struct pvclock_vcpu_time_info *vcpu,
struct timespec *ts); struct timespec *ts);
void pvclock_resume(void);
/* /*
* Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,

View file

@ -83,6 +83,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
static atomic64_t last_value = ATOMIC64_INIT(0); static atomic64_t last_value = ATOMIC64_INIT(0);
void pvclock_resume(void)
{
atomic64_set(&last_value, 0);
}
cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
{ {
struct pvclock_shadow_time shadow; struct pvclock_shadow_time shadow;

View file

@ -426,6 +426,8 @@ void xen_timer_resume(void)
{ {
int cpu; int cpu;
pvclock_resume();
if (xen_clockevent != &xen_vcpuop_clockevent) if (xen_clockevent != &xen_vcpuop_clockevent)
return; return;

View file

@ -812,8 +812,10 @@ static int intel_fake_agp_fetch_size(void)
static void i830_cleanup(void) static void i830_cleanup(void)
{ {
kunmap(intel_private.i8xx_page); if (intel_private.i8xx_flush_page) {
intel_private.i8xx_flush_page = NULL; kunmap(intel_private.i8xx_flush_page);
intel_private.i8xx_flush_page = NULL;
}
__free_page(intel_private.i8xx_page); __free_page(intel_private.i8xx_page);
intel_private.i8xx_page = NULL; intel_private.i8xx_page = NULL;

View file

@ -241,7 +241,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
} }
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (!drm_helper_encoder_in_use(encoder)) { if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) {
drm_encoder_disable(encoder); drm_encoder_disable(encoder);
/* disconnector encoder from any connector */ /* disconnector encoder from any connector */
encoder->crtc = NULL; encoder->crtc = NULL;

View file

@ -585,10 +585,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
struct timeval now; struct timeval now;
unsigned long flags; unsigned long flags;
unsigned int seq; unsigned int seq;
int ret;
e = kzalloc(sizeof *e, GFP_KERNEL); e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL) if (e == NULL) {
return -ENOMEM; ret = -ENOMEM;
goto err_put;
}
e->pipe = pipe; e->pipe = pipe;
e->base.pid = current->pid; e->base.pid = current->pid;
@ -603,9 +606,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
if (file_priv->event_space < sizeof e->event) { if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags); ret = -EBUSY;
kfree(e); goto err_unlock;
return -ENOMEM;
} }
file_priv->event_space -= sizeof e->event; file_priv->event_space -= sizeof e->event;
@ -638,6 +640,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
return 0; return 0;
err_unlock:
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
err_put:
drm_vblank_put(dev, e->pipe);
return ret;
} }
/** /**

View file

@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_BLT: case I915_PARAM_HAS_BLT:
value = HAS_BLT(dev); value = HAS_BLT(dev);
break; break;
case I915_PARAM_HAS_COHERENT_RINGS:
value = 1;
break;
default: default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n", DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param); param->param);

View file

@ -4374,10 +4374,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
* use this buffer rather sooner than later, so issuing the required * use this buffer rather sooner than later, so issuing the required
* flush earlier is beneficial. * flush earlier is beneficial.
*/ */
if (obj->write_domain & I915_GEM_GPU_DOMAINS) if (obj->write_domain & I915_GEM_GPU_DOMAINS) {
i915_gem_flush_ring(dev, file_priv, i915_gem_flush_ring(dev, file_priv,
obj_priv->ring, obj_priv->ring,
0, obj->write_domain); 0, obj->write_domain);
} else if (obj_priv->ring->outstanding_lazy_request) {
/* This ring is not being cleared by active usage,
* so emit a request to do so.
*/
u32 seqno = i915_add_request(dev,
NULL, NULL,
obj_priv->ring);
if (seqno == 0)
ret = -ENOMEM;
}
/* Update the active list for the hardware's current position. /* Update the active list for the hardware's current position.
* Otherwise this only updates on a delayed timer or when irqs * Otherwise this only updates on a delayed timer or when irqs

View file

@ -3033,6 +3033,7 @@
#define TRANS_DP_10BPC (1<<9) #define TRANS_DP_10BPC (1<<9)
#define TRANS_DP_6BPC (2<<9) #define TRANS_DP_6BPC (2<<9)
#define TRANS_DP_12BPC (3<<9) #define TRANS_DP_12BPC (3<<9)
#define TRANS_DP_BPC_MASK (3<<9)
#define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4) #define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4)
#define TRANS_DP_VSYNC_ACTIVE_LOW 0 #define TRANS_DP_VSYNC_ACTIVE_LOW 0
#define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3) #define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3)

View file

@ -190,37 +190,6 @@ out:
kfree(output.pointer); kfree(output.pointer);
} }
static int intel_dsm_switchto(enum vga_switcheroo_client_id id)
{
return 0;
}
static int intel_dsm_power_state(enum vga_switcheroo_client_id id,
enum vga_switcheroo_state state)
{
return 0;
}
static int intel_dsm_init(void)
{
return 0;
}
static int intel_dsm_get_client_id(struct pci_dev *pdev)
{
if (intel_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
return VGA_SWITCHEROO_IGD;
else
return VGA_SWITCHEROO_DIS;
}
static struct vga_switcheroo_handler intel_dsm_handler = {
.switchto = intel_dsm_switchto,
.power_state = intel_dsm_power_state,
.init = intel_dsm_init,
.get_client_id = intel_dsm_get_client_id,
};
static bool intel_dsm_pci_probe(struct pci_dev *pdev) static bool intel_dsm_pci_probe(struct pci_dev *pdev)
{ {
acpi_handle dhandle, intel_handle; acpi_handle dhandle, intel_handle;
@ -276,11 +245,8 @@ void intel_register_dsm_handler(void)
{ {
if (!intel_dsm_detect()) if (!intel_dsm_detect())
return; return;
vga_switcheroo_register_handler(&intel_dsm_handler);
} }
void intel_unregister_dsm_handler(void) void intel_unregister_dsm_handler(void)
{ {
vga_switcheroo_unregister_handler();
} }

View file

@ -2120,9 +2120,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
reg = TRANS_DP_CTL(pipe); reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
temp &= ~(TRANS_DP_PORT_SEL_MASK | temp &= ~(TRANS_DP_PORT_SEL_MASK |
TRANS_DP_SYNC_MASK); TRANS_DP_SYNC_MASK |
TRANS_DP_BPC_MASK);
temp |= (TRANS_DP_OUTPUT_ENABLE | temp |= (TRANS_DP_OUTPUT_ENABLE |
TRANS_DP_ENH_FRAMING); TRANS_DP_ENH_FRAMING);
temp |= TRANS_DP_8BPC;
if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
@ -2712,27 +2714,19 @@ fdi_reduce_ratio(u32 *num, u32 *den)
} }
} }
#define DATA_N 0x800000
#define LINK_N 0x80000
static void static void
ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
int link_clock, struct fdi_m_n *m_n) int link_clock, struct fdi_m_n *m_n)
{ {
u64 temp;
m_n->tu = 64; /* default size */ m_n->tu = 64; /* default size */
temp = (u64) DATA_N * pixel_clock; /* BUG_ON(pixel_clock > INT_MAX / 36); */
temp = div_u64(temp, link_clock); m_n->gmch_m = bits_per_pixel * pixel_clock;
m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes); m_n->gmch_n = link_clock * nlanes * 8;
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); fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
temp = (u64) LINK_N * pixel_clock; m_n->link_m = pixel_clock;
m_n->link_m = div_u64(temp, link_clock); m_n->link_n = link_clock;
m_n->link_n = LINK_N;
fdi_reduce_ratio(&m_n->link_m, &m_n->link_n); fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
} }
@ -3716,6 +3710,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
/* FDI link */ /* FDI link */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
int lane = 0, link_bw, bpp; int lane = 0, link_bw, bpp;
/* CPU eDP doesn't require FDI link, so just set DP M/N /* CPU eDP doesn't require FDI link, so just set DP M/N
according to current link config */ according to current link config */
@ -3799,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
intel_crtc->fdi_lanes = lane; intel_crtc->fdi_lanes = lane;
if (pixel_multiplier > 1)
link_bw *= pixel_multiplier;
ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
} }
@ -5236,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
.page_flip = intel_crtc_page_flip, .page_flip = intel_crtc_page_flip,
}; };
static void intel_sanitize_modesetting(struct drm_device *dev,
int pipe, int plane)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg, val;
if (HAS_PCH_SPLIT(dev))
return;
/* Who knows what state these registers were left in by the BIOS or
* grub?
*
* If we leave the registers in a conflicting state (e.g. with the
* display plane reading from the other pipe than the one we intend
* to use) then when we attempt to teardown the active mode, we will
* not disable the pipes and planes in the correct order -- leaving
* a plane reading from a disabled pipe and possibly leading to
* undefined behaviour.
*/
reg = DSPCNTR(plane);
val = I915_READ(reg);
if ((val & DISPLAY_PLANE_ENABLE) == 0)
return;
if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
return;
/* This display plane is active and attached to the other CPU pipe. */
pipe = !pipe;
/* Disable the plane and wait for it to stop reading from the pipe. */
I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
intel_flush_display_plane(dev, plane);
if (IS_GEN2(dev))
intel_wait_for_vblank(dev, pipe);
if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
return;
/* Switch off the pipe. */
reg = PIPECONF(pipe);
val = I915_READ(reg);
if (val & PIPECONF_ENABLE) {
I915_WRITE(reg, val & ~PIPECONF_ENABLE);
intel_wait_for_pipe_off(dev, pipe);
}
}
static void intel_crtc_init(struct drm_device *dev, int pipe) static void intel_crtc_init(struct drm_device *dev, int pipe)
{ {
@ -5287,6 +5333,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer, setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
(unsigned long)intel_crtc); (unsigned long)intel_crtc);
intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
} }
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,

View file

@ -1376,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t DP = intel_dp->DP; uint32_t DP = intel_dp->DP;
if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
return;
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
@ -1398,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp)
if (is_edp(intel_dp)) if (is_edp(intel_dp))
DP |= DP_LINK_TRAIN_OFF; DP |= DP_LINK_TRAIN_OFF;
if (!HAS_PCH_CPT(dev) &&
I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
/* Hardware workaround: leaving our transcoder select
* set to transcoder B while it's off will prevent the
* corresponding HDMI output on transcoder A.
*
* Combine this with another hardware workaround:
* transcoder select bit can only be cleared while the
* port is enabled.
*/
DP &= ~DP_PIPEB_SELECT;
I915_WRITE(intel_dp->output_reg, DP);
/* Changes to enable or select take place the vblank
* after being written.
*/
intel_wait_for_vblank(intel_dp->base.base.dev,
intel_crtc->pipe);
}
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
} }

View file

@ -68,7 +68,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
/** /**
* Sets the power state for the panel. * Sets the power state for the panel.
*/ */
static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on) static void intel_lvds_enable(struct intel_lvds *intel_lvds)
{ {
struct drm_device *dev = intel_lvds->base.base.dev; struct drm_device *dev = intel_lvds->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
@ -82,26 +82,61 @@ static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
lvds_reg = LVDS; lvds_reg = LVDS;
} }
if (on) { I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
} else {
dev_priv->backlight_level = intel_panel_get_backlight(dev);
intel_panel_set_backlight(dev, 0); if (intel_lvds->pfit_dirty) {
I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); /*
* Enable automatic panel scaling so that non-native modes
if (intel_lvds->pfit_control) { * fill the screen. The panel fitter should only be
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) * adjusted whilst the pipe is disabled, according to
DRM_ERROR("timed out waiting for panel to power off\n"); * register description and PRM.
I915_WRITE(PFIT_CONTROL, 0); */
intel_lvds->pfit_control = 0; DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
intel_lvds->pfit_control,
intel_lvds->pfit_pgm_ratios);
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) {
DRM_ERROR("timed out waiting for panel to power off\n");
} else {
I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
intel_lvds->pfit_dirty = false; intel_lvds->pfit_dirty = false;
} }
I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
} }
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
POSTING_READ(lvds_reg);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
}
static void intel_lvds_disable(struct intel_lvds *intel_lvds)
{
struct drm_device *dev = intel_lvds->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 ctl_reg, lvds_reg;
if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL;
lvds_reg = PCH_LVDS;
} else {
ctl_reg = PP_CONTROL;
lvds_reg = LVDS;
}
dev_priv->backlight_level = intel_panel_get_backlight(dev);
intel_panel_set_backlight(dev, 0);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
if (intel_lvds->pfit_control) {
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");
I915_WRITE(PFIT_CONTROL, 0);
intel_lvds->pfit_dirty = true;
}
I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
POSTING_READ(lvds_reg); POSTING_READ(lvds_reg);
} }
@ -110,9 +145,9 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
struct intel_lvds *intel_lvds = to_intel_lvds(encoder); struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
if (mode == DRM_MODE_DPMS_ON) if (mode == DRM_MODE_DPMS_ON)
intel_lvds_set_power(intel_lvds, true); intel_lvds_enable(intel_lvds);
else else
intel_lvds_set_power(intel_lvds, false); intel_lvds_disable(intel_lvds);
/* XXX: We never power down the LVDS pairs. */ /* XXX: We never power down the LVDS pairs. */
} }
@ -411,43 +446,18 @@ static void intel_lvds_commit(struct drm_encoder *encoder)
/* Always do a full power on as we do not know what state /* Always do a full power on as we do not know what state
* we were left in. * we were left in.
*/ */
intel_lvds_set_power(intel_lvds, true); intel_lvds_enable(intel_lvds);
} }
static void intel_lvds_mode_set(struct drm_encoder *encoder, static void intel_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
/* /*
* The LVDS pin pair will already have been turned on in the * The LVDS pin pair will already have been turned on in the
* intel_crtc_mode_set since it has a large impact on the DPLL * intel_crtc_mode_set since it has a large impact on the DPLL
* settings. * settings.
*/ */
if (HAS_PCH_SPLIT(dev))
return;
if (!intel_lvds->pfit_dirty)
return;
/*
* Enable automatic panel scaling so that non-native modes fill the
* screen. Should be enabled before the pipe is enabled, according to
* register description and PRM.
*/
DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
intel_lvds->pfit_control,
intel_lvds->pfit_pgm_ratios);
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");
I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
intel_lvds->pfit_dirty = false;
} }
/** /**

View file

@ -156,23 +156,25 @@ static int init_ring_common(struct drm_device *dev,
/* G45 ring initialization fails to reset head to zero */ /* G45 ring initialization fails to reset head to zero */
if (head != 0) { if (head != 0) {
DRM_ERROR("%s head not reset to zero " DRM_DEBUG_KMS("%s head not reset to zero "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
ring->name, ring->name,
I915_READ_CTL(ring), I915_READ_CTL(ring),
I915_READ_HEAD(ring), I915_READ_HEAD(ring),
I915_READ_TAIL(ring), I915_READ_TAIL(ring),
I915_READ_START(ring)); I915_READ_START(ring));
I915_WRITE_HEAD(ring, 0); I915_WRITE_HEAD(ring, 0);
DRM_ERROR("%s head forced to zero " if (I915_READ_HEAD(ring) & HEAD_ADDR) {
"ctl %08x head %08x tail %08x start %08x\n", DRM_ERROR("failed to set %s head to zero "
ring->name, "ctl %08x head %08x tail %08x start %08x\n",
I915_READ_CTL(ring), ring->name,
I915_READ_HEAD(ring), I915_READ_CTL(ring),
I915_READ_TAIL(ring), I915_READ_HEAD(ring),
I915_READ_START(ring)); I915_READ_TAIL(ring),
I915_READ_START(ring));
}
} }
I915_WRITE_CTL(ring, I915_WRITE_CTL(ring,

View file

@ -1195,8 +1195,10 @@ void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
mc->vram_end, mc->real_vram_size >> 20); mc->vram_end, mc->real_vram_size >> 20);
} else { } else {
u64 base = 0; u64 base = 0;
if (rdev->flags & RADEON_IS_IGP) if (rdev->flags & RADEON_IS_IGP) {
base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24; base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
base <<= 24;
}
radeon_vram_location(rdev, &rdev->mc, base); radeon_vram_location(rdev, &rdev->mc, base);
rdev->mc.gtt_base_align = 0; rdev->mc.gtt_base_align = 0;
radeon_gtt_location(rdev, mc); radeon_gtt_location(rdev, mc);

View file

@ -286,7 +286,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
mc->mc_vram_size = mc->aper_size; mc->mc_vram_size = mc->aper_size;
} }
mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
mc->mc_vram_size >> 20, mc->vram_start, mc->mc_vram_size >> 20, mc->vram_start,
mc->vram_end, mc->real_vram_size >> 20); mc->vram_end, mc->real_vram_size >> 20);
} }
@ -323,7 +323,7 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align;
} }
mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;
dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n", dev_info(rdev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n",
mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end);
} }

View file

@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
u32 c = 0; u32 c = 0;
rbo->placement.fpfn = 0; rbo->placement.fpfn = 0;
rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT; rbo->placement.lpfn = 0;
rbo->placement.placement = rbo->placements; rbo->placement.placement = rbo->placements;
rbo->placement.busy_placement = rbo->placements; rbo->placement.busy_placement = rbo->placements;
if (domain & RADEON_GEM_DOMAIN_VRAM) if (domain & RADEON_GEM_DOMAIN_VRAM)
@ -91,7 +91,8 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
{ {
struct radeon_bo *bo; struct radeon_bo *bo;
enum ttm_bo_type type; enum ttm_bo_type type;
int page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
unsigned long max_size = 0;
int r; int r;
if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
@ -104,6 +105,14 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
} }
*bo_ptr = NULL; *bo_ptr = NULL;
/* maximun bo size is the minimun btw visible vram and gtt size */
max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
if ((page_align << PAGE_SHIFT) >= max_size) {
printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
__func__, __LINE__, page_align >> (20 - PAGE_SHIFT), max_size >> 20);
return -ENOMEM;
}
retry: retry:
bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
if (bo == NULL) if (bo == NULL)

View file

@ -245,6 +245,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
goto err_free_tgfx; goto err_free_tgfx;
} }
parport_put_port(pp);
return tgfx; return tgfx;
err_free_dev: err_free_dev:

View file

@ -179,6 +179,22 @@ config KEYBOARD_GPIO
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called gpio_keys. module will be called gpio_keys.
config KEYBOARD_GPIO_POLLED
tristate "Polled GPIO buttons"
depends on GENERIC_GPIO
select INPUT_POLLDEV
help
This driver implements support for buttons connected
to GPIO pins that are not capable of generating interrupts.
Say Y here if your device has buttons connected
directly to such GPIO pins. Your board-specific
setup logic must also provide a platform device,
with configuration data saying which GPIOs are used.
To compile this driver as a module, choose M here: the
module will be called gpio_keys_polled.
config KEYBOARD_TCA6416 config KEYBOARD_TCA6416
tristate "TCA6416 Keypad Support" tristate "TCA6416 Keypad Support"
depends on I2C depends on I2C

View file

@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o

View file

@ -0,0 +1,261 @@
/*
* Driver for buttons on GPIO lines not capable of generating interrupts
*
* Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
*
* This file was based on: /drivers/input/misc/cobalt_btns.c
* Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* also was based on: /drivers/input/keyboard/gpio_keys.c
* Copyright 2005 Phil Blundell
*
* 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/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#define DRV_NAME "gpio-keys-polled"
struct gpio_keys_button_data {
int last_state;
int count;
int threshold;
int can_sleep;
};
struct gpio_keys_polled_dev {
struct input_polled_dev *poll_dev;
struct device *dev;
struct gpio_keys_platform_data *pdata;
struct gpio_keys_button_data data[0];
};
static void gpio_keys_polled_check_state(struct input_dev *input,
struct gpio_keys_button *button,
struct gpio_keys_button_data *bdata)
{
int state;
if (bdata->can_sleep)
state = !!gpio_get_value_cansleep(button->gpio);
else
state = !!gpio_get_value(button->gpio);
if (state != bdata->last_state) {
unsigned int type = button->type ?: EV_KEY;
input_event(input, type, button->code,
!!(state ^ button->active_low));
input_sync(input);
bdata->count = 0;
bdata->last_state = state;
}
}
static void gpio_keys_polled_poll(struct input_polled_dev *dev)
{
struct gpio_keys_polled_dev *bdev = dev->private;
struct gpio_keys_platform_data *pdata = bdev->pdata;
struct input_dev *input = dev->input;
int i;
for (i = 0; i < bdev->pdata->nbuttons; i++) {
struct gpio_keys_button_data *bdata = &bdev->data[i];
if (bdata->count < bdata->threshold)
bdata->count++;
else
gpio_keys_polled_check_state(input, &pdata->buttons[i],
bdata);
}
}
static void gpio_keys_polled_open(struct input_polled_dev *dev)
{
struct gpio_keys_polled_dev *bdev = dev->private;
struct gpio_keys_platform_data *pdata = bdev->pdata;
if (pdata->enable)
pdata->enable(bdev->dev);
}
static void gpio_keys_polled_close(struct input_polled_dev *dev)
{
struct gpio_keys_polled_dev *bdev = dev->private;
struct gpio_keys_platform_data *pdata = bdev->pdata;
if (pdata->disable)
pdata->disable(bdev->dev);
}
static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
struct gpio_keys_polled_dev *bdev;
struct input_polled_dev *poll_dev;
struct input_dev *input;
int error;
int i;
if (!pdata || !pdata->poll_interval)
return -EINVAL;
bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
pdata->nbuttons * sizeof(struct gpio_keys_button_data),
GFP_KERNEL);
if (!bdev) {
dev_err(dev, "no memory for private data\n");
return -ENOMEM;
}
poll_dev = input_allocate_polled_device();
if (!poll_dev) {
dev_err(dev, "no memory for polled device\n");
error = -ENOMEM;
goto err_free_bdev;
}
poll_dev->private = bdev;
poll_dev->poll = gpio_keys_polled_poll;
poll_dev->poll_interval = pdata->poll_interval;
poll_dev->open = gpio_keys_polled_open;
poll_dev->close = gpio_keys_polled_close;
input = poll_dev->input;
input->evbit[0] = BIT(EV_KEY);
input->name = pdev->name;
input->phys = DRV_NAME"/input0";
input->dev.parent = &pdev->dev;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_keys_button_data *bdata = &bdev->data[i];
unsigned int gpio = button->gpio;
unsigned int type = button->type ?: EV_KEY;
if (button->wakeup) {
dev_err(dev, DRV_NAME " does not support wakeup\n");
error = -EINVAL;
goto err_free_gpio;
}
error = gpio_request(gpio,
button->desc ? button->desc : DRV_NAME);
if (error) {
dev_err(dev, "unable to claim gpio %u, err=%d\n",
gpio, error);
goto err_free_gpio;
}
error = gpio_direction_input(gpio);
if (error) {
dev_err(dev,
"unable to set direction on gpio %u, err=%d\n",
gpio, error);
goto err_free_gpio;
}
bdata->can_sleep = gpio_cansleep(gpio);
bdata->last_state = -1;
bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
pdata->poll_interval);
input_set_capability(input, type, button->code);
}
bdev->poll_dev = poll_dev;
bdev->dev = dev;
bdev->pdata = pdata;
platform_set_drvdata(pdev, bdev);
error = input_register_polled_device(poll_dev);
if (error) {
dev_err(dev, "unable to register polled device, err=%d\n",
error);
goto err_free_gpio;
}
/* report initial state of the buttons */
for (i = 0; i < pdata->nbuttons; i++)
gpio_keys_polled_check_state(input, &pdata->buttons[i],
&bdev->data[i]);
return 0;
err_free_gpio:
while (--i >= 0)
gpio_free(pdata->buttons[i].gpio);
input_free_polled_device(poll_dev);
err_free_bdev:
kfree(bdev);
platform_set_drvdata(pdev, NULL);
return error;
}
static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
{
struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
struct gpio_keys_platform_data *pdata = bdev->pdata;
int i;
input_unregister_polled_device(bdev->poll_dev);
for (i = 0; i < pdata->nbuttons; i++)
gpio_free(pdata->buttons[i].gpio);
input_free_polled_device(bdev->poll_dev);
kfree(bdev);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver gpio_keys_polled_driver = {
.probe = gpio_keys_polled_probe,
.remove = __devexit_p(gpio_keys_polled_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
static int __init gpio_keys_polled_init(void)
{
return platform_driver_register(&gpio_keys_polled_driver);
}
static void __exit gpio_keys_polled_exit(void)
{
platform_driver_unregister(&gpio_keys_polled_driver);
}
module_init(gpio_keys_polled_init);
module_exit(gpio_keys_polled_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
MODULE_DESCRIPTION("Polled GPIO Buttons driver");
MODULE_ALIAS("platform:" DRV_NAME);

View file

@ -51,7 +51,8 @@
#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16)
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */
#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */
#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000)
/* synaptics modes query bits */ /* synaptics modes query bits */

View file

@ -1436,6 +1436,12 @@ static struct wacom_features wacom_features_0xD2 =
{ "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT };
static struct wacom_features wacom_features_0xD3 = static struct wacom_features wacom_features_0xD3 =
{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT };
static struct wacom_features wacom_features_0xD8 =
{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT };
static struct wacom_features wacom_features_0xDA =
{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT };
static struct wacom_features wacom_features_0xDB =
{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT };
#define USB_DEVICE_WACOM(prod) \ #define USB_DEVICE_WACOM(prod) \
USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \
@ -1504,6 +1510,9 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xD1) }, { USB_DEVICE_WACOM(0xD1) },
{ USB_DEVICE_WACOM(0xD2) }, { USB_DEVICE_WACOM(0xD2) },
{ USB_DEVICE_WACOM(0xD3) }, { USB_DEVICE_WACOM(0xD3) },
{ USB_DEVICE_WACOM(0xD8) },
{ USB_DEVICE_WACOM(0xDA) },
{ USB_DEVICE_WACOM(0xDB) },
{ USB_DEVICE_WACOM(0xF0) }, { USB_DEVICE_WACOM(0xF0) },
{ USB_DEVICE_WACOM(0xCC) }, { USB_DEVICE_WACOM(0xCC) },
{ USB_DEVICE_WACOM(0x90) }, { USB_DEVICE_WACOM(0x90) },

View file

@ -178,6 +178,7 @@ static const struct usb_device_id usbtouch_devices[] = {
#ifdef CONFIG_TOUCHSCREEN_USB_ITM #ifdef CONFIG_TOUCHSCREEN_USB_ITM
{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
{USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM},
#endif #endif
#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO

View file

@ -81,6 +81,8 @@ MODULE_PARM_DESC(wapf, "WAPF value");
static int wlan_status = 1; static int wlan_status = 1;
static int bluetooth_status = 1; static int bluetooth_status = 1;
static int wimax_status = -1;
static int wwan_status = -1;
module_param(wlan_status, int, 0444); module_param(wlan_status, int, 0444);
MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
@ -92,6 +94,16 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). " "(0 = disabled, 1 = enabled, -1 = don't do anything). "
"default is 1"); "default is 1");
module_param(wimax_status, int, 0444);
MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
"default is 1");
module_param(wwan_status, int, 0444);
MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
"default is 1");
/* /*
* Some events we use, same for all Asus * Some events we use, same for all Asus
*/ */
@ -114,6 +126,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
*/ */
#define WL_RSTS 0x01 /* internal Wifi */ #define WL_RSTS 0x01 /* internal Wifi */
#define BT_RSTS 0x02 /* internal Bluetooth */ #define BT_RSTS 0x02 /* internal Bluetooth */
#define WM_RSTS 0x08 /* internal wimax */
#define WW_RSTS 0x20 /* internal wwan */
/* LED */ /* LED */
#define METHOD_MLED "MLED" #define METHOD_MLED "MLED"
@ -132,6 +146,11 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
*/ */
#define METHOD_WLAN "WLED" #define METHOD_WLAN "WLED"
#define METHOD_BLUETOOTH "BLED" #define METHOD_BLUETOOTH "BLED"
/* WWAN and WIMAX */
#define METHOD_WWAN "GSMC"
#define METHOD_WIMAX "WMXC"
#define METHOD_WL_STATUS "RSTS" #define METHOD_WL_STATUS "RSTS"
/* Brightness */ /* Brightness */
@ -882,6 +901,64 @@ static ssize_t store_bluetooth(struct device *dev,
return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH); return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH);
} }
/*
* Wimax
*/
static int asus_wimax_set(struct asus_laptop *asus, int status)
{
if (write_acpi_int(asus->handle, METHOD_WIMAX, !!status)) {
pr_warning("Error setting wimax status to %d", status);
return -EIO;
}
return 0;
}
static ssize_t show_wimax(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct asus_laptop *asus = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", asus_wireless_status(asus, WM_RSTS));
}
static ssize_t store_wimax(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
struct asus_laptop *asus = dev_get_drvdata(dev);
return sysfs_acpi_set(asus, buf, count, METHOD_WIMAX);
}
/*
* Wwan
*/
static int asus_wwan_set(struct asus_laptop *asus, int status)
{
if (write_acpi_int(asus->handle, METHOD_WWAN, !!status)) {
pr_warning("Error setting wwan status to %d", status);
return -EIO;
}
return 0;
}
static ssize_t show_wwan(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct asus_laptop *asus = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", asus_wireless_status(asus, WW_RSTS));
}
static ssize_t store_wwan(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
struct asus_laptop *asus = dev_get_drvdata(dev);
return sysfs_acpi_set(asus, buf, count, METHOD_WWAN);
}
/* /*
* Display * Display
*/ */
@ -1202,6 +1279,8 @@ static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan); static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
show_bluetooth, store_bluetooth); show_bluetooth, store_bluetooth);
static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp); static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
@ -1212,6 +1291,8 @@ static struct attribute *asus_attributes[] = {
&dev_attr_infos.attr, &dev_attr_infos.attr,
&dev_attr_wlan.attr, &dev_attr_wlan.attr,
&dev_attr_bluetooth.attr, &dev_attr_bluetooth.attr,
&dev_attr_wimax.attr,
&dev_attr_wwan.attr,
&dev_attr_display.attr, &dev_attr_display.attr,
&dev_attr_ledd.attr, &dev_attr_ledd.attr,
&dev_attr_ls_level.attr, &dev_attr_ls_level.attr,
@ -1239,6 +1320,13 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
} else if (attr == &dev_attr_display.attr) { } else if (attr == &dev_attr_display.attr) {
supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL); supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
} else if (attr == &dev_attr_wimax.attr) {
supported =
!acpi_check_handle(asus->handle, METHOD_WIMAX, NULL);
} else if (attr == &dev_attr_wwan.attr) {
supported = !acpi_check_handle(asus->handle, METHOD_WWAN, NULL);
} else if (attr == &dev_attr_ledd.attr) { } else if (attr == &dev_attr_ledd.attr) {
supported = !acpi_check_handle(handle, METHOD_LEDD, NULL); supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
@ -1397,7 +1485,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
/* /*
* The HWRS method return informations about the hardware. * The HWRS method return informations about the hardware.
* 0x80 bit is for WLAN, 0x100 for Bluetooth. * 0x80 bit is for WLAN, 0x100 for Bluetooth,
* 0x40 for WWAN, 0x10 for WIMAX.
* The significance of others is yet to be found. * The significance of others is yet to be found.
*/ */
status = status =
@ -1440,6 +1529,12 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
if (wlan_status >= 0) if (wlan_status >= 0)
asus_wlan_set(asus, !!wlan_status); asus_wlan_set(asus, !!wlan_status);
if (wimax_status >= 0)
asus_wimax_set(asus, !!wimax_status);
if (wwan_status >= 0)
asus_wwan_set(asus, !!wwan_status);
/* Keyboard Backlight is on by default */ /* Keyboard Backlight is on by default */
if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
asus_kled_set(asus, 1); asus_kled_set(asus, 1);

View file

@ -298,8 +298,8 @@ static void eeepc_wmi_notify(u32 value, void *context)
kfree(obj); kfree(obj);
} }
static int store_cpufv(struct device *dev, struct device_attribute *attr, static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
int value; int value;
struct acpi_buffer input = { (acpi_size)sizeof(value), &value }; struct acpi_buffer input = { (acpi_size)sizeof(value), &value };

View file

@ -172,6 +172,8 @@ static int hp_wmi_perform_query(int query, int write, u32 *buffer,
bios_return = *((struct bios_return *)obj->buffer.pointer); bios_return = *((struct bios_return *)obj->buffer.pointer);
memcpy(buffer, &bios_return.value, sizeof(bios_return.value)); memcpy(buffer, &bios_return.value, sizeof(bios_return.value));
kfree(obj);
return 0; return 0;
} }

View file

@ -28,6 +28,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/efi.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <asm/bios_ebda.h> #include <asm/bios_ebda.h>
@ -220,32 +221,13 @@ static void rtl_teardown_sysfs(void) {
sysdev_class_unregister(&class_rtl); sysdev_class_unregister(&class_rtl);
} }
static int dmi_check_cb(const struct dmi_system_id *id)
{
RTL_DEBUG("found IBM server '%s'\n", id->ident);
return 0;
}
#define ibm_dmi_entry(NAME, TYPE) \
{ \
.ident = NAME, \
.matches = { \
DMI_MATCH(DMI_SYS_VENDOR, "IBM"), \
DMI_MATCH(DMI_PRODUCT_NAME, TYPE), \
}, \
.callback = dmi_check_cb \
}
static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = { static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = {
ibm_dmi_entry("BladeCenter LS21", "7971"), { \
ibm_dmi_entry("BladeCenter LS22", "7901"), .matches = { \
ibm_dmi_entry("BladeCenter HS21 XM", "7995"), DMI_MATCH(DMI_SYS_VENDOR, "IBM"), \
ibm_dmi_entry("BladeCenter HS22", "7870"), }, \
ibm_dmi_entry("BladeCenter HS22V", "7871"), },
ibm_dmi_entry("System x3550 M2", "7946"),
ibm_dmi_entry("System x3650 M2", "7947"),
ibm_dmi_entry("System x3550 M3", "7944"),
ibm_dmi_entry("System x3650 M3", "7945"),
{ } { }
}; };
@ -257,7 +239,7 @@ static int __init ibm_rtl_init(void) {
if (force) if (force)
pr_warning("ibm-rtl: module loaded by force\n"); pr_warning("ibm-rtl: module loaded by force\n");
/* first ensure that we are running on IBM HW */ /* first ensure that we are running on IBM HW */
else if (!dmi_check_system(ibm_rtl_dmi_table)) else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table))
return -ENODEV; return -ENODEV;
/* Get the address for the Extended BIOS Data Area */ /* Get the address for the Extended BIOS Data Area */
@ -302,7 +284,7 @@ static int __init ibm_rtl_init(void) {
RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n", RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
rtl_cmd_width, rtl_cmd_type); rtl_cmd_width, rtl_cmd_type);
addr = ioread32(&rtl_table->cmd_port_address); addr = ioread32(&rtl_table->cmd_port_address);
RTL_DEBUG("addr = %#llx\n", addr); RTL_DEBUG("addr = %#llx\n", (unsigned long long)addr);
plen = rtl_cmd_width/sizeof(char); plen = rtl_cmd_width/sizeof(char);
rtl_cmd_addr = rtl_port_map(addr, plen); rtl_cmd_addr = rtl_port_map(addr, plen);
RTL_DEBUG("rtl_cmd_addr = %#llx\n", (u64)rtl_cmd_addr); RTL_DEBUG("rtl_cmd_addr = %#llx\n", (u64)rtl_cmd_addr);

View file

@ -43,16 +43,18 @@ MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
#define dprintk(msg...) pr_debug(DRV_PFX msg) #define dprintk(msg...) pr_debug(DRV_PFX msg)
#define KEYCODE_BASE 0xD0 #define SCANCODE_BASE 0xD0
#define MSI_WMI_BRIGHTNESSUP KEYCODE_BASE #define MSI_WMI_BRIGHTNESSUP SCANCODE_BASE
#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1) #define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1)
#define MSI_WMI_VOLUMEUP (KEYCODE_BASE + 2) #define MSI_WMI_VOLUMEUP (SCANCODE_BASE + 2)
#define MSI_WMI_VOLUMEDOWN (KEYCODE_BASE + 3) #define MSI_WMI_VOLUMEDOWN (SCANCODE_BASE + 3)
#define MSI_WMI_MUTE (SCANCODE_BASE + 4)
static struct key_entry msi_wmi_keymap[] = { static struct key_entry msi_wmi_keymap[] = {
{ KE_KEY, MSI_WMI_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} }, { KE_KEY, MSI_WMI_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} },
{ KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} }, { KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} },
{ KE_KEY, MSI_WMI_VOLUMEUP, {KEY_VOLUMEUP} }, { KE_KEY, MSI_WMI_VOLUMEUP, {KEY_VOLUMEUP} },
{ KE_KEY, MSI_WMI_VOLUMEDOWN, {KEY_VOLUMEDOWN} }, { KE_KEY, MSI_WMI_VOLUMEDOWN, {KEY_VOLUMEDOWN} },
{ KE_KEY, MSI_WMI_MUTE, {KEY_MUTE} },
{ KE_END, 0} { KE_END, 0}
}; };
static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1];
@ -169,7 +171,7 @@ static void msi_wmi_notify(u32 value, void *context)
ktime_t diff; ktime_t diff;
cur = ktime_get_real(); cur = ktime_get_real();
diff = ktime_sub(cur, last_pressed[key->code - diff = ktime_sub(cur, last_pressed[key->code -
KEYCODE_BASE]); SCANCODE_BASE]);
/* Ignore event if the same event happened in a 50 ms /* Ignore event if the same event happened in a 50 ms
timeframe -> Key press may result in 10-20 GPEs */ timeframe -> Key press may result in 10-20 GPEs */
if (ktime_to_us(diff) < 1000 * 50) { if (ktime_to_us(diff) < 1000 * 50) {
@ -178,7 +180,7 @@ static void msi_wmi_notify(u32 value, void *context)
key->code, ktime_to_us(diff)); key->code, ktime_to_us(diff));
return; return;
} }
last_pressed[key->code - KEYCODE_BASE] = cur; last_pressed[key->code - SCANCODE_BASE] = cur;
if (key->type == KE_KEY && if (key->type == KE_KEY &&
/* Brightness is served via acpi video driver */ /* Brightness is served via acpi video driver */

View file

@ -8497,7 +8497,6 @@ static void ibm_exit(struct ibm_struct *ibm)
ibm->acpi->type, ibm->acpi->type,
dispatch_acpi_notify); dispatch_acpi_notify);
ibm->flags.acpi_notify_installed = 0; ibm->flags.acpi_notify_installed = 0;
ibm->flags.acpi_notify_installed = 0;
} }
if (ibm->flags.proc_created) { if (ibm->flags.proc_created) {

View file

@ -135,6 +135,7 @@ static const struct key_entry toshiba_acpi_keymap[] __initconst = {
{ KE_KEY, 0x141, { KEY_BRIGHTNESSUP } }, { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
{ KE_KEY, 0x142, { KEY_WLAN } }, { KE_KEY, 0x142, { KEY_WLAN } },
{ KE_KEY, 0x143, { KEY_PROG1 } }, { KE_KEY, 0x143, { KEY_PROG1 } },
{ KE_KEY, 0x17f, { KEY_FN } },
{ KE_KEY, 0xb05, { KEY_PROG2 } }, { KE_KEY, 0xb05, { KEY_PROG2 } },
{ KE_KEY, 0xb06, { KEY_WWW } }, { KE_KEY, 0xb06, { KEY_WWW } },
{ KE_KEY, 0xb07, { KEY_MAIL } }, { KE_KEY, 0xb07, { KEY_MAIL } },

View file

@ -755,7 +755,7 @@ static bool guid_already_parsed(const char *guid_string)
struct wmi_block *wblock; struct wmi_block *wblock;
list_for_each_entry(wblock, &wmi_block_list, list) list_for_each_entry(wblock, &wmi_block_list, list)
if (strncmp(wblock->gblock.guid, guid_string, 16) == 0) if (memcmp(wblock->gblock.guid, guid_string, 16) == 0)
return true; return true;
return false; return false;

View file

@ -635,7 +635,7 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
init_subchannel_id(&mchk_schid); init_subchannel_id(&mchk_schid);
mchk_schid.sch_no = crw0->rsid; mchk_schid.sch_no = crw0->rsid;
if (crw1) if (crw1)
mchk_schid.ssid = (crw1->rsid >> 8) & 3; mchk_schid.ssid = (crw1->rsid >> 4) & 3;
/* /*
* Since we are always presented with IPI in the CRW, we have to * Since we are always presented with IPI in the CRW, we have to

View file

@ -980,19 +980,11 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp,
} }
} }
static DEFINE_MUTEX(autofs4_ioctl_mutex);
static long autofs4_root_ioctl(struct file *filp, static long autofs4_root_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
long ret;
struct inode *inode = filp->f_dentry->d_inode; struct inode *inode = filp->f_dentry->d_inode;
return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
mutex_lock(&autofs4_ioctl_mutex);
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
mutex_unlock(&autofs4_ioctl_mutex);
return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
@ -1002,13 +994,11 @@ static long autofs4_root_compat_ioctl(struct file *filp,
struct inode *inode = filp->f_path.dentry->d_inode; struct inode *inode = filp->f_path.dentry->d_inode;
int ret; int ret;
mutex_lock(&autofs4_ioctl_mutex);
if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
else else
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
(unsigned long)compat_ptr(arg)); (unsigned long)compat_ptr(arg));
mutex_unlock(&autofs4_ioctl_mutex);
return ret; return ret;
} }

View file

@ -287,6 +287,8 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_EXECBUF2 9 #define I915_PARAM_HAS_EXECBUF2 9
#define I915_PARAM_HAS_BSD 10 #define I915_PARAM_HAS_BSD 10
#define I915_PARAM_HAS_BLT 11 #define I915_PARAM_HAS_BLT 11
#define I915_PARAM_HAS_RELAXED_FENCING 12
#define I915_PARAM_HAS_COHERENT_RINGS 13
typedef struct drm_i915_getparam { typedef struct drm_i915_getparam {
int param; int param;

View file

@ -16,6 +16,8 @@ struct gpio_keys_button {
struct gpio_keys_platform_data { struct gpio_keys_platform_data {
struct gpio_keys_button *buttons; struct gpio_keys_button *buttons;
int nbuttons; int nbuttons;
unsigned int poll_interval; /* polling interval in msecs -
for polling driver only */
unsigned int rep:1; /* enable input subsystem auto repeat */ unsigned int rep:1; /* enable input subsystem auto repeat */
int (*enable)(struct device *dev); int (*enable)(struct device *dev);
void (*disable)(struct device *dev); void (*disable)(struct device *dev);

View file

@ -47,6 +47,25 @@ struct input_id {
__u16 version; __u16 version;
}; };
/**
* struct input_absinfo - used by EVIOCGABS/EVIOCSABS ioctls
* @value: latest reported value for the axis.
* @minimum: specifies minimum value for the axis.
* @maximum: specifies maximum value for the axis.
* @fuzz: specifies fuzz value that is used to filter noise from
* the event stream.
* @flat: values that are within this value will be discarded by
* joydev interface and reported as 0 instead.
* @resolution: specifies resolution for the values reported for
* the axis.
*
* Note that input core does not clamp reported values to the
* [minimum, maximum] limits, such task is left to userspace.
*
* Resolution for main axes (ABS_X, ABS_Y, ABS_Z) is reported in
* units per millimeter (units/mm), resolution for rotational axes
* (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian.
*/
struct input_absinfo { struct input_absinfo {
__s32 value; __s32 value;
__s32 minimum; __s32 minimum;
@ -624,6 +643,10 @@ struct input_keymap_entry {
#define KEY_CAMERA_FOCUS 0x210 #define KEY_CAMERA_FOCUS 0x210
#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */ #define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */
#define KEY_TOUCHPAD_TOGGLE 0x212 /* Request switch touchpad on or off */
#define KEY_TOUCHPAD_ON 0x213
#define KEY_TOUCHPAD_OFF 0x214
#define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY 0x2c0
#define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0
#define BTN_TRIGGER_HAPPY2 0x2c1 #define BTN_TRIGGER_HAPPY2 0x2c1
@ -1130,7 +1153,7 @@ struct input_mt_slot {
* of tracked contacts * of tracked contacts
* @mtsize: number of MT slots the device uses * @mtsize: number of MT slots the device uses
* @slot: MT slot currently being transmitted * @slot: MT slot currently being transmitted
* @absinfo: array of &struct absinfo elements holding information * @absinfo: array of &struct input_absinfo elements holding information
* about absolute axes (current value, min, max, flat, fuzz, * about absolute axes (current value, min, max, flat, fuzz,
* resolution) * resolution)
* @key: reflects current state of device's keys/buttons * @key: reflects current state of device's keys/buttons

View file

@ -900,6 +900,7 @@ struct perf_cpu_context {
int exclusive; int exclusive;
struct list_head rotation_list; struct list_head rotation_list;
int jiffies_interval; int jiffies_interval;
struct pmu *active_pmu;
}; };
struct perf_output_handle { struct perf_output_handle {

View file

@ -214,7 +214,7 @@ static int irq_spurious_proc_show(struct seq_file *m, void *v)
static int irq_spurious_proc_open(struct inode *inode, struct file *file) static int irq_spurious_proc_open(struct inode *inode, struct file *file)
{ {
return single_open(file, irq_spurious_proc_show, NULL); return single_open(file, irq_spurious_proc_show, PDE(inode)->data);
} }
static const struct file_operations irq_spurious_proc_fops = { static const struct file_operations irq_spurious_proc_fops = {

View file

@ -3922,6 +3922,8 @@ static void perf_event_task_event(struct perf_task_event *task_event)
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(pmu, &pmus, entry) { list_for_each_entry_rcu(pmu, &pmus, entry) {
cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
if (cpuctx->active_pmu != pmu)
goto next;
perf_event_task_ctx(&cpuctx->ctx, task_event); perf_event_task_ctx(&cpuctx->ctx, task_event);
ctx = task_event->task_ctx; ctx = task_event->task_ctx;
@ -4066,6 +4068,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(pmu, &pmus, entry) { list_for_each_entry_rcu(pmu, &pmus, entry) {
cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
if (cpuctx->active_pmu != pmu)
goto next;
perf_event_comm_ctx(&cpuctx->ctx, comm_event); perf_event_comm_ctx(&cpuctx->ctx, comm_event);
ctxn = pmu->task_ctx_nr; ctxn = pmu->task_ctx_nr;
@ -4260,6 +4264,8 @@ got_name:
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(pmu, &pmus, entry) { list_for_each_entry_rcu(pmu, &pmus, entry) {
cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
if (cpuctx->active_pmu != pmu)
goto next;
perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
vma->vm_flags & VM_EXEC); vma->vm_flags & VM_EXEC);
@ -4841,7 +4847,7 @@ static int perf_swevent_init(struct perf_event *event)
break; break;
} }
if (event_id > PERF_COUNT_SW_MAX) if (event_id >= PERF_COUNT_SW_MAX)
return -ENOENT; return -ENOENT;
if (!event->parent) { if (!event->parent) {
@ -5266,20 +5272,36 @@ static void *find_pmu_context(int ctxn)
return NULL; return NULL;
} }
static void free_pmu_context(void * __percpu cpu_context) static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)
{ {
struct pmu *pmu; int cpu;
for_each_possible_cpu(cpu) {
struct perf_cpu_context *cpuctx;
cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
if (cpuctx->active_pmu == old_pmu)
cpuctx->active_pmu = pmu;
}
}
static void free_pmu_context(struct pmu *pmu)
{
struct pmu *i;
mutex_lock(&pmus_lock); mutex_lock(&pmus_lock);
/* /*
* Like a real lame refcount. * Like a real lame refcount.
*/ */
list_for_each_entry(pmu, &pmus, entry) { list_for_each_entry(i, &pmus, entry) {
if (pmu->pmu_cpu_context == cpu_context) if (i->pmu_cpu_context == pmu->pmu_cpu_context) {
update_pmu_context(i, pmu);
goto out; goto out;
}
} }
free_percpu(cpu_context); free_percpu(pmu->pmu_cpu_context);
out: out:
mutex_unlock(&pmus_lock); mutex_unlock(&pmus_lock);
} }
@ -5311,6 +5333,7 @@ int perf_pmu_register(struct pmu *pmu)
cpuctx->ctx.pmu = pmu; cpuctx->ctx.pmu = pmu;
cpuctx->jiffies_interval = 1; cpuctx->jiffies_interval = 1;
INIT_LIST_HEAD(&cpuctx->rotation_list); INIT_LIST_HEAD(&cpuctx->rotation_list);
cpuctx->active_pmu = pmu;
} }
got_cpu_context: got_cpu_context:
@ -5362,7 +5385,7 @@ void perf_pmu_unregister(struct pmu *pmu)
synchronize_rcu(); synchronize_rcu();
free_percpu(pmu->pmu_disable_count); free_percpu(pmu->pmu_disable_count);
free_pmu_context(pmu->pmu_cpu_context); free_pmu_context(pmu);
} }
struct pmu *perf_init_event(struct perf_event *event) struct pmu *perf_init_event(struct perf_event *event)

View file

@ -1082,13 +1082,15 @@ void printk_tick(void)
int printk_needs_cpu(int cpu) int printk_needs_cpu(int cpu)
{ {
if (unlikely(cpu_is_offline(cpu)))
printk_tick();
return per_cpu(printk_pending, cpu); return per_cpu(printk_pending, cpu);
} }
void wake_up_klogd(void) void wake_up_klogd(void)
{ {
if (waitqueue_active(&log_wait)) if (waitqueue_active(&log_wait))
__raw_get_cpu_var(printk_pending) = 1; this_cpu_write(printk_pending, 1);
} }
/** /**

View file

@ -2338,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,
return count; return count;
} }
static loff_t tracing_seek(struct file *file, loff_t offset, int origin)
{
if (file->f_mode & FMODE_READ)
return seq_lseek(file, offset, origin);
else
return 0;
}
static const struct file_operations tracing_fops = { static const struct file_operations tracing_fops = {
.open = tracing_open, .open = tracing_open,
.read = seq_read, .read = seq_read,
.write = tracing_write_stub, .write = tracing_write_stub,
.llseek = seq_lseek, .llseek = tracing_seek,
.release = tracing_release, .release = tracing_release,
}; };

View file

@ -119,7 +119,7 @@ static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type) static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
{ {
rp->r_info = ELF_R_INFO(sym, type); rp->r_info = _w(ELF_R_INFO(sym, type));
} }
static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;

View file

@ -202,7 +202,7 @@ static void sig_atexit(void)
if (child_pid > 0) if (child_pid > 0)
kill(child_pid, SIGTERM); kill(child_pid, SIGTERM);
if (signr == -1) if (signr == -1 || signr == SIGUSR1)
return; return;
signal(signr, SIG_DFL); signal(signr, SIG_DFL);
@ -535,6 +535,7 @@ static int __cmd_record(int argc, const char **argv)
atexit(sig_atexit); atexit(sig_atexit);
signal(SIGCHLD, sig_handler); signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);
signal(SIGUSR1, sig_handler);
if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
perror("failed to create pipes"); perror("failed to create pipes");
@ -629,6 +630,7 @@ static int __cmd_record(int argc, const char **argv)
execvp(argv[0], (char **)argv); execvp(argv[0], (char **)argv);
perror(argv[0]); perror(argv[0]);
kill(getppid(), SIGUSR1);
exit(-1); exit(-1);
} }
@ -789,7 +791,7 @@ static int __cmd_record(int argc, const char **argv)
} }
} }
if (quiet) if (quiet || signr == SIGUSR1)
return 0; return 0;
fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);

View file

@ -971,11 +971,16 @@ perf_header__find_attr(u64 id, struct perf_header *header)
/* /*
* We set id to -1 if the data file doesn't contain sample * We set id to -1 if the data file doesn't contain sample
* ids. Check for this and avoid walking through the entire * ids. This can happen when the data file contains one type
* list of ids which may be large. * of event and in that case, the header can still store the
* event attribute information. Check for this and avoid
* walking through the entire list of ids which may be large.
*/ */
if (id == -1ULL) if (id == -1ULL) {
if (header->attrs > 0)
return &header->attr[0]->attr;
return NULL; return NULL;
}
for (i = 0; i < header->attrs; i++) { for (i = 0; i < header->attrs; i++) {
struct perf_header_attr *attr = header->attr[i]; struct perf_header_attr *attr = header->attr[i];

View file

@ -532,7 +532,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
struct machine *machine = kmaps->machine; struct machine *machine = kmaps->machine;
struct map *curr_map = map; struct map *curr_map = map;
struct symbol *pos; struct symbol *pos;
int count = 0; int count = 0, moved = 0;
struct rb_root *root = &self->symbols[map->type]; struct rb_root *root = &self->symbols[map->type];
struct rb_node *next = rb_first(root); struct rb_node *next = rb_first(root);
int kernel_range = 0; int kernel_range = 0;
@ -590,6 +590,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
char dso_name[PATH_MAX]; char dso_name[PATH_MAX];
struct dso *dso; struct dso *dso;
if (count == 0) {
curr_map = map;
goto filter_symbol;
}
if (self->kernel == DSO_TYPE_GUEST_KERNEL) if (self->kernel == DSO_TYPE_GUEST_KERNEL)
snprintf(dso_name, sizeof(dso_name), snprintf(dso_name, sizeof(dso_name),
"[guest.kernel].%d", "[guest.kernel].%d",
@ -615,7 +620,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
map_groups__insert(kmaps, curr_map); map_groups__insert(kmaps, curr_map);
++kernel_range; ++kernel_range;
} }
filter_symbol:
if (filter && filter(curr_map, pos)) { if (filter && filter(curr_map, pos)) {
discard_symbol: rb_erase(&pos->rb_node, root); discard_symbol: rb_erase(&pos->rb_node, root);
symbol__delete(pos); symbol__delete(pos);
@ -623,8 +628,9 @@ discard_symbol: rb_erase(&pos->rb_node, root);
if (curr_map != map) { if (curr_map != map) {
rb_erase(&pos->rb_node, root); rb_erase(&pos->rb_node, root);
symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
} ++moved;
count++; } else
++count;
} }
} }
@ -634,7 +640,7 @@ discard_symbol: rb_erase(&pos->rb_node, root);
dso__set_loaded(curr_map->dso, curr_map->type); dso__set_loaded(curr_map->dso, curr_map->type);
} }
return count; return count + moved;
} }
int dso__load_kallsyms(struct dso *self, const char *filename, int dso__load_kallsyms(struct dso *self, const char *filename,
@ -2130,14 +2136,55 @@ static struct dso *machine__create_kernel(struct machine *self)
return kernel; return kernel;
} }
struct process_args {
u64 start;
};
static int symbol__in_kernel(void *arg, const char *name,
char type __used, u64 start)
{
struct process_args *args = arg;
if (strchr(name, '['))
return 0;
args->start = start;
return 1;
}
/* Figure out the start address of kernel map from /proc/kallsyms */
static u64 machine__get_kernel_start_addr(struct machine *machine)
{
const char *filename;
char path[PATH_MAX];
struct process_args args;
if (machine__is_host(machine)) {
filename = "/proc/kallsyms";
} else {
if (machine__is_default_guest(machine))
filename = (char *)symbol_conf.default_guest_kallsyms;
else {
sprintf(path, "%s/proc/kallsyms", machine->root_dir);
filename = path;
}
}
if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
return 0;
return args.start;
}
int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
{ {
enum map_type type; enum map_type type;
u64 start = machine__get_kernel_start_addr(self);
for (type = 0; type < MAP__NR_TYPES; ++type) { for (type = 0; type < MAP__NR_TYPES; ++type) {
struct kmap *kmap; struct kmap *kmap;
self->vmlinux_maps[type] = map__new2(0, kernel, type); self->vmlinux_maps[type] = map__new2(start, kernel, type);
if (self->vmlinux_maps[type] == NULL) if (self->vmlinux_maps[type] == NULL)
return -1; return -1;