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:
commit
006b20fe4c
@ -47,6 +47,20 @@ Date: January 2007
|
||||
KernelVersion: 2.6.20
|
||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||
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.
|
||||
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.
|
||||
|
10
Documentation/ABI/testing/sysfs-platform-eeepc-wmi
Normal file
10
Documentation/ABI/testing/sysfs-platform-eeepc-wmi
Normal 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
|
@ -16,7 +16,7 @@ config CPU_S3C2412
|
||||
config CPU_S3C2412_ONLY
|
||||
bool
|
||||
depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
|
||||
!CPU_2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
|
||||
!CPU_S3C2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
|
||||
!CPU_S3C2443 && CPU_S3C2412
|
||||
default y if CPU_S3C2412
|
||||
|
||||
|
@ -35,9 +35,12 @@ menu "S3C2416 Machines"
|
||||
config MACH_SMDK2416
|
||||
bool "SMDK2416"
|
||||
select CPU_S3C2416
|
||||
select MACH_SMDK
|
||||
select S3C_DEV_FB
|
||||
select S3C_DEV_HSMMC
|
||||
select S3C_DEV_HSMMC1
|
||||
select S3C_DEV_NAND
|
||||
select S3C_DEV_USB_HOST
|
||||
select S3C2416_PM if PM
|
||||
help
|
||||
Say Y here if you are using an SMDK2416
|
||||
|
@ -18,6 +18,7 @@ config CPU_S3C2440
|
||||
config CPU_S3C2442
|
||||
bool
|
||||
select CPU_ARM920T
|
||||
select S3C_GPIO_PULL_DOWN
|
||||
select S3C2410_CLOCK
|
||||
select S3C2410_GPIO
|
||||
select S3C2410_PM if PM
|
||||
@ -178,6 +179,9 @@ config MACH_MINI2440
|
||||
bool "MINI2440 development board"
|
||||
select CPU_S3C2440
|
||||
select EEPROM_AT24
|
||||
select NEW_LEDS
|
||||
select LEDS_CLASS
|
||||
select LEDS_TRIGGER
|
||||
select LEDS_TRIGGER_BACKLIGHT
|
||||
select S3C_DEV_NAND
|
||||
select S3C_DEV_USB_HOST
|
||||
|
@ -46,9 +46,6 @@ int __init s3c2440_init(void)
|
||||
{
|
||||
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 */
|
||||
|
||||
s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
|
||||
@ -58,3 +55,11 @@ int __init s3c2440_init(void)
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
@ -43,6 +44,11 @@
|
||||
|
||||
#include <plat/clock.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 */
|
||||
|
||||
@ -163,3 +169,11 @@ int __init s3c2442_init(void)
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
config CPU_S3C2443
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
select CPU_ARM920T
|
||||
select S3C2443_DMA if S3C2410_DMA
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
select SAMSUNG_CLKSRC
|
||||
|
@ -88,7 +88,7 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
{
|
||||
.idcode = 0x32440000,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c244x_map_io,
|
||||
.map_io = s3c2440_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2440_init,
|
||||
@ -97,7 +97,7 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
{
|
||||
.idcode = 0x32440001,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c244x_map_io,
|
||||
.map_io = s3c2440_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2440_init,
|
||||
@ -106,7 +106,7 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
{
|
||||
.idcode = 0x32440aaa,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c244x_map_io,
|
||||
.map_io = s3c2442_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2442_init,
|
||||
@ -115,7 +115,7 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
{
|
||||
.idcode = 0x32440aab,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c244x_map_io,
|
||||
.map_io = s3c2442_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2442_init,
|
||||
|
@ -82,8 +82,6 @@ static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
|
||||
struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
|
||||
.set_config = s3c_gpio_setcfg_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[] = {
|
||||
|
@ -21,17 +21,22 @@ extern void s3c244x_init_clocks(int xtal);
|
||||
#else
|
||||
#define s3c244x_init_clocks NULL
|
||||
#define s3c244x_init_uarts NULL
|
||||
#define s3c244x_map_io NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
extern int s3c2440_init(void);
|
||||
|
||||
extern void s3c2440_map_io(void);
|
||||
#else
|
||||
#define s3c2440_init NULL
|
||||
#define s3c2440_map_io NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2442
|
||||
extern int s3c2442_init(void);
|
||||
|
||||
extern void s3c2442_map_io(void);
|
||||
#else
|
||||
#define s3c2442_init NULL
|
||||
#define s3c2442_map_io NULL
|
||||
#endif
|
||||
|
@ -280,18 +280,17 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_S3C_GPIO_PULL_UP
|
||||
int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
|
||||
unsigned int off, s3c_gpio_pull_t pull)
|
||||
#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
|
||||
static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
|
||||
unsigned int off, s3c_gpio_pull_t pull,
|
||||
s3c_gpio_pull_t updown)
|
||||
{
|
||||
void __iomem *reg = chip->base + 0x08;
|
||||
u32 pup = __raw_readl(reg);
|
||||
|
||||
pup = __raw_readl(reg);
|
||||
|
||||
if (pup == S3C_GPIO_PULL_UP)
|
||||
if (pull == updown)
|
||||
pup &= ~(1 << off);
|
||||
else if (pup == S3C_GPIO_PULL_NONE)
|
||||
else if (pull == S3C_GPIO_PULL_NONE)
|
||||
pup |= (1 << off);
|
||||
else
|
||||
return -EINVAL;
|
||||
@ -300,17 +299,45 @@ int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
|
||||
unsigned int off)
|
||||
static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
|
||||
unsigned int off, s3c_gpio_pull_t updown)
|
||||
{
|
||||
void __iomem *reg = chip->base + 0x08;
|
||||
u32 pup = __raw_readl(reg);
|
||||
|
||||
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 */
|
||||
|
||||
#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
|
||||
s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
|
||||
{
|
||||
|
@ -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,
|
||||
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.
|
||||
* @chip: The gpio chip that is being configured.
|
||||
|
@ -73,7 +73,8 @@ void gdbstub_io_init(void)
|
||||
GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -87,7 +87,8 @@ void __init gdbstub_io_init(void)
|
||||
tmp = *gdbstub_port->_control;
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1194,7 +1194,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
|
||||
|
||||
asm volatile("mov mdr,%0" : "=d"(mdr));
|
||||
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();
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/s390_ext.h>
|
||||
#include <asm/timer.h>
|
||||
@ -566,6 +567,23 @@ void init_cpu_vtimer(void)
|
||||
__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)
|
||||
{
|
||||
/* request the cpu timer external interrupt */
|
||||
@ -574,5 +592,6 @@ void __init vtime_init(void)
|
||||
|
||||
/* Enable cpu timer interrupts on the boot cpu. */
|
||||
init_cpu_vtimer();
|
||||
cpu_notifier(s390_nohz_notify, 0);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
|
||||
void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
|
||||
struct pvclock_vcpu_time_info *vcpu,
|
||||
struct timespec *ts);
|
||||
void pvclock_resume(void);
|
||||
|
||||
/*
|
||||
* Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
|
||||
|
@ -83,6 +83,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
|
||||
|
||||
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)
|
||||
{
|
||||
struct pvclock_shadow_time shadow;
|
||||
|
@ -426,6 +426,8 @@ void xen_timer_resume(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
pvclock_resume();
|
||||
|
||||
if (xen_clockevent != &xen_vcpuop_clockevent)
|
||||
return;
|
||||
|
||||
|
@ -812,8 +812,10 @@ static int intel_fake_agp_fetch_size(void)
|
||||
|
||||
static void i830_cleanup(void)
|
||||
{
|
||||
kunmap(intel_private.i8xx_page);
|
||||
intel_private.i8xx_flush_page = NULL;
|
||||
if (intel_private.i8xx_flush_page) {
|
||||
kunmap(intel_private.i8xx_flush_page);
|
||||
intel_private.i8xx_flush_page = NULL;
|
||||
}
|
||||
|
||||
__free_page(intel_private.i8xx_page);
|
||||
intel_private.i8xx_page = NULL;
|
||||
|
@ -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) {
|
||||
if (!drm_helper_encoder_in_use(encoder)) {
|
||||
if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) {
|
||||
drm_encoder_disable(encoder);
|
||||
/* disconnector encoder from any connector */
|
||||
encoder->crtc = NULL;
|
||||
|
@ -585,10 +585,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
|
||||
struct timeval now;
|
||||
unsigned long flags;
|
||||
unsigned int seq;
|
||||
int ret;
|
||||
|
||||
e = kzalloc(sizeof *e, GFP_KERNEL);
|
||||
if (e == NULL)
|
||||
return -ENOMEM;
|
||||
if (e == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
e->pipe = pipe;
|
||||
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);
|
||||
|
||||
if (file_priv->event_space < sizeof e->event) {
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
kfree(e);
|
||||
return -ENOMEM;
|
||||
ret = -EBUSY;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unlock:
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
kfree(e);
|
||||
err_put:
|
||||
drm_vblank_put(dev, e->pipe);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_HAS_BLT:
|
||||
value = HAS_BLT(dev);
|
||||
break;
|
||||
case I915_PARAM_HAS_COHERENT_RINGS:
|
||||
value = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
|
||||
param->param);
|
||||
|
@ -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
|
||||
* 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,
|
||||
obj_priv->ring,
|
||||
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.
|
||||
* Otherwise this only updates on a delayed timer or when irqs
|
||||
|
@ -3033,6 +3033,7 @@
|
||||
#define TRANS_DP_10BPC (1<<9)
|
||||
#define TRANS_DP_6BPC (2<<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_LOW 0
|
||||
#define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3)
|
||||
|
@ -190,37 +190,6 @@ out:
|
||||
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)
|
||||
{
|
||||
acpi_handle dhandle, intel_handle;
|
||||
@ -276,11 +245,8 @@ void intel_register_dsm_handler(void)
|
||||
{
|
||||
if (!intel_dsm_detect())
|
||||
return;
|
||||
|
||||
vga_switcheroo_register_handler(&intel_dsm_handler);
|
||||
}
|
||||
|
||||
void intel_unregister_dsm_handler(void)
|
||||
{
|
||||
vga_switcheroo_unregister_handler();
|
||||
}
|
||||
|
@ -2120,9 +2120,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
|
||||
reg = TRANS_DP_CTL(pipe);
|
||||
temp = I915_READ(reg);
|
||||
temp &= ~(TRANS_DP_PORT_SEL_MASK |
|
||||
TRANS_DP_SYNC_MASK);
|
||||
TRANS_DP_SYNC_MASK |
|
||||
TRANS_DP_BPC_MASK);
|
||||
temp |= (TRANS_DP_OUTPUT_ENABLE |
|
||||
TRANS_DP_ENH_FRAMING);
|
||||
temp |= TRANS_DP_8BPC;
|
||||
|
||||
if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
|
||||
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
|
||||
ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
|
||||
int link_clock, struct fdi_m_n *m_n)
|
||||
{
|
||||
u64 temp;
|
||||
|
||||
m_n->tu = 64; /* default size */
|
||||
|
||||
temp = (u64) DATA_N * pixel_clock;
|
||||
temp = div_u64(temp, link_clock);
|
||||
m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes);
|
||||
m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */
|
||||
m_n->gmch_n = DATA_N;
|
||||
/* BUG_ON(pixel_clock > INT_MAX / 36); */
|
||||
m_n->gmch_m = bits_per_pixel * pixel_clock;
|
||||
m_n->gmch_n = link_clock * nlanes * 8;
|
||||
fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
|
||||
|
||||
temp = (u64) LINK_N * pixel_clock;
|
||||
m_n->link_m = div_u64(temp, link_clock);
|
||||
m_n->link_n = LINK_N;
|
||||
m_n->link_m = pixel_clock;
|
||||
m_n->link_n = link_clock;
|
||||
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 */
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
|
||||
int lane = 0, link_bw, bpp;
|
||||
/* CPU eDP doesn't require FDI link, so just set DP M/N
|
||||
according to current link config */
|
||||
@ -3799,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -5236,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
|
||||
.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)
|
||||
{
|
||||
@ -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,
|
||||
(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,
|
||||
|
@ -1376,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t DP = intel_dp->DP;
|
||||
|
||||
if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (is_edp(intel_dp)) {
|
||||
@ -1398,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp)
|
||||
|
||||
if (is_edp(intel_dp))
|
||||
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);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
|
||||
/**
|
||||
* 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_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;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
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);
|
||||
I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
|
||||
|
||||
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_control = 0;
|
||||
if (intel_lvds->pfit_dirty) {
|
||||
/*
|
||||
* Enable automatic panel scaling so that non-native modes
|
||||
* fill the screen. The panel fitter should only be
|
||||
* adjusted whilst the pipe is disabled, 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");
|
||||
} else {
|
||||
I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
|
||||
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -110,9 +145,9 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
|
||||
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON)
|
||||
intel_lvds_set_power(intel_lvds, true);
|
||||
intel_lvds_enable(intel_lvds);
|
||||
else
|
||||
intel_lvds_set_power(intel_lvds, false);
|
||||
intel_lvds_disable(intel_lvds);
|
||||
|
||||
/* 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
|
||||
* 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,
|
||||
struct drm_display_mode *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
|
||||
* intel_crtc_mode_set since it has a large impact on the DPLL
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,23 +156,25 @@ static int init_ring_common(struct drm_device *dev,
|
||||
|
||||
/* G45 ring initialization fails to reset head to zero */
|
||||
if (head != 0) {
|
||||
DRM_ERROR("%s head not reset to zero "
|
||||
"ctl %08x head %08x tail %08x start %08x\n",
|
||||
ring->name,
|
||||
I915_READ_CTL(ring),
|
||||
I915_READ_HEAD(ring),
|
||||
I915_READ_TAIL(ring),
|
||||
I915_READ_START(ring));
|
||||
DRM_DEBUG_KMS("%s head not reset to zero "
|
||||
"ctl %08x head %08x tail %08x start %08x\n",
|
||||
ring->name,
|
||||
I915_READ_CTL(ring),
|
||||
I915_READ_HEAD(ring),
|
||||
I915_READ_TAIL(ring),
|
||||
I915_READ_START(ring));
|
||||
|
||||
I915_WRITE_HEAD(ring, 0);
|
||||
|
||||
DRM_ERROR("%s head forced to zero "
|
||||
"ctl %08x head %08x tail %08x start %08x\n",
|
||||
ring->name,
|
||||
I915_READ_CTL(ring),
|
||||
I915_READ_HEAD(ring),
|
||||
I915_READ_TAIL(ring),
|
||||
I915_READ_START(ring));
|
||||
if (I915_READ_HEAD(ring) & HEAD_ADDR) {
|
||||
DRM_ERROR("failed to set %s head to zero "
|
||||
"ctl %08x head %08x tail %08x start %08x\n",
|
||||
ring->name,
|
||||
I915_READ_CTL(ring),
|
||||
I915_READ_HEAD(ring),
|
||||
I915_READ_TAIL(ring),
|
||||
I915_READ_START(ring));
|
||||
}
|
||||
}
|
||||
|
||||
I915_WRITE_CTL(ring,
|
||||
|
@ -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);
|
||||
} else {
|
||||
u64 base = 0;
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
|
||||
base <<= 24;
|
||||
}
|
||||
radeon_vram_location(rdev, &rdev->mc, base);
|
||||
rdev->mc.gtt_base_align = 0;
|
||||
radeon_gtt_location(rdev, mc);
|
||||
|
@ -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->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->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_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);
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
|
||||
u32 c = 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.busy_placement = rbo->placements;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/* 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:
|
||||
bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
|
||||
if (bo == NULL)
|
||||
|
@ -245,6 +245,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
|
||||
goto err_free_tgfx;
|
||||
}
|
||||
|
||||
parport_put_port(pp);
|
||||
return tgfx;
|
||||
|
||||
err_free_dev:
|
||||
|
@ -179,6 +179,22 @@ config KEYBOARD_GPIO
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
tristate "TCA6416 Keypad Support"
|
||||
depends on I2C
|
||||
|
@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
|
||||
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
|
||||
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.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_HIL) += hil_kbd.o
|
||||
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
|
||||
|
261
drivers/input/keyboard/gpio_keys_polled.c
Normal file
261
drivers/input/keyboard/gpio_keys_polled.c
Normal 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);
|
@ -51,7 +51,8 @@
|
||||
#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
|
||||
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
|
||||
#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)
|
||||
|
||||
/* synaptics modes query bits */
|
||||
|
@ -1436,6 +1436,12 @@ static struct wacom_features wacom_features_0xD2 =
|
||||
{ "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT };
|
||||
static struct wacom_features wacom_features_0xD3 =
|
||||
{ "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) \
|
||||
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(0xD2) },
|
||||
{ USB_DEVICE_WACOM(0xD3) },
|
||||
{ USB_DEVICE_WACOM(0xD8) },
|
||||
{ USB_DEVICE_WACOM(0xDA) },
|
||||
{ USB_DEVICE_WACOM(0xDB) },
|
||||
{ USB_DEVICE_WACOM(0xF0) },
|
||||
{ USB_DEVICE_WACOM(0xCC) },
|
||||
{ USB_DEVICE_WACOM(0x90) },
|
||||
|
@ -178,6 +178,7 @@ static const struct usb_device_id usbtouch_devices[] = {
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_USB_ITM
|
||||
{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
|
||||
{USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM},
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
|
||||
|
@ -81,6 +81,8 @@ MODULE_PARM_DESC(wapf, "WAPF value");
|
||||
|
||||
static int wlan_status = 1;
|
||||
static int bluetooth_status = 1;
|
||||
static int wimax_status = -1;
|
||||
static int wwan_status = -1;
|
||||
|
||||
module_param(wlan_status, int, 0444);
|
||||
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). "
|
||||
"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
|
||||
*/
|
||||
@ -114,6 +126,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
|
||||
*/
|
||||
#define WL_RSTS 0x01 /* internal Wifi */
|
||||
#define BT_RSTS 0x02 /* internal Bluetooth */
|
||||
#define WM_RSTS 0x08 /* internal wimax */
|
||||
#define WW_RSTS 0x20 /* internal wwan */
|
||||
|
||||
/* LED */
|
||||
#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_BLUETOOTH "BLED"
|
||||
|
||||
/* WWAN and WIMAX */
|
||||
#define METHOD_WWAN "GSMC"
|
||||
#define METHOD_WIMAX "WMXC"
|
||||
|
||||
#define METHOD_WL_STATUS "RSTS"
|
||||
|
||||
/* Brightness */
|
||||
@ -882,6 +901,64 @@ static ssize_t store_bluetooth(struct device *dev,
|
||||
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
|
||||
*/
|
||||
@ -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(bluetooth, S_IRUGO | S_IWUSR,
|
||||
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(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
|
||||
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_wlan.attr,
|
||||
&dev_attr_bluetooth.attr,
|
||||
&dev_attr_wimax.attr,
|
||||
&dev_attr_wwan.attr,
|
||||
&dev_attr_display.attr,
|
||||
&dev_attr_ledd.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) {
|
||||
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) {
|
||||
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.
|
||||
* 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.
|
||||
*/
|
||||
status =
|
||||
@ -1440,6 +1529,12 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
|
||||
if (wlan_status >= 0)
|
||||
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 */
|
||||
if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
|
||||
asus_kled_set(asus, 1);
|
||||
|
@ -298,8 +298,8 @@ static void eeepc_wmi_notify(u32 value, void *context)
|
||||
kfree(obj);
|
||||
}
|
||||
|
||||
static int store_cpufv(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int value;
|
||||
struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
|
||||
|
@ -172,6 +172,8 @@ static int hp_wmi_perform_query(int query, int write, u32 *buffer,
|
||||
bios_return = *((struct bios_return *)obj->buffer.pointer);
|
||||
|
||||
memcpy(buffer, &bios_return.value, sizeof(bios_return.value));
|
||||
|
||||
kfree(obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/bios_ebda.h>
|
||||
|
||||
@ -220,32 +221,13 @@ static void rtl_teardown_sysfs(void) {
|
||||
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[] = {
|
||||
ibm_dmi_entry("BladeCenter LS21", "7971"),
|
||||
ibm_dmi_entry("BladeCenter LS22", "7901"),
|
||||
ibm_dmi_entry("BladeCenter HS21 XM", "7995"),
|
||||
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"),
|
||||
{ \
|
||||
.matches = { \
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "IBM"), \
|
||||
}, \
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -257,7 +239,7 @@ static int __init ibm_rtl_init(void) {
|
||||
if (force)
|
||||
pr_warning("ibm-rtl: module loaded by force\n");
|
||||
/* 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;
|
||||
|
||||
/* 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_cmd_width, rtl_cmd_type);
|
||||
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);
|
||||
rtl_cmd_addr = rtl_port_map(addr, plen);
|
||||
RTL_DEBUG("rtl_cmd_addr = %#llx\n", (u64)rtl_cmd_addr);
|
||||
|
@ -43,16 +43,18 @@ MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
|
||||
|
||||
#define dprintk(msg...) pr_debug(DRV_PFX msg)
|
||||
|
||||
#define KEYCODE_BASE 0xD0
|
||||
#define MSI_WMI_BRIGHTNESSUP KEYCODE_BASE
|
||||
#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1)
|
||||
#define MSI_WMI_VOLUMEUP (KEYCODE_BASE + 2)
|
||||
#define MSI_WMI_VOLUMEDOWN (KEYCODE_BASE + 3)
|
||||
#define SCANCODE_BASE 0xD0
|
||||
#define MSI_WMI_BRIGHTNESSUP SCANCODE_BASE
|
||||
#define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1)
|
||||
#define MSI_WMI_VOLUMEUP (SCANCODE_BASE + 2)
|
||||
#define MSI_WMI_VOLUMEDOWN (SCANCODE_BASE + 3)
|
||||
#define MSI_WMI_MUTE (SCANCODE_BASE + 4)
|
||||
static struct key_entry msi_wmi_keymap[] = {
|
||||
{ KE_KEY, MSI_WMI_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} },
|
||||
{ KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} },
|
||||
{ KE_KEY, MSI_WMI_VOLUMEUP, {KEY_VOLUMEUP} },
|
||||
{ KE_KEY, MSI_WMI_VOLUMEDOWN, {KEY_VOLUMEDOWN} },
|
||||
{ KE_KEY, MSI_WMI_MUTE, {KEY_MUTE} },
|
||||
{ KE_END, 0}
|
||||
};
|
||||
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;
|
||||
cur = ktime_get_real();
|
||||
diff = ktime_sub(cur, last_pressed[key->code -
|
||||
KEYCODE_BASE]);
|
||||
SCANCODE_BASE]);
|
||||
/* Ignore event if the same event happened in a 50 ms
|
||||
timeframe -> Key press may result in 10-20 GPEs */
|
||||
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));
|
||||
return;
|
||||
}
|
||||
last_pressed[key->code - KEYCODE_BASE] = cur;
|
||||
last_pressed[key->code - SCANCODE_BASE] = cur;
|
||||
|
||||
if (key->type == KE_KEY &&
|
||||
/* Brightness is served via acpi video driver */
|
||||
|
@ -8497,7 +8497,6 @@ static void ibm_exit(struct ibm_struct *ibm)
|
||||
ibm->acpi->type,
|
||||
dispatch_acpi_notify);
|
||||
ibm->flags.acpi_notify_installed = 0;
|
||||
ibm->flags.acpi_notify_installed = 0;
|
||||
}
|
||||
|
||||
if (ibm->flags.proc_created) {
|
||||
|
@ -135,6 +135,7 @@ static const struct key_entry toshiba_acpi_keymap[] __initconst = {
|
||||
{ KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
|
||||
{ KE_KEY, 0x142, { KEY_WLAN } },
|
||||
{ KE_KEY, 0x143, { KEY_PROG1 } },
|
||||
{ KE_KEY, 0x17f, { KEY_FN } },
|
||||
{ KE_KEY, 0xb05, { KEY_PROG2 } },
|
||||
{ KE_KEY, 0xb06, { KEY_WWW } },
|
||||
{ KE_KEY, 0xb07, { KEY_MAIL } },
|
||||
|
@ -755,7 +755,7 @@ static bool guid_already_parsed(const char *guid_string)
|
||||
struct wmi_block *wblock;
|
||||
|
||||
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 false;
|
||||
|
@ -635,7 +635,7 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
|
||||
init_subchannel_id(&mchk_schid);
|
||||
mchk_schid.sch_no = crw0->rsid;
|
||||
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
|
||||
|
@ -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,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
long ret;
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
|
||||
mutex_lock(&autofs4_ioctl_mutex);
|
||||
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
|
||||
mutex_unlock(&autofs4_ioctl_mutex);
|
||||
|
||||
return ret;
|
||||
return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
|
||||
}
|
||||
|
||||
#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;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&autofs4_ioctl_mutex);
|
||||
if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
|
||||
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
|
||||
else
|
||||
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
|
||||
(unsigned long)compat_ptr(arg));
|
||||
mutex_unlock(&autofs4_ioctl_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -287,6 +287,8 @@ typedef struct drm_i915_irq_wait {
|
||||
#define I915_PARAM_HAS_EXECBUF2 9
|
||||
#define I915_PARAM_HAS_BSD 10
|
||||
#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 {
|
||||
int param;
|
||||
|
@ -16,6 +16,8 @@ struct gpio_keys_button {
|
||||
struct gpio_keys_platform_data {
|
||||
struct gpio_keys_button *buttons;
|
||||
int nbuttons;
|
||||
unsigned int poll_interval; /* polling interval in msecs -
|
||||
for polling driver only */
|
||||
unsigned int rep:1; /* enable input subsystem auto repeat */
|
||||
int (*enable)(struct device *dev);
|
||||
void (*disable)(struct device *dev);
|
||||
|
@ -47,6 +47,25 @@ struct input_id {
|
||||
__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 {
|
||||
__s32 value;
|
||||
__s32 minimum;
|
||||
@ -624,6 +643,10 @@ struct input_keymap_entry {
|
||||
#define KEY_CAMERA_FOCUS 0x210
|
||||
#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_HAPPY1 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||
@ -1130,7 +1153,7 @@ struct input_mt_slot {
|
||||
* of tracked contacts
|
||||
* @mtsize: number of MT slots the device uses
|
||||
* @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,
|
||||
* resolution)
|
||||
* @key: reflects current state of device's keys/buttons
|
||||
|
@ -900,6 +900,7 @@ struct perf_cpu_context {
|
||||
int exclusive;
|
||||
struct list_head rotation_list;
|
||||
int jiffies_interval;
|
||||
struct pmu *active_pmu;
|
||||
};
|
||||
|
||||
struct perf_output_handle {
|
||||
|
@ -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)
|
||||
{
|
||||
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 = {
|
||||
|
@ -3922,6 +3922,8 @@ static void perf_event_task_event(struct perf_task_event *task_event)
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(pmu, &pmus, entry) {
|
||||
cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
|
||||
if (cpuctx->active_pmu != pmu)
|
||||
goto next;
|
||||
perf_event_task_ctx(&cpuctx->ctx, task_event);
|
||||
|
||||
ctx = task_event->task_ctx;
|
||||
@ -4066,6 +4068,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(pmu, &pmus, entry) {
|
||||
cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
|
||||
if (cpuctx->active_pmu != pmu)
|
||||
goto next;
|
||||
perf_event_comm_ctx(&cpuctx->ctx, comm_event);
|
||||
|
||||
ctxn = pmu->task_ctx_nr;
|
||||
@ -4260,6 +4264,8 @@ got_name:
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(pmu, &pmus, entry) {
|
||||
cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
|
||||
if (cpuctx->active_pmu != pmu)
|
||||
goto next;
|
||||
perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
|
||||
vma->vm_flags & VM_EXEC);
|
||||
|
||||
@ -4841,7 +4847,7 @@ static int perf_swevent_init(struct perf_event *event)
|
||||
break;
|
||||
}
|
||||
|
||||
if (event_id > PERF_COUNT_SW_MAX)
|
||||
if (event_id >= PERF_COUNT_SW_MAX)
|
||||
return -ENOENT;
|
||||
|
||||
if (!event->parent) {
|
||||
@ -5266,20 +5272,36 @@ static void *find_pmu_context(int ctxn)
|
||||
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);
|
||||
/*
|
||||
* Like a real lame refcount.
|
||||
*/
|
||||
list_for_each_entry(pmu, &pmus, entry) {
|
||||
if (pmu->pmu_cpu_context == cpu_context)
|
||||
list_for_each_entry(i, &pmus, entry) {
|
||||
if (i->pmu_cpu_context == pmu->pmu_cpu_context) {
|
||||
update_pmu_context(i, pmu);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
free_percpu(cpu_context);
|
||||
free_percpu(pmu->pmu_cpu_context);
|
||||
out:
|
||||
mutex_unlock(&pmus_lock);
|
||||
}
|
||||
@ -5311,6 +5333,7 @@ int perf_pmu_register(struct pmu *pmu)
|
||||
cpuctx->ctx.pmu = pmu;
|
||||
cpuctx->jiffies_interval = 1;
|
||||
INIT_LIST_HEAD(&cpuctx->rotation_list);
|
||||
cpuctx->active_pmu = pmu;
|
||||
}
|
||||
|
||||
got_cpu_context:
|
||||
@ -5362,7 +5385,7 @@ void perf_pmu_unregister(struct pmu *pmu)
|
||||
synchronize_rcu();
|
||||
|
||||
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)
|
||||
|
@ -1082,13 +1082,15 @@ void printk_tick(void)
|
||||
|
||||
int printk_needs_cpu(int cpu)
|
||||
{
|
||||
if (unlikely(cpu_is_offline(cpu)))
|
||||
printk_tick();
|
||||
return per_cpu(printk_pending, cpu);
|
||||
}
|
||||
|
||||
void wake_up_klogd(void)
|
||||
{
|
||||
if (waitqueue_active(&log_wait))
|
||||
__raw_get_cpu_var(printk_pending) = 1;
|
||||
this_cpu_write(printk_pending, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2338,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,
|
||||
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 = {
|
||||
.open = tracing_open,
|
||||
.read = seq_read,
|
||||
.write = tracing_write_stub,
|
||||
.llseek = seq_lseek,
|
||||
.llseek = tracing_seek,
|
||||
.release = tracing_release,
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -202,7 +202,7 @@ static void sig_atexit(void)
|
||||
if (child_pid > 0)
|
||||
kill(child_pid, SIGTERM);
|
||||
|
||||
if (signr == -1)
|
||||
if (signr == -1 || signr == SIGUSR1)
|
||||
return;
|
||||
|
||||
signal(signr, SIG_DFL);
|
||||
@ -535,6 +535,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||
atexit(sig_atexit);
|
||||
signal(SIGCHLD, sig_handler);
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGUSR1, sig_handler);
|
||||
|
||||
if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
|
||||
perror("failed to create pipes");
|
||||
@ -629,6 +630,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||
execvp(argv[0], (char **)argv);
|
||||
|
||||
perror(argv[0]);
|
||||
kill(getppid(), SIGUSR1);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -789,7 +791,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (quiet)
|
||||
if (quiet || signr == SIGUSR1)
|
||||
return 0;
|
||||
|
||||
fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
|
||||
|
@ -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
|
||||
* ids. Check for this and avoid walking through the entire
|
||||
* list of ids which may be large.
|
||||
* ids. This can happen when the data file contains one type
|
||||
* 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;
|
||||
}
|
||||
|
||||
for (i = 0; i < header->attrs; i++) {
|
||||
struct perf_header_attr *attr = header->attr[i];
|
||||
|
@ -532,7 +532,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
|
||||
struct machine *machine = kmaps->machine;
|
||||
struct map *curr_map = map;
|
||||
struct symbol *pos;
|
||||
int count = 0;
|
||||
int count = 0, moved = 0;
|
||||
struct rb_root *root = &self->symbols[map->type];
|
||||
struct rb_node *next = rb_first(root);
|
||||
int kernel_range = 0;
|
||||
@ -590,6 +590,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
|
||||
char dso_name[PATH_MAX];
|
||||
struct dso *dso;
|
||||
|
||||
if (count == 0) {
|
||||
curr_map = map;
|
||||
goto filter_symbol;
|
||||
}
|
||||
|
||||
if (self->kernel == DSO_TYPE_GUEST_KERNEL)
|
||||
snprintf(dso_name, sizeof(dso_name),
|
||||
"[guest.kernel].%d",
|
||||
@ -615,7 +620,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
|
||||
map_groups__insert(kmaps, curr_map);
|
||||
++kernel_range;
|
||||
}
|
||||
|
||||
filter_symbol:
|
||||
if (filter && filter(curr_map, pos)) {
|
||||
discard_symbol: rb_erase(&pos->rb_node, root);
|
||||
symbol__delete(pos);
|
||||
@ -623,8 +628,9 @@ discard_symbol: rb_erase(&pos->rb_node, root);
|
||||
if (curr_map != map) {
|
||||
rb_erase(&pos->rb_node, root);
|
||||
symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
|
||||
}
|
||||
count++;
|
||||
++moved;
|
||||
} else
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,7 +640,7 @@ discard_symbol: rb_erase(&pos->rb_node, root);
|
||||
dso__set_loaded(curr_map->dso, curr_map->type);
|
||||
}
|
||||
|
||||
return count;
|
||||
return count + moved;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
enum map_type type;
|
||||
u64 start = machine__get_kernel_start_addr(self);
|
||||
|
||||
for (type = 0; type < MAP__NR_TYPES; ++type) {
|
||||
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)
|
||||
return -1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user