Merge branches 'clks' and 'pnx' into devel
This commit is contained in:
commit
9f33be2c3a
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 33
|
||||
EXTRAVERSION = -rc4
|
||||
EXTRAVERSION = -rc5
|
||||
NAME = Man-Eating Seals of Antiquity
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -574,6 +574,7 @@ config ARCH_PNX4008
|
||||
bool "Philips Nexperia PNX4008 Mobile"
|
||||
select CPU_ARM926T
|
||||
select HAVE_CLK
|
||||
select COMMON_CLKDEV
|
||||
help
|
||||
This enables support for Philips PNX4008 mobile platform.
|
||||
|
||||
|
@ -99,6 +99,16 @@ void clkdev_add(struct clk_lookup *cl)
|
||||
}
|
||||
EXPORT_SYMBOL(clkdev_add);
|
||||
|
||||
void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
|
||||
{
|
||||
mutex_lock(&clocks_mutex);
|
||||
while (num--) {
|
||||
list_add_tail(&cl->node, &clocks);
|
||||
cl++;
|
||||
}
|
||||
mutex_unlock(&clocks_mutex);
|
||||
}
|
||||
|
||||
#define MAX_DEV_ID 20
|
||||
#define MAX_CON_ID 16
|
||||
|
||||
|
@ -154,16 +154,16 @@
|
||||
* Please note that the implementation of these, and the required
|
||||
* effects are cache-type (VIVT/VIPT/PIPT) specific.
|
||||
*
|
||||
* flush_cache_kern_all()
|
||||
* flush_kern_all()
|
||||
*
|
||||
* Unconditionally clean and invalidate the entire cache.
|
||||
*
|
||||
* flush_cache_user_mm(mm)
|
||||
* flush_user_all()
|
||||
*
|
||||
* Clean and invalidate all user space cache entries
|
||||
* before a change of page tables.
|
||||
*
|
||||
* flush_cache_user_range(start, end, flags)
|
||||
* flush_user_range(start, end, flags)
|
||||
*
|
||||
* Clean and invalidate a range of cache entries in the
|
||||
* specified address space before a change of page tables.
|
||||
@ -179,6 +179,20 @@
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*
|
||||
* coherent_user_range(start, end)
|
||||
*
|
||||
* Ensure coherency between the Icache and the Dcache in the
|
||||
* region described by start, end. If you have non-snooping
|
||||
* Harvard caches, you need to implement this function.
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*
|
||||
* flush_kern_dcache_area(kaddr, size)
|
||||
*
|
||||
* Ensure that the data held in page is written back.
|
||||
* - kaddr - page address
|
||||
* - size - region size
|
||||
*
|
||||
* DMA Cache Coherency
|
||||
* ===================
|
||||
*
|
||||
|
@ -27,4 +27,7 @@ struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
|
||||
void clkdev_add(struct clk_lookup *cl);
|
||||
void clkdev_drop(struct clk_lookup *cl);
|
||||
|
||||
void clkdev_add_table(struct clk_lookup *, size_t);
|
||||
int clk_add_alias(const char *, const char *, char *, struct device *);
|
||||
|
||||
#endif
|
||||
|
@ -142,8 +142,7 @@ void __init bcmring_amba_init(void)
|
||||
|
||||
chipcHw_busInterfaceClockEnable(bus_clock);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
struct amba_device *d = amba_devs[i];
|
||||
|
@ -447,7 +447,6 @@ static void __init ep93xx_dma_clock_init(void)
|
||||
static int __init ep93xx_clock_init(void)
|
||||
{
|
||||
u32 value;
|
||||
int i;
|
||||
|
||||
/* Determine the bootloader configured pll1 rate */
|
||||
value = __raw_readl(EP93XX_SYSCON_CLKSET1);
|
||||
@ -480,8 +479,7 @@ static int __init ep93xx_clock_init(void)
|
||||
clk_f.rate / 1000000, clk_h.rate / 1000000,
|
||||
clk_p.rate / 1000000);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clocks); i++)
|
||||
clkdev_add(&clocks[i]);
|
||||
clkdev_add_table(clocks, ARRAY_SIZE(clocks));
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(ep93xx_clock_init);
|
||||
|
@ -144,8 +144,7 @@ static int __init integrator_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
struct amba_device *d = amba_devs[i];
|
||||
|
@ -558,9 +558,7 @@ static void __init intcp_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cp_lookups); i++)
|
||||
clkdev_add(&cp_lookups[i]);
|
||||
|
||||
clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
|
||||
platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
|
@ -88,11 +88,3 @@ unsigned long clk_get_rate(struct clk *clk)
|
||||
return rate;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
void clks_register(struct clk_lookup *clks, size_t num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
clkdev_add(&clks[i]);
|
||||
}
|
||||
|
@ -68,5 +68,3 @@ struct clk clk_##_name = { \
|
||||
|
||||
extern struct clk clk_pxa168_gpio;
|
||||
extern struct clk clk_pxa168_timers;
|
||||
|
||||
extern void clks_register(struct clk_lookup *, size_t);
|
||||
|
@ -94,7 +94,7 @@ static int __init pxa168_init(void)
|
||||
mfp_init_base(MFPR_VIRT_BASE);
|
||||
mfp_init_addr(pxa168_mfp_addr_map);
|
||||
pxa_init_dma(IRQ_PXA168_DMA_INT0, 32);
|
||||
clks_register(ARRAY_AND_SIZE(pxa168_clkregs));
|
||||
clkdev_add_table(ARRAY_AND_SIZE(pxa168_clkregs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -131,7 +131,7 @@ static int __init pxa910_init(void)
|
||||
mfp_init_base(MFPR_VIRT_BASE);
|
||||
mfp_init_addr(pxa910_mfp_addr_map);
|
||||
pxa_init_dma(IRQ_PXA910_DMA_INT0, 32);
|
||||
clks_register(ARRAY_AND_SIZE(pxa910_clkregs));
|
||||
clkdev_add_table(ARRAY_AND_SIZE(pxa910_clkregs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -570,7 +570,6 @@ static struct clk_lookup lookups[] __initdata = {
|
||||
int __init mx1_clocks_init(unsigned long fref)
|
||||
{
|
||||
unsigned int reg;
|
||||
int i;
|
||||
|
||||
/* disable clocks we are able to */
|
||||
__raw_writel(0, SCM_GCCR);
|
||||
@ -592,8 +591,7 @@ int __init mx1_clocks_init(unsigned long fref)
|
||||
reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET;
|
||||
clko_clk.parent = (struct clk *)clko_clocks[reg];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
clk_enable(&hclk);
|
||||
clk_enable(&fclk);
|
||||
|
@ -968,7 +968,6 @@ static struct clk_lookup lookups[] = {
|
||||
*/
|
||||
int __init mx21_clocks_init(unsigned long lref, unsigned long href)
|
||||
{
|
||||
int i;
|
||||
u32 cscr;
|
||||
|
||||
external_low_reference = lref;
|
||||
@ -986,8 +985,7 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)
|
||||
else
|
||||
spll_clk.parent = &fpm_clk;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
/* Turn off all clock gates */
|
||||
__raw_writel(0, CCM_PCCR0);
|
||||
|
@ -719,7 +719,6 @@ static void __init to2_adjust_clocks(void)
|
||||
int __init mx27_clocks_init(unsigned long fref)
|
||||
{
|
||||
u32 cscr = __raw_readl(CCM_CSCR);
|
||||
int i;
|
||||
|
||||
external_high_reference = fref;
|
||||
|
||||
@ -736,8 +735,7 @@ int __init mx27_clocks_init(unsigned long fref)
|
||||
|
||||
to2_adjust_clocks();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
/* Turn off all clocks we do not need */
|
||||
__raw_writel(0, CCM_PCCR0);
|
||||
|
@ -210,11 +210,7 @@ static struct clk_lookup lookups[] = {
|
||||
|
||||
int __init mx25_clocks_init(unsigned long fref)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
|
||||
|
||||
return 0;
|
||||
|
@ -485,15 +485,13 @@ static struct clk_lookup lookups[] = {
|
||||
|
||||
int __init mx35_clocks_init()
|
||||
{
|
||||
int i;
|
||||
unsigned int ll = 0;
|
||||
|
||||
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
|
||||
ll = (3 << 16);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
/* Turn off all clocks except the ones we need to survive, namely:
|
||||
* EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart
|
||||
|
@ -578,12 +578,10 @@ static struct clk_lookup lookups[] = {
|
||||
int __init mx31_clocks_init(unsigned long fref)
|
||||
{
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
ckih_rate = fref;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
/* change the csi_clk parent if necessary */
|
||||
reg = __raw_readl(MXC_CCM_CCMR);
|
||||
|
@ -624,7 +624,6 @@ static struct clk_lookup lookups[] = {
|
||||
int __init mxc91231_clocks_init(unsigned long fref)
|
||||
{
|
||||
void __iomem *gpt_base;
|
||||
int i;
|
||||
|
||||
ckih_rate = fref;
|
||||
|
||||
@ -632,8 +631,7 @@ int __init mxc91231_clocks_init(unsigned long fref)
|
||||
sdhc_clk[0].parent = clk_sdhc_parent(&sdhc_clk[0]);
|
||||
sdhc_clk[1].parent = clk_sdhc_parent(&sdhc_clk[1]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
gpt_base = MXC91231_IO_ADDRESS(MXC91231_GPT1_BASE_ADDR);
|
||||
mxc_timer_init(&gpt_clk, gpt_base, MXC91231_INT_GPT);
|
||||
|
@ -22,8 +22,9 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/clock.h>
|
||||
#include "clock.h"
|
||||
|
||||
@ -56,18 +57,19 @@ static void propagate_rate(struct clk *clk)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clk_reg_disable(struct clk *clk)
|
||||
static void clk_reg_disable(struct clk *clk)
|
||||
{
|
||||
if (clk->enable_reg)
|
||||
__raw_writel(__raw_readl(clk->enable_reg) &
|
||||
~(1 << clk->enable_shift), clk->enable_reg);
|
||||
}
|
||||
|
||||
static inline void clk_reg_enable(struct clk *clk)
|
||||
static int clk_reg_enable(struct clk *clk)
|
||||
{
|
||||
if (clk->enable_reg)
|
||||
__raw_writel(__raw_readl(clk->enable_reg) |
|
||||
(1 << clk->enable_shift), clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void clk_reg_disable1(struct clk *clk)
|
||||
@ -636,31 +638,34 @@ static struct clk flash_ck = {
|
||||
static struct clk i2c0_ck = {
|
||||
.name = "i2c0_ck",
|
||||
.parent = &per_ck,
|
||||
.flags = NEEDS_INITIALIZATION,
|
||||
.round_rate = &on_off_round_rate,
|
||||
.set_rate = &on_off_set_rate,
|
||||
.flags = NEEDS_INITIALIZATION | FIXED_RATE,
|
||||
.enable_shift = 0,
|
||||
.enable_reg = I2CCLKCTRL_REG,
|
||||
.rate = 13000000,
|
||||
.enable = clk_reg_enable,
|
||||
.disable = clk_reg_disable,
|
||||
};
|
||||
|
||||
static struct clk i2c1_ck = {
|
||||
.name = "i2c1_ck",
|
||||
.parent = &per_ck,
|
||||
.flags = NEEDS_INITIALIZATION,
|
||||
.round_rate = &on_off_round_rate,
|
||||
.set_rate = &on_off_set_rate,
|
||||
.flags = NEEDS_INITIALIZATION | FIXED_RATE,
|
||||
.enable_shift = 1,
|
||||
.enable_reg = I2CCLKCTRL_REG,
|
||||
.rate = 13000000,
|
||||
.enable = clk_reg_enable,
|
||||
.disable = clk_reg_disable,
|
||||
};
|
||||
|
||||
static struct clk i2c2_ck = {
|
||||
.name = "i2c2_ck",
|
||||
.parent = &per_ck,
|
||||
.flags = NEEDS_INITIALIZATION,
|
||||
.round_rate = &on_off_round_rate,
|
||||
.set_rate = &on_off_set_rate,
|
||||
.flags = NEEDS_INITIALIZATION | FIXED_RATE,
|
||||
.enable_shift = 2,
|
||||
.enable_reg = USB_OTG_CLKCTRL_REG,
|
||||
.rate = 13000000,
|
||||
.enable = clk_reg_enable,
|
||||
.disable = clk_reg_disable,
|
||||
};
|
||||
|
||||
static struct clk spi0_ck = {
|
||||
@ -738,16 +743,16 @@ static struct clk wdt_ck = {
|
||||
.name = "wdt_ck",
|
||||
.parent = &per_ck,
|
||||
.flags = NEEDS_INITIALIZATION,
|
||||
.round_rate = &on_off_round_rate,
|
||||
.set_rate = &on_off_set_rate,
|
||||
.enable_shift = 0,
|
||||
.enable_reg = TIMCLKCTRL_REG,
|
||||
.enable = clk_reg_enable,
|
||||
.disable = clk_reg_disable,
|
||||
};
|
||||
|
||||
/* These clocks are visible outside this module
|
||||
* and can be initialized
|
||||
*/
|
||||
static struct clk *onchip_clks[] = {
|
||||
static struct clk *onchip_clks[] __initdata = {
|
||||
&ck_13MHz,
|
||||
&ck_pll1,
|
||||
&ck_pll4,
|
||||
@ -777,49 +782,74 @@ static struct clk *onchip_clks[] = {
|
||||
&wdt_ck,
|
||||
};
|
||||
|
||||
static struct clk_lookup onchip_clkreg[] = {
|
||||
{ .clk = &ck_13MHz, .con_id = "ck_13MHz" },
|
||||
{ .clk = &ck_pll1, .con_id = "ck_pll1" },
|
||||
{ .clk = &ck_pll4, .con_id = "ck_pll4" },
|
||||
{ .clk = &ck_pll5, .con_id = "ck_pll5" },
|
||||
{ .clk = &ck_pll3, .con_id = "ck_pll3" },
|
||||
{ .clk = &vfp9_ck, .con_id = "vfp9_ck" },
|
||||
{ .clk = &m2hclk_ck, .con_id = "m2hclk_ck" },
|
||||
{ .clk = &hclk_ck, .con_id = "hclk_ck" },
|
||||
{ .clk = &dma_ck, .con_id = "dma_ck" },
|
||||
{ .clk = &flash_ck, .con_id = "flash_ck" },
|
||||
{ .clk = &dum_ck, .con_id = "dum_ck" },
|
||||
{ .clk = &keyscan_ck, .con_id = "keyscan_ck" },
|
||||
{ .clk = &pwm1_ck, .con_id = "pwm1_ck" },
|
||||
{ .clk = &pwm2_ck, .con_id = "pwm2_ck" },
|
||||
{ .clk = &jpeg_ck, .con_id = "jpeg_ck" },
|
||||
{ .clk = &ms_ck, .con_id = "ms_ck" },
|
||||
{ .clk = &touch_ck, .con_id = "touch_ck" },
|
||||
{ .clk = &i2c0_ck, .dev_id = "pnx-i2c.0" },
|
||||
{ .clk = &i2c1_ck, .dev_id = "pnx-i2c.1" },
|
||||
{ .clk = &i2c2_ck, .dev_id = "pnx-i2c.2" },
|
||||
{ .clk = &spi0_ck, .con_id = "spi0_ck" },
|
||||
{ .clk = &spi1_ck, .con_id = "spi1_ck" },
|
||||
{ .clk = &uart3_ck, .con_id = "uart3_ck" },
|
||||
{ .clk = &uart4_ck, .con_id = "uart4_ck" },
|
||||
{ .clk = &uart5_ck, .con_id = "uart5_ck" },
|
||||
{ .clk = &uart6_ck, .con_id = "uart6_ck" },
|
||||
{ .clk = &wdt_ck, .dev_id = "pnx4008-watchdog" },
|
||||
};
|
||||
|
||||
static void local_clk_disable(struct clk *clk)
|
||||
{
|
||||
if (WARN_ON(clk->usecount == 0))
|
||||
return;
|
||||
|
||||
if (!(--clk->usecount)) {
|
||||
if (clk->disable)
|
||||
clk->disable(clk);
|
||||
else if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
|
||||
clk->set_rate(clk, 0);
|
||||
if (clk->parent)
|
||||
local_clk_disable(clk->parent);
|
||||
}
|
||||
}
|
||||
|
||||
static int local_clk_enable(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
|
||||
&& clk->user_rate)
|
||||
ret = clk->set_rate(clk, clk->user_rate);
|
||||
return ret;
|
||||
}
|
||||
if (clk->usecount == 0) {
|
||||
if (clk->parent) {
|
||||
ret = local_clk_enable(clk->parent);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void local_clk_disable(struct clk *clk)
|
||||
{
|
||||
if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
|
||||
clk->set_rate(clk, 0);
|
||||
}
|
||||
if (clk->enable)
|
||||
ret = clk->enable(clk);
|
||||
else if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
|
||||
&& clk->user_rate)
|
||||
ret = clk->set_rate(clk, clk->user_rate);
|
||||
|
||||
static void local_clk_unuse(struct clk *clk)
|
||||
{
|
||||
if (clk->usecount > 0 && !(--clk->usecount)) {
|
||||
local_clk_disable(clk);
|
||||
if (clk->parent)
|
||||
local_clk_unuse(clk->parent);
|
||||
}
|
||||
}
|
||||
|
||||
static int local_clk_use(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
if (clk->usecount++ == 0) {
|
||||
if (clk->parent)
|
||||
ret = local_clk_use(clk->parent);
|
||||
|
||||
if (ret != 0) {
|
||||
clk->usecount--;
|
||||
if (ret != 0 && clk->parent) {
|
||||
local_clk_disable(clk->parent);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = local_clk_enable(clk);
|
||||
|
||||
if (ret != 0 && clk->parent) {
|
||||
local_clk_unuse(clk->parent);
|
||||
clk->usecount--;
|
||||
}
|
||||
clk->usecount++;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
@ -866,35 +896,6 @@ out:
|
||||
|
||||
EXPORT_SYMBOL(clk_set_rate);
|
||||
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
struct clk *clk = ERR_PTR(-ENOENT);
|
||||
struct clk **clkp;
|
||||
|
||||
clock_lock();
|
||||
for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
|
||||
clkp++) {
|
||||
if (strcmp(id, (*clkp)->name) == 0
|
||||
&& try_module_get((*clkp)->owner)) {
|
||||
clk = (*clkp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
clock_unlock();
|
||||
|
||||
return clk;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
clock_lock();
|
||||
if (clk && !IS_ERR(clk))
|
||||
module_put(clk->owner);
|
||||
clock_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(clk_put);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long ret;
|
||||
@ -907,10 +908,10 @@ EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
clock_lock();
|
||||
ret = local_clk_use(clk);
|
||||
ret = local_clk_enable(clk);
|
||||
clock_unlock();
|
||||
return ret;
|
||||
}
|
||||
@ -920,7 +921,7 @@ EXPORT_SYMBOL(clk_enable);
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
clock_lock();
|
||||
local_clk_unuse(clk);
|
||||
local_clk_disable(clk);
|
||||
clock_unlock();
|
||||
}
|
||||
|
||||
@ -967,18 +968,24 @@ static int __init clk_init(void)
|
||||
|
||||
for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
|
||||
clkp++) {
|
||||
if (((*clkp)->flags & NEEDS_INITIALIZATION)
|
||||
&& ((*clkp)->set_rate)) {
|
||||
(*clkp)->user_rate = (*clkp)->rate;
|
||||
local_set_rate((*clkp), (*clkp)->user_rate);
|
||||
if ((*clkp)->set_parent)
|
||||
(*clkp)->set_parent((*clkp), (*clkp)->parent);
|
||||
struct clk *clk = *clkp;
|
||||
if (clk->flags & NEEDS_INITIALIZATION) {
|
||||
if (clk->set_rate) {
|
||||
clk->user_rate = clk->rate;
|
||||
local_set_rate(clk, clk->user_rate);
|
||||
if (clk->set_parent)
|
||||
clk->set_parent(clk, clk->parent);
|
||||
}
|
||||
if (clk->enable && clk->usecount)
|
||||
clk->enable(clk);
|
||||
if (clk->disable && !clk->usecount)
|
||||
clk->disable(clk);
|
||||
}
|
||||
pr_debug("%s: clock %s, rate %ld\n",
|
||||
__func__, (*clkp)->name, (*clkp)->rate);
|
||||
__func__, clk->name, clk->rate);
|
||||
}
|
||||
|
||||
local_clk_use(&ck_pll4);
|
||||
local_clk_enable(&ck_pll4);
|
||||
|
||||
/* if ck_13MHz is not used, disable it. */
|
||||
if (ck_13MHz.usecount == 0)
|
||||
@ -987,6 +994,8 @@ static int __init clk_init(void)
|
||||
/* Disable autoclocking */
|
||||
__raw_writeb(0xff, AUTOCLK_CTRL);
|
||||
|
||||
clkdev_add_table(onchip_clkreg, ARRAY_SIZE(onchip_clkreg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
#define __ARCH_ARM_PNX4008_CLOCK_H__
|
||||
|
||||
struct clk {
|
||||
struct list_head node;
|
||||
struct module *owner;
|
||||
const char *name;
|
||||
struct clk *parent;
|
||||
struct clk *propagate_next;
|
||||
@ -29,9 +27,11 @@ struct clk {
|
||||
u8 enable_shift1;
|
||||
u32 enable_reg1;
|
||||
u32 parent_switch_reg;
|
||||
u32(*round_rate) (struct clk *, u32);
|
||||
u32(*round_rate) (struct clk *, u32);
|
||||
int (*set_rate) (struct clk *, u32);
|
||||
int (*set_parent) (struct clk * clk, struct clk * parent);
|
||||
int (*enable)(struct clk *);
|
||||
void (*disable)(struct clk *);
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
|
@ -18,120 +18,24 @@
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/i2c.h>
|
||||
|
||||
static int set_clock_run(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
char name[10];
|
||||
int retval = 0;
|
||||
|
||||
snprintf(name, 10, "i2c%d_ck", pdev->id);
|
||||
clk = clk_get(&pdev->dev, name);
|
||||
if (!IS_ERR(clk)) {
|
||||
clk_set_rate(clk, 1);
|
||||
clk_put(clk);
|
||||
} else
|
||||
retval = -ENOENT;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int set_clock_stop(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
char name[10];
|
||||
int retval = 0;
|
||||
|
||||
snprintf(name, 10, "i2c%d_ck", pdev->id);
|
||||
clk = clk_get(&pdev->dev, name);
|
||||
if (!IS_ERR(clk)) {
|
||||
clk_set_rate(clk, 0);
|
||||
clk_put(clk);
|
||||
} else
|
||||
retval = -ENOENT;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
int retval = 0;
|
||||
#ifdef CONFIG_PM
|
||||
retval = set_clock_run(pdev);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int i2c_pnx_resume(struct platform_device *pdev)
|
||||
{
|
||||
int retval = 0;
|
||||
#ifdef CONFIG_PM
|
||||
retval = set_clock_run(pdev);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
static u32 calculate_input_freq(struct platform_device *pdev)
|
||||
{
|
||||
return HCLK_MHZ;
|
||||
}
|
||||
|
||||
|
||||
static struct i2c_pnx_algo_data pnx_algo_data0 = {
|
||||
static struct i2c_pnx_data i2c0_data = {
|
||||
.name = I2C_CHIP_NAME "0",
|
||||
.base = PNX4008_I2C1_BASE,
|
||||
.irq = I2C_1_INT,
|
||||
};
|
||||
|
||||
static struct i2c_pnx_algo_data pnx_algo_data1 = {
|
||||
static struct i2c_pnx_data i2c1_data = {
|
||||
.name = I2C_CHIP_NAME "1",
|
||||
.base = PNX4008_I2C2_BASE,
|
||||
.irq = I2C_2_INT,
|
||||
};
|
||||
|
||||
static struct i2c_pnx_algo_data pnx_algo_data2 = {
|
||||
static struct i2c_pnx_data i2c2_data = {
|
||||
.name = "USB-I2C",
|
||||
.base = (PNX4008_USB_CONFIG_BASE + 0x300),
|
||||
.irq = USB_I2C_INT,
|
||||
};
|
||||
|
||||
static struct i2c_adapter pnx_adapter0 = {
|
||||
.name = I2C_CHIP_NAME "0",
|
||||
.algo_data = &pnx_algo_data0,
|
||||
};
|
||||
static struct i2c_adapter pnx_adapter1 = {
|
||||
.name = I2C_CHIP_NAME "1",
|
||||
.algo_data = &pnx_algo_data1,
|
||||
};
|
||||
|
||||
static struct i2c_adapter pnx_adapter2 = {
|
||||
.name = "USB-I2C",
|
||||
.algo_data = &pnx_algo_data2,
|
||||
};
|
||||
|
||||
static struct i2c_pnx_data i2c0_data = {
|
||||
.suspend = i2c_pnx_suspend,
|
||||
.resume = i2c_pnx_resume,
|
||||
.calculate_input_freq = calculate_input_freq,
|
||||
.set_clock_run = set_clock_run,
|
||||
.set_clock_stop = set_clock_stop,
|
||||
.adapter = &pnx_adapter0,
|
||||
};
|
||||
|
||||
static struct i2c_pnx_data i2c1_data = {
|
||||
.suspend = i2c_pnx_suspend,
|
||||
.resume = i2c_pnx_resume,
|
||||
.calculate_input_freq = calculate_input_freq,
|
||||
.set_clock_run = set_clock_run,
|
||||
.set_clock_stop = set_clock_stop,
|
||||
.adapter = &pnx_adapter1,
|
||||
};
|
||||
|
||||
static struct i2c_pnx_data i2c2_data = {
|
||||
.suspend = i2c_pnx_suspend,
|
||||
.resume = i2c_pnx_resume,
|
||||
.calculate_input_freq = calculate_input_freq,
|
||||
.set_clock_run = set_clock_run,
|
||||
.set_clock_stop = set_clock_stop,
|
||||
.adapter = &pnx_adapter2,
|
||||
};
|
||||
|
||||
static struct platform_device i2c0_device = {
|
||||
.name = "pnx-i2c",
|
||||
.id = 0,
|
||||
|
7
arch/arm/mach-pnx4008/include/mach/clkdev.h
Normal file
7
arch/arm/mach-pnx4008/include/mach/clkdev.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __ASM_MACH_CLKDEV_H
|
||||
#define __ASM_MACH_CLKDEV_H
|
||||
|
||||
#define __clk_get(clk) ({ 1; })
|
||||
#define __clk_put(clk) do { } while (0)
|
||||
|
||||
#endif
|
@ -14,60 +14,6 @@
|
||||
#ifndef __PNX4008_TIMEX_H
|
||||
#define __PNX4008_TIMEX_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#define CLOCK_TICK_RATE 1000000
|
||||
|
||||
#define TICKS2USECS(x) (x)
|
||||
|
||||
/* MilliSecond Timer - Chapter 21 Page 202 */
|
||||
|
||||
#define MSTIM_INT IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0))
|
||||
#define MSTIM_CTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4))
|
||||
#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8))
|
||||
#define MSTIM_MCTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14))
|
||||
#define MSTIM_MATCH0 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18))
|
||||
#define MSTIM_MATCH1 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c))
|
||||
|
||||
/* High Speed Timer - Chpater 22, Page 205 */
|
||||
|
||||
#define HSTIM_INT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0))
|
||||
#define HSTIM_CTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4))
|
||||
#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8))
|
||||
#define HSTIM_PMATCH IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC))
|
||||
#define HSTIM_PCOUNT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10))
|
||||
#define HSTIM_MCTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14))
|
||||
#define HSTIM_MATCH0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18))
|
||||
#define HSTIM_MATCH1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c))
|
||||
#define HSTIM_MATCH2 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20))
|
||||
#define HSTIM_CCR IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28))
|
||||
#define HSTIM_CR0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C))
|
||||
#define HSTIM_CR1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30))
|
||||
|
||||
/* IMPORTANT: both timers are UPCOUNTING */
|
||||
|
||||
/* xSTIM_MCTRL bit definitions */
|
||||
#define MR0_INT 1
|
||||
#define RESET_COUNT0 (1<<1)
|
||||
#define STOP_COUNT0 (1<<2)
|
||||
#define MR1_INT (1<<3)
|
||||
#define RESET_COUNT1 (1<<4)
|
||||
#define STOP_COUNT1 (1<<5)
|
||||
#define MR2_INT (1<<6)
|
||||
#define RESET_COUNT2 (1<<7)
|
||||
#define STOP_COUNT2 (1<<8)
|
||||
|
||||
/* xSTIM_CTRL bit definitions */
|
||||
#define COUNT_ENAB 1
|
||||
#define RESET_COUNT (1<<1)
|
||||
#define DEBUG_EN (1<<2)
|
||||
|
||||
/* xSTIM_INT bit definitions */
|
||||
#define MATCH0_INT 1
|
||||
#define MATCH1_INT (1<<1)
|
||||
#define MATCH2_INT (1<<2)
|
||||
#define RTC_TICK0 (1<<4)
|
||||
#define RTC_TICK1 (1<<5)
|
||||
|
||||
#endif
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/pm.h>
|
||||
#include <mach/clock.h>
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#include "time.h"
|
||||
|
||||
/*! Note: all timers are UPCOUNTING */
|
||||
|
||||
/*!
|
||||
|
70
arch/arm/mach-pnx4008/time.h
Normal file
70
arch/arm/mach-pnx4008/time.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* arch/arm/mach-pnx4008/include/mach/timex.h
|
||||
*
|
||||
* PNX4008 timers header file
|
||||
*
|
||||
* Author: Dmitry Chigirev <source@mvista.com>
|
||||
*
|
||||
* 2005 (c) MontaVista Software, Inc. This file is licensed under
|
||||
* the terms of the GNU General Public License version 2. This program
|
||||
* is licensed "as is" without any warranty of any kind, whether express
|
||||
* or implied.
|
||||
*/
|
||||
#ifndef PNX_TIME_H
|
||||
#define PNX_TIME_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#define TICKS2USECS(x) (x)
|
||||
|
||||
/* MilliSecond Timer - Chapter 21 Page 202 */
|
||||
|
||||
#define MSTIM_INT IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0))
|
||||
#define MSTIM_CTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4))
|
||||
#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8))
|
||||
#define MSTIM_MCTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14))
|
||||
#define MSTIM_MATCH0 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18))
|
||||
#define MSTIM_MATCH1 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c))
|
||||
|
||||
/* High Speed Timer - Chpater 22, Page 205 */
|
||||
|
||||
#define HSTIM_INT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0))
|
||||
#define HSTIM_CTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4))
|
||||
#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8))
|
||||
#define HSTIM_PMATCH IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC))
|
||||
#define HSTIM_PCOUNT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10))
|
||||
#define HSTIM_MCTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14))
|
||||
#define HSTIM_MATCH0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18))
|
||||
#define HSTIM_MATCH1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c))
|
||||
#define HSTIM_MATCH2 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20))
|
||||
#define HSTIM_CCR IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28))
|
||||
#define HSTIM_CR0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C))
|
||||
#define HSTIM_CR1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30))
|
||||
|
||||
/* IMPORTANT: both timers are UPCOUNTING */
|
||||
|
||||
/* xSTIM_MCTRL bit definitions */
|
||||
#define MR0_INT 1
|
||||
#define RESET_COUNT0 (1<<1)
|
||||
#define STOP_COUNT0 (1<<2)
|
||||
#define MR1_INT (1<<3)
|
||||
#define RESET_COUNT1 (1<<4)
|
||||
#define STOP_COUNT1 (1<<5)
|
||||
#define MR2_INT (1<<6)
|
||||
#define RESET_COUNT2 (1<<7)
|
||||
#define STOP_COUNT2 (1<<8)
|
||||
|
||||
/* xSTIM_CTRL bit definitions */
|
||||
#define COUNT_ENAB 1
|
||||
#define RESET_COUNT (1<<1)
|
||||
#define DEBUG_EN (1<<2)
|
||||
|
||||
/* xSTIM_INT bit definitions */
|
||||
#define MATCH0_INT 1
|
||||
#define MATCH1_INT (1<<1)
|
||||
#define MATCH2_INT (1<<2)
|
||||
#define RTC_TICK0 (1<<4)
|
||||
#define RTC_TICK1 (1<<5)
|
||||
|
||||
#endif
|
@ -78,11 +78,3 @@ const struct clkops clk_cken_ops = {
|
||||
.enable = clk_cken_enable,
|
||||
.disable = clk_cken_disable,
|
||||
};
|
||||
|
||||
void clks_register(struct clk_lookup *clks, size_t num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
clkdev_add(&clks[i]);
|
||||
}
|
||||
|
@ -67,7 +67,3 @@ extern void clk_pxa3xx_cken_enable(struct clk *);
|
||||
extern void clk_pxa3xx_cken_disable(struct clk *);
|
||||
#endif
|
||||
|
||||
void clks_register(struct clk_lookup *clks, size_t num);
|
||||
int clk_add_alias(const char *alias, const char *alias_name, char *id,
|
||||
struct device *dev);
|
||||
|
||||
|
@ -128,6 +128,6 @@ static struct clk_lookup eseries_clkregs[] = {
|
||||
|
||||
void eseries_register_clks(void)
|
||||
{
|
||||
clks_register(eseries_clkregs, ARRAY_SIZE(eseries_clkregs));
|
||||
clkdev_add_table(eseries_clkregs, ARRAY_SIZE(eseries_clkregs));
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,7 @@ static int __init pxa25x_init(void)
|
||||
|
||||
reset_status = RCSR;
|
||||
|
||||
clks_register(pxa25x_clkregs, ARRAY_SIZE(pxa25x_clkregs));
|
||||
clkdev_add_table(pxa25x_clkregs, ARRAY_SIZE(pxa25x_clkregs));
|
||||
|
||||
if ((ret = pxa_init_dma(IRQ_DMA, 16)))
|
||||
return ret;
|
||||
@ -370,7 +370,7 @@ static int __init pxa25x_init(void)
|
||||
|
||||
/* Only add HWUART for PXA255/26x; PXA210/250 do not have it. */
|
||||
if (cpu_is_pxa255())
|
||||
clks_register(&pxa25x_hwuart_clkreg, 1);
|
||||
clkdev_add(&pxa25x_hwuart_clkreg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ static int __init pxa27x_init(void)
|
||||
|
||||
reset_status = RCSR;
|
||||
|
||||
clks_register(pxa27x_clkregs, ARRAY_SIZE(pxa27x_clkregs));
|
||||
clkdev_add_table(pxa27x_clkregs, ARRAY_SIZE(pxa27x_clkregs));
|
||||
|
||||
if ((ret = pxa_init_dma(IRQ_DMA, 32)))
|
||||
return ret;
|
||||
|
@ -102,12 +102,12 @@ static int __init pxa300_init(void)
|
||||
if (cpu_is_pxa300() || cpu_is_pxa310()) {
|
||||
mfp_init_base(io_p2v(MFPR_BASE));
|
||||
mfp_init_addr(pxa300_mfp_addr_map);
|
||||
clks_register(ARRAY_AND_SIZE(common_clkregs));
|
||||
clkdev_add_table(ARRAY_AND_SIZE(common_clkregs));
|
||||
}
|
||||
|
||||
if (cpu_is_pxa310()) {
|
||||
mfp_init_addr(pxa310_mfp_addr_map);
|
||||
clks_register(ARRAY_AND_SIZE(pxa310_clkregs));
|
||||
clkdev_add_table(ARRAY_AND_SIZE(pxa310_clkregs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -90,7 +90,7 @@ static int __init pxa320_init(void)
|
||||
if (cpu_is_pxa320()) {
|
||||
mfp_init_base(io_p2v(MFPR_BASE));
|
||||
mfp_init_addr(pxa320_mfp_addr_map);
|
||||
clks_register(ARRAY_AND_SIZE(pxa320_clkregs));
|
||||
clkdev_add_table(ARRAY_AND_SIZE(pxa320_clkregs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -634,7 +634,7 @@ static int __init pxa3xx_init(void)
|
||||
*/
|
||||
ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
|
||||
|
||||
clks_register(pxa3xx_clkregs, ARRAY_SIZE(pxa3xx_clkregs));
|
||||
clkdev_add_table(pxa3xx_clkregs, ARRAY_SIZE(pxa3xx_clkregs));
|
||||
|
||||
if ((ret = pxa_init_dma(IRQ_DMA, 32)))
|
||||
return ret;
|
||||
|
@ -346,10 +346,7 @@ static struct clk_lookup lookups[] = {
|
||||
|
||||
static int __init clk_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(clk_init);
|
||||
|
@ -1276,11 +1276,8 @@ static struct clk_lookup lookups[] = {
|
||||
|
||||
static void __init clk_register(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Register the lookups */
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -85,11 +85,8 @@ static struct clk_lookup lookups[] = {
|
||||
|
||||
static int __init clk_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* register the clock lookups */
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(clk_init);
|
||||
|
@ -851,8 +851,7 @@ void __init versatile_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
platform_device_register(&versatile_flash_device);
|
||||
platform_device_register(&versatile_i2c_device);
|
||||
|
@ -90,12 +90,3 @@ void nuc900_subclk_enable(struct clk *clk, int enable)
|
||||
|
||||
__raw_writel(clken, W90X900_VA_CLKPWR + SUBCLK);
|
||||
}
|
||||
|
||||
|
||||
void clks_register(struct clk_lookup *clks, size_t num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
clkdev_add(&clks[i]);
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
void nuc900_clk_enable(struct clk *clk, int enable);
|
||||
void nuc900_subclk_enable(struct clk *clk, int enable);
|
||||
void clks_register(struct clk_lookup *clks, size_t num);
|
||||
|
||||
struct clk {
|
||||
unsigned long cken;
|
||||
|
@ -219,6 +219,6 @@ void __init nuc900_map_io(struct map_desc *mach_desc, int mach_size)
|
||||
|
||||
void __init nuc900_init_clocks(void)
|
||||
{
|
||||
clks_register(nuc900_clkregs, ARRAY_SIZE(nuc900_clkregs));
|
||||
clkdev_add_table(nuc900_clkregs, ARRAY_SIZE(nuc900_clkregs));
|
||||
}
|
||||
|
||||
|
@ -1068,4 +1068,6 @@ void setup_mm_for_reboot(char mode)
|
||||
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
|
||||
flush_pmd_entry(pmd);
|
||||
}
|
||||
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
@ -59,8 +59,6 @@ ENTRY(cpu_v6_proc_fin)
|
||||
* to what would be the reset vector.
|
||||
*
|
||||
* - loc - location to jump to for soft reset
|
||||
*
|
||||
* It is assumed that:
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(cpu_v6_reset)
|
||||
|
@ -45,7 +45,14 @@ ENTRY(cpu_v7_proc_init)
|
||||
ENDPROC(cpu_v7_proc_init)
|
||||
|
||||
ENTRY(cpu_v7_proc_fin)
|
||||
mov pc, lr
|
||||
stmfd sp!, {lr}
|
||||
cpsid if @ disable interrupts
|
||||
bl v7_flush_kern_cache_all
|
||||
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
|
||||
bic r0, r0, #0x1000 @ ...i............
|
||||
bic r0, r0, #0x0006 @ .............ca.
|
||||
mcr p15, 0, r0, c1, c0, 0 @ disable caches
|
||||
ldmfd sp!, {pc}
|
||||
ENDPROC(cpu_v7_proc_fin)
|
||||
|
||||
/*
|
||||
@ -56,8 +63,6 @@ ENDPROC(cpu_v7_proc_fin)
|
||||
* to what would be the reset vector.
|
||||
*
|
||||
* - loc - location to jump to for soft reset
|
||||
*
|
||||
* It is assumed that:
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(cpu_v7_reset)
|
||||
|
@ -1126,9 +1126,8 @@ static int __init clk_init(void)
|
||||
if (ops && ops->set_parent)
|
||||
ops->set_parent(cl->clk, cl->clk->parent);
|
||||
}
|
||||
|
||||
clkdev_add(cl);
|
||||
}
|
||||
clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ static int __init sh_eth_is_eeprom_ready(void)
|
||||
while (t--) {
|
||||
if (!ctrl_inw(EEPROM_STAT))
|
||||
return 1;
|
||||
cpu_relax();
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
printk(KERN_ERR "ms7724se can not access to eeprom\n");
|
||||
|
@ -345,12 +345,13 @@
|
||||
#define __NR_pwritev 334
|
||||
#define __NR_rt_tgsigqueueinfo 335
|
||||
#define __NR_perf_event_open 336
|
||||
#define __NR_recvmmsg 337
|
||||
|
||||
#define NR_syscalls 338
|
||||
#define NR_syscalls 337
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define __IGNORE_recvmmsg
|
||||
|
||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
#define __ARCH_WANT_OLD_STAT
|
||||
|
@ -386,10 +386,11 @@
|
||||
#define __NR_rt_tgsigqueueinfo 363
|
||||
#define __NR_perf_event_open 364
|
||||
#define __NR_recvmmsg 365
|
||||
#define __NR_accept4 366
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define NR_syscalls 366
|
||||
#define NR_syscalls 367
|
||||
|
||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
|
@ -353,4 +353,3 @@ ENTRY(sys_call_table)
|
||||
.long sys_pwritev
|
||||
.long sys_rt_tgsigqueueinfo /* 335 */
|
||||
.long sys_perf_event_open
|
||||
.long sys_recvmmsg
|
||||
|
@ -392,3 +392,4 @@ sys_call_table:
|
||||
.long sys_rt_tgsigqueueinfo
|
||||
.long sys_perf_event_open
|
||||
.long sys_recvmmsg /* 365 */
|
||||
.long sys_accept4
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define MSR_ARCH_PERFMON_EVENTSEL1 0x187
|
||||
|
||||
#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22)
|
||||
#define ARCH_PERFMON_EVENTSEL_ANY (1 << 21)
|
||||
#define ARCH_PERFMON_EVENTSEL_INT (1 << 20)
|
||||
#define ARCH_PERFMON_EVENTSEL_OS (1 << 17)
|
||||
#define ARCH_PERFMON_EVENTSEL_USR (1 << 16)
|
||||
|
@ -1529,16 +1529,10 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
|
||||
* if acpi_blacklisted() acpi_disabled = 1;
|
||||
* acpi_irq_model=...
|
||||
* ...
|
||||
*
|
||||
* return value: (currently ignored)
|
||||
* 0: success
|
||||
* !0: failure
|
||||
*/
|
||||
|
||||
int __init acpi_boot_table_init(void)
|
||||
void __init acpi_boot_table_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
dmi_check_system(acpi_dmi_table);
|
||||
|
||||
/*
|
||||
@ -1546,15 +1540,14 @@ int __init acpi_boot_table_init(void)
|
||||
* One exception: acpi=ht continues far enough to enumerate LAPICs
|
||||
*/
|
||||
if (acpi_disabled && !acpi_ht)
|
||||
return 1;
|
||||
return;
|
||||
|
||||
/*
|
||||
* Initialize the ACPI boot-time table parser.
|
||||
*/
|
||||
error = acpi_table_init();
|
||||
if (error) {
|
||||
if (acpi_table_init()) {
|
||||
disable_acpi();
|
||||
return error;
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
|
||||
@ -1562,18 +1555,15 @@ int __init acpi_boot_table_init(void)
|
||||
/*
|
||||
* blacklist may disable ACPI entirely
|
||||
*/
|
||||
error = acpi_blacklisted();
|
||||
if (error) {
|
||||
if (acpi_blacklisted()) {
|
||||
if (acpi_force) {
|
||||
printk(KERN_WARNING PREFIX "acpi=force override\n");
|
||||
} else {
|
||||
printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
|
||||
disable_acpi();
|
||||
return error;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init early_acpi_boot_init(void)
|
||||
|
@ -1343,6 +1343,13 @@ intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx)
|
||||
bits |= 0x2;
|
||||
if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)
|
||||
bits |= 0x1;
|
||||
|
||||
/*
|
||||
* ANY bit is supported in v3 and up
|
||||
*/
|
||||
if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY)
|
||||
bits |= 0x4;
|
||||
|
||||
bits <<= (idx * 4);
|
||||
mask = 0xfULL << (idx * 4);
|
||||
|
||||
|
@ -538,14 +538,15 @@ static int
|
||||
kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args)
|
||||
{
|
||||
struct die_args *arg = args;
|
||||
unsigned long* dr6_p = (unsigned long *)ERR_PTR(arg->err);
|
||||
|
||||
if (val == DIE_DEBUG && (arg->err & DR_STEP))
|
||||
if (post_kmmio_handler(arg->err, arg->regs) == 1) {
|
||||
if (val == DIE_DEBUG && (*dr6_p & DR_STEP))
|
||||
if (post_kmmio_handler(*dr6_p, arg->regs) == 1) {
|
||||
/*
|
||||
* Reset the BS bit in dr6 (pointed by args->err) to
|
||||
* denote completion of processing
|
||||
*/
|
||||
(*(unsigned long *)ERR_PTR(arg->err)) &= ~DR_STEP;
|
||||
*dr6_p &= ~DR_STEP;
|
||||
return NOTIFY_STOP;
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,6 @@ int put_io_context(struct io_context *ioc)
|
||||
|
||||
if (atomic_long_dec_and_test(&ioc->refcount)) {
|
||||
rcu_read_lock();
|
||||
if (ioc->aic && ioc->aic->dtor)
|
||||
ioc->aic->dtor(ioc->aic);
|
||||
cfq_dtor(ioc);
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -76,8 +74,6 @@ void exit_io_context(struct task_struct *task)
|
||||
task_unlock(task);
|
||||
|
||||
if (atomic_dec_and_test(&ioc->nr_tasks)) {
|
||||
if (ioc->aic && ioc->aic->exit)
|
||||
ioc->aic->exit(ioc->aic);
|
||||
cfq_exit(ioc);
|
||||
|
||||
}
|
||||
@ -97,7 +93,6 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
|
||||
ret->ioprio = 0;
|
||||
ret->last_waited = jiffies; /* doesn't matter... */
|
||||
ret->nr_batch_requests = 0; /* because this is 0 */
|
||||
ret->aic = NULL;
|
||||
INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);
|
||||
INIT_HLIST_HEAD(&ret->cic_list);
|
||||
ret->ioc_data = NULL;
|
||||
|
@ -528,7 +528,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
sector_t offset)
|
||||
{
|
||||
sector_t alignment;
|
||||
unsigned int top, bottom;
|
||||
unsigned int top, bottom, ret = 0;
|
||||
|
||||
t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
|
||||
t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
|
||||
@ -546,6 +546,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
t->max_segment_size = min_not_zero(t->max_segment_size,
|
||||
b->max_segment_size);
|
||||
|
||||
t->misaligned |= b->misaligned;
|
||||
|
||||
alignment = queue_limit_alignment_offset(b, offset);
|
||||
|
||||
/* Bottom device has different alignment. Check that it is
|
||||
@ -558,8 +560,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
bottom = max(b->physical_block_size, b->io_min) + alignment;
|
||||
|
||||
/* Verify that top and bottom intervals line up */
|
||||
if (max(top, bottom) & (min(top, bottom) - 1))
|
||||
if (max(top, bottom) & (min(top, bottom) - 1)) {
|
||||
t->misaligned = 1;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
t->logical_block_size = max(t->logical_block_size,
|
||||
@ -578,18 +582,21 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
if (t->physical_block_size & (t->logical_block_size - 1)) {
|
||||
t->physical_block_size = t->logical_block_size;
|
||||
t->misaligned = 1;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Minimum I/O a multiple of the physical block size? */
|
||||
if (t->io_min & (t->physical_block_size - 1)) {
|
||||
t->io_min = t->physical_block_size;
|
||||
t->misaligned = 1;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Optimal I/O a multiple of the physical block size? */
|
||||
if (t->io_opt & (t->physical_block_size - 1)) {
|
||||
t->io_opt = 0;
|
||||
t->misaligned = 1;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Find lowest common alignment_offset */
|
||||
@ -597,8 +604,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
& (max(t->physical_block_size, t->io_min) - 1);
|
||||
|
||||
/* Verify that new alignment_offset is on a logical block boundary */
|
||||
if (t->alignment_offset & (t->logical_block_size - 1))
|
||||
if (t->alignment_offset & (t->logical_block_size - 1)) {
|
||||
t->misaligned = 1;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Discard alignment and granularity */
|
||||
if (b->discard_granularity) {
|
||||
@ -626,10 +635,32 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
(t->discard_granularity - 1);
|
||||
}
|
||||
|
||||
return t->misaligned ? -1 : 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_stack_limits);
|
||||
|
||||
/**
|
||||
* bdev_stack_limits - adjust queue limits for stacked drivers
|
||||
* @t: the stacking driver limits (top device)
|
||||
* @bdev: the component block_device (bottom)
|
||||
* @start: first data sector within component device
|
||||
*
|
||||
* Description:
|
||||
* Merges queue limits for a top device and a block_device. Returns
|
||||
* 0 if alignment didn't change. Returns -1 if adding the bottom
|
||||
* device caused misalignment.
|
||||
*/
|
||||
int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev,
|
||||
sector_t start)
|
||||
{
|
||||
struct request_queue *bq = bdev_get_queue(bdev);
|
||||
|
||||
start += get_start_sect(bdev);
|
||||
|
||||
return blk_stack_limits(t, &bq->limits, start << 9);
|
||||
}
|
||||
EXPORT_SYMBOL(bdev_stack_limits);
|
||||
|
||||
/**
|
||||
* disk_stack_limits - adjust queue limits for stacked drivers
|
||||
* @disk: MD/DM gendisk (top)
|
||||
|
@ -3076,6 +3076,12 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
|
||||
if (cfq_class_idle(cfqq))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Don't allow a non-RT request to preempt an ongoing RT cfqq timeslice.
|
||||
*/
|
||||
if (cfq_class_rt(cfqq) && !cfq_class_rt(new_cfqq))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* if the new request is sync, but the currently running queue is
|
||||
* not, let the sync request have priority.
|
||||
|
@ -867,7 +867,7 @@ static ssize_t disk_discard_alignment_show(struct device *dev,
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
return sprintf(buf, "%u\n", queue_discard_alignment(disk->queue));
|
||||
return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
|
||||
|
@ -208,7 +208,7 @@ static int power_saving_thread(void *data)
|
||||
* the mechanism only works when all CPUs have RT task running,
|
||||
* as if one CPU hasn't RT task, RT task from other CPUs will
|
||||
* borrow CPU time from this CPU and cause RT task use > 95%
|
||||
* CPU time. To make 'avoid staration' work, takes a nap here.
|
||||
* CPU time. To make 'avoid starvation' work, takes a nap here.
|
||||
*/
|
||||
if (do_sleep)
|
||||
schedule_timeout_killable(HZ * idle_pct / 100);
|
||||
@ -222,14 +222,18 @@ static struct task_struct *ps_tsks[NR_CPUS];
|
||||
static unsigned int ps_tsk_num;
|
||||
static int create_power_saving_task(void)
|
||||
{
|
||||
int rc = -ENOMEM;
|
||||
|
||||
ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread,
|
||||
(void *)(unsigned long)ps_tsk_num,
|
||||
"power_saving/%d", ps_tsk_num);
|
||||
if (ps_tsks[ps_tsk_num]) {
|
||||
rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0;
|
||||
if (!rc)
|
||||
ps_tsk_num++;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
else
|
||||
ps_tsks[ps_tsk_num] = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void destroy_power_saving_task(void)
|
||||
@ -237,6 +241,7 @@ static void destroy_power_saving_task(void)
|
||||
if (ps_tsk_num > 0) {
|
||||
ps_tsk_num--;
|
||||
kthread_stop(ps_tsks[ps_tsk_num]);
|
||||
ps_tsks[ps_tsk_num] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +258,7 @@ static void set_power_saving_task_num(unsigned int num)
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_pad_idle_cpus(unsigned int num_cpus)
|
||||
static void acpi_pad_idle_cpus(unsigned int num_cpus)
|
||||
{
|
||||
get_online_cpus();
|
||||
|
||||
@ -261,7 +266,6 @@ static int acpi_pad_idle_cpus(unsigned int num_cpus)
|
||||
set_power_saving_task_num(num_cpus);
|
||||
|
||||
put_online_cpus();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t acpi_pad_idle_cpus_num(void)
|
||||
@ -369,19 +373,21 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device)
|
||||
static int acpi_pad_pur(acpi_handle handle, int *num_cpus)
|
||||
{
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_status status;
|
||||
union acpi_object *package;
|
||||
int rev, num, ret = -EINVAL;
|
||||
|
||||
status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status))
|
||||
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!buffer.length || !buffer.pointer)
|
||||
return -EINVAL;
|
||||
|
||||
package = buffer.pointer;
|
||||
if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2)
|
||||
goto out;
|
||||
rev = package->package.elements[0].integer.value;
|
||||
num = package->package.elements[1].integer.value;
|
||||
if (rev != 1)
|
||||
if (rev != 1 || num < 0)
|
||||
goto out;
|
||||
*num_cpus = num;
|
||||
ret = 0;
|
||||
@ -410,7 +416,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat,
|
||||
|
||||
static void acpi_pad_handle_notify(acpi_handle handle)
|
||||
{
|
||||
int num_cpus, ret;
|
||||
int num_cpus;
|
||||
uint32_t idle_cpus;
|
||||
|
||||
mutex_lock(&isolated_cpus_lock);
|
||||
@ -418,12 +424,9 @@ static void acpi_pad_handle_notify(acpi_handle handle)
|
||||
mutex_unlock(&isolated_cpus_lock);
|
||||
return;
|
||||
}
|
||||
ret = acpi_pad_idle_cpus(num_cpus);
|
||||
acpi_pad_idle_cpus(num_cpus);
|
||||
idle_cpus = acpi_pad_idle_cpus_num();
|
||||
if (!ret)
|
||||
acpi_pad_ost(handle, 0, idle_cpus);
|
||||
else
|
||||
acpi_pad_ost(handle, 1, 0);
|
||||
acpi_pad_ost(handle, 0, idle_cpus);
|
||||
mutex_unlock(&isolated_cpus_lock);
|
||||
}
|
||||
|
||||
|
@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void)
|
||||
|
||||
capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
|
||||
capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
|
||||
#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR
|
||||
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
|
||||
defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
|
||||
capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
|
||||
capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
|
||||
#endif
|
||||
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
|
||||
return;
|
||||
if (ACPI_SUCCESS(acpi_run_osc(handle, &context)))
|
||||
|
@ -201,14 +201,13 @@ unlock:
|
||||
spin_unlock_irqrestore(&ec->curr_lock, flags);
|
||||
}
|
||||
|
||||
static void acpi_ec_gpe_query(void *ec_cxt);
|
||||
static int acpi_ec_sync_query(struct acpi_ec *ec);
|
||||
|
||||
static int ec_check_sci(struct acpi_ec *ec, u8 state)
|
||||
static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
|
||||
{
|
||||
if (state & ACPI_EC_FLAG_SCI) {
|
||||
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
|
||||
return acpi_os_execute(OSL_EC_BURST_HANDLER,
|
||||
acpi_ec_gpe_query, ec);
|
||||
return acpi_ec_sync_query(ec);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
|
||||
{
|
||||
unsigned long tmp;
|
||||
int ret = 0;
|
||||
pr_debug(PREFIX "transaction start\n");
|
||||
/* disable GPE during transaction if storm is detected */
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
acpi_disable_gpe(NULL, ec->gpe);
|
||||
}
|
||||
if (EC_FLAGS_MSI)
|
||||
udelay(ACPI_EC_MSI_UDELAY);
|
||||
/* start transaction */
|
||||
@ -265,20 +259,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
spin_unlock_irqrestore(&ec->curr_lock, tmp);
|
||||
ret = ec_poll(ec);
|
||||
pr_debug(PREFIX "transaction end\n");
|
||||
spin_lock_irqsave(&ec->curr_lock, tmp);
|
||||
ec->curr = NULL;
|
||||
spin_unlock_irqrestore(&ec->curr_lock, tmp);
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
/* check if we received SCI during transaction */
|
||||
ec_check_sci(ec, acpi_ec_read_status(ec));
|
||||
/* it is safe to enable GPE outside of transaction */
|
||||
acpi_enable_gpe(NULL, ec->gpe);
|
||||
} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
|
||||
pr_info(PREFIX "GPE storm detected, "
|
||||
"transactions will use polling mode\n");
|
||||
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -321,7 +304,26 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
||||
status = -ETIME;
|
||||
goto end;
|
||||
}
|
||||
pr_debug(PREFIX "transaction start\n");
|
||||
/* disable GPE during transaction if storm is detected */
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
acpi_disable_gpe(NULL, ec->gpe);
|
||||
}
|
||||
|
||||
status = acpi_ec_transaction_unlocked(ec, t);
|
||||
|
||||
/* check if we received SCI during transaction */
|
||||
ec_check_sci_sync(ec, acpi_ec_read_status(ec));
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
msleep(1);
|
||||
/* it is safe to enable GPE outside of transaction */
|
||||
acpi_enable_gpe(NULL, ec->gpe);
|
||||
} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
|
||||
pr_info(PREFIX "GPE storm detected, "
|
||||
"transactions will use polling mode\n");
|
||||
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
|
||||
}
|
||||
pr_debug(PREFIX "transaction end\n");
|
||||
end:
|
||||
if (ec->global_lock)
|
||||
acpi_release_global_lock(glk);
|
||||
@ -443,7 +445,7 @@ int ec_transaction(u8 command,
|
||||
|
||||
EXPORT_SYMBOL(ec_transaction);
|
||||
|
||||
static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
|
||||
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
@ -452,20 +454,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
|
||||
.wlen = 0, .rlen = 1};
|
||||
if (!ec || !data)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Query the EC to find out which _Qxx method we need to evaluate.
|
||||
* Note that successful completion of the query causes the ACPI_EC_SCI
|
||||
* bit to be cleared (and thus clearing the interrupt source).
|
||||
*/
|
||||
|
||||
result = acpi_ec_transaction(ec, &t);
|
||||
result = acpi_ec_transaction_unlocked(ec, &t);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (!d)
|
||||
return -ENODATA;
|
||||
|
||||
*data = d;
|
||||
return 0;
|
||||
}
|
||||
@ -509,43 +507,79 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
||||
|
||||
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
||||
|
||||
static void acpi_ec_gpe_query(void *ec_cxt)
|
||||
static void acpi_ec_run(void *cxt)
|
||||
{
|
||||
struct acpi_ec *ec = ec_cxt;
|
||||
u8 value = 0;
|
||||
struct acpi_ec_query_handler *handler, copy;
|
||||
|
||||
if (!ec || acpi_ec_query(ec, &value))
|
||||
struct acpi_ec_query_handler *handler = cxt;
|
||||
if (!handler)
|
||||
return;
|
||||
mutex_lock(&ec->lock);
|
||||
pr_debug(PREFIX "start query execution\n");
|
||||
if (handler->func)
|
||||
handler->func(handler->data);
|
||||
else if (handler->handle)
|
||||
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
||||
pr_debug(PREFIX "stop query execution\n");
|
||||
kfree(handler);
|
||||
}
|
||||
|
||||
static int acpi_ec_sync_query(struct acpi_ec *ec)
|
||||
{
|
||||
u8 value = 0;
|
||||
int status;
|
||||
struct acpi_ec_query_handler *handler, *copy;
|
||||
if ((status = acpi_ec_query_unlocked(ec, &value)))
|
||||
return status;
|
||||
list_for_each_entry(handler, &ec->list, node) {
|
||||
if (value == handler->query_bit) {
|
||||
/* have custom handler for this bit */
|
||||
memcpy(©, handler, sizeof(copy));
|
||||
mutex_unlock(&ec->lock);
|
||||
if (copy.func) {
|
||||
copy.func(copy.data);
|
||||
} else if (copy.handle) {
|
||||
acpi_evaluate_object(copy.handle, NULL, NULL, NULL);
|
||||
}
|
||||
return;
|
||||
copy = kmalloc(sizeof(*handler), GFP_KERNEL);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
memcpy(copy, handler, sizeof(*copy));
|
||||
pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value);
|
||||
return acpi_os_execute((copy->func) ?
|
||||
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
|
||||
acpi_ec_run, copy);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_ec_gpe_query(void *ec_cxt)
|
||||
{
|
||||
struct acpi_ec *ec = ec_cxt;
|
||||
if (!ec)
|
||||
return;
|
||||
mutex_lock(&ec->lock);
|
||||
acpi_ec_sync_query(ec);
|
||||
mutex_unlock(&ec->lock);
|
||||
}
|
||||
|
||||
static void acpi_ec_gpe_query(void *ec_cxt);
|
||||
|
||||
static int ec_check_sci(struct acpi_ec *ec, u8 state)
|
||||
{
|
||||
if (state & ACPI_EC_FLAG_SCI) {
|
||||
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
|
||||
pr_debug(PREFIX "push gpe query to the queue\n");
|
||||
return acpi_os_execute(OSL_NOTIFY_HANDLER,
|
||||
acpi_ec_gpe_query, ec);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 acpi_ec_gpe_handler(void *data)
|
||||
{
|
||||
struct acpi_ec *ec = data;
|
||||
u8 status;
|
||||
|
||||
pr_debug(PREFIX "~~~> interrupt\n");
|
||||
status = acpi_ec_read_status(ec);
|
||||
|
||||
advance_transaction(ec, status);
|
||||
if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
|
||||
advance_transaction(ec, acpi_ec_read_status(ec));
|
||||
if (ec_transaction_done(ec) &&
|
||||
(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
|
||||
wake_up(&ec->wait);
|
||||
ec_check_sci(ec, status);
|
||||
ec_check_sci(ec, acpi_ec_read_status(ec));
|
||||
}
|
||||
return ACPI_INTERRUPT_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link");
|
||||
static int acpi_pci_link_add(struct acpi_device *device);
|
||||
static int acpi_pci_link_remove(struct acpi_device *device, int type);
|
||||
|
||||
static struct acpi_device_id link_device_ids[] = {
|
||||
static const struct acpi_device_id link_device_ids[] = {
|
||||
{"PNP0C0F", 0},
|
||||
{"", 0},
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device);
|
||||
static int acpi_pci_root_remove(struct acpi_device *device, int type);
|
||||
static int acpi_pci_root_start(struct acpi_device *device);
|
||||
|
||||
static struct acpi_device_id root_device_ids[] = {
|
||||
static const struct acpi_device_id root_device_ids[] = {
|
||||
{"PNP0A03", 0},
|
||||
{"", 0},
|
||||
};
|
||||
|
@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type);
|
||||
static int acpi_power_resume(struct acpi_device *device);
|
||||
static int acpi_power_open_fs(struct inode *inode, struct file *file);
|
||||
|
||||
static struct acpi_device_id power_device_ids[] = {
|
||||
static const struct acpi_device_id power_device_ids[] = {
|
||||
{ACPI_POWER_HID, 0},
|
||||
{"", 0},
|
||||
};
|
||||
|
@ -64,7 +64,7 @@ static int can_cap_in_hardware(void)
|
||||
return force_cap_on || cap_in_hardware;
|
||||
}
|
||||
|
||||
static struct acpi_device_id power_meter_ids[] = {
|
||||
static const struct acpi_device_id power_meter_ids[] = {
|
||||
{"ACPI000D", 0},
|
||||
{"", 0},
|
||||
};
|
||||
@ -534,6 +534,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource)
|
||||
|
||||
kfree(resource->domain_devices);
|
||||
kobject_put(resource->holders_dir);
|
||||
resource->num_domain_devices = 0;
|
||||
}
|
||||
|
||||
static int read_domain_devices(struct acpi_power_meter_resource *resource)
|
||||
@ -740,7 +741,6 @@ skip_unsafe_cap:
|
||||
|
||||
return res;
|
||||
error:
|
||||
remove_domain_devices(resource);
|
||||
remove_attrs(resource);
|
||||
return res;
|
||||
}
|
||||
|
@ -305,6 +305,28 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
|
||||
pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency;
|
||||
pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency;
|
||||
|
||||
/*
|
||||
* FADT specified C2 latency must be less than or equal to
|
||||
* 100 microseconds.
|
||||
*/
|
||||
if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency));
|
||||
/* invalidate C2 */
|
||||
pr->power.states[ACPI_STATE_C2].address = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FADT supplied C3 latency must be less than or equal to
|
||||
* 1000 microseconds.
|
||||
*/
|
||||
if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency));
|
||||
/* invalidate C3 */
|
||||
pr->power.states[ACPI_STATE_C3].address = 0;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"lvl2[0x%08x] lvl3[0x%08x]\n",
|
||||
pr->power.states[ACPI_STATE_C2].address,
|
||||
@ -494,33 +516,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
|
||||
return status;
|
||||
}
|
||||
|
||||
static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
|
||||
{
|
||||
|
||||
if (!cx->address)
|
||||
return;
|
||||
|
||||
/*
|
||||
* C2 latency must be less than or equal to 100
|
||||
* microseconds.
|
||||
*/
|
||||
else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"latency too large [%d]\n", cx->latency));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise we've met all of our C2 requirements.
|
||||
* Normalize the C2 latency to expidite policy
|
||||
*/
|
||||
cx->valid = 1;
|
||||
|
||||
cx->latency_ticks = cx->latency;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
||||
struct acpi_processor_cx *cx)
|
||||
{
|
||||
@ -531,16 +526,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
||||
if (!cx->address)
|
||||
return;
|
||||
|
||||
/*
|
||||
* C3 latency must be less than or equal to 1000
|
||||
* microseconds.
|
||||
*/
|
||||
else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"latency too large [%d]\n", cx->latency));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PIIX4 Erratum #18: We don't support C3 when Type-F (fast)
|
||||
* DMA transfers are used by any ISA device to avoid livelock.
|
||||
@ -629,7 +614,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
|
||||
break;
|
||||
|
||||
case ACPI_STATE_C2:
|
||||
acpi_processor_power_verify_c2(cx);
|
||||
if (!cx->address)
|
||||
break;
|
||||
cx->valid = 1;
|
||||
cx->latency_ticks = cx->latency; /* Normalize latency */
|
||||
break;
|
||||
|
||||
case ACPI_STATE_C3:
|
||||
|
@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
|
||||
|
||||
static int early_pdc_optin;
|
||||
static int set_early_pdc_optin(const struct dmi_system_id *id)
|
||||
{
|
||||
early_pdc_optin = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = {
|
||||
{
|
||||
set_early_pdc_optin, "HP Envy", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL},
|
||||
{
|
||||
set_early_pdc_optin, "HP Pavilion dv6", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL},
|
||||
{
|
||||
set_early_pdc_optin, "HP Pavilion dv7", {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL},
|
||||
{},
|
||||
};
|
||||
|
||||
static acpi_status
|
||||
early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
@ -151,7 +174,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
void acpi_early_processor_set_pdc(void)
|
||||
void __init acpi_early_processor_set_pdc(void)
|
||||
{
|
||||
/*
|
||||
* Check whether the system is DMI table. If yes, OSPM
|
||||
@ -159,6 +182,13 @@ void acpi_early_processor_set_pdc(void)
|
||||
*/
|
||||
dmi_check_system(processor_idle_dmi_table);
|
||||
|
||||
/*
|
||||
* Allow systems to opt-in to early _PDC evaluation.
|
||||
*/
|
||||
dmi_check_system(early_pdc_optin_table);
|
||||
if (!early_pdc_optin)
|
||||
return;
|
||||
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
early_init_pdc, NULL, NULL, NULL);
|
||||
|
@ -443,8 +443,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = {
|
||||
#ifdef CONFIG_ACPI_PROCFS
|
||||
static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_processor *pr = (struct acpi_processor *)seq->private;
|
||||
|
||||
struct acpi_processor *pr = seq->private;
|
||||
|
||||
if (!pr)
|
||||
goto end;
|
||||
|
@ -822,7 +822,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
|
||||
|
||||
static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
|
||||
{
|
||||
#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER)
|
||||
struct acpi_battery *battery = &sbs->battery[id];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI_SYSFS_POWER
|
||||
if (battery->bat.dev) {
|
||||
if (battery->have_sysfs_alarm)
|
||||
|
@ -242,7 +242,7 @@ static int smbus_alarm(void *context)
|
||||
case ACPI_SBS_CHARGER:
|
||||
case ACPI_SBS_MANAGER:
|
||||
case ACPI_SBS_BATTERY:
|
||||
acpi_os_execute(OSL_GPE_HANDLER,
|
||||
acpi_os_execute(OSL_NOTIFY_HANDLER,
|
||||
acpi_smbus_callback, hc);
|
||||
default:;
|
||||
}
|
||||
|
@ -78,6 +78,13 @@ MODULE_LICENSE("GPL");
|
||||
static int brightness_switch_enabled = 1;
|
||||
module_param(brightness_switch_enabled, bool, 0644);
|
||||
|
||||
/*
|
||||
* By default, we don't allow duplicate ACPI video bus devices
|
||||
* under the same VGA controller
|
||||
*/
|
||||
static int allow_duplicates;
|
||||
module_param(allow_duplicates, bool, 0644);
|
||||
|
||||
static int register_count = 0;
|
||||
static int acpi_video_bus_add(struct acpi_device *device);
|
||||
static int acpi_video_bus_remove(struct acpi_device *device, int type);
|
||||
@ -2239,11 +2246,47 @@ static int acpi_video_resume(struct acpi_device *device)
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
|
||||
void **return_value)
|
||||
{
|
||||
struct acpi_device *device = context;
|
||||
struct acpi_device *sibling;
|
||||
int result;
|
||||
|
||||
if (handle == device->handle)
|
||||
return AE_CTRL_TERMINATE;
|
||||
|
||||
result = acpi_bus_get_device(handle, &sibling);
|
||||
if (result)
|
||||
return AE_OK;
|
||||
|
||||
if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME))
|
||||
return AE_ALREADY_EXISTS;
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int acpi_video_bus_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_video_bus *video;
|
||||
struct input_dev *input;
|
||||
int error;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
|
||||
device->parent->handle, 1,
|
||||
acpi_video_bus_match, NULL,
|
||||
device, NULL);
|
||||
if (status == AE_ALREADY_EXISTS) {
|
||||
printk(KERN_WARNING FW_BUG
|
||||
"Duplicate ACPI video bus devices for the"
|
||||
" same VGA controller, please try module "
|
||||
"parameter \"video.allow_duplicates=1\""
|
||||
"if the current driver doesn't work.\n");
|
||||
if (!allow_duplicates)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
|
||||
if (!video)
|
||||
|
@ -2028,8 +2028,9 @@ static void ata_eh_link_autopsy(struct ata_link *link)
|
||||
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
|
||||
|
||||
/* determine whether the command is worth retrying */
|
||||
if (!(qc->err_mask & AC_ERR_INVALID) &&
|
||||
((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV))
|
||||
if (qc->flags & ATA_QCFLAG_IO ||
|
||||
(!(qc->err_mask & AC_ERR_INVALID) &&
|
||||
qc->err_mask != AC_ERR_DEV))
|
||||
qc->flags |= ATA_QCFLAG_RETRY;
|
||||
|
||||
/* accumulate error info */
|
||||
|
@ -354,6 +354,7 @@ int __init devtmpfs_init(void)
|
||||
{
|
||||
int err;
|
||||
struct vfsmount *mnt;
|
||||
char options[] = "mode=0755";
|
||||
|
||||
err = register_filesystem(&dev_fs_type);
|
||||
if (err) {
|
||||
@ -362,7 +363,7 @@ int __init devtmpfs_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
mnt = kern_mount_data(&dev_fs_type, "mode=0755");
|
||||
mnt = kern_mount_data(&dev_fs_type, options);
|
||||
if (IS_ERR(mnt)) {
|
||||
err = PTR_ERR(mnt);
|
||||
printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
|
||||
|
@ -309,19 +309,17 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
|
||||
* Block size attribute stuff
|
||||
*/
|
||||
static ssize_t
|
||||
print_block_size(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *class_attr,
|
||||
char *buf)
|
||||
print_block_size(struct class *class, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
|
||||
}
|
||||
|
||||
static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
|
||||
static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
|
||||
|
||||
static int block_size_init(void)
|
||||
{
|
||||
return sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&attr_block_size_bytes.attr);
|
||||
&class_attr_block_size_bytes.attr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -332,9 +330,7 @@ static int block_size_init(void)
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_MEMORY_PROBE
|
||||
static ssize_t
|
||||
memory_probe_store(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *class_attr,
|
||||
const char *buf, size_t count)
|
||||
memory_probe_store(struct class *class, const char *buf, size_t count)
|
||||
{
|
||||
u64 phys_addr;
|
||||
int nid;
|
||||
@ -350,12 +346,12 @@ memory_probe_store(struct sysdev_class *class,
|
||||
|
||||
return count;
|
||||
}
|
||||
static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
|
||||
static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
|
||||
|
||||
static int memory_probe_init(void)
|
||||
{
|
||||
return sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&attr_probe.attr);
|
||||
&class_attr_probe.attr);
|
||||
}
|
||||
#else
|
||||
static inline int memory_probe_init(void)
|
||||
@ -371,9 +367,7 @@ static inline int memory_probe_init(void)
|
||||
|
||||
/* Soft offline a page */
|
||||
static ssize_t
|
||||
store_soft_offline_page(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *class_attr,
|
||||
const char *buf, size_t count)
|
||||
store_soft_offline_page(struct class *class, const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
u64 pfn;
|
||||
@ -390,9 +384,7 @@ store_soft_offline_page(struct sysdev_class *class,
|
||||
|
||||
/* Forcibly offline a page, including killing processes. */
|
||||
static ssize_t
|
||||
store_hard_offline_page(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *class_attr,
|
||||
const char *buf, size_t count)
|
||||
store_hard_offline_page(struct class *class, const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
u64 pfn;
|
||||
@ -405,18 +397,18 @@ store_hard_offline_page(struct sysdev_class *class,
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static SYSDEV_CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page);
|
||||
static SYSDEV_CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);
|
||||
static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page);
|
||||
static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);
|
||||
|
||||
static __init int memory_fail_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&attr_soft_offline_page.attr);
|
||||
&class_attr_soft_offline_page.attr);
|
||||
if (!err)
|
||||
err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&attr_hard_offline_page.attr);
|
||||
&class_attr_hard_offline_page.attr);
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
comment "DRBD disabled because PROC_FS, INET or CONNECTOR not selected"
|
||||
depends on !PROC_FS || !INET || !CONNECTOR
|
||||
depends on PROC_FS='n' || INET='n' || CONNECTOR='n'
|
||||
|
||||
config BLK_DEV_DRBD
|
||||
tristate "DRBD Distributed Replicated Block Device support"
|
||||
|
@ -1275,7 +1275,7 @@ struct bm_extent {
|
||||
#if DRBD_MAX_SECTORS_BM < DRBD_MAX_SECTORS_32
|
||||
#define DRBD_MAX_SECTORS DRBD_MAX_SECTORS_BM
|
||||
#define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_BM
|
||||
#elif !defined(CONFIG_LBD) && BITS_PER_LONG == 32
|
||||
#elif !defined(CONFIG_LBDAF) && BITS_PER_LONG == 32
|
||||
#define DRBD_MAX_SECTORS DRBD_MAX_SECTORS_32
|
||||
#define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_32
|
||||
#else
|
||||
@ -1371,10 +1371,9 @@ extern int is_valid_ar_handle(struct drbd_request *, sector_t);
|
||||
extern void drbd_suspend_io(struct drbd_conf *mdev);
|
||||
extern void drbd_resume_io(struct drbd_conf *mdev);
|
||||
extern char *ppsize(char *buf, unsigned long long size);
|
||||
extern sector_t drbd_new_dev_size(struct drbd_conf *,
|
||||
struct drbd_backing_dev *);
|
||||
extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, int);
|
||||
enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = 2 };
|
||||
extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *) __must_hold(local);
|
||||
extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, int force) __must_hold(local);
|
||||
extern void resync_after_online_grow(struct drbd_conf *);
|
||||
extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local);
|
||||
extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role,
|
||||
|
@ -1298,6 +1298,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
|
||||
dev_err(DEV, "Sending state in drbd_io_error() failed\n");
|
||||
}
|
||||
|
||||
wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
|
||||
lc_destroy(mdev->resync);
|
||||
mdev->resync = NULL;
|
||||
lc_destroy(mdev->act_log);
|
||||
|
@ -510,7 +510,7 @@ void drbd_resume_io(struct drbd_conf *mdev)
|
||||
* Returns 0 on success, negative return values indicate errors.
|
||||
* You should call drbd_md_sync() after calling this function.
|
||||
*/
|
||||
enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_hold(local)
|
||||
enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force) __must_hold(local)
|
||||
{
|
||||
sector_t prev_first_sect, prev_size; /* previous meta location */
|
||||
sector_t la_size;
|
||||
@ -541,7 +541,7 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_ho
|
||||
/* TODO: should only be some assert here, not (re)init... */
|
||||
drbd_md_set_sector_offsets(mdev, mdev->ldev);
|
||||
|
||||
size = drbd_new_dev_size(mdev, mdev->ldev);
|
||||
size = drbd_new_dev_size(mdev, mdev->ldev, force);
|
||||
|
||||
if (drbd_get_capacity(mdev->this_bdev) != size ||
|
||||
drbd_bm_capacity(mdev) != size) {
|
||||
@ -596,7 +596,7 @@ out:
|
||||
}
|
||||
|
||||
sector_t
|
||||
drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
|
||||
drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, int assume_peer_has_space)
|
||||
{
|
||||
sector_t p_size = mdev->p_size; /* partner's disk size. */
|
||||
sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */
|
||||
@ -606,6 +606,11 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
|
||||
|
||||
m_size = drbd_get_max_capacity(bdev);
|
||||
|
||||
if (mdev->state.conn < C_CONNECTED && assume_peer_has_space) {
|
||||
dev_warn(DEV, "Resize while not connected was forced by the user!\n");
|
||||
p_size = m_size;
|
||||
}
|
||||
|
||||
if (p_size && m_size) {
|
||||
size = min_t(sector_t, p_size, m_size);
|
||||
} else {
|
||||
@ -965,7 +970,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
|
||||
|
||||
/* Prevent shrinking of consistent devices ! */
|
||||
if (drbd_md_test_flag(nbc, MDF_CONSISTENT) &&
|
||||
drbd_new_dev_size(mdev, nbc) < nbc->md.la_size_sect) {
|
||||
drbd_new_dev_size(mdev, nbc, 0) < nbc->md.la_size_sect) {
|
||||
dev_warn(DEV, "refusing to truncate a consistent device\n");
|
||||
retcode = ERR_DISK_TO_SMALL;
|
||||
goto force_diskless_dec;
|
||||
@ -1052,7 +1057,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
|
||||
!drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND))
|
||||
set_bit(USE_DEGR_WFC_T, &mdev->flags);
|
||||
|
||||
dd = drbd_determin_dev_size(mdev);
|
||||
dd = drbd_determin_dev_size(mdev, 0);
|
||||
if (dd == dev_size_error) {
|
||||
retcode = ERR_NOMEM_BITMAP;
|
||||
goto force_diskless_dec;
|
||||
@ -1271,7 +1276,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (crypto_tfm_alg_type(crypto_hash_tfm(tfm)) != CRYPTO_ALG_TYPE_SHASH) {
|
||||
if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) {
|
||||
retcode = ERR_AUTH_ALG_ND;
|
||||
goto fail;
|
||||
}
|
||||
@ -1504,7 +1509,7 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
|
||||
}
|
||||
|
||||
mdev->ldev->dc.disk_size = (sector_t)rs.resize_size;
|
||||
dd = drbd_determin_dev_size(mdev);
|
||||
dd = drbd_determin_dev_size(mdev, rs.resize_force);
|
||||
drbd_md_sync(mdev);
|
||||
put_ldev(mdev);
|
||||
if (dd == dev_size_error) {
|
||||
|
@ -878,9 +878,13 @@ retry:
|
||||
|
||||
if (mdev->cram_hmac_tfm) {
|
||||
/* drbd_request_state(mdev, NS(conn, WFAuth)); */
|
||||
if (!drbd_do_auth(mdev)) {
|
||||
switch (drbd_do_auth(mdev)) {
|
||||
case -1:
|
||||
dev_err(DEV, "Authentication of peer failed\n");
|
||||
return -1;
|
||||
case 0:
|
||||
dev_err(DEV, "Authentication of peer failed, trying again.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1201,10 +1205,11 @@ static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h)
|
||||
|
||||
case WO_bdev_flush:
|
||||
case WO_drain_io:
|
||||
D_ASSERT(rv == FE_STILL_LIVE);
|
||||
set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags);
|
||||
drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
|
||||
rv = drbd_flush_after_epoch(mdev, mdev->current_epoch);
|
||||
if (rv == FE_STILL_LIVE) {
|
||||
set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags);
|
||||
drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
|
||||
rv = drbd_flush_after_epoch(mdev, mdev->current_epoch);
|
||||
}
|
||||
if (rv == FE_RECYCLED)
|
||||
return TRUE;
|
||||
|
||||
@ -2865,7 +2870,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
|
||||
|
||||
/* Never shrink a device with usable data during connect.
|
||||
But allow online shrinking if we are connected. */
|
||||
if (drbd_new_dev_size(mdev, mdev->ldev) <
|
||||
if (drbd_new_dev_size(mdev, mdev->ldev, 0) <
|
||||
drbd_get_capacity(mdev->this_bdev) &&
|
||||
mdev->state.disk >= D_OUTDATED &&
|
||||
mdev->state.conn < C_CONNECTED) {
|
||||
@ -2880,7 +2885,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
|
||||
#undef min_not_zero
|
||||
|
||||
if (get_ldev(mdev)) {
|
||||
dd = drbd_determin_dev_size(mdev);
|
||||
dd = drbd_determin_dev_size(mdev, 0);
|
||||
put_ldev(mdev);
|
||||
if (dd == dev_size_error)
|
||||
return FALSE;
|
||||
@ -3830,10 +3835,17 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
{
|
||||
dev_err(DEV, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
|
||||
dev_err(DEV, "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
#define CHALLENGE_LEN 64
|
||||
|
||||
/* Return value:
|
||||
1 - auth succeeded,
|
||||
0 - failed, try again (network error),
|
||||
-1 - auth failed, don't try again.
|
||||
*/
|
||||
|
||||
static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
{
|
||||
char my_challenge[CHALLENGE_LEN]; /* 64 Bytes... */
|
||||
@ -3854,7 +3866,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
(u8 *)mdev->net_conf->shared_secret, key_len);
|
||||
if (rv) {
|
||||
dev_err(DEV, "crypto_hash_setkey() failed with %d\n", rv);
|
||||
rv = 0;
|
||||
rv = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -3877,14 +3889,14 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
|
||||
if (p.length > CHALLENGE_LEN*2) {
|
||||
dev_err(DEV, "expected AuthChallenge payload too big.\n");
|
||||
rv = 0;
|
||||
rv = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
peers_ch = kmalloc(p.length, GFP_NOIO);
|
||||
if (peers_ch == NULL) {
|
||||
dev_err(DEV, "kmalloc of peers_ch failed\n");
|
||||
rv = 0;
|
||||
rv = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -3900,7 +3912,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
response = kmalloc(resp_size, GFP_NOIO);
|
||||
if (response == NULL) {
|
||||
dev_err(DEV, "kmalloc of response failed\n");
|
||||
rv = 0;
|
||||
rv = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -3910,7 +3922,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
rv = crypto_hash_digest(&desc, &sg, sg.length, response);
|
||||
if (rv) {
|
||||
dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv);
|
||||
rv = 0;
|
||||
rv = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -3944,9 +3956,9 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
}
|
||||
|
||||
right_response = kmalloc(resp_size, GFP_NOIO);
|
||||
if (response == NULL) {
|
||||
if (right_response == NULL) {
|
||||
dev_err(DEV, "kmalloc of right_response failed\n");
|
||||
rv = 0;
|
||||
rv = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -3955,7 +3967,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
rv = crypto_hash_digest(&desc, &sg, sg.length, right_response);
|
||||
if (rv) {
|
||||
dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv);
|
||||
rv = 0;
|
||||
rv = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -3964,6 +3976,8 @@ static int drbd_do_auth(struct drbd_conf *mdev)
|
||||
if (rv)
|
||||
dev_info(DEV, "Peer authenticated using %d bytes of '%s' HMAC\n",
|
||||
resp_size, mdev->net_conf->cram_hmac_alg);
|
||||
else
|
||||
rv = -1;
|
||||
|
||||
fail:
|
||||
kfree(peers_ch);
|
||||
|
@ -1651,10 +1651,10 @@ static void ntty_close(struct tty_struct *tty, struct file *file)
|
||||
|
||||
dc->open_ttys--;
|
||||
port->count--;
|
||||
tty_port_tty_set(port, NULL);
|
||||
|
||||
if (port->count == 0) {
|
||||
DBG1("close: %d", nport->token_dl);
|
||||
tty_port_tty_set(port, NULL);
|
||||
spin_lock_irqsave(&dc->spin_mutex, flags);
|
||||
dc->last_ier &= ~(nport->token_dl);
|
||||
writew(dc->last_ier, dc->reg_ier);
|
||||
|
@ -1951,8 +1951,8 @@ static int tty_fasync(int fd, struct file *filp, int on)
|
||||
pid = task_pid(current);
|
||||
type = PIDTYPE_PID;
|
||||
}
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
retval = __f_setown(filp, pid, type, 0);
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
if (retval)
|
||||
goto out;
|
||||
} else {
|
||||
|
@ -20,15 +20,15 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c-pnx.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/i2c.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define I2C_PNX_TIMEOUT 10 /* msec */
|
||||
#define I2C_PNX_SPEED_KHZ 100
|
||||
#define I2C_PNX_REGION_SIZE 0x100
|
||||
#define PNX_DEFAULT_FREQ 13 /* MHz */
|
||||
|
||||
static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
|
||||
{
|
||||
@ -50,22 +50,21 @@ static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
|
||||
return (timeout <= 0);
|
||||
}
|
||||
|
||||
static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap)
|
||||
static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct i2c_pnx_algo_data *data = adap->algo_data;
|
||||
struct timer_list *timer = &data->mif.timer;
|
||||
int expires = I2C_PNX_TIMEOUT / (1000 / HZ);
|
||||
struct timer_list *timer = &alg_data->mif.timer;
|
||||
unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
|
||||
|
||||
if (expires <= 1)
|
||||
expires = 2;
|
||||
|
||||
del_timer_sync(timer);
|
||||
|
||||
dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
|
||||
jiffies, expires);
|
||||
|
||||
timer->expires = jiffies + expires;
|
||||
timer->data = (unsigned long)adap;
|
||||
timer->data = (unsigned long)&alg_data;
|
||||
|
||||
add_timer(timer);
|
||||
}
|
||||
@ -77,34 +76,34 @@ static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap)
|
||||
*
|
||||
* Generate a START signal in the desired mode.
|
||||
*/
|
||||
static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
|
||||
static int i2c_pnx_start(unsigned char slave_addr,
|
||||
struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __func__,
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
|
||||
slave_addr, alg_data->mif.mode);
|
||||
|
||||
/* Check for 7 bit slave addresses only */
|
||||
if (slave_addr & ~0x7f) {
|
||||
dev_err(&adap->dev, "%s: Invalid slave address %x. "
|
||||
"Only 7-bit addresses are supported\n",
|
||||
adap->name, slave_addr);
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
|
||||
alg_data->adapter.name, slave_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* First, make sure bus is idle */
|
||||
if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
|
||||
/* Somebody else is monopolizing the bus */
|
||||
dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, "
|
||||
"cntrl = %x, stat = %x\n",
|
||||
adap->name, slave_addr,
|
||||
ioread32(I2C_REG_CTL(alg_data)),
|
||||
ioread32(I2C_REG_STS(alg_data)));
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
|
||||
alg_data->adapter.name, slave_addr,
|
||||
ioread32(I2C_REG_CTL(alg_data)),
|
||||
ioread32(I2C_REG_STS(alg_data)));
|
||||
return -EBUSY;
|
||||
} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
|
||||
/* Sorry, we lost the bus */
|
||||
dev_err(&adap->dev, "%s: Arbitration failure. "
|
||||
"Slave addr = %02x\n", adap->name, slave_addr);
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"%s: Arbitration failure. Slave addr = %02x\n",
|
||||
alg_data->adapter.name, slave_addr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -115,14 +114,14 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
|
||||
iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
|
||||
I2C_REG_STS(alg_data));
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): sending %#x\n", __func__,
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
|
||||
(slave_addr << 1) | start_bit | alg_data->mif.mode);
|
||||
|
||||
/* Write the slave address, START bit and R/W bit */
|
||||
iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
|
||||
I2C_REG_TX(alg_data));
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): exit\n", __func__);
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -133,13 +132,12 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
|
||||
*
|
||||
* Generate a STOP signal to terminate the master transaction.
|
||||
*/
|
||||
static void i2c_pnx_stop(struct i2c_adapter *adap)
|
||||
static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
/* Only 1 msec max timeout due to interrupt context */
|
||||
long timeout = 1000;
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)));
|
||||
|
||||
/* Write a STOP bit to TX FIFO */
|
||||
@ -153,7 +151,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
|
||||
timeout--;
|
||||
}
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)));
|
||||
}
|
||||
|
||||
@ -163,12 +161,11 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
|
||||
*
|
||||
* Sends one byte of data to the slave
|
||||
*/
|
||||
static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
|
||||
static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
u32 val;
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)));
|
||||
|
||||
if (alg_data->mif.len > 0) {
|
||||
@ -184,15 +181,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
|
||||
alg_data->mif.len--;
|
||||
iowrite32(val, I2C_REG_TX(alg_data));
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __func__,
|
||||
val, alg_data->mif.len + 1);
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
|
||||
__func__, val, alg_data->mif.len + 1);
|
||||
|
||||
if (alg_data->mif.len == 0) {
|
||||
if (alg_data->last) {
|
||||
/* Wait until the STOP is seen. */
|
||||
if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
|
||||
dev_err(&adap->dev, "The bus is still "
|
||||
"active after timeout\n");
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"The bus is still active after timeout\n");
|
||||
}
|
||||
/* Disable master interrupts */
|
||||
iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
|
||||
@ -201,14 +198,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
|
||||
|
||||
del_timer_sync(&alg_data->mif.timer);
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): Waking up xfer routine.\n",
|
||||
__func__);
|
||||
|
||||
complete(&alg_data->mif.complete);
|
||||
}
|
||||
} else if (alg_data->mif.len == 0) {
|
||||
/* zero-sized transfer */
|
||||
i2c_pnx_stop(adap);
|
||||
i2c_pnx_stop(alg_data);
|
||||
|
||||
/* Disable master interrupts. */
|
||||
iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
|
||||
@ -217,13 +215,14 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
|
||||
|
||||
/* Stop timer. */
|
||||
del_timer_sync(&alg_data->mif.timer);
|
||||
dev_dbg(&adap->dev, "%s(): Waking up xfer routine after "
|
||||
"zero-xfer.\n", __func__);
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): Waking up xfer routine after zero-xfer.\n",
|
||||
__func__);
|
||||
|
||||
complete(&alg_data->mif.complete);
|
||||
}
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)));
|
||||
|
||||
return 0;
|
||||
@ -235,21 +234,21 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
|
||||
*
|
||||
* Reads one byte data from the slave
|
||||
*/
|
||||
static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
|
||||
static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
unsigned int val = 0;
|
||||
u32 ctl = 0;
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)));
|
||||
|
||||
/* Check, whether there is already data,
|
||||
* or we didn't 'ask' for it yet.
|
||||
*/
|
||||
if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
|
||||
dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
|
||||
"Rx-fifo...\n", __func__);
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): Write dummy data to fill Rx-fifo...\n",
|
||||
__func__);
|
||||
|
||||
if (alg_data->mif.len == 1) {
|
||||
/* Last byte, do not acknowledge next rcv. */
|
||||
@ -281,16 +280,16 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
|
||||
if (alg_data->mif.len > 0) {
|
||||
val = ioread32(I2C_REG_RX(alg_data));
|
||||
*alg_data->mif.buf++ = (u8) (val & 0xff);
|
||||
dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val,
|
||||
alg_data->mif.len);
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
|
||||
__func__, val, alg_data->mif.len);
|
||||
|
||||
alg_data->mif.len--;
|
||||
if (alg_data->mif.len == 0) {
|
||||
if (alg_data->last)
|
||||
/* Wait until the STOP is seen. */
|
||||
if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
|
||||
dev_err(&adap->dev, "The bus is still "
|
||||
"active after timeout\n");
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"The bus is still active after timeout\n");
|
||||
|
||||
/* Disable master interrupts */
|
||||
ctl = ioread32(I2C_REG_CTL(alg_data));
|
||||
@ -304,7 +303,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)));
|
||||
|
||||
return 0;
|
||||
@ -312,11 +311,11 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
|
||||
|
||||
static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = dev_id;
|
||||
u32 stat, ctl;
|
||||
struct i2c_adapter *adap = dev_id;
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n",
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): mstat = %x mctrl = %x, mode = %d\n",
|
||||
__func__,
|
||||
ioread32(I2C_REG_STS(alg_data)),
|
||||
ioread32(I2C_REG_CTL(alg_data)),
|
||||
@ -339,10 +338,10 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
complete(&alg_data->mif.complete);
|
||||
} else if (stat & mstatus_nai) {
|
||||
/* Slave did not acknowledge, generate a STOP */
|
||||
dev_dbg(&adap->dev, "%s(): "
|
||||
"Slave did not acknowledge, generating a STOP.\n",
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): Slave did not acknowledge, generating a STOP.\n",
|
||||
__func__);
|
||||
i2c_pnx_stop(adap);
|
||||
i2c_pnx_stop(alg_data);
|
||||
|
||||
/* Disable master interrupts. */
|
||||
ctl = ioread32(I2C_REG_CTL(alg_data));
|
||||
@ -368,9 +367,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
*/
|
||||
if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
|
||||
if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
|
||||
i2c_pnx_master_xmit(adap);
|
||||
i2c_pnx_master_xmit(alg_data);
|
||||
} else if (alg_data->mif.mode == I2C_SMBUS_READ) {
|
||||
i2c_pnx_master_rcv(adap);
|
||||
i2c_pnx_master_rcv(alg_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,7 +378,8 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
stat = ioread32(I2C_REG_STS(alg_data));
|
||||
iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): exiting, stat = %x ctrl = %x.\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)),
|
||||
ioread32(I2C_REG_CTL(alg_data)));
|
||||
|
||||
@ -388,14 +388,13 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
|
||||
static void i2c_pnx_timeout(unsigned long data)
|
||||
{
|
||||
struct i2c_adapter *adap = (struct i2c_adapter *)data;
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data;
|
||||
u32 ctl;
|
||||
|
||||
dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. "
|
||||
"Resetting master...\n",
|
||||
ioread32(I2C_REG_STS(alg_data)),
|
||||
ioread32(I2C_REG_CTL(alg_data)));
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n",
|
||||
ioread32(I2C_REG_STS(alg_data)),
|
||||
ioread32(I2C_REG_CTL(alg_data)));
|
||||
|
||||
/* Reset master and disable interrupts */
|
||||
ctl = ioread32(I2C_REG_CTL(alg_data));
|
||||
@ -409,15 +408,14 @@ static void i2c_pnx_timeout(unsigned long data)
|
||||
complete(&alg_data->mif.complete);
|
||||
}
|
||||
|
||||
static inline void bus_reset_if_active(struct i2c_adapter *adap)
|
||||
static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
u32 stat;
|
||||
|
||||
if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
|
||||
dev_err(&adap->dev,
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"%s: Bus is still active after xfer. Reset it...\n",
|
||||
adap->name);
|
||||
alg_data->adapter.name);
|
||||
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
|
||||
I2C_REG_CTL(alg_data));
|
||||
wait_reset(I2C_PNX_TIMEOUT, alg_data);
|
||||
@ -451,10 +449,11 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
u32 stat = ioread32(I2C_REG_STS(alg_data));
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n",
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): entering: %d messages, stat = %04x.\n",
|
||||
__func__, num, ioread32(I2C_REG_STS(alg_data)));
|
||||
|
||||
bus_reset_if_active(adap);
|
||||
bus_reset_if_active(alg_data);
|
||||
|
||||
/* Process transactions in a loop. */
|
||||
for (i = 0; rc >= 0 && i < num; i++) {
|
||||
@ -464,9 +463,9 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
addr = pmsg->addr;
|
||||
|
||||
if (pmsg->flags & I2C_M_TEN) {
|
||||
dev_err(&adap->dev,
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
"%s: 10 bits addr not supported!\n",
|
||||
adap->name);
|
||||
alg_data->adapter.name);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@ -478,11 +477,10 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
alg_data->mif.ret = 0;
|
||||
alg_data->last = (i == num - 1);
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __func__,
|
||||
alg_data->mif.mode,
|
||||
alg_data->mif.len);
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
|
||||
__func__, alg_data->mif.mode, alg_data->mif.len);
|
||||
|
||||
i2c_pnx_arm_timer(adap);
|
||||
i2c_pnx_arm_timer(alg_data);
|
||||
|
||||
/* initialize the completion var */
|
||||
init_completion(&alg_data->mif.complete);
|
||||
@ -493,7 +491,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
I2C_REG_CTL(alg_data));
|
||||
|
||||
/* Put start-code and slave-address on the bus. */
|
||||
rc = i2c_pnx_start(addr, adap);
|
||||
rc = i2c_pnx_start(addr, alg_data);
|
||||
if (rc < 0)
|
||||
break;
|
||||
|
||||
@ -502,31 +500,32 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
|
||||
if (!(rc = alg_data->mif.ret))
|
||||
completed++;
|
||||
dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n",
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): Complete, return code = %d.\n",
|
||||
__func__, rc);
|
||||
|
||||
/* Clear TDI and AFI bits in case they are set. */
|
||||
if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
|
||||
dev_dbg(&adap->dev,
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s: TDI still set... clearing now.\n",
|
||||
adap->name);
|
||||
alg_data->adapter.name);
|
||||
iowrite32(stat, I2C_REG_STS(alg_data));
|
||||
}
|
||||
if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
|
||||
dev_dbg(&adap->dev,
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s: AFI still set... clearing now.\n",
|
||||
adap->name);
|
||||
alg_data->adapter.name);
|
||||
iowrite32(stat, I2C_REG_STS(alg_data));
|
||||
}
|
||||
}
|
||||
|
||||
bus_reset_if_active(adap);
|
||||
bus_reset_if_active(alg_data);
|
||||
|
||||
/* Cleanup to be sure... */
|
||||
alg_data->mif.buf = NULL;
|
||||
alg_data->mif.len = 0;
|
||||
|
||||
dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
|
||||
__func__, ioread32(I2C_REG_STS(alg_data)));
|
||||
|
||||
if (completed != num)
|
||||
@ -545,69 +544,92 @@ static struct i2c_algorithm pnx_algorithm = {
|
||||
.functionality = i2c_pnx_func,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int i2c_pnx_controller_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
|
||||
return i2c_pnx->suspend(pdev, state);
|
||||
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
|
||||
|
||||
/* FIXME: shouldn't this be clk_disable? */
|
||||
clk_enable(alg_data->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_pnx_controller_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
|
||||
return i2c_pnx->resume(pdev);
|
||||
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
|
||||
|
||||
return clk_enable(alg_data->clk);
|
||||
}
|
||||
#else
|
||||
#define i2c_pnx_controller_suspend NULL
|
||||
#define i2c_pnx_controller_resume NULL
|
||||
#endif
|
||||
|
||||
static int __devinit i2c_pnx_probe(struct platform_device *pdev)
|
||||
{
|
||||
unsigned long tmp;
|
||||
int ret = 0;
|
||||
struct i2c_pnx_algo_data *alg_data;
|
||||
int freq_mhz;
|
||||
unsigned long freq;
|
||||
struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
|
||||
|
||||
if (!i2c_pnx || !i2c_pnx->adapter) {
|
||||
if (!i2c_pnx || !i2c_pnx->name) {
|
||||
dev_err(&pdev->dev, "%s: no platform data supplied\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, i2c_pnx);
|
||||
|
||||
if (i2c_pnx->calculate_input_freq)
|
||||
freq_mhz = i2c_pnx->calculate_input_freq(pdev);
|
||||
else {
|
||||
freq_mhz = PNX_DEFAULT_FREQ;
|
||||
dev_info(&pdev->dev, "Setting bus frequency to default value: "
|
||||
"%d MHz\n", freq_mhz);
|
||||
alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
|
||||
if (!alg_data) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc;
|
||||
}
|
||||
|
||||
i2c_pnx->adapter->algo = &pnx_algorithm;
|
||||
platform_set_drvdata(pdev, alg_data);
|
||||
|
||||
alg_data = i2c_pnx->adapter->algo_data;
|
||||
init_timer(&alg_data->mif.timer);
|
||||
alg_data->mif.timer.function = i2c_pnx_timeout;
|
||||
alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter;
|
||||
strlcpy(alg_data->adapter.name, i2c_pnx->name,
|
||||
sizeof(alg_data->adapter.name));
|
||||
alg_data->adapter.dev.parent = &pdev->dev;
|
||||
alg_data->adapter.algo = &pnx_algorithm;
|
||||
alg_data->adapter.algo_data = alg_data;
|
||||
alg_data->adapter.nr = pdev->id;
|
||||
alg_data->i2c_pnx = i2c_pnx;
|
||||
|
||||
/* Register I/O resource */
|
||||
if (!request_mem_region(alg_data->base, I2C_PNX_REGION_SIZE,
|
||||
pdev->name)) {
|
||||
dev_err(&pdev->dev,
|
||||
"I/O region 0x%08x for I2C already in use.\n",
|
||||
alg_data->base);
|
||||
ret = -ENODEV;
|
||||
alg_data->clk = clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(alg_data->clk)) {
|
||||
ret = PTR_ERR(alg_data->clk);
|
||||
goto out_drvdata;
|
||||
}
|
||||
|
||||
if (!(alg_data->ioaddr =
|
||||
(u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) {
|
||||
init_timer(&alg_data->mif.timer);
|
||||
alg_data->mif.timer.function = i2c_pnx_timeout;
|
||||
alg_data->mif.timer.data = (unsigned long)alg_data;
|
||||
|
||||
/* Register I/O resource */
|
||||
if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE,
|
||||
pdev->name)) {
|
||||
dev_err(&pdev->dev,
|
||||
"I/O region 0x%08x for I2C already in use.\n",
|
||||
i2c_pnx->base);
|
||||
ret = -ENODEV;
|
||||
goto out_clkget;
|
||||
}
|
||||
|
||||
alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE);
|
||||
if (!alg_data->ioaddr) {
|
||||
dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
i2c_pnx->set_clock_run(pdev);
|
||||
ret = clk_enable(alg_data->clk);
|
||||
if (ret)
|
||||
goto out_unmap;
|
||||
|
||||
freq = clk_get_rate(alg_data->clk);
|
||||
|
||||
/*
|
||||
* Clock Divisor High This value is the number of system clocks
|
||||
@ -620,45 +642,47 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
|
||||
* the deglitching filter length.
|
||||
*/
|
||||
|
||||
tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
|
||||
tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
|
||||
iowrite32(tmp, I2C_REG_CKH(alg_data));
|
||||
iowrite32(tmp, I2C_REG_CKL(alg_data));
|
||||
|
||||
iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
|
||||
if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
|
||||
ret = -ENODEV;
|
||||
goto out_unmap;
|
||||
goto out_clock;
|
||||
}
|
||||
init_completion(&alg_data->mif.complete);
|
||||
|
||||
ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
|
||||
0, pdev->name, i2c_pnx->adapter);
|
||||
ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt,
|
||||
0, pdev->name, alg_data);
|
||||
if (ret)
|
||||
goto out_clock;
|
||||
|
||||
/* Register this adapter with the I2C subsystem */
|
||||
i2c_pnx->adapter->dev.parent = &pdev->dev;
|
||||
i2c_pnx->adapter->nr = pdev->id;
|
||||
ret = i2c_add_numbered_adapter(i2c_pnx->adapter);
|
||||
ret = i2c_add_numbered_adapter(&alg_data->adapter);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "I2C: Failed to add bus\n");
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
|
||||
i2c_pnx->adapter->name, alg_data->base, alg_data->irq);
|
||||
alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq);
|
||||
|
||||
return 0;
|
||||
|
||||
out_irq:
|
||||
free_irq(alg_data->irq, i2c_pnx->adapter);
|
||||
free_irq(i2c_pnx->irq, alg_data);
|
||||
out_clock:
|
||||
i2c_pnx->set_clock_stop(pdev);
|
||||
clk_disable(alg_data->clk);
|
||||
out_unmap:
|
||||
iounmap((void *)alg_data->ioaddr);
|
||||
iounmap(alg_data->ioaddr);
|
||||
out_release:
|
||||
release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE);
|
||||
release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
|
||||
out_clkget:
|
||||
clk_put(alg_data->clk);
|
||||
out_drvdata:
|
||||
kfree(alg_data);
|
||||
err_kzalloc:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
out:
|
||||
return ret;
|
||||
@ -666,15 +690,16 @@ out:
|
||||
|
||||
static int __devexit i2c_pnx_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
|
||||
struct i2c_adapter *adap = i2c_pnx->adapter;
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
|
||||
struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx;
|
||||
|
||||
free_irq(alg_data->irq, i2c_pnx->adapter);
|
||||
i2c_del_adapter(adap);
|
||||
i2c_pnx->set_clock_stop(pdev);
|
||||
iounmap((void *)alg_data->ioaddr);
|
||||
release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE);
|
||||
free_irq(i2c_pnx->irq, alg_data);
|
||||
i2c_del_adapter(&alg_data->adapter);
|
||||
clk_disable(alg_data->clk);
|
||||
iounmap(alg_data->ioaddr);
|
||||
release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
|
||||
clk_put(alg_data->clk);
|
||||
kfree(alg_data);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
|
@ -503,16 +503,15 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (blk_stack_limits(limits, &q->limits, start << 9) < 0)
|
||||
DMWARN("%s: target device %s is misaligned: "
|
||||
if (bdev_stack_limits(limits, bdev, start) < 0)
|
||||
DMWARN("%s: adding target device %s caused an alignment inconsistency: "
|
||||
"physical_block_size=%u, logical_block_size=%u, "
|
||||
"alignment_offset=%u, start=%llu",
|
||||
dm_device_name(ti->table->md), bdevname(bdev, b),
|
||||
q->limits.physical_block_size,
|
||||
q->limits.logical_block_size,
|
||||
q->limits.alignment_offset,
|
||||
(unsigned long long) start << 9);
|
||||
|
||||
(unsigned long long) start << SECTOR_SHIFT);
|
||||
|
||||
/*
|
||||
* Check if merge fn is supported.
|
||||
@ -1026,9 +1025,9 @@ combine_limits:
|
||||
* for the table.
|
||||
*/
|
||||
if (blk_stack_limits(limits, &ti_limits, 0) < 0)
|
||||
DMWARN("%s: target device "
|
||||
DMWARN("%s: adding target device "
|
||||
"(start sect %llu len %llu) "
|
||||
"is misaligned",
|
||||
"caused an alignment inconsistency",
|
||||
dm_device_name(table->md),
|
||||
(unsigned long long) ti->begin,
|
||||
(unsigned long long) ti->len);
|
||||
@ -1079,15 +1078,6 @@ no_integrity:
|
||||
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
|
||||
struct queue_limits *limits)
|
||||
{
|
||||
/*
|
||||
* Each target device in the table has a data area that should normally
|
||||
* be aligned such that the DM device's alignment_offset is 0.
|
||||
* FIXME: Propagate alignment_offsets up the stack and warn of
|
||||
* sub-optimal or inconsistent settings.
|
||||
*/
|
||||
limits->alignment_offset = 0;
|
||||
limits->misaligned = 0;
|
||||
|
||||
/*
|
||||
* Copy table's limits to the DM device's request_queue
|
||||
*/
|
||||
|
@ -364,6 +364,7 @@ config EEEPC_LAPTOP
|
||||
select HWMON
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
select INPUT_SPARSEKMAP
|
||||
---help---
|
||||
This driver supports the Fn-Fx keys on Eee PC laptops.
|
||||
|
||||
|
@ -31,10 +31,12 @@
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/sparse-keymap.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_hotplug.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#define EEEPC_LAPTOP_VERSION "0.1"
|
||||
#define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
|
||||
@ -48,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper");
|
||||
MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static bool hotplug_disabled;
|
||||
|
||||
module_param(hotplug_disabled, bool, 0644);
|
||||
MODULE_PARM_DESC(hotplug_disabled,
|
||||
"Disable hotplug for wireless device. "
|
||||
"If your laptop need that, please report to "
|
||||
"acpi4asus-user@lists.sourceforge.net.");
|
||||
|
||||
/*
|
||||
* Definitions for Asus EeePC
|
||||
*/
|
||||
@ -120,38 +130,28 @@ static const char *cm_setv[] = {
|
||||
NULL, NULL, "PBPS", "TPDS"
|
||||
};
|
||||
|
||||
struct key_entry {
|
||||
char type;
|
||||
u8 code;
|
||||
u16 keycode;
|
||||
};
|
||||
|
||||
enum { KE_KEY, KE_END };
|
||||
|
||||
static const struct key_entry eeepc_keymap[] = {
|
||||
/* Sleep already handled via generic ACPI code */
|
||||
{KE_KEY, 0x10, KEY_WLAN },
|
||||
{KE_KEY, 0x11, KEY_WLAN },
|
||||
{KE_KEY, 0x12, KEY_PROG1 },
|
||||
{KE_KEY, 0x13, KEY_MUTE },
|
||||
{KE_KEY, 0x14, KEY_VOLUMEDOWN },
|
||||
{KE_KEY, 0x15, KEY_VOLUMEUP },
|
||||
{KE_KEY, 0x16, KEY_DISPLAY_OFF },
|
||||
{KE_KEY, 0x1a, KEY_COFFEE },
|
||||
{KE_KEY, 0x1b, KEY_ZOOM },
|
||||
{KE_KEY, 0x1c, KEY_PROG2 },
|
||||
{KE_KEY, 0x1d, KEY_PROG3 },
|
||||
{KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
|
||||
{KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
|
||||
{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
|
||||
{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
|
||||
{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
|
||||
{KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */
|
||||
{KE_KEY, 0x38, KEY_F14 },
|
||||
{KE_END, 0},
|
||||
{ KE_KEY, 0x10, { KEY_WLAN } },
|
||||
{ KE_KEY, 0x11, { KEY_WLAN } },
|
||||
{ KE_KEY, 0x12, { KEY_PROG1 } },
|
||||
{ KE_KEY, 0x13, { KEY_MUTE } },
|
||||
{ KE_KEY, 0x14, { KEY_VOLUMEDOWN } },
|
||||
{ KE_KEY, 0x15, { KEY_VOLUMEUP } },
|
||||
{ KE_KEY, 0x16, { KEY_DISPLAY_OFF } },
|
||||
{ KE_KEY, 0x1a, { KEY_COFFEE } },
|
||||
{ KE_KEY, 0x1b, { KEY_ZOOM } },
|
||||
{ KE_KEY, 0x1c, { KEY_PROG2 } },
|
||||
{ KE_KEY, 0x1d, { KEY_PROG3 } },
|
||||
{ KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } },
|
||||
{ KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } },
|
||||
{ KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } },
|
||||
{ KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */
|
||||
{ KE_KEY, 0x38, { KEY_F14 } },
|
||||
{ KE_END, 0 },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This is the main structure, we can use it to store useful information
|
||||
*/
|
||||
@ -159,6 +159,8 @@ struct eeepc_laptop {
|
||||
acpi_handle handle; /* the handle of the acpi device */
|
||||
u32 cm_supported; /* the control methods supported
|
||||
by this BIOS */
|
||||
bool cpufv_disabled;
|
||||
bool hotplug_disabled;
|
||||
u16 event_count[128]; /* count for each event */
|
||||
|
||||
struct platform_device *platform_device;
|
||||
@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev,
|
||||
struct eeepc_cpufv c;
|
||||
int rv, value;
|
||||
|
||||
if (eeepc->cpufv_disabled)
|
||||
return -EPERM;
|
||||
if (get_cpufv(eeepc, &c))
|
||||
return -ENODEV;
|
||||
rv = parse_arg(buf, count, &value);
|
||||
@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev,
|
||||
return rv;
|
||||
}
|
||||
|
||||
static ssize_t show_cpufv_disabled(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", eeepc->cpufv_disabled);
|
||||
}
|
||||
|
||||
static ssize_t store_cpufv_disabled(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
|
||||
int rv, value;
|
||||
|
||||
rv = parse_arg(buf, count, &value);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
switch (value) {
|
||||
case 0:
|
||||
if (eeepc->cpufv_disabled)
|
||||
pr_warning("cpufv enabled (not officially supported "
|
||||
"on this model)\n");
|
||||
eeepc->cpufv_disabled = false;
|
||||
return rv;
|
||||
case 1:
|
||||
return -EPERM;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct device_attribute dev_attr_cpufv = {
|
||||
.attr = {
|
||||
.name = "cpufv",
|
||||
@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = {
|
||||
.show = show_available_cpufv
|
||||
};
|
||||
|
||||
static struct device_attribute dev_attr_cpufv_disabled = {
|
||||
.attr = {
|
||||
.name = "cpufv_disabled",
|
||||
.mode = 0644 },
|
||||
.show = show_cpufv_disabled,
|
||||
.store = store_cpufv_disabled
|
||||
};
|
||||
|
||||
|
||||
static struct attribute *platform_attributes[] = {
|
||||
&dev_attr_camera.attr,
|
||||
&dev_attr_cardr.attr,
|
||||
&dev_attr_disp.attr,
|
||||
&dev_attr_cpufv.attr,
|
||||
&dev_attr_available_cpufv.attr,
|
||||
&dev_attr_cpufv_disabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -796,6 +845,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
|
||||
if (result && result != -ENODEV)
|
||||
goto exit;
|
||||
|
||||
if (eeepc->hotplug_disabled)
|
||||
return 0;
|
||||
|
||||
result = eeepc_setup_pci_hotplug(eeepc);
|
||||
/*
|
||||
* If we get -EBUSY then something else is handling the PCI hotplug -
|
||||
@ -1090,120 +1142,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
|
||||
/*
|
||||
* Input device (i.e. hotkeys)
|
||||
*/
|
||||
static struct key_entry *eeepc_get_entry_by_scancode(
|
||||
struct eeepc_laptop *eeepc,
|
||||
int code)
|
||||
{
|
||||
struct key_entry *key;
|
||||
|
||||
for (key = eeepc->keymap; key->type != KE_END; key++)
|
||||
if (code == key->code)
|
||||
return key;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
|
||||
{
|
||||
static struct key_entry *key;
|
||||
|
||||
key = eeepc_get_entry_by_scancode(eeepc, event);
|
||||
if (key) {
|
||||
switch (key->type) {
|
||||
case KE_KEY:
|
||||
input_report_key(eeepc->inputdev, key->keycode,
|
||||
1);
|
||||
input_sync(eeepc->inputdev);
|
||||
input_report_key(eeepc->inputdev, key->keycode,
|
||||
0);
|
||||
input_sync(eeepc->inputdev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct key_entry *eeepc_get_entry_by_keycode(
|
||||
struct eeepc_laptop *eeepc, int code)
|
||||
{
|
||||
struct key_entry *key;
|
||||
|
||||
for (key = eeepc->keymap; key->type != KE_END; key++)
|
||||
if (code == key->keycode && key->type == KE_KEY)
|
||||
return key;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
|
||||
{
|
||||
struct eeepc_laptop *eeepc = input_get_drvdata(dev);
|
||||
struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode);
|
||||
|
||||
if (key && key->type == KE_KEY) {
|
||||
*keycode = key->keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
|
||||
{
|
||||
struct eeepc_laptop *eeepc = input_get_drvdata(dev);
|
||||
struct key_entry *key;
|
||||
int old_keycode;
|
||||
|
||||
if (keycode < 0 || keycode > KEY_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
key = eeepc_get_entry_by_scancode(eeepc, scancode);
|
||||
if (key && key->type == KE_KEY) {
|
||||
old_keycode = key->keycode;
|
||||
key->keycode = keycode;
|
||||
set_bit(keycode, dev->keybit);
|
||||
if (!eeepc_get_entry_by_keycode(eeepc, old_keycode))
|
||||
clear_bit(old_keycode, dev->keybit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int eeepc_input_init(struct eeepc_laptop *eeepc)
|
||||
{
|
||||
const struct key_entry *key;
|
||||
int result;
|
||||
struct input_dev *input;
|
||||
int error;
|
||||
|
||||
eeepc->inputdev = input_allocate_device();
|
||||
if (!eeepc->inputdev) {
|
||||
input = input_allocate_device();
|
||||
if (!input) {
|
||||
pr_info("Unable to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
eeepc->inputdev->name = "Asus EeePC extra buttons";
|
||||
eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
|
||||
eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0";
|
||||
eeepc->inputdev->id.bustype = BUS_HOST;
|
||||
eeepc->inputdev->getkeycode = eeepc_getkeycode;
|
||||
eeepc->inputdev->setkeycode = eeepc_setkeycode;
|
||||
input_set_drvdata(eeepc->inputdev, eeepc);
|
||||
|
||||
eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap),
|
||||
GFP_KERNEL);
|
||||
for (key = eeepc_keymap; key->type != KE_END; key++) {
|
||||
switch (key->type) {
|
||||
case KE_KEY:
|
||||
set_bit(EV_KEY, eeepc->inputdev->evbit);
|
||||
set_bit(key->keycode, eeepc->inputdev->keybit);
|
||||
break;
|
||||
}
|
||||
input->name = "Asus EeePC extra buttons";
|
||||
input->phys = EEEPC_LAPTOP_FILE "/input0";
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->dev.parent = &eeepc->platform_device->dev;
|
||||
|
||||
error = sparse_keymap_setup(input, eeepc_keymap, NULL);
|
||||
if (error) {
|
||||
pr_err("Unable to setup input device keymap\n");
|
||||
goto err_free_dev;
|
||||
}
|
||||
result = input_register_device(eeepc->inputdev);
|
||||
if (result) {
|
||||
pr_info("Unable to register input device\n");
|
||||
input_free_device(eeepc->inputdev);
|
||||
return result;
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
pr_err("Unable to register input device\n");
|
||||
goto err_free_keymap;
|
||||
}
|
||||
|
||||
eeepc->inputdev = input;
|
||||
return 0;
|
||||
|
||||
err_free_keymap:
|
||||
sparse_keymap_free(input);
|
||||
err_free_dev:
|
||||
input_free_device(input);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void eeepc_input_exit(struct eeepc_laptop *eeepc)
|
||||
@ -1253,11 +1227,59 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
|
||||
* event will be desired value (or else ignored)
|
||||
*/
|
||||
}
|
||||
eeepc_input_notify(eeepc, event);
|
||||
sparse_keymap_report_event(eeepc->inputdev, event,
|
||||
1, true);
|
||||
}
|
||||
} else {
|
||||
/* Everything else is a bona-fide keypress event */
|
||||
eeepc_input_notify(eeepc, event);
|
||||
sparse_keymap_report_event(eeepc->inputdev, event, 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
|
||||
{
|
||||
const char *model;
|
||||
|
||||
model = dmi_get_system_info(DMI_PRODUCT_NAME);
|
||||
if (!model)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Blacklist for setting cpufv (cpu speed).
|
||||
*
|
||||
* EeePC 4G ("701") implements CFVS, but it is not supported
|
||||
* by the pre-installed OS, and the original option to change it
|
||||
* in the BIOS setup screen was removed in later versions.
|
||||
*
|
||||
* Judging by the lack of "Super Hybrid Engine" on Asus product pages,
|
||||
* this applies to all "701" models (4G/4G Surf/2G Surf).
|
||||
*
|
||||
* So Asus made a deliberate decision not to support it on this model.
|
||||
* We have several reports that using it can cause the system to hang
|
||||
*
|
||||
* The hang has also been reported on a "702" (Model name "8G"?).
|
||||
*
|
||||
* We avoid dmi_check_system() / dmi_match(), because they use
|
||||
* substring matching. We don't want to affect the "701SD"
|
||||
* and "701SDX" models, because they do support S.H.E.
|
||||
*/
|
||||
if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
|
||||
eeepc->cpufv_disabled = true;
|
||||
pr_info("model %s does not officially support setting cpu "
|
||||
"speed\n", model);
|
||||
pr_info("cpufv disabled to avoid instability\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Blacklist for wlan hotplug
|
||||
*
|
||||
* Eeepc 1005HA doesn't work like others models and don't need the
|
||||
* hotplug code. In fact, current hotplug code seems to unplug another
|
||||
* device...
|
||||
*/
|
||||
if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) {
|
||||
eeepc->hotplug_disabled = true;
|
||||
pr_info("wlan hotplug disabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1342,6 +1364,10 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)
|
||||
strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
|
||||
device->driver_data = eeepc;
|
||||
|
||||
eeepc->hotplug_disabled = hotplug_disabled;
|
||||
|
||||
eeepc_dmi_check(eeepc);
|
||||
|
||||
result = eeepc_acpi_init(eeepc, device);
|
||||
if (result)
|
||||
goto fail_platform;
|
||||
@ -1452,10 +1478,12 @@ static int __init eeepc_laptop_init(void)
|
||||
result = acpi_bus_register_driver(&eeepc_acpi_driver);
|
||||
if (result < 0)
|
||||
goto fail_acpi_driver;
|
||||
|
||||
if (!eeepc_device_present) {
|
||||
result = -ENODEV;
|
||||
goto fail_no_device;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_no_device:
|
||||
|
@ -1201,9 +1201,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device)
|
||||
/* the buffer is filled with magic numbers describing the devices
|
||||
* available, 0xff terminates the enumeration
|
||||
*/
|
||||
while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff &&
|
||||
i < device_enum->buffer.length) {
|
||||
i++;
|
||||
for (i = 0; i < device_enum->buffer.length; i++) {
|
||||
|
||||
dev_code = *(device_enum->buffer.pointer + i);
|
||||
if (dev_code == 0xff)
|
||||
break;
|
||||
|
||||
dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
|
||||
|
||||
if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
|
||||
|
@ -328,15 +328,7 @@ static const struct pnp_device_id pnp_dev_table[] = {
|
||||
/* U.S. Robotics 56K Voice INT PnP*/
|
||||
{ "USR9190", 0 },
|
||||
/* Wacom tablets */
|
||||
{ "WACF004", 0 },
|
||||
{ "WACF005", 0 },
|
||||
{ "WACF006", 0 },
|
||||
{ "WACF007", 0 },
|
||||
{ "WACF008", 0 },
|
||||
{ "WACF009", 0 },
|
||||
{ "WACF00A", 0 },
|
||||
{ "WACF00B", 0 },
|
||||
{ "WACF00C", 0 },
|
||||
{ "WACFXXX", 0 },
|
||||
/* Compaq touchscreen */
|
||||
{ "FPI2002", 0 },
|
||||
/* Fujitsu Stylistic touchscreens */
|
||||
|
@ -1088,7 +1088,7 @@ imx_console_get_options(struct imx_port *sport, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
|
||||
if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) {
|
||||
if (readl(sport->port.membase + UCR1) & UCR1_UARTEN) {
|
||||
/* ok, the port was enabled */
|
||||
unsigned int ucr2, ubir,ubmr, uartclk;
|
||||
unsigned int baud_raw;
|
||||
|
@ -385,13 +385,20 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
|
||||
}
|
||||
|
||||
/*
|
||||
* As a last resort, if the quotient is zero,
|
||||
* default to 9600 bps
|
||||
* As a last resort, if the range cannot be met then clip to
|
||||
* the nearest chip supported rate.
|
||||
*/
|
||||
if (!hung_up)
|
||||
tty_termios_encode_baud_rate(termios, 9600, 9600);
|
||||
if (!hung_up) {
|
||||
if (baud <= min)
|
||||
tty_termios_encode_baud_rate(termios,
|
||||
min + 1, min + 1);
|
||||
else
|
||||
tty_termios_encode_baud_rate(termios,
|
||||
max - 1, max - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Should never happen */
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2006,12 +2013,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
|
||||
mutex_lock(&port->mutex);
|
||||
|
||||
if (!console_suspend_enabled && uart_console(uport)) {
|
||||
/* we're going to avoid suspending serial console */
|
||||
mutex_unlock(&port->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
|
||||
if (device_may_wakeup(tty_dev)) {
|
||||
enable_irq_wake(uport->irq);
|
||||
@ -2019,20 +2020,23 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
mutex_unlock(&port->mutex);
|
||||
return 0;
|
||||
}
|
||||
uport->suspended = 1;
|
||||
if (console_suspend_enabled || !uart_console(uport))
|
||||
uport->suspended = 1;
|
||||
|
||||
if (port->flags & ASYNC_INITIALIZED) {
|
||||
const struct uart_ops *ops = uport->ops;
|
||||
int tries;
|
||||
|
||||
set_bit(ASYNCB_SUSPENDED, &port->flags);
|
||||
clear_bit(ASYNCB_INITIALIZED, &port->flags);
|
||||
if (console_suspend_enabled || !uart_console(uport)) {
|
||||
set_bit(ASYNCB_SUSPENDED, &port->flags);
|
||||
clear_bit(ASYNCB_INITIALIZED, &port->flags);
|
||||
|
||||
spin_lock_irq(&uport->lock);
|
||||
ops->stop_tx(uport);
|
||||
ops->set_mctrl(uport, 0);
|
||||
ops->stop_rx(uport);
|
||||
spin_unlock_irq(&uport->lock);
|
||||
spin_lock_irq(&uport->lock);
|
||||
ops->stop_tx(uport);
|
||||
ops->set_mctrl(uport, 0);
|
||||
ops->stop_rx(uport);
|
||||
spin_unlock_irq(&uport->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the transmitter to empty.
|
||||
@ -2047,16 +2051,18 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
drv->dev_name,
|
||||
drv->tty_driver->name_base + uport->line);
|
||||
|
||||
ops->shutdown(uport);
|
||||
if (console_suspend_enabled || !uart_console(uport))
|
||||
ops->shutdown(uport);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the console device before suspending.
|
||||
*/
|
||||
if (uart_console(uport))
|
||||
if (console_suspend_enabled && uart_console(uport))
|
||||
console_stop(uport->cons);
|
||||
|
||||
uart_change_pm(state, 3);
|
||||
if (console_suspend_enabled || !uart_console(uport))
|
||||
uart_change_pm(state, 3);
|
||||
|
||||
mutex_unlock(&port->mutex);
|
||||
|
||||
@ -2073,29 +2079,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
|
||||
mutex_lock(&port->mutex);
|
||||
|
||||
if (!console_suspend_enabled && uart_console(uport)) {
|
||||
/* no need to resume serial console, it wasn't suspended */
|
||||
/*
|
||||
* First try to use the console cflag setting.
|
||||
*/
|
||||
memset(&termios, 0, sizeof(struct ktermios));
|
||||
termios.c_cflag = uport->cons->cflag;
|
||||
/*
|
||||
* If that's unset, use the tty termios setting.
|
||||
*/
|
||||
if (termios.c_cflag == 0)
|
||||
termios = *state->port.tty->termios;
|
||||
else {
|
||||
termios.c_ispeed = termios.c_ospeed =
|
||||
tty_termios_input_baud_rate(&termios);
|
||||
termios.c_ispeed = termios.c_ospeed =
|
||||
tty_termios_baud_rate(&termios);
|
||||
}
|
||||
uport->ops->set_termios(uport, &termios, NULL);
|
||||
mutex_unlock(&port->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
|
||||
if (!uport->suspended && device_may_wakeup(tty_dev)) {
|
||||
disable_irq_wake(uport->irq);
|
||||
@ -2121,21 +2104,23 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
spin_lock_irq(&uport->lock);
|
||||
ops->set_mctrl(uport, 0);
|
||||
spin_unlock_irq(&uport->lock);
|
||||
ret = ops->startup(uport);
|
||||
if (ret == 0) {
|
||||
uart_change_speed(state, NULL);
|
||||
spin_lock_irq(&uport->lock);
|
||||
ops->set_mctrl(uport, uport->mctrl);
|
||||
ops->start_tx(uport);
|
||||
spin_unlock_irq(&uport->lock);
|
||||
set_bit(ASYNCB_INITIALIZED, &port->flags);
|
||||
} else {
|
||||
/*
|
||||
* Failed to resume - maybe hardware went away?
|
||||
* Clear the "initialized" flag so we won't try
|
||||
* to call the low level drivers shutdown method.
|
||||
*/
|
||||
uart_shutdown(state);
|
||||
if (console_suspend_enabled || !uart_console(uport)) {
|
||||
ret = ops->startup(uport);
|
||||
if (ret == 0) {
|
||||
uart_change_speed(state, NULL);
|
||||
spin_lock_irq(&uport->lock);
|
||||
ops->set_mctrl(uport, uport->mctrl);
|
||||
ops->start_tx(uport);
|
||||
spin_unlock_irq(&uport->lock);
|
||||
set_bit(ASYNCB_INITIALIZED, &port->flags);
|
||||
} else {
|
||||
/*
|
||||
* Failed to resume - maybe hardware went away?
|
||||
* Clear the "initialized" flag so we won't try
|
||||
* to call the low level drivers shutdown method.
|
||||
*/
|
||||
uart_shutdown(state);
|
||||
}
|
||||
}
|
||||
|
||||
clear_bit(ASYNCB_SUSPENDED, &port->flags);
|
||||
|
@ -146,7 +146,8 @@ static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
|
||||
{
|
||||
struct serial_info *info = link->priv;
|
||||
|
||||
outb(12, info->c950ctrl + 1);
|
||||
if (info->c950ctrl)
|
||||
outb(12, info->c950ctrl + 1);
|
||||
}
|
||||
|
||||
/* request_region? oxsemi branch does no request_region too... */
|
||||
|
@ -194,9 +194,11 @@ static ssize_t set_enabled(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct asus_oled_dev *odev = usb_get_intfdata(intf);
|
||||
int temp = strict_strtoul(buf, 10, NULL);
|
||||
unsigned long value;
|
||||
if (strict_strtoul(buf, 10, &value))
|
||||
return -EINVAL;
|
||||
|
||||
enable_oled(odev, temp);
|
||||
enable_oled(odev, value);
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -207,10 +209,12 @@ static ssize_t class_set_enabled(struct device *device,
|
||||
{
|
||||
struct asus_oled_dev *odev =
|
||||
(struct asus_oled_dev *) dev_get_drvdata(device);
|
||||
unsigned long value;
|
||||
|
||||
int temp = strict_strtoul(buf, 10, NULL);
|
||||
if (strict_strtoul(buf, 10, &value))
|
||||
return -EINVAL;
|
||||
|
||||
enable_oled(odev, temp);
|
||||
enable_oled(odev, value);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -203,11 +203,14 @@ typedef struct _GLOBAL_t { /* Location: */
|
||||
* 9-0: pr ndes
|
||||
*/
|
||||
|
||||
#define ET_DMA10_MASK 0x3FF /* 10 bit mask for DMA10W types */
|
||||
#define ET_DMA10_WRAP 0x400
|
||||
#define ET_DMA4_MASK 0x00F /* 4 bit mask for DMA4W types */
|
||||
#define ET_DMA4_WRAP 0x010
|
||||
#define ET_DMA12_MASK 0x0FFF /* 12 bit mask for DMA12W types */
|
||||
#define ET_DMA12_WRAP 0x1000
|
||||
#define ET_DMA10_MASK 0x03FF /* 10 bit mask for DMA10W types */
|
||||
#define ET_DMA10_WRAP 0x0400
|
||||
#define ET_DMA4_MASK 0x000F /* 4 bit mask for DMA4W types */
|
||||
#define ET_DMA4_WRAP 0x0010
|
||||
|
||||
#define INDEX12(x) ((x) & ET_DMA12_MASK)
|
||||
#define INDEX10(x) ((x) & ET_DMA10_MASK)
|
||||
#define INDEX4(x) ((x) & ET_DMA4_MASK)
|
||||
|
||||
@ -216,6 +219,11 @@ extern inline void add_10bit(u32 *v, int n)
|
||||
*v = INDEX10(*v + n) | (*v & ET_DMA10_WRAP);
|
||||
}
|
||||
|
||||
extern inline void add_12bit(u32 *v, int n)
|
||||
{
|
||||
*v = INDEX12(*v + n) | (*v & ET_DMA12_WRAP);
|
||||
}
|
||||
|
||||
/*
|
||||
* 10bit DMA with wrap
|
||||
* txdma tx queue write address reg in txdma address map at 0x1010
|
||||
|
@ -831,10 +831,10 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
|
||||
|
||||
/* Indicate that we have used this PSR entry. */
|
||||
/* FIXME wrap 12 */
|
||||
rx_local->local_psr_full = (rx_local->local_psr_full + 1) & 0xFFF;
|
||||
if (rx_local->local_psr_full > rx_local->PsrNumEntries - 1) {
|
||||
add_12bit(&rx_local->local_psr_full, 1);
|
||||
if ((rx_local->local_psr_full & 0xFFF) > rx_local->PsrNumEntries - 1) {
|
||||
/* Clear psr full and toggle the wrap bit */
|
||||
rx_local->local_psr_full &= 0xFFF;
|
||||
rx_local->local_psr_full &= ~0xFFF;
|
||||
rx_local->local_psr_full ^= 0x1000;
|
||||
}
|
||||
|
||||
|
@ -386,7 +386,7 @@ u16 HvSignalEvent(void)
|
||||
* retrieve the initialized message and event pages. Otherwise, we create and
|
||||
* initialize the message and event pages.
|
||||
*/
|
||||
int HvSynicInit(u32 irqVector)
|
||||
void HvSynicInit(void *irqarg)
|
||||
{
|
||||
u64 version;
|
||||
union hv_synic_simp simp;
|
||||
@ -394,13 +394,14 @@ int HvSynicInit(u32 irqVector)
|
||||
union hv_synic_sint sharedSint;
|
||||
union hv_synic_scontrol sctrl;
|
||||
u64 guestID;
|
||||
int ret = 0;
|
||||
u32 irqVector = *((u32 *)(irqarg));
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
DPRINT_ENTER(VMBUS);
|
||||
|
||||
if (!gHvContext.HypercallPage) {
|
||||
DPRINT_EXIT(VMBUS);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check the version */
|
||||
@ -425,27 +426,27 @@ int HvSynicInit(u32 irqVector)
|
||||
*/
|
||||
rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);
|
||||
if (guestID == HV_LINUX_GUEST_ID) {
|
||||
gHvContext.synICMessagePage[0] =
|
||||
gHvContext.synICMessagePage[cpu] =
|
||||
phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT);
|
||||
gHvContext.synICEventPage[0] =
|
||||
gHvContext.synICEventPage[cpu] =
|
||||
phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);
|
||||
} else {
|
||||
DPRINT_ERR(VMBUS, "unknown guest id!!");
|
||||
goto Cleanup;
|
||||
}
|
||||
DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p",
|
||||
gHvContext.synICMessagePage[0],
|
||||
gHvContext.synICEventPage[0]);
|
||||
gHvContext.synICMessagePage[cpu],
|
||||
gHvContext.synICEventPage[cpu]);
|
||||
} else {
|
||||
gHvContext.synICMessagePage[0] = osd_PageAlloc(1);
|
||||
if (gHvContext.synICMessagePage[0] == NULL) {
|
||||
gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
|
||||
if (gHvContext.synICMessagePage[cpu] == NULL) {
|
||||
DPRINT_ERR(VMBUS,
|
||||
"unable to allocate SYNIC message page!!");
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
gHvContext.synICEventPage[0] = osd_PageAlloc(1);
|
||||
if (gHvContext.synICEventPage[0] == NULL) {
|
||||
gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
|
||||
if (gHvContext.synICEventPage[cpu] == NULL) {
|
||||
DPRINT_ERR(VMBUS,
|
||||
"unable to allocate SYNIC event page!!");
|
||||
goto Cleanup;
|
||||
@ -454,7 +455,7 @@ int HvSynicInit(u32 irqVector)
|
||||
/* Setup the Synic's message page */
|
||||
rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
|
||||
simp.SimpEnabled = 1;
|
||||
simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0])
|
||||
simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
|
||||
>> PAGE_SHIFT;
|
||||
|
||||
DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx",
|
||||
@ -465,7 +466,7 @@ int HvSynicInit(u32 irqVector)
|
||||
/* Setup the Synic's event page */
|
||||
rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
|
||||
siefp.SiefpEnabled = 1;
|
||||
siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0])
|
||||
siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
|
||||
>> PAGE_SHIFT;
|
||||
|
||||
DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx",
|
||||
@ -501,32 +502,30 @@ int HvSynicInit(u32 irqVector)
|
||||
|
||||
DPRINT_EXIT(VMBUS);
|
||||
|
||||
return ret;
|
||||
return;
|
||||
|
||||
Cleanup:
|
||||
ret = -1;
|
||||
|
||||
if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
|
||||
if (gHvContext.synICEventPage[0])
|
||||
osd_PageFree(gHvContext.synICEventPage[0], 1);
|
||||
if (gHvContext.synICEventPage[cpu])
|
||||
osd_PageFree(gHvContext.synICEventPage[cpu], 1);
|
||||
|
||||
if (gHvContext.synICMessagePage[0])
|
||||
osd_PageFree(gHvContext.synICMessagePage[0], 1);
|
||||
if (gHvContext.synICMessagePage[cpu])
|
||||
osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
|
||||
}
|
||||
|
||||
DPRINT_EXIT(VMBUS);
|
||||
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* HvSynicCleanup - Cleanup routine for HvSynicInit().
|
||||
*/
|
||||
void HvSynicCleanup(void)
|
||||
void HvSynicCleanup(void *arg)
|
||||
{
|
||||
union hv_synic_sint sharedSint;
|
||||
union hv_synic_simp simp;
|
||||
union hv_synic_siefp siefp;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
DPRINT_ENTER(VMBUS);
|
||||
|
||||
@ -539,6 +538,7 @@ void HvSynicCleanup(void)
|
||||
|
||||
sharedSint.Masked = 1;
|
||||
|
||||
/* Need to correctly cleanup in the case of SMP!!! */
|
||||
/* Disable the interrupt */
|
||||
wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
|
||||
|
||||
@ -560,8 +560,8 @@ void HvSynicCleanup(void)
|
||||
|
||||
wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
|
||||
|
||||
osd_PageFree(gHvContext.synICMessagePage[0], 1);
|
||||
osd_PageFree(gHvContext.synICEventPage[0], 1);
|
||||
osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
|
||||
osd_PageFree(gHvContext.synICEventPage[cpu], 1);
|
||||
}
|
||||
|
||||
DPRINT_EXIT(VMBUS);
|
||||
|
@ -93,7 +93,7 @@ static const struct hv_guid VMBUS_SERVICE_ID = {
|
||||
},
|
||||
};
|
||||
|
||||
#define MAX_NUM_CPUS 1
|
||||
#define MAX_NUM_CPUS 32
|
||||
|
||||
|
||||
struct hv_input_signal_event_buffer {
|
||||
@ -137,8 +137,8 @@ extern u16 HvPostMessage(union hv_connection_id connectionId,
|
||||
|
||||
extern u16 HvSignalEvent(void);
|
||||
|
||||
extern int HvSynicInit(u32 irqVector);
|
||||
extern void HvSynicInit(void *irqarg);
|
||||
|
||||
extern void HvSynicCleanup(void);
|
||||
extern void HvSynicCleanup(void *arg);
|
||||
|
||||
#endif /* __HV_H__ */
|
||||
|
@ -129,7 +129,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
|
||||
|
||||
/* strcpy(dev->name, "vmbus"); */
|
||||
/* SynIC setup... */
|
||||
ret = HvSynicInit(*irqvector);
|
||||
on_each_cpu(HvSynicInit, (void *)irqvector, 1);
|
||||
|
||||
/* Connect to VMBus in the root partition */
|
||||
ret = VmbusConnect();
|
||||
@ -150,7 +150,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev)
|
||||
DPRINT_ENTER(VMBUS);
|
||||
VmbusChannelReleaseUnattachedChannels();
|
||||
VmbusDisconnect();
|
||||
HvSynicCleanup();
|
||||
on_each_cpu(HvSynicCleanup, NULL, 1);
|
||||
DPRINT_EXIT(VMBUS);
|
||||
|
||||
return ret;
|
||||
@ -173,7 +173,8 @@ static void VmbusOnCleanup(struct hv_driver *drv)
|
||||
*/
|
||||
static void VmbusOnMsgDPC(struct hv_driver *drv)
|
||||
{
|
||||
void *page_addr = gHvContext.synICMessagePage[0];
|
||||
int cpu = smp_processor_id();
|
||||
void *page_addr = gHvContext.synICMessagePage[cpu];
|
||||
struct hv_message *msg = (struct hv_message *)page_addr +
|
||||
VMBUS_MESSAGE_SINT;
|
||||
struct hv_message *copied;
|
||||
@ -230,11 +231,12 @@ static void VmbusOnEventDPC(struct hv_driver *drv)
|
||||
static int VmbusOnISR(struct hv_driver *drv)
|
||||
{
|
||||
int ret = 0;
|
||||
int cpu = smp_processor_id();
|
||||
void *page_addr;
|
||||
struct hv_message *msg;
|
||||
union hv_synic_event_flags *event;
|
||||
|
||||
page_addr = gHvContext.synICMessagePage[0];
|
||||
page_addr = gHvContext.synICMessagePage[cpu];
|
||||
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
|
||||
|
||||
DPRINT_ENTER(VMBUS);
|
||||
@ -248,7 +250,7 @@ static int VmbusOnISR(struct hv_driver *drv)
|
||||
}
|
||||
|
||||
/* TODO: Check if there are events to be process */
|
||||
page_addr = gHvContext.synICEventPage[0];
|
||||
page_addr = gHvContext.synICEventPage[cpu];
|
||||
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
|
||||
|
||||
/* Since we are a child, we only need to check bit 0 */
|
||||
|
@ -494,7 +494,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
|
||||
return 0;
|
||||
/* allocate 2^1 pages = 8K (on i386);
|
||||
* should be more than enough for one device */
|
||||
pages_start = (char *)__get_free_pages(GFP_KERNEL, 1);
|
||||
pages_start = (char *)__get_free_pages(GFP_NOIO, 1);
|
||||
if (!pages_start)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1684,6 +1684,24 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,
|
||||
}
|
||||
}
|
||||
if (cur_alt && new_alt) {
|
||||
struct usb_interface *iface = usb_ifnum_to_if(udev,
|
||||
cur_alt->desc.bInterfaceNumber);
|
||||
|
||||
if (iface->resetting_device) {
|
||||
/*
|
||||
* The USB core just reset the device, so the xHCI host
|
||||
* and the device will think alt setting 0 is installed.
|
||||
* However, the USB core will pass in the alternate
|
||||
* setting installed before the reset as cur_alt. Dig
|
||||
* out the alternate setting 0 structure, or the first
|
||||
* alternate setting if a broken device doesn't have alt
|
||||
* setting 0.
|
||||
*/
|
||||
cur_alt = usb_altnum_to_altsetting(iface, 0);
|
||||
if (!cur_alt)
|
||||
cur_alt = &iface->altsetting[0];
|
||||
}
|
||||
|
||||
/* Drop all the endpoints in the current alt setting */
|
||||
for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) {
|
||||
ret = hcd->driver->drop_endpoint(hcd, udev,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user