Merge commit 'v2.6.27-rc6' into sched/devel
This commit is contained in:
commit
09b22a2f67
|
@ -144,8 +144,8 @@ prototypes:
|
|||
void (*kill_sb) (struct super_block *);
|
||||
locking rules:
|
||||
may block BKL
|
||||
get_sb yes yes
|
||||
kill_sb yes yes
|
||||
get_sb yes no
|
||||
kill_sb yes no
|
||||
|
||||
->get_sb() returns error or 0 with locked superblock attached to the vfsmount
|
||||
(exclusive on ->s_umount).
|
||||
|
@ -409,12 +409,12 @@ ioctl: yes (see below)
|
|||
unlocked_ioctl: no (see below)
|
||||
compat_ioctl: no
|
||||
mmap: no
|
||||
open: maybe (see below)
|
||||
open: no
|
||||
flush: no
|
||||
release: no
|
||||
fsync: no (see below)
|
||||
aio_fsync: no
|
||||
fasync: yes (see below)
|
||||
fasync: no
|
||||
lock: yes
|
||||
readv: no
|
||||
writev: no
|
||||
|
@ -431,13 +431,6 @@ For many filesystems, it is probably safe to acquire the inode
|
|||
semaphore. Note some filesystems (i.e. remote ones) provide no
|
||||
protection for i_size so you will need to use the BKL.
|
||||
|
||||
->open() locking is in-transit: big lock partially moved into the methods.
|
||||
The only exception is ->open() in the instances of file_operations that never
|
||||
end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices
|
||||
(chrdev_open() takes lock before replacing ->f_op and calling the secondary
|
||||
method. As soon as we fix the handling of module reference counters all
|
||||
instances of ->open() will be called without the BKL.
|
||||
|
||||
Note: ext2_release() was *the* source of contention on fs-intensive
|
||||
loads and dropping BKL on ->release() helps to get rid of that (we still
|
||||
grab BKL for cases when we close a file that had been opened r/w, but that
|
||||
|
|
|
@ -750,11 +750,13 @@ P: Ville Syrjala
|
|||
M: syrjala@sci.fi
|
||||
S: Maintained
|
||||
|
||||
ATL1 ETHERNET DRIVER
|
||||
ATLX ETHERNET DRIVERS
|
||||
P: Jay Cliburn
|
||||
M: jcliburn@gmail.com
|
||||
P: Chris Snook
|
||||
M: csnook@redhat.com
|
||||
P: Jie Yang
|
||||
M: jie.yang@atheros.com
|
||||
L: atl1-devel@lists.sourceforge.net
|
||||
W: http://sourceforge.net/projects/atl1
|
||||
W: http://atl1.sourceforge.net
|
||||
|
@ -1593,7 +1595,7 @@ S: Supported
|
|||
EMBEDDED LINUX
|
||||
P: Paul Gortmaker
|
||||
M: paul.gortmaker@windriver.com
|
||||
P David Woodhouse
|
||||
P: David Woodhouse
|
||||
M: dwmw2@infradead.org
|
||||
L: linux-embedded@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 27
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Rotary Wombat
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -61,8 +61,9 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
|
|||
#define MT_DEVICE_NONSHARED 1
|
||||
#define MT_DEVICE_CACHED 2
|
||||
#define MT_DEVICE_IXP2000 3
|
||||
#define MT_DEVICE_WC 4
|
||||
/*
|
||||
* types 4 onwards can be found in asm/mach/map.h and are undefined
|
||||
* types 5 onwards can be found in asm/mach/map.h and are undefined
|
||||
* for ioremap
|
||||
*/
|
||||
|
||||
|
@ -215,11 +216,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
|
|||
#define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
|
||||
#define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
|
||||
#define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
|
||||
#define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC)
|
||||
#define iounmap(cookie) __iounmap(cookie)
|
||||
#else
|
||||
#define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
|
||||
#define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
|
||||
#define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
|
||||
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
|
||||
#define iounmap(cookie) __arch_iounmap(cookie)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,13 +18,13 @@ struct map_desc {
|
|||
unsigned int type;
|
||||
};
|
||||
|
||||
/* types 0-3 are defined in asm/io.h */
|
||||
#define MT_CACHECLEAN 4
|
||||
#define MT_MINICLEAN 5
|
||||
#define MT_LOW_VECTORS 6
|
||||
#define MT_HIGH_VECTORS 7
|
||||
#define MT_MEMORY 8
|
||||
#define MT_ROM 9
|
||||
/* types 0-4 are defined in asm/io.h */
|
||||
#define MT_CACHECLEAN 5
|
||||
#define MT_MINICLEAN 6
|
||||
#define MT_LOW_VECTORS 7
|
||||
#define MT_HIGH_VECTORS 8
|
||||
#define MT_MEMORY 9
|
||||
#define MT_ROM 10
|
||||
|
||||
#define MT_NONSHARED_DEVICE MT_DEVICE_NONSHARED
|
||||
#define MT_IXP2000_DEVICE MT_DEVICE_IXP2000
|
||||
|
|
|
@ -159,6 +159,7 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
|
|||
#ifdef CONFIG_ARCH_OMAP730
|
||||
static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
|
||||
{
|
||||
.phys_base = OMAP730_MCBSP1_BASE,
|
||||
.virt_base = io_p2v(OMAP730_MCBSP1_BASE),
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP1_TX,
|
||||
|
@ -167,6 +168,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
|
|||
.ops = &omap1_mcbsp_ops,
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP730_MCBSP2_BASE,
|
||||
.virt_base = io_p2v(OMAP730_MCBSP2_BASE),
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP3_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP3_TX,
|
||||
|
@ -184,6 +186,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
|
|||
#ifdef CONFIG_ARCH_OMAP15XX
|
||||
static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
|
||||
{
|
||||
.phys_base = OMAP1510_MCBSP1_BASE,
|
||||
.virt_base = OMAP1510_MCBSP1_BASE,
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP1_TX,
|
||||
|
@ -193,6 +196,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
|
|||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP1510_MCBSP2_BASE,
|
||||
.virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP2_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP2_TX,
|
||||
|
@ -201,6 +205,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
|
|||
.ops = &omap1_mcbsp_ops,
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP1510_MCBSP3_BASE,
|
||||
.virt_base = OMAP1510_MCBSP3_BASE,
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP3_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP3_TX,
|
||||
|
@ -219,6 +224,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
|
|||
#ifdef CONFIG_ARCH_OMAP16XX
|
||||
static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
|
||||
{
|
||||
.phys_base = OMAP1610_MCBSP1_BASE,
|
||||
.virt_base = OMAP1610_MCBSP1_BASE,
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP1_TX,
|
||||
|
@ -228,6 +234,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
|
|||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP1610_MCBSP2_BASE,
|
||||
.virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP2_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP2_TX,
|
||||
|
@ -236,6 +243,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
|
|||
.ops = &omap1_mcbsp_ops,
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP1610_MCBSP3_BASE,
|
||||
.virt_base = OMAP1610_MCBSP3_BASE,
|
||||
.dma_rx_sync = OMAP_DMA_MCBSP3_RX,
|
||||
.dma_tx_sync = OMAP_DMA_MCBSP3_TX,
|
||||
|
|
|
@ -134,6 +134,7 @@ static struct omap_mcbsp_ops omap2_mcbsp_ops = {
|
|||
#ifdef CONFIG_ARCH_OMAP24XX
|
||||
static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
|
||||
{
|
||||
.phys_base = OMAP24XX_MCBSP1_BASE,
|
||||
.virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
|
||||
|
@ -143,6 +144,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
|
|||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP24XX_MCBSP2_BASE,
|
||||
.virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
|
||||
|
@ -161,6 +163,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
|
|||
#ifdef CONFIG_ARCH_OMAP34XX
|
||||
static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
||||
{
|
||||
.phys_base = OMAP34XX_MCBSP1_BASE,
|
||||
.virt_base = IO_ADDRESS(OMAP34XX_MCBSP1_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
|
||||
|
@ -170,6 +173,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
|||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP34XX_MCBSP2_BASE,
|
||||
.virt_base = IO_ADDRESS(OMAP34XX_MCBSP2_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
|
||||
|
|
|
@ -211,6 +211,12 @@ static struct mem_type mem_types[] = {
|
|||
PMD_SECT_TEX(1),
|
||||
.domain = DOMAIN_IO,
|
||||
},
|
||||
[MT_DEVICE_WC] = { /* ioremap_wc */
|
||||
.prot_pte = PROT_PTE_DEVICE,
|
||||
.prot_l1 = PMD_TYPE_TABLE,
|
||||
.prot_sect = PROT_SECT_DEVICE,
|
||||
.domain = DOMAIN_IO,
|
||||
},
|
||||
[MT_CACHECLEAN] = {
|
||||
.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
|
@ -272,6 +278,20 @@ static void __init build_mem_type_table(void)
|
|||
ecc_mask = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On non-Xscale3 ARMv5-and-older systems, use CB=01
|
||||
* (Uncached/Buffered) for ioremap_wc() mappings. On XScale3
|
||||
* and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable
|
||||
* in xsc3 parlance, Uncached Normal in ARMv6 parlance).
|
||||
*/
|
||||
if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) {
|
||||
mem_types[MT_DEVICE_WC].prot_pte_ext |= PTE_EXT_TEX(1);
|
||||
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
|
||||
} else {
|
||||
mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_BUFFERABLE;
|
||||
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ARMv5 and lower, bit 4 must be set for page tables.
|
||||
* (was: cache "update-able on write" bit on ARM610)
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
|
||||
|
|
|
@ -1488,7 +1488,7 @@ static int __init _omap_gpio_init(void)
|
|||
bank->chip.set = gpio_set;
|
||||
if (bank_is_mpuio(bank)) {
|
||||
bank->chip.label = "mpuio";
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#ifdef CONFIG_ARCH_OMAP16XX
|
||||
bank->chip.dev = &omap_mpuio_device.dev;
|
||||
#endif
|
||||
bank->chip.base = OMAP_MPUIO(0);
|
||||
|
|
|
@ -315,6 +315,7 @@ struct omap_mcbsp_ops {
|
|||
};
|
||||
|
||||
struct omap_mcbsp_platform_data {
|
||||
unsigned long phys_base;
|
||||
u32 virt_base;
|
||||
u8 dma_rx_sync, dma_tx_sync;
|
||||
u16 rx_irq, tx_irq;
|
||||
|
@ -324,6 +325,7 @@ struct omap_mcbsp_platform_data {
|
|||
|
||||
struct omap_mcbsp {
|
||||
struct device *dev;
|
||||
unsigned long phys_base;
|
||||
u32 io_base;
|
||||
u8 id;
|
||||
u8 free;
|
||||
|
|
|
@ -651,7 +651,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
|
|||
omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
|
||||
src_port,
|
||||
OMAP_DMA_AMODE_CONSTANT,
|
||||
mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
|
||||
mcbsp[id].phys_base + OMAP_MCBSP_REG_DXR1,
|
||||
0, 0);
|
||||
|
||||
omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
|
||||
|
@ -712,7 +712,7 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
|
|||
omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
|
||||
src_port,
|
||||
OMAP_DMA_AMODE_CONSTANT,
|
||||
mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
|
||||
mcbsp[id].phys_base + OMAP_MCBSP_REG_DRR1,
|
||||
0, 0);
|
||||
|
||||
omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
|
||||
|
@ -830,6 +830,7 @@ static int __init omap_mcbsp_probe(struct platform_device *pdev)
|
|||
mcbsp[id].dma_tx_lch = -1;
|
||||
mcbsp[id].dma_rx_lch = -1;
|
||||
|
||||
mcbsp[id].phys_base = pdata->phys_base;
|
||||
mcbsp[id].io_base = pdata->virt_base;
|
||||
/* Default I/O is IRQ based */
|
||||
mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* to extract and format the required data.
|
||||
*/
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/kbuild.h>
|
||||
|
||||
|
@ -17,4 +19,8 @@ void foo(void)
|
|||
OFFSET(TI_rar_saved, thread_info, rar_saved);
|
||||
OFFSET(TI_rsr_saved, thread_info, rsr_saved);
|
||||
OFFSET(TI_restart_block, thread_info, restart_block);
|
||||
BLANK();
|
||||
OFFSET(TSK_active_mm, task_struct, active_mm);
|
||||
BLANK();
|
||||
OFFSET(MM_pgd, mm_struct, pgd);
|
||||
}
|
||||
|
|
|
@ -334,9 +334,64 @@ save_full_context_ex:
|
|||
|
||||
/* Low-level exception handlers */
|
||||
handle_critical:
|
||||
/*
|
||||
* AT32AP700x errata:
|
||||
*
|
||||
* After a Java stack overflow or underflow trap, any CPU
|
||||
* memory access may cause erratic behavior. This will happen
|
||||
* when the four least significant bits of the JOSP system
|
||||
* register contains any value between 9 and 15 (inclusive).
|
||||
*
|
||||
* Possible workarounds:
|
||||
* - Don't use the Java Extension Module
|
||||
* - Ensure that the stack overflow and underflow trap
|
||||
* handlers do not do any memory access or trigger any
|
||||
* exceptions before the overflow/underflow condition is
|
||||
* cleared (by incrementing or decrementing the JOSP)
|
||||
* - Make sure that JOSP does not contain any problematic
|
||||
* value before doing any exception or interrupt
|
||||
* processing.
|
||||
* - Set up a critical exception handler which writes a
|
||||
* known-to-be-safe value, e.g. 4, to JOSP before doing
|
||||
* any further processing.
|
||||
*
|
||||
* We'll use the last workaround for now since we cannot
|
||||
* guarantee that user space processes don't use Java mode.
|
||||
* Non-well-behaving userland will be terminated with extreme
|
||||
* prejudice.
|
||||
*/
|
||||
#ifdef CONFIG_CPU_AT32AP700X
|
||||
/*
|
||||
* There's a chance we can't touch memory, so temporarily
|
||||
* borrow PTBR to save the stack pointer while we fix things
|
||||
* up...
|
||||
*/
|
||||
mtsr SYSREG_PTBR, sp
|
||||
mov sp, 4
|
||||
mtsr SYSREG_JOSP, sp
|
||||
mfsr sp, SYSREG_PTBR
|
||||
sub pc, -2
|
||||
|
||||
/* Push most of pt_regs on stack. We'll do the rest later */
|
||||
sub sp, 4
|
||||
stmts --sp, r0-lr
|
||||
rcall save_full_context_ex
|
||||
pushm r0-r12
|
||||
|
||||
/* PTBR mirrors current_thread_info()->task->active_mm->pgd */
|
||||
get_thread_info r0
|
||||
ld.w r1, r0[TI_task]
|
||||
ld.w r2, r1[TSK_active_mm]
|
||||
ld.w r3, r2[MM_pgd]
|
||||
mtsr SYSREG_PTBR, r3
|
||||
#else
|
||||
sub sp, 4
|
||||
pushm r0-r12
|
||||
#endif
|
||||
sub r0, sp, -(14 * 4)
|
||||
mov r1, lr
|
||||
mfsr r2, SYSREG_RAR_EX
|
||||
mfsr r3, SYSREG_RSR_EX
|
||||
pushm r0-r3
|
||||
|
||||
mfsr r12, SYSREG_ECR
|
||||
mov r11, sp
|
||||
rcall do_critical_exception
|
||||
|
|
|
@ -134,7 +134,7 @@ pm_standby:
|
|||
mov r11, SDRAMC_LPR_LPCB_SELF_RFR
|
||||
bfins r10, r11, 0, 2 /* LPCB <- self Refresh */
|
||||
sync 0 /* flush write buffer */
|
||||
st.w r12[SDRAMC_LPR], r11 /* put SDRAM in self-refresh mode */
|
||||
st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */
|
||||
ld.w r11, r12[SDRAMC_LPR]
|
||||
unmask_interrupts
|
||||
sleep CPU_SLEEP_FROZEN
|
||||
|
|
|
@ -21,5 +21,8 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b
|
|||
extern char __start_unwind[], __end_unwind[];
|
||||
extern char __start_ivt_text[], __end_ivt_text[];
|
||||
|
||||
#undef dereference_function_descriptor
|
||||
void *dereference_function_descriptor(void *);
|
||||
|
||||
#endif /* _ASM_IA64_SECTIONS_H */
|
||||
|
||||
|
|
|
@ -31,9 +31,11 @@
|
|||
#include <linux/elf.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/patch.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define ARCH_MODULE_DEBUG 0
|
||||
|
@ -941,3 +943,13 @@ module_arch_cleanup (struct module *mod)
|
|||
if (mod->arch.core_unw_table)
|
||||
unw_remove_unwind_table(mod->arch.core_unw_table);
|
||||
}
|
||||
|
||||
void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
struct fdesc *desc = ptr;
|
||||
void *p;
|
||||
|
||||
if (!probe_kernel_address(&desc->ip, p))
|
||||
ptr = p;
|
||||
return ptr;
|
||||
}
|
||||
|
|
|
@ -1886,6 +1886,15 @@ config STACKTRACE_SUPPORT
|
|||
|
||||
source "init/Kconfig"
|
||||
|
||||
config PROBE_INITRD_HEADER
|
||||
bool "Probe initrd header created by addinitrd"
|
||||
depends on BLK_DEV_INITRD
|
||||
help
|
||||
Probe initrd header at the last page of kernel image.
|
||||
Say Y here if you are using arch/mips/boot/addinitrd.c to
|
||||
add initrd or initramfs image to the kernel image.
|
||||
Otherwise, say N.
|
||||
|
||||
menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
|
||||
|
||||
config HW_HAS_EISA
|
||||
|
|
|
@ -160,30 +160,33 @@ early_param("rd_size", rd_size_early);
|
|||
static unsigned long __init init_initrd(void)
|
||||
{
|
||||
unsigned long end;
|
||||
u32 *initrd_header;
|
||||
|
||||
/*
|
||||
* Board specific code or command line parser should have
|
||||
* already set up initrd_start and initrd_end. In these cases
|
||||
* perfom sanity checks and use them if all looks good.
|
||||
*/
|
||||
if (initrd_start && initrd_end > initrd_start)
|
||||
goto sanitize;
|
||||
if (!initrd_start || initrd_end <= initrd_start) {
|
||||
#ifdef CONFIG_PROBE_INITRD_HEADER
|
||||
u32 *initrd_header;
|
||||
|
||||
/*
|
||||
* See if initrd has been added to the kernel image by
|
||||
* arch/mips/boot/addinitrd.c. In that case a header is
|
||||
* prepended to initrd and is made up by 8 bytes. The fisrt
|
||||
* word is a magic number and the second one is the size of
|
||||
* initrd. Initrd start must be page aligned in any cases.
|
||||
*/
|
||||
initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
|
||||
if (initrd_header[0] != 0x494E5244)
|
||||
/*
|
||||
* See if initrd has been added to the kernel image by
|
||||
* arch/mips/boot/addinitrd.c. In that case a header is
|
||||
* prepended to initrd and is made up by 8 bytes. The first
|
||||
* word is a magic number and the second one is the size of
|
||||
* initrd. Initrd start must be page aligned in any cases.
|
||||
*/
|
||||
initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
|
||||
if (initrd_header[0] != 0x494E5244)
|
||||
goto disable;
|
||||
initrd_start = (unsigned long)(initrd_header + 2);
|
||||
initrd_end = initrd_start + initrd_header[1];
|
||||
#else
|
||||
goto disable;
|
||||
initrd_start = (unsigned long)(initrd_header + 2);
|
||||
initrd_end = initrd_start + initrd_header[1];
|
||||
#endif
|
||||
}
|
||||
|
||||
sanitize:
|
||||
if (initrd_start & ~PAGE_MASK) {
|
||||
pr_err("initrd start must be page aligned\n");
|
||||
goto disable;
|
||||
|
|
|
@ -373,8 +373,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs)
|
|||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
extern const struct exception_table_entry __start___dbe_table[];
|
||||
extern const struct exception_table_entry __stop___dbe_table[];
|
||||
extern struct exception_table_entry __start___dbe_table[];
|
||||
extern struct exception_table_entry __stop___dbe_table[];
|
||||
|
||||
__asm__(
|
||||
" .section __dbe_table, \"a\"\n"
|
||||
|
@ -1200,7 +1200,7 @@ void *set_except_vector(int n, void *addr)
|
|||
if (n == 0 && cpu_has_divec) {
|
||||
*(u32 *)(ebase + 0x200) = 0x08000000 |
|
||||
(0x03ffffff & (handler >> 2));
|
||||
flush_icache_range(ebase + 0x200, ebase + 0x204);
|
||||
local_flush_icache_range(ebase + 0x200, ebase + 0x204);
|
||||
}
|
||||
return (void *)old_handler;
|
||||
}
|
||||
|
@ -1283,7 +1283,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
|
|||
*w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
|
||||
w = (u32 *)(b + ori_offset);
|
||||
*w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
|
||||
flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len));
|
||||
local_flush_icache_range((unsigned long)b,
|
||||
(unsigned long)(b+handler_len));
|
||||
}
|
||||
else {
|
||||
/*
|
||||
|
@ -1295,7 +1296,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
|
|||
w = (u32 *)b;
|
||||
*w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */
|
||||
*w = 0;
|
||||
flush_icache_range((unsigned long)b, (unsigned long)(b+8));
|
||||
local_flush_icache_range((unsigned long)b,
|
||||
(unsigned long)(b+8));
|
||||
}
|
||||
|
||||
return (void *)old_handler;
|
||||
|
@ -1515,7 +1517,7 @@ void __cpuinit per_cpu_trap_init(void)
|
|||
void __init set_handler(unsigned long offset, void *addr, unsigned long size)
|
||||
{
|
||||
memcpy((void *)(ebase + offset), addr, size);
|
||||
flush_icache_range(ebase + offset, ebase + offset + size);
|
||||
local_flush_icache_range(ebase + offset, ebase + offset + size);
|
||||
}
|
||||
|
||||
static char panic_null_cerr[] __cpuinitdata =
|
||||
|
@ -1680,6 +1682,8 @@ void __init trap_init(void)
|
|||
signal32_init();
|
||||
#endif
|
||||
|
||||
flush_icache_range(ebase, ebase + 0x400);
|
||||
local_flush_icache_range(ebase, ebase + 0x400);
|
||||
flush_tlb_handlers();
|
||||
|
||||
sort_extable(__start___dbe_table, __stop___dbe_table);
|
||||
}
|
||||
|
|
|
@ -320,6 +320,7 @@ void __cpuinit r3k_cache_init(void)
|
|||
flush_cache_range = r3k_flush_cache_range;
|
||||
flush_cache_page = r3k_flush_cache_page;
|
||||
flush_icache_range = r3k_flush_icache_range;
|
||||
local_flush_icache_range = r3k_flush_icache_range;
|
||||
|
||||
flush_cache_sigtramp = r3k_flush_cache_sigtramp;
|
||||
local_flush_data_cache_page = local_r3k_flush_data_cache_page;
|
||||
|
|
|
@ -543,12 +543,8 @@ struct flush_icache_range_args {
|
|||
unsigned long end;
|
||||
};
|
||||
|
||||
static inline void local_r4k_flush_icache_range(void *args)
|
||||
static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
struct flush_icache_range_args *fir_args = args;
|
||||
unsigned long start = fir_args->start;
|
||||
unsigned long end = fir_args->end;
|
||||
|
||||
if (!cpu_has_ic_fills_f_dc) {
|
||||
if (end - start >= dcache_size) {
|
||||
r4k_blast_dcache();
|
||||
|
@ -564,6 +560,15 @@ static inline void local_r4k_flush_icache_range(void *args)
|
|||
protected_blast_icache_range(start, end);
|
||||
}
|
||||
|
||||
static inline void local_r4k_flush_icache_range_ipi(void *args)
|
||||
{
|
||||
struct flush_icache_range_args *fir_args = args;
|
||||
unsigned long start = fir_args->start;
|
||||
unsigned long end = fir_args->end;
|
||||
|
||||
local_r4k_flush_icache_range(start, end);
|
||||
}
|
||||
|
||||
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
struct flush_icache_range_args args;
|
||||
|
@ -571,7 +576,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
|
|||
args.start = start;
|
||||
args.end = end;
|
||||
|
||||
r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1);
|
||||
r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args, 1);
|
||||
instruction_hazard();
|
||||
}
|
||||
|
||||
|
@ -1375,6 +1380,7 @@ void __cpuinit r4k_cache_init(void)
|
|||
local_flush_data_cache_page = local_r4k_flush_data_cache_page;
|
||||
flush_data_cache_page = r4k_flush_data_cache_page;
|
||||
flush_icache_range = r4k_flush_icache_range;
|
||||
local_flush_icache_range = local_r4k_flush_icache_range;
|
||||
|
||||
#if defined(CONFIG_DMA_NONCOHERENT)
|
||||
if (coherentio) {
|
||||
|
|
|
@ -362,6 +362,7 @@ void __cpuinit tx39_cache_init(void)
|
|||
flush_cache_range = (void *) tx39h_flush_icache_all;
|
||||
flush_cache_page = (void *) tx39h_flush_icache_all;
|
||||
flush_icache_range = (void *) tx39h_flush_icache_all;
|
||||
local_flush_icache_range = (void *) tx39h_flush_icache_all;
|
||||
|
||||
flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
|
||||
local_flush_data_cache_page = (void *) tx39h_flush_icache_all;
|
||||
|
@ -390,6 +391,7 @@ void __cpuinit tx39_cache_init(void)
|
|||
flush_cache_range = tx39_flush_cache_range;
|
||||
flush_cache_page = tx39_flush_cache_page;
|
||||
flush_icache_range = tx39_flush_icache_range;
|
||||
local_flush_icache_range = tx39_flush_icache_range;
|
||||
|
||||
flush_cache_sigtramp = tx39_flush_cache_sigtramp;
|
||||
local_flush_data_cache_page = local_tx39_flush_data_cache_page;
|
||||
|
|
|
@ -29,6 +29,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
|
|||
void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
|
||||
unsigned long pfn);
|
||||
void (*flush_icache_range)(unsigned long start, unsigned long end);
|
||||
void (*local_flush_icache_range)(unsigned long start, unsigned long end);
|
||||
|
||||
void (*__flush_cache_vmap)(void);
|
||||
void (*__flush_cache_vunmap)(void);
|
||||
|
|
|
@ -1273,10 +1273,10 @@ void __cpuinit build_tlb_refill_handler(void)
|
|||
|
||||
void __cpuinit flush_tlb_handlers(void)
|
||||
{
|
||||
flush_icache_range((unsigned long)handle_tlbl,
|
||||
local_flush_icache_range((unsigned long)handle_tlbl,
|
||||
(unsigned long)handle_tlbl + sizeof(handle_tlbl));
|
||||
flush_icache_range((unsigned long)handle_tlbs,
|
||||
local_flush_icache_range((unsigned long)handle_tlbs,
|
||||
(unsigned long)handle_tlbs + sizeof(handle_tlbs));
|
||||
flush_icache_range((unsigned long)handle_tlbm,
|
||||
local_flush_icache_range((unsigned long)handle_tlbm,
|
||||
(unsigned long)handle_tlbm + sizeof(handle_tlbm));
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ static int __init sgiseeq_devinit(void)
|
|||
return res;
|
||||
|
||||
/* Second HPC is missing? */
|
||||
if (!ip22_is_fullhouse() ||
|
||||
if (ip22_is_fullhouse() ||
|
||||
get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size)
|
|||
txx9_ce_res[i].name = txx9_ce_res_name[i];
|
||||
}
|
||||
|
||||
txx9_pcode = pcode;
|
||||
sprintf(txx9_pcode_str, "TX%x", pcode);
|
||||
if (base) {
|
||||
txx9_reg_res.start = base & 0xfffffffffULL;
|
||||
|
|
|
@ -47,7 +47,9 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/sections.h>
|
||||
#include <asm/unwind.h>
|
||||
|
||||
#if 0
|
||||
|
@ -860,3 +862,15 @@ void module_arch_cleanup(struct module *mod)
|
|||
deregister_unwind_table(mod);
|
||||
module_bug_cleanup(mod);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
Elf64_Fdesc *desc = ptr;
|
||||
void *p;
|
||||
|
||||
if (!probe_kernel_address(&desc->addr, p))
|
||||
ptr = p;
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,7 @@ zlib := inffast.c inflate.c inftrees.c
|
|||
zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
|
||||
zliblinuxheader := zlib.h zconf.h zutil.h
|
||||
|
||||
$(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
|
||||
$(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \
|
||||
$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
|
||||
|
||||
src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
|
||||
|
|
|
@ -16,6 +16,9 @@ static inline int in_kernel_text(unsigned long addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#undef dereference_function_descriptor
|
||||
void *dereference_function_descriptor(void *);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/module.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/code-patching.h>
|
||||
#include <linux/sort.h>
|
||||
|
@ -451,3 +452,13 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
struct ppc64_opd_entry *desc = ptr;
|
||||
void *p;
|
||||
|
||||
if (!probe_kernel_address(&desc->funcaddr, p))
|
||||
ptr = p;
|
||||
return ptr;
|
||||
}
|
||||
|
|
|
@ -643,9 +643,10 @@ static struct spu *find_victim(struct spu_context *ctx)
|
|||
!(tmp->flags & SPU_CREATE_NOSCHED) &&
|
||||
(!victim || tmp->prio > victim->prio)) {
|
||||
victim = spu->ctx;
|
||||
get_spu_context(victim);
|
||||
}
|
||||
}
|
||||
if (victim)
|
||||
get_spu_context(victim);
|
||||
mutex_unlock(&cbe_spu_info[node].list_mutex);
|
||||
|
||||
if (victim) {
|
||||
|
@ -727,17 +728,33 @@ static void spu_schedule(struct spu *spu, struct spu_context *ctx)
|
|||
/* not a candidate for interruptible because it's called either
|
||||
from the scheduler thread or from spu_deactivate */
|
||||
mutex_lock(&ctx->state_mutex);
|
||||
__spu_schedule(spu, ctx);
|
||||
if (ctx->state == SPU_STATE_SAVED)
|
||||
__spu_schedule(spu, ctx);
|
||||
spu_release(ctx);
|
||||
}
|
||||
|
||||
static void spu_unschedule(struct spu *spu, struct spu_context *ctx)
|
||||
/**
|
||||
* spu_unschedule - remove a context from a spu, and possibly release it.
|
||||
* @spu: The SPU to unschedule from
|
||||
* @ctx: The context currently scheduled on the SPU
|
||||
* @free_spu Whether to free the SPU for other contexts
|
||||
*
|
||||
* Unbinds the context @ctx from the SPU @spu. If @free_spu is non-zero, the
|
||||
* SPU is made available for other contexts (ie, may be returned by
|
||||
* spu_get_idle). If this is zero, the caller is expected to schedule another
|
||||
* context to this spu.
|
||||
*
|
||||
* Should be called with ctx->state_mutex held.
|
||||
*/
|
||||
static void spu_unschedule(struct spu *spu, struct spu_context *ctx,
|
||||
int free_spu)
|
||||
{
|
||||
int node = spu->node;
|
||||
|
||||
mutex_lock(&cbe_spu_info[node].list_mutex);
|
||||
cbe_spu_info[node].nr_active--;
|
||||
spu->alloc_state = SPU_FREE;
|
||||
if (free_spu)
|
||||
spu->alloc_state = SPU_FREE;
|
||||
spu_unbind_context(spu, ctx);
|
||||
ctx->stats.invol_ctx_switch++;
|
||||
spu->stats.invol_ctx_switch++;
|
||||
|
@ -837,7 +854,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
|
|||
if (spu) {
|
||||
new = grab_runnable_context(max_prio, spu->node);
|
||||
if (new || force) {
|
||||
spu_unschedule(spu, ctx);
|
||||
spu_unschedule(spu, ctx, new == NULL);
|
||||
if (new) {
|
||||
if (new->flags & SPU_CREATE_NOSCHED)
|
||||
wake_up(&new->stop_wq);
|
||||
|
@ -910,7 +927,7 @@ static noinline void spusched_tick(struct spu_context *ctx)
|
|||
|
||||
new = grab_runnable_context(ctx->prio + 1, spu->node);
|
||||
if (new) {
|
||||
spu_unschedule(spu, ctx);
|
||||
spu_unschedule(spu, ctx, 0);
|
||||
if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags))
|
||||
spu_add_to_rq(ctx);
|
||||
} else {
|
||||
|
|
|
@ -42,6 +42,7 @@ struct user_regs_struct32
|
|||
u32 gprs[NUM_GPRS];
|
||||
u32 acrs[NUM_ACRS];
|
||||
u32 orig_gpr2;
|
||||
/* nb: there's a 4-byte hole here */
|
||||
s390_fp_regs fp_regs;
|
||||
/*
|
||||
* These per registers are in here so that gdb can modify them
|
||||
|
|
|
@ -170,6 +170,13 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
|
|||
*/
|
||||
tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
|
||||
|
||||
} else if (addr < (addr_t) &dummy->regs.fp_regs) {
|
||||
/*
|
||||
* prevent reads of padding hole between
|
||||
* orig_gpr2 and fp_regs on s390.
|
||||
*/
|
||||
tmp = 0;
|
||||
|
||||
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
||||
/*
|
||||
* floating point regs. are stored in the thread structure
|
||||
|
@ -270,6 +277,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
|
|||
*/
|
||||
task_pt_regs(child)->orig_gpr2 = data;
|
||||
|
||||
} else if (addr < (addr_t) &dummy->regs.fp_regs) {
|
||||
/*
|
||||
* prevent writes of padding hole between
|
||||
* orig_gpr2 and fp_regs on s390.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
||||
/*
|
||||
* floating point regs. are stored in the thread structure
|
||||
|
@ -428,6 +442,13 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
|
|||
*/
|
||||
tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
|
||||
|
||||
} else if (addr < (addr_t) &dummy32->regs.fp_regs) {
|
||||
/*
|
||||
* prevent reads of padding hole between
|
||||
* orig_gpr2 and fp_regs on s390.
|
||||
*/
|
||||
tmp = 0;
|
||||
|
||||
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
||||
/*
|
||||
* floating point regs. are stored in the thread structure
|
||||
|
@ -514,6 +535,13 @@ static int __poke_user_compat(struct task_struct *child,
|
|||
*/
|
||||
*(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
|
||||
|
||||
} else if (addr < (addr_t) &dummy32->regs.fp_regs) {
|
||||
/*
|
||||
* prevent writess of padding hole between
|
||||
* orig_gpr2 and fp_regs on s390.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
||||
/*
|
||||
* floating point regs. are stored in the thread structure
|
||||
|
|
|
@ -792,6 +792,8 @@ void fixup_irqs(void)
|
|||
}
|
||||
spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
|
||||
}
|
||||
|
||||
tick_ops->disable_irq();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -80,8 +80,6 @@ void smp_bogo(struct seq_file *m)
|
|||
i, cpu_data(i).clock_tick);
|
||||
}
|
||||
|
||||
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
|
||||
|
||||
extern void setup_sparc64_timer(void);
|
||||
|
||||
static volatile unsigned long callin_flag = 0;
|
||||
|
@ -120,9 +118,9 @@ void __cpuinit smp_callin(void)
|
|||
while (!cpu_isset(cpuid, smp_commenced_mask))
|
||||
rmb();
|
||||
|
||||
spin_lock(&call_lock);
|
||||
ipi_call_lock();
|
||||
cpu_set(cpuid, cpu_online_map);
|
||||
spin_unlock(&call_lock);
|
||||
ipi_call_unlock();
|
||||
|
||||
/* idle thread is expected to have preempt disabled */
|
||||
preempt_disable();
|
||||
|
@ -1305,10 +1303,6 @@ int __cpu_disable(void)
|
|||
c->core_id = 0;
|
||||
c->proc_id = -1;
|
||||
|
||||
spin_lock(&call_lock);
|
||||
cpu_clear(cpu, cpu_online_map);
|
||||
spin_unlock(&call_lock);
|
||||
|
||||
smp_wmb();
|
||||
|
||||
/* Make sure no interrupts point to this cpu. */
|
||||
|
@ -1318,6 +1312,10 @@ int __cpu_disable(void)
|
|||
mdelay(1);
|
||||
local_irq_disable();
|
||||
|
||||
ipi_call_lock();
|
||||
cpu_clear(cpu, cpu_online_map);
|
||||
ipi_call_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -382,14 +382,17 @@ config X86_OOSTORE
|
|||
# P6_NOPs are a relatively minor optimization that require a family >=
|
||||
# 6 processor, except that it is broken on certain VIA chips.
|
||||
# Furthermore, AMD chips prefer a totally different sequence of NOPs
|
||||
# (which work on all CPUs). As a result, disallow these if we're
|
||||
# compiling X86_GENERIC but not X86_64 (these NOPs do work on all
|
||||
# x86-64 capable chips); the list of processors in the right-hand clause
|
||||
# are the cores that benefit from this optimization.
|
||||
# (which work on all CPUs). In addition, it looks like Virtual PC
|
||||
# does not understand them.
|
||||
#
|
||||
# As a result, disallow these if we're not compiling for X86_64 (these
|
||||
# NOPs do work on all x86-64 capable chips); the list of processors in
|
||||
# the right-hand clause are the cores that benefit from this optimization.
|
||||
#
|
||||
config X86_P6_NOP
|
||||
def_bool y
|
||||
depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC)
|
||||
depends on X86_64
|
||||
depends on (MCORE2 || MPENTIUM4 || MPSC)
|
||||
|
||||
config X86_TSC
|
||||
def_bool y
|
||||
|
|
|
@ -38,12 +38,12 @@ static const u32 req_flags[NCAPINTS] =
|
|||
{
|
||||
REQUIRED_MASK0,
|
||||
REQUIRED_MASK1,
|
||||
REQUIRED_MASK2,
|
||||
REQUIRED_MASK3,
|
||||
0, /* REQUIRED_MASK2 not implemented in this file */
|
||||
0, /* REQUIRED_MASK3 not implemented in this file */
|
||||
REQUIRED_MASK4,
|
||||
REQUIRED_MASK5,
|
||||
0, /* REQUIRED_MASK5 not implemented in this file */
|
||||
REQUIRED_MASK6,
|
||||
REQUIRED_MASK7,
|
||||
0, /* REQUIRED_MASK7 not implemented in this file */
|
||||
};
|
||||
|
||||
#define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
|
||||
|
|
|
@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = {
|
|||
extern char __vsyscall_0;
|
||||
const unsigned char *const *find_nop_table(void)
|
||||
{
|
||||
return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
|
||||
boot_cpu_data.x86 < 6 ? k8_nops : p6_nops;
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
|
||||
boot_cpu_has(X86_FEATURE_NOPL))
|
||||
return p6_nops;
|
||||
else
|
||||
return k8_nops;
|
||||
}
|
||||
|
||||
#else /* CONFIG_X86_64 */
|
||||
|
||||
static const struct nop {
|
||||
int cpuid;
|
||||
const unsigned char *const *noptable;
|
||||
} noptypes[] = {
|
||||
{ X86_FEATURE_K8, k8_nops },
|
||||
{ X86_FEATURE_K7, k7_nops },
|
||||
{ X86_FEATURE_P4, p6_nops },
|
||||
{ X86_FEATURE_P3, p6_nops },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
const unsigned char *const *find_nop_table(void)
|
||||
{
|
||||
const unsigned char *const *noptable = intel_nops;
|
||||
int i;
|
||||
|
||||
for (i = 0; noptypes[i].cpuid >= 0; i++) {
|
||||
if (boot_cpu_has(noptypes[i].cpuid)) {
|
||||
noptable = noptypes[i].noptable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return noptable;
|
||||
if (boot_cpu_has(X86_FEATURE_K8))
|
||||
return k8_nops;
|
||||
else if (boot_cpu_has(X86_FEATURE_K7))
|
||||
return k7_nops;
|
||||
else if (boot_cpu_has(X86_FEATURE_NOPL))
|
||||
return p6_nops;
|
||||
else
|
||||
return intel_nops;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
|
|
@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
|
|||
if (c->x86_power & (1<<8))
|
||||
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
||||
}
|
||||
|
||||
/* Set MTRR capability flag if appropriate */
|
||||
if (c->x86_model == 13 || c->x86_model == 9 ||
|
||||
(c->x86_model == 8 && c->x86_mask >= 8))
|
||||
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
|
||||
}
|
||||
|
||||
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
||||
|
@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
|||
mbytes);
|
||||
}
|
||||
|
||||
/* Set MTRR capability flag if appropriate */
|
||||
if (c->x86_model == 13 || c->x86_model == 9 ||
|
||||
(c->x86_model == 8 && c->x86_mask >= 8))
|
||||
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -314,6 +314,16 @@ enum {
|
|||
EAMD3D = 1<<20,
|
||||
};
|
||||
|
||||
static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
|
||||
{
|
||||
switch (c->x86) {
|
||||
case 5:
|
||||
/* Emulate MTRRs using Centaur's MCR. */
|
||||
set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
|
||||
{
|
||||
|
||||
|
@ -462,6 +472,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
|
|||
static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
|
||||
.c_vendor = "Centaur",
|
||||
.c_ident = { "CentaurHauls" },
|
||||
.c_early_init = early_init_centaur,
|
||||
.c_init = init_centaur,
|
||||
.c_size_cache = centaur_size_cache,
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <asm/mtrr.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/pat.h>
|
||||
#include <asm/asm.h>
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/apic.h>
|
||||
|
@ -334,11 +335,40 @@ static void __init early_cpu_detect(void)
|
|||
|
||||
get_cpu_vendor(c, 1);
|
||||
|
||||
early_get_cap(c);
|
||||
|
||||
if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
|
||||
cpu_devs[c->x86_vendor]->c_early_init)
|
||||
cpu_devs[c->x86_vendor]->c_early_init(c);
|
||||
}
|
||||
|
||||
early_get_cap(c);
|
||||
/*
|
||||
* The NOPL instruction is supposed to exist on all CPUs with
|
||||
* family >= 6, unfortunately, that's not true in practice because
|
||||
* of early VIA chips and (more importantly) broken virtualizers that
|
||||
* are not easy to detect. Hence, probe for it based on first
|
||||
* principles.
|
||||
*/
|
||||
static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
|
||||
{
|
||||
const u32 nopl_signature = 0x888c53b1; /* Random number */
|
||||
u32 has_nopl = nopl_signature;
|
||||
|
||||
clear_cpu_cap(c, X86_FEATURE_NOPL);
|
||||
if (c->x86 >= 6) {
|
||||
asm volatile("\n"
|
||||
"1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
|
||||
"2:\n"
|
||||
" .section .fixup,\"ax\"\n"
|
||||
"3: xor %0,%0\n"
|
||||
" jmp 2b\n"
|
||||
" .previous\n"
|
||||
_ASM_EXTABLE(1b,3b)
|
||||
: "+a" (has_nopl));
|
||||
|
||||
if (has_nopl == nopl_signature)
|
||||
set_cpu_cap(c, X86_FEATURE_NOPL);
|
||||
}
|
||||
}
|
||||
|
||||
static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
|
||||
|
@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
|
|||
}
|
||||
|
||||
init_scattered_cpuid_features(c);
|
||||
detect_nopl(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <asm/mtrr.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/pat.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/numa.h>
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
#include <asm/mpspec.h>
|
||||
|
@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The NOPL instruction is supposed to exist on all CPUs with
|
||||
* family >= 6, unfortunately, that's not true in practice because
|
||||
* of early VIA chips and (more importantly) broken virtualizers that
|
||||
* are not easy to detect. Hence, probe for it based on first
|
||||
* principles.
|
||||
*
|
||||
* Note: no 64-bit chip is known to lack these, but put the code here
|
||||
* for consistency with 32 bits, and to make it utterly trivial to
|
||||
* diagnose the problem should it ever surface.
|
||||
*/
|
||||
static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
|
||||
{
|
||||
const u32 nopl_signature = 0x888c53b1; /* Random number */
|
||||
u32 has_nopl = nopl_signature;
|
||||
|
||||
clear_cpu_cap(c, X86_FEATURE_NOPL);
|
||||
if (c->x86 >= 6) {
|
||||
asm volatile("\n"
|
||||
"1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
|
||||
"2:\n"
|
||||
" .section .fixup,\"ax\"\n"
|
||||
"3: xor %0,%0\n"
|
||||
" jmp 2b\n"
|
||||
" .previous\n"
|
||||
_ASM_EXTABLE(1b,3b)
|
||||
: "+a" (has_nopl));
|
||||
|
||||
if (has_nopl == nopl_signature)
|
||||
set_cpu_cap(c, X86_FEATURE_NOPL);
|
||||
}
|
||||
}
|
||||
|
||||
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
|
||||
|
||||
void __init early_cpu_init(void)
|
||||
|
@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
|
|||
c->x86_phys_bits = eax & 0xff;
|
||||
}
|
||||
|
||||
detect_nopl(c);
|
||||
|
||||
if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
|
||||
cpu_devs[c->x86_vendor]->c_early_init)
|
||||
cpu_devs[c->x86_vendor]->c_early_init(c);
|
||||
|
@ -493,17 +529,20 @@ void pda_init(int cpu)
|
|||
/* others are initialized in smpboot.c */
|
||||
pda->pcurrent = &init_task;
|
||||
pda->irqstackptr = boot_cpu_stack;
|
||||
pda->irqstackptr += IRQSTACKSIZE - 64;
|
||||
} else {
|
||||
pda->irqstackptr = (char *)
|
||||
__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
|
||||
if (!pda->irqstackptr)
|
||||
panic("cannot allocate irqstack for cpu %d", cpu);
|
||||
if (!pda->irqstackptr) {
|
||||
pda->irqstackptr = (char *)
|
||||
__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
|
||||
if (!pda->irqstackptr)
|
||||
panic("cannot allocate irqstack for cpu %d",
|
||||
cpu);
|
||||
pda->irqstackptr += IRQSTACKSIZE - 64;
|
||||
}
|
||||
|
||||
if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
|
||||
pda->nodenumber = cpu_to_node(cpu);
|
||||
}
|
||||
|
||||
pda->irqstackptr += IRQSTACKSIZE-64;
|
||||
}
|
||||
|
||||
char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
|
||||
|
@ -601,19 +640,22 @@ void __cpuinit cpu_init(void)
|
|||
/*
|
||||
* set up and load the per-CPU TSS
|
||||
*/
|
||||
for (v = 0; v < N_EXCEPTION_STACKS; v++) {
|
||||
if (!orig_ist->ist[0]) {
|
||||
static const unsigned int order[N_EXCEPTION_STACKS] = {
|
||||
[0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
|
||||
[DEBUG_STACK - 1] = DEBUG_STACK_ORDER
|
||||
[0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
|
||||
[DEBUG_STACK - 1] = DEBUG_STACK_ORDER
|
||||
};
|
||||
if (cpu) {
|
||||
estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
|
||||
if (!estacks)
|
||||
panic("Cannot allocate exception stack %ld %d\n",
|
||||
v, cpu);
|
||||
for (v = 0; v < N_EXCEPTION_STACKS; v++) {
|
||||
if (cpu) {
|
||||
estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
|
||||
if (!estacks)
|
||||
panic("Cannot allocate exception "
|
||||
"stack %ld %d\n", v, cpu);
|
||||
}
|
||||
estacks += PAGE_SIZE << order[v];
|
||||
orig_ist->ist[v] = t->x86_tss.ist[v] =
|
||||
(unsigned long)estacks;
|
||||
}
|
||||
estacks += PAGE_SIZE << order[v];
|
||||
orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks;
|
||||
}
|
||||
|
||||
t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
/*
|
||||
* Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
|
||||
*/
|
||||
static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
||||
static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
||||
{
|
||||
unsigned char ccr2, ccr3;
|
||||
unsigned long flags;
|
||||
|
||||
/* we test for DEVID by checking whether CCR3 is writable */
|
||||
local_irq_save(flags);
|
||||
ccr3 = getCx86(CX86_CCR3);
|
||||
setCx86(CX86_CCR3, ccr3 ^ 0x80);
|
||||
getCx86(0xc0); /* dummy to change bus */
|
||||
|
@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
|||
*dir0 = getCx86(CX86_DIR0);
|
||||
*dir1 = getCx86(CX86_DIR1);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
__do_cyrix_devid(dir0, dir1);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
/*
|
||||
* Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
|
||||
* order to identify the Cyrix CPU model after we're out of setup.c
|
||||
|
@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c)
|
||||
{
|
||||
unsigned char dir0, dir0_msn, dir1 = 0;
|
||||
|
||||
__do_cyrix_devid(&dir0, &dir1);
|
||||
dir0_msn = dir0 >> 4; /* identifies CPU "family" */
|
||||
|
||||
switch (dir0_msn) {
|
||||
case 3: /* 6x86/6x86L */
|
||||
/* Emulate MTRRs using Cyrix's ARRs. */
|
||||
set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
|
||||
break;
|
||||
case 5: /* 6x86MX/M II */
|
||||
/* Emulate MTRRs using Cyrix's ARRs. */
|
||||
set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
|
||||
{
|
||||
|
@ -416,6 +439,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
|
|||
static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
|
||||
.c_vendor = "Cyrix",
|
||||
.c_ident = { "CyrixInstead" },
|
||||
.c_early_init = early_init_cyrix,
|
||||
.c_init = init_cyrix,
|
||||
.c_identify = cyrix_identify,
|
||||
};
|
||||
|
|
|
@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = {
|
|||
NULL, NULL, NULL, NULL,
|
||||
"constant_tsc", "up", NULL, "arch_perfmon",
|
||||
"pebs", "bts", NULL, NULL,
|
||||
"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
"rep_good", NULL, NULL, NULL,
|
||||
"nopl", NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/* Intel-defined (#2) */
|
||||
|
|
|
@ -1203,7 +1203,7 @@ static int __init parse_memmap_opt(char *p)
|
|||
if (!p)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(p, "exactmap")) {
|
||||
if (!strncmp(p, "exactmap", 8)) {
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
/*
|
||||
* If we are doing a crash dump, we still need to know
|
||||
|
|
|
@ -210,8 +210,8 @@ static void hpet_legacy_clockevent_register(void)
|
|||
/* Calculate the min / max delta */
|
||||
hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
|
||||
&hpet_clockevent);
|
||||
hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30,
|
||||
&hpet_clockevent);
|
||||
/* 5 usec minimum reprogramming delta. */
|
||||
hpet_clockevent.min_delta_ns = 5000;
|
||||
|
||||
/*
|
||||
* Start hpet with the boot cpu mask and make it
|
||||
|
@ -270,15 +270,22 @@ static void hpet_legacy_set_mode(enum clock_event_mode mode,
|
|||
}
|
||||
|
||||
static int hpet_legacy_next_event(unsigned long delta,
|
||||
struct clock_event_device *evt)
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long cnt;
|
||||
u32 cnt;
|
||||
|
||||
cnt = hpet_readl(HPET_COUNTER);
|
||||
cnt += delta;
|
||||
cnt += (u32) delta;
|
||||
hpet_writel(cnt, HPET_T0_CMP);
|
||||
|
||||
return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0;
|
||||
/*
|
||||
* We need to read back the CMP register to make sure that
|
||||
* what we wrote hit the chip before we compare it to the
|
||||
* counter.
|
||||
*/
|
||||
WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt);
|
||||
|
||||
return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1324,7 +1324,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
|
|||
.ptep_modify_prot_commit = __ptep_modify_prot_commit,
|
||||
|
||||
.pte_val = xen_pte_val,
|
||||
.pte_flags = native_pte_val,
|
||||
.pte_flags = native_pte_flags,
|
||||
.pgd_val = xen_pgd_val,
|
||||
|
||||
.make_pte = xen_make_pte,
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
static const u32 camellia_sp1110[256] = {
|
||||
0x70707000,0x82828200,0x2c2c2c00,0xececec00,
|
||||
|
@ -337,6 +335,20 @@ static const u32 camellia_sp4404[256] = {
|
|||
/*
|
||||
* macros
|
||||
*/
|
||||
#define GETU32(v, pt) \
|
||||
do { \
|
||||
/* latest breed of gcc is clever enough to use move */ \
|
||||
memcpy(&(v), (pt), 4); \
|
||||
(v) = be32_to_cpu(v); \
|
||||
} while(0)
|
||||
|
||||
/* rotation right shift 1byte */
|
||||
#define ROR8(x) (((x) >> 8) + ((x) << 24))
|
||||
/* rotation left shift 1bit */
|
||||
#define ROL1(x) (((x) << 1) + ((x) >> 31))
|
||||
/* rotation left shift 1byte */
|
||||
#define ROL8(x) (((x) << 8) + ((x) >> 24))
|
||||
|
||||
#define ROLDQ(ll, lr, rl, rr, w0, w1, bits) \
|
||||
do { \
|
||||
w0 = ll; \
|
||||
|
@ -371,7 +383,7 @@ static const u32 camellia_sp4404[256] = {
|
|||
^ camellia_sp3033[(u8)(il >> 8)] \
|
||||
^ camellia_sp4404[(u8)(il )]; \
|
||||
yl ^= yr; \
|
||||
yr = ror32(yr, 8); \
|
||||
yr = ROR8(yr); \
|
||||
yr ^= yl; \
|
||||
} while(0)
|
||||
|
||||
|
@ -393,7 +405,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
subL[7] ^= subL[1]; subR[7] ^= subR[1];
|
||||
subL[1] ^= subR[1] & ~subR[9];
|
||||
dw = subL[1] & subL[9],
|
||||
subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl2) */
|
||||
subR[1] ^= ROL1(dw); /* modified for FLinv(kl2) */
|
||||
/* round 8 */
|
||||
subL[11] ^= subL[1]; subR[11] ^= subR[1];
|
||||
/* round 10 */
|
||||
|
@ -402,7 +414,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
subL[15] ^= subL[1]; subR[15] ^= subR[1];
|
||||
subL[1] ^= subR[1] & ~subR[17];
|
||||
dw = subL[1] & subL[17],
|
||||
subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl4) */
|
||||
subR[1] ^= ROL1(dw); /* modified for FLinv(kl4) */
|
||||
/* round 14 */
|
||||
subL[19] ^= subL[1]; subR[19] ^= subR[1];
|
||||
/* round 16 */
|
||||
|
@ -418,7 +430,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
} else {
|
||||
subL[1] ^= subR[1] & ~subR[25];
|
||||
dw = subL[1] & subL[25],
|
||||
subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl6) */
|
||||
subR[1] ^= ROL1(dw); /* modified for FLinv(kl6) */
|
||||
/* round 20 */
|
||||
subL[27] ^= subL[1]; subR[27] ^= subR[1];
|
||||
/* round 22 */
|
||||
|
@ -438,7 +450,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
subL[26] ^= kw4l; subR[26] ^= kw4r;
|
||||
kw4l ^= kw4r & ~subR[24];
|
||||
dw = kw4l & subL[24],
|
||||
kw4r ^= rol32(dw, 1); /* modified for FL(kl5) */
|
||||
kw4r ^= ROL1(dw); /* modified for FL(kl5) */
|
||||
}
|
||||
/* round 17 */
|
||||
subL[22] ^= kw4l; subR[22] ^= kw4r;
|
||||
|
@ -448,7 +460,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
subL[18] ^= kw4l; subR[18] ^= kw4r;
|
||||
kw4l ^= kw4r & ~subR[16];
|
||||
dw = kw4l & subL[16],
|
||||
kw4r ^= rol32(dw, 1); /* modified for FL(kl3) */
|
||||
kw4r ^= ROL1(dw); /* modified for FL(kl3) */
|
||||
/* round 11 */
|
||||
subL[14] ^= kw4l; subR[14] ^= kw4r;
|
||||
/* round 9 */
|
||||
|
@ -457,7 +469,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
subL[10] ^= kw4l; subR[10] ^= kw4r;
|
||||
kw4l ^= kw4r & ~subR[8];
|
||||
dw = kw4l & subL[8],
|
||||
kw4r ^= rol32(dw, 1); /* modified for FL(kl1) */
|
||||
kw4r ^= ROL1(dw); /* modified for FL(kl1) */
|
||||
/* round 5 */
|
||||
subL[6] ^= kw4l; subR[6] ^= kw4r;
|
||||
/* round 3 */
|
||||
|
@ -482,7 +494,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
SUBKEY_R(6) = subR[5] ^ subR[7];
|
||||
tl = subL[10] ^ (subR[10] & ~subR[8]);
|
||||
dw = tl & subL[8], /* FL(kl1) */
|
||||
tr = subR[10] ^ rol32(dw, 1);
|
||||
tr = subR[10] ^ ROL1(dw);
|
||||
SUBKEY_L(7) = subL[6] ^ tl; /* round 6 */
|
||||
SUBKEY_R(7) = subR[6] ^ tr;
|
||||
SUBKEY_L(8) = subL[8]; /* FL(kl1) */
|
||||
|
@ -491,7 +503,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
SUBKEY_R(9) = subR[9];
|
||||
tl = subL[7] ^ (subR[7] & ~subR[9]);
|
||||
dw = tl & subL[9], /* FLinv(kl2) */
|
||||
tr = subR[7] ^ rol32(dw, 1);
|
||||
tr = subR[7] ^ ROL1(dw);
|
||||
SUBKEY_L(10) = tl ^ subL[11]; /* round 7 */
|
||||
SUBKEY_R(10) = tr ^ subR[11];
|
||||
SUBKEY_L(11) = subL[10] ^ subL[12]; /* round 8 */
|
||||
|
@ -504,7 +516,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
SUBKEY_R(14) = subR[13] ^ subR[15];
|
||||
tl = subL[18] ^ (subR[18] & ~subR[16]);
|
||||
dw = tl & subL[16], /* FL(kl3) */
|
||||
tr = subR[18] ^ rol32(dw, 1);
|
||||
tr = subR[18] ^ ROL1(dw);
|
||||
SUBKEY_L(15) = subL[14] ^ tl; /* round 12 */
|
||||
SUBKEY_R(15) = subR[14] ^ tr;
|
||||
SUBKEY_L(16) = subL[16]; /* FL(kl3) */
|
||||
|
@ -513,7 +525,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
SUBKEY_R(17) = subR[17];
|
||||
tl = subL[15] ^ (subR[15] & ~subR[17]);
|
||||
dw = tl & subL[17], /* FLinv(kl4) */
|
||||
tr = subR[15] ^ rol32(dw, 1);
|
||||
tr = subR[15] ^ ROL1(dw);
|
||||
SUBKEY_L(18) = tl ^ subL[19]; /* round 13 */
|
||||
SUBKEY_R(18) = tr ^ subR[19];
|
||||
SUBKEY_L(19) = subL[18] ^ subL[20]; /* round 14 */
|
||||
|
@ -532,7 +544,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
} else {
|
||||
tl = subL[26] ^ (subR[26] & ~subR[24]);
|
||||
dw = tl & subL[24], /* FL(kl5) */
|
||||
tr = subR[26] ^ rol32(dw, 1);
|
||||
tr = subR[26] ^ ROL1(dw);
|
||||
SUBKEY_L(23) = subL[22] ^ tl; /* round 18 */
|
||||
SUBKEY_R(23) = subR[22] ^ tr;
|
||||
SUBKEY_L(24) = subL[24]; /* FL(kl5) */
|
||||
|
@ -541,7 +553,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
SUBKEY_R(25) = subR[25];
|
||||
tl = subL[23] ^ (subR[23] & ~subR[25]);
|
||||
dw = tl & subL[25], /* FLinv(kl6) */
|
||||
tr = subR[23] ^ rol32(dw, 1);
|
||||
tr = subR[23] ^ ROL1(dw);
|
||||
SUBKEY_L(26) = tl ^ subL[27]; /* round 19 */
|
||||
SUBKEY_R(26) = tr ^ subR[27];
|
||||
SUBKEY_L(27) = subL[26] ^ subL[28]; /* round 20 */
|
||||
|
@ -561,17 +573,17 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
|
|||
/* apply the inverse of the last half of P-function */
|
||||
i = 2;
|
||||
do {
|
||||
dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = rol32(dw, 8);/* round 1 */
|
||||
dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = ROL8(dw);/* round 1 */
|
||||
SUBKEY_R(i + 0) = SUBKEY_L(i + 0) ^ dw; SUBKEY_L(i + 0) = dw;
|
||||
dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = rol32(dw, 8);/* round 2 */
|
||||
dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = ROL8(dw);/* round 2 */
|
||||
SUBKEY_R(i + 1) = SUBKEY_L(i + 1) ^ dw; SUBKEY_L(i + 1) = dw;
|
||||
dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = rol32(dw, 8);/* round 3 */
|
||||
dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = ROL8(dw);/* round 3 */
|
||||
SUBKEY_R(i + 2) = SUBKEY_L(i + 2) ^ dw; SUBKEY_L(i + 2) = dw;
|
||||
dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = rol32(dw, 8);/* round 4 */
|
||||
dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = ROL8(dw);/* round 4 */
|
||||
SUBKEY_R(i + 3) = SUBKEY_L(i + 3) ^ dw; SUBKEY_L(i + 3) = dw;
|
||||
dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = rol32(dw, 9);/* round 5 */
|
||||
dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = ROL8(dw);/* round 5 */
|
||||
SUBKEY_R(i + 4) = SUBKEY_L(i + 4) ^ dw; SUBKEY_L(i + 4) = dw;
|
||||
dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = rol32(dw, 8);/* round 6 */
|
||||
dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = ROL8(dw);/* round 6 */
|
||||
SUBKEY_R(i + 5) = SUBKEY_L(i + 5) ^ dw; SUBKEY_L(i + 5) = dw;
|
||||
i += 8;
|
||||
} while (i < max);
|
||||
|
@ -587,10 +599,10 @@ static void camellia_setup128(const unsigned char *key, u32 *subkey)
|
|||
/**
|
||||
* k == kll || klr || krl || krr (|| is concatenation)
|
||||
*/
|
||||
kll = get_unaligned_be32(key);
|
||||
klr = get_unaligned_be32(key + 4);
|
||||
krl = get_unaligned_be32(key + 8);
|
||||
krr = get_unaligned_be32(key + 12);
|
||||
GETU32(kll, key );
|
||||
GETU32(klr, key + 4);
|
||||
GETU32(krl, key + 8);
|
||||
GETU32(krr, key + 12);
|
||||
|
||||
/* generate KL dependent subkeys */
|
||||
/* kw1 */
|
||||
|
@ -695,14 +707,14 @@ static void camellia_setup256(const unsigned char *key, u32 *subkey)
|
|||
* key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
|
||||
* (|| is concatenation)
|
||||
*/
|
||||
kll = get_unaligned_be32(key);
|
||||
klr = get_unaligned_be32(key + 4);
|
||||
krl = get_unaligned_be32(key + 8);
|
||||
krr = get_unaligned_be32(key + 12);
|
||||
krll = get_unaligned_be32(key + 16);
|
||||
krlr = get_unaligned_be32(key + 20);
|
||||
krrl = get_unaligned_be32(key + 24);
|
||||
krrr = get_unaligned_be32(key + 28);
|
||||
GETU32(kll, key );
|
||||
GETU32(klr, key + 4);
|
||||
GETU32(krl, key + 8);
|
||||
GETU32(krr, key + 12);
|
||||
GETU32(krll, key + 16);
|
||||
GETU32(krlr, key + 20);
|
||||
GETU32(krrl, key + 24);
|
||||
GETU32(krrr, key + 28);
|
||||
|
||||
/* generate KL dependent subkeys */
|
||||
/* kw1 */
|
||||
|
@ -858,13 +870,13 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
|
|||
t0 &= ll; \
|
||||
t2 |= rr; \
|
||||
rl ^= t2; \
|
||||
lr ^= rol32(t0, 1); \
|
||||
lr ^= ROL1(t0); \
|
||||
t3 = krl; \
|
||||
t1 = klr; \
|
||||
t3 &= rl; \
|
||||
t1 |= lr; \
|
||||
ll ^= t1; \
|
||||
rr ^= rol32(t3, 1); \
|
||||
rr ^= ROL1(t3); \
|
||||
} while(0)
|
||||
|
||||
#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir) \
|
||||
|
@ -880,7 +892,7 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
|
|||
il ^= kl; \
|
||||
ir ^= il ^ kr; \
|
||||
yl ^= ir; \
|
||||
yr ^= ror32(il, 8) ^ ir; \
|
||||
yr ^= ROR8(il) ^ ir; \
|
||||
} while(0)
|
||||
|
||||
/* max = 24: 128bit encrypt, max = 32: 256bit encrypt */
|
||||
|
|
|
@ -448,8 +448,10 @@ config PATA_MARVELL
|
|||
tristate "Marvell PATA support via legacy mode"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables limited support for the Marvell 88SE6145 ATA
|
||||
controller.
|
||||
This option enables limited support for the Marvell 88SE61xx ATA
|
||||
controllers. If you wish to use only the SATA ports then select
|
||||
the AHCI driver alone. If you wish to the use the PATA port or
|
||||
both SATA and PATA include this driver.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = {
|
|||
/* board_ahci_mv */
|
||||
{
|
||||
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
|
||||
AHCI_HFLAG_MV_PATA),
|
||||
AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
|
||||
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
|
@ -487,7 +487,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
|
||||
{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
|
||||
|
||||
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
|
||||
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
|
@ -610,6 +612,15 @@ module_param(ahci_em_messages, int, 0444);
|
|||
MODULE_PARM_DESC(ahci_em_messages,
|
||||
"Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
|
||||
|
||||
#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
|
||||
static int marvell_enable;
|
||||
#else
|
||||
static int marvell_enable = 1;
|
||||
#endif
|
||||
module_param(marvell_enable, int, 0644);
|
||||
MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
|
||||
|
||||
|
||||
static inline int ahci_nr_ports(u32 cap)
|
||||
{
|
||||
return (cap & 0x1f) + 1;
|
||||
|
@ -732,6 +743,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
|
|||
"MV_AHCI HACK: port_map %x -> %x\n",
|
||||
port_map,
|
||||
port_map & mv);
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
|
||||
|
||||
port_map &= mv;
|
||||
}
|
||||
|
@ -2533,6 +2546,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (!printed_version++)
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
|
||||
|
||||
/* The AHCI driver can only drive the SATA ports, the PATA driver
|
||||
can drive them all so if both drivers are selected make sure
|
||||
AHCI stays out of the way */
|
||||
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
|
||||
return -ENODEV;
|
||||
|
||||
/* acquire resources */
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
|
|
|
@ -1315,11 +1315,6 @@ fsm_start:
|
|||
break;
|
||||
|
||||
case HSM_ST_ERR:
|
||||
/* make sure qc->err_mask is available to
|
||||
* know what's wrong and recover
|
||||
*/
|
||||
WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
|
||||
|
||||
ap->hsm_task_state = HSM_ST_IDLE;
|
||||
|
||||
/* complete taskfile transaction */
|
||||
|
|
|
@ -20,7 +20,42 @@
|
|||
#include <linux/ata.h>
|
||||
|
||||
#define DRV_NAME "pata_marvell"
|
||||
#define DRV_VERSION "0.1.4"
|
||||
#define DRV_VERSION "0.1.6"
|
||||
|
||||
/**
|
||||
* marvell_pata_active - check if PATA is active
|
||||
* @pdev: PCI device
|
||||
*
|
||||
* Returns 1 if the PATA port may be active. We know how to check this
|
||||
* for the 6145 but not the other devices
|
||||
*/
|
||||
|
||||
static int marvell_pata_active(struct pci_dev *pdev)
|
||||
{
|
||||
int i;
|
||||
u32 devices;
|
||||
void __iomem *barp;
|
||||
|
||||
/* We don't yet know how to do this for other devices */
|
||||
if (pdev->device != 0x6145)
|
||||
return 1;
|
||||
|
||||
barp = pci_iomap(pdev, 5, 0x10);
|
||||
if (barp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
printk("BAR5:");
|
||||
for(i = 0; i <= 0x0F; i++)
|
||||
printk("%02X:%02X ", i, ioread8(barp + i));
|
||||
printk("\n");
|
||||
|
||||
devices = ioread32(barp + 0x0C);
|
||||
pci_iounmap(pdev, barp);
|
||||
|
||||
if (devices & 0x10)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* marvell_pre_reset - check for 40/80 pin
|
||||
|
@ -34,26 +69,10 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
|
|||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u32 devices;
|
||||
void __iomem *barp;
|
||||
int i;
|
||||
|
||||
/* Check if our port is enabled */
|
||||
|
||||
barp = pci_iomap(pdev, 5, 0x10);
|
||||
if (barp == NULL)
|
||||
return -ENOMEM;
|
||||
printk("BAR5:");
|
||||
for(i = 0; i <= 0x0F; i++)
|
||||
printk("%02X:%02X ", i, ioread8(barp + i));
|
||||
printk("\n");
|
||||
|
||||
devices = ioread32(barp + 0x0C);
|
||||
pci_iounmap(pdev, barp);
|
||||
|
||||
if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
|
||||
(!(devices & 0x10))) /* PATA enable ? */
|
||||
return -ENOENT;
|
||||
if (pdev->device == 0x6145 && ap->port_no == 0 &&
|
||||
!marvell_pata_active(pdev)) /* PATA enable ? */
|
||||
return -ENOENT;
|
||||
|
||||
return ata_sff_prereset(link, deadline);
|
||||
}
|
||||
|
@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
|
|||
if (pdev->device == 0x6101)
|
||||
ppi[1] = &ata_dummy_port_info;
|
||||
|
||||
#if defined(CONFIG_AHCI) || defined(CONFIG_AHCI_MODULE)
|
||||
if (!marvell_pata_active(pdev)) {
|
||||
printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -322,9 +322,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
|
|||
/* Try to acquire MMIO resources and fallback to PIO if
|
||||
* that fails
|
||||
*/
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
|
||||
if (rc)
|
||||
goto use_ioports;
|
||||
|
|
|
@ -667,7 +667,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
|
||||
{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
|
||||
{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
|
||||
/* RocketRAID 1740/174x have different identifiers */
|
||||
/* RocketRAID 1720/174x have different identifiers */
|
||||
{ PCI_VDEVICE(TTI, 0x1720), chip_6042 },
|
||||
{ PCI_VDEVICE(TTI, 0x1740), chip_508x },
|
||||
{ PCI_VDEVICE(TTI, 0x1742), chip_508x },
|
||||
|
||||
|
|
|
@ -309,8 +309,6 @@ static void nv_nf2_freeze(struct ata_port *ap);
|
|||
static void nv_nf2_thaw(struct ata_port *ap);
|
||||
static void nv_ck804_freeze(struct ata_port *ap);
|
||||
static void nv_ck804_thaw(struct ata_port *ap);
|
||||
static int nv_hardreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline);
|
||||
static int nv_adma_slave_config(struct scsi_device *sdev);
|
||||
static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||
static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
|
||||
|
@ -407,7 +405,7 @@ static struct scsi_host_template nv_swncq_sht = {
|
|||
|
||||
static struct ata_port_operations nv_generic_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.hardreset = nv_hardreset,
|
||||
.hardreset = ATA_OP_NULL,
|
||||
.scr_read = nv_scr_read,
|
||||
.scr_write = nv_scr_write,
|
||||
};
|
||||
|
@ -1588,21 +1586,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
|
|||
ata_sff_thaw(ap);
|
||||
}
|
||||
|
||||
static int nv_hardreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* SATA hardreset fails to retrieve proper device signature on
|
||||
* some controllers. Request follow up SRST. For more info,
|
||||
* see http://bugzilla.kernel.org/show_bug.cgi?id=3352
|
||||
*/
|
||||
rc = sata_sff_hardreset(link, class, deadline);
|
||||
if (rc)
|
||||
return rc;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static void nv_adma_error_handler(struct ata_port *ap)
|
||||
{
|
||||
struct nv_adma_port_priv *pp = ap->private_data;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
|
@ -151,13 +152,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
|
|||
*/
|
||||
static int verify_pmtmr_rate(void)
|
||||
{
|
||||
u32 value1, value2;
|
||||
cycle_t value1, value2;
|
||||
unsigned long count, delta;
|
||||
|
||||
mach_prepare_counter();
|
||||
value1 = read_pmtmr();
|
||||
value1 = clocksource_acpi_pm.read();
|
||||
mach_countup(&count);
|
||||
value2 = read_pmtmr();
|
||||
value2 = clocksource_acpi_pm.read();
|
||||
delta = (value2 - value1) & ACPI_PM_MASK;
|
||||
|
||||
/* Check that the PMTMR delta is within 5% of what we expect */
|
||||
|
@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void)
|
|||
#define verify_pmtmr_rate() (0)
|
||||
#endif
|
||||
|
||||
/* Number of monotonicity checks to perform during initialization */
|
||||
#define ACPI_PM_MONOTONICITY_CHECKS 10
|
||||
|
||||
static int __init init_acpi_pm_clocksource(void)
|
||||
{
|
||||
u32 value1, value2;
|
||||
unsigned int i;
|
||||
cycle_t value1, value2;
|
||||
unsigned int i, j, good = 0;
|
||||
|
||||
if (!pmtmr_ioport)
|
||||
return -ENODEV;
|
||||
|
@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void)
|
|||
clocksource_acpi_pm.shift);
|
||||
|
||||
/* "verify" this timing source: */
|
||||
value1 = read_pmtmr();
|
||||
for (i = 0; i < 10000; i++) {
|
||||
value2 = read_pmtmr();
|
||||
if (value2 == value1)
|
||||
continue;
|
||||
if (value2 > value1)
|
||||
goto pm_good;
|
||||
if ((value2 < value1) && ((value2) < 0xFFF))
|
||||
goto pm_good;
|
||||
printk(KERN_INFO "PM-Timer had inconsistent results:"
|
||||
" 0x%#x, 0x%#x - aborting.\n", value1, value2);
|
||||
return -EINVAL;
|
||||
for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
|
||||
value1 = clocksource_acpi_pm.read();
|
||||
for (i = 0; i < 10000; i++) {
|
||||
value2 = clocksource_acpi_pm.read();
|
||||
if (value2 == value1)
|
||||
continue;
|
||||
if (value2 > value1)
|
||||
good++;
|
||||
break;
|
||||
if ((value2 < value1) && ((value2) < 0xFFF))
|
||||
good++;
|
||||
break;
|
||||
printk(KERN_INFO "PM-Timer had inconsistent results:"
|
||||
" 0x%#llx, 0x%#llx - aborting.\n",
|
||||
value1, value2);
|
||||
return -EINVAL;
|
||||
}
|
||||
udelay(300 * i);
|
||||
}
|
||||
|
||||
if (good != ACPI_PM_MONOTONICITY_CHECKS) {
|
||||
printk(KERN_INFO "PM-Timer failed consistency check "
|
||||
" (0x%#llx) - aborting.\n", value1);
|
||||
return -ENODEV;
|
||||
}
|
||||
printk(KERN_INFO "PM-Timer had no reasonable result:"
|
||||
" 0x%#x - aborting.\n", value1);
|
||||
return -ENODEV;
|
||||
|
||||
pm_good:
|
||||
if (verify_pmtmr_rate() != 0)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
}
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static const struct usb_device_id bcm5974_table [] = {
|
||||
static const struct usb_device_id bcm5974_table[] = {
|
||||
/* MacbookAir1.1 */
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
|
||||
|
@ -105,7 +105,7 @@ struct tp_header {
|
|||
|
||||
/* trackpad finger structure */
|
||||
struct tp_finger {
|
||||
__le16 origin; /* left/right origin? */
|
||||
__le16 origin; /* zero when switching track finger */
|
||||
__le16 abs_x; /* absolute x coodinate */
|
||||
__le16 abs_y; /* absolute y coodinate */
|
||||
__le16 rel_x; /* relative x coodinate */
|
||||
|
@ -159,6 +159,7 @@ struct bcm5974 {
|
|||
struct bt_data *bt_data; /* button transferred data */
|
||||
struct urb *tp_urb; /* trackpad usb request block */
|
||||
struct tp_data *tp_data; /* trackpad transferred data */
|
||||
int fingers; /* number of fingers on trackpad */
|
||||
};
|
||||
|
||||
/* logical dimensions */
|
||||
|
@ -172,6 +173,10 @@ struct bcm5974 {
|
|||
#define SN_WIDTH 100 /* width signal-to-noise ratio */
|
||||
#define SN_COORD 250 /* coordinate signal-to-noise ratio */
|
||||
|
||||
/* pressure thresholds */
|
||||
#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE)
|
||||
#define PRESSURE_HIGH (3 * PRESSURE_LOW)
|
||||
|
||||
/* device constants */
|
||||
static const struct bcm5974_config bcm5974_config_table[] = {
|
||||
{
|
||||
|
@ -248,6 +253,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
|
|||
0, cfg->y.dim, cfg->y.fuzz, 0);
|
||||
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
|
||||
|
@ -273,32 +279,66 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||
const struct tp_finger *f = dev->tp_data->finger;
|
||||
struct input_dev *input = dev->input;
|
||||
const int fingers = (size - 26) / 28;
|
||||
int p = 0, w, x, y, n = 0;
|
||||
int raw_p, raw_w, raw_x, raw_y;
|
||||
int ptest = 0, origin = 0, nmin = 0, nmax = 0;
|
||||
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
|
||||
|
||||
if (size < 26 || (size - 26) % 28 != 0)
|
||||
return -EIO;
|
||||
|
||||
/* always track the first finger; when detached, start over */
|
||||
if (fingers) {
|
||||
p = raw2int(f->force_major);
|
||||
w = raw2int(f->size_major);
|
||||
x = raw2int(f->abs_x);
|
||||
y = raw2int(f->abs_y);
|
||||
n = p > 0 ? fingers : 0;
|
||||
raw_p = raw2int(f->force_major);
|
||||
raw_w = raw2int(f->size_major);
|
||||
raw_x = raw2int(f->abs_x);
|
||||
raw_y = raw2int(f->abs_y);
|
||||
|
||||
dprintk(9,
|
||||
"bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
|
||||
p, w, x, y, n);
|
||||
"bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
|
||||
raw_p, raw_w, raw_x, raw_y);
|
||||
|
||||
input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w));
|
||||
input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin));
|
||||
input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y));
|
||||
ptest = int2bound(&c->p, raw_p);
|
||||
origin = raw2int(f->origin);
|
||||
}
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p));
|
||||
/* while tracking finger still valid, count all fingers */
|
||||
if (ptest > PRESSURE_LOW && origin) {
|
||||
abs_p = ptest;
|
||||
abs_w = int2bound(&c->w, raw_w);
|
||||
abs_x = int2bound(&c->x, raw_x - c->x.devmin);
|
||||
abs_y = int2bound(&c->y, c->y.devmax - raw_y);
|
||||
for (; f != dev->tp_data->finger + fingers; f++) {
|
||||
ptest = int2bound(&c->p, raw2int(f->force_major));
|
||||
if (ptest > PRESSURE_LOW)
|
||||
nmax++;
|
||||
if (ptest > PRESSURE_HIGH)
|
||||
nmin++;
|
||||
}
|
||||
}
|
||||
|
||||
input_report_key(input, BTN_TOOL_FINGER, n == 1);
|
||||
input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
|
||||
input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2);
|
||||
if (dev->fingers < nmin)
|
||||
dev->fingers = nmin;
|
||||
if (dev->fingers > nmax)
|
||||
dev->fingers = nmax;
|
||||
|
||||
input_report_key(input, BTN_TOUCH, dev->fingers > 0);
|
||||
input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
|
||||
input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
|
||||
input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, abs_p);
|
||||
input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
|
||||
|
||||
if (abs_p) {
|
||||
input_report_abs(input, ABS_X, abs_x);
|
||||
input_report_abs(input, ABS_Y, abs_y);
|
||||
|
||||
dprintk(8,
|
||||
"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
|
||||
"nmin: %d nmax: %d n: %d\n",
|
||||
abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
|
||||
|
||||
}
|
||||
|
||||
input_sync(input);
|
||||
|
||||
|
|
|
@ -305,7 +305,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
|
|||
.ident = "Lenovo 3000 n100",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -423,7 +423,7 @@ int chp_new(struct chp_id chpid)
|
|||
ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
|
||||
if (ret) {
|
||||
device_unregister(&chp->dev);
|
||||
goto out_free;
|
||||
goto out;
|
||||
}
|
||||
mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
|
||||
if (channel_subsystems[chpid.cssid]->cm_enabled) {
|
||||
|
@ -432,14 +432,15 @@ int chp_new(struct chp_id chpid)
|
|||
sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
|
||||
device_unregister(&chp->dev);
|
||||
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
|
||||
goto out_free;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
|
||||
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
|
||||
return ret;
|
||||
goto out;
|
||||
out_free:
|
||||
kfree(chp);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -208,8 +208,10 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
|
|||
case 1: /* status pending */
|
||||
case 2: /* busy */
|
||||
return -EBUSY;
|
||||
default: /* device/path not operational */
|
||||
case 3: /* device/path not operational */
|
||||
return cio_start_handle_notoper(sch, lpm);
|
||||
default:
|
||||
return ccode;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev)
|
|||
|
||||
css = to_css(dev);
|
||||
mutex_destroy(&css->mutex);
|
||||
if (css->pseudo_subchannel) {
|
||||
/* Implies that it has been generated but never registered. */
|
||||
css_subchannel_release(&css->pseudo_subchannel->dev);
|
||||
css->pseudo_subchannel = NULL;
|
||||
}
|
||||
kfree(css);
|
||||
}
|
||||
|
||||
|
@ -785,11 +790,15 @@ init_channel_subsystem (void)
|
|||
}
|
||||
channel_subsystems[i] = css;
|
||||
ret = setup_css(i);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
if (ret) {
|
||||
kfree(channel_subsystems[i]);
|
||||
goto out_unregister;
|
||||
}
|
||||
ret = device_register(&css->device);
|
||||
if (ret)
|
||||
goto out_free_all;
|
||||
if (ret) {
|
||||
put_device(&css->device);
|
||||
goto out_unregister;
|
||||
}
|
||||
if (css_chsc_characteristics.secm) {
|
||||
ret = device_create_file(&css->device,
|
||||
&dev_attr_cm_enable);
|
||||
|
@ -802,7 +811,7 @@ init_channel_subsystem (void)
|
|||
}
|
||||
ret = register_reboot_notifier(&css_reboot_notifier);
|
||||
if (ret)
|
||||
goto out_pseudo;
|
||||
goto out_unregister;
|
||||
css_init_done = 1;
|
||||
|
||||
/* Enable default isc for I/O subchannels. */
|
||||
|
@ -810,18 +819,12 @@ init_channel_subsystem (void)
|
|||
|
||||
for_each_subchannel(__init_channel_subsystem, NULL);
|
||||
return 0;
|
||||
out_pseudo:
|
||||
device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
|
||||
out_file:
|
||||
device_remove_file(&channel_subsystems[i]->device,
|
||||
&dev_attr_cm_enable);
|
||||
if (css_chsc_characteristics.secm)
|
||||
device_remove_file(&channel_subsystems[i]->device,
|
||||
&dev_attr_cm_enable);
|
||||
out_device:
|
||||
device_unregister(&channel_subsystems[i]->device);
|
||||
out_free_all:
|
||||
kfree(channel_subsystems[i]->pseudo_subchannel->lock);
|
||||
kfree(channel_subsystems[i]->pseudo_subchannel);
|
||||
out_free:
|
||||
kfree(channel_subsystems[i]);
|
||||
out_unregister:
|
||||
while (i > 0) {
|
||||
struct channel_subsystem *css;
|
||||
|
@ -829,6 +832,7 @@ out_unregister:
|
|||
i--;
|
||||
css = channel_subsystems[i];
|
||||
device_unregister(&css->pseudo_subchannel->dev);
|
||||
css->pseudo_subchannel = NULL;
|
||||
if (css_chsc_characteristics.secm)
|
||||
device_remove_file(&css->device,
|
||||
&dev_attr_cm_enable);
|
||||
|
|
|
@ -658,6 +658,13 @@ ccw_device_offline(struct ccw_device *cdev)
|
|||
{
|
||||
struct subchannel *sch;
|
||||
|
||||
/* Allow ccw_device_offline while disconnected. */
|
||||
if (cdev->private->state == DEV_STATE_DISCONNECTED ||
|
||||
cdev->private->state == DEV_STATE_NOT_OPER) {
|
||||
cdev->private->flags.donotify = 0;
|
||||
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
|
||||
return 0;
|
||||
}
|
||||
if (ccw_device_is_orphan(cdev)) {
|
||||
ccw_device_done(cdev, DEV_STATE_OFFLINE);
|
||||
return 0;
|
||||
|
|
|
@ -208,7 +208,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
|
|||
if (cpu_is_omap16xx())
|
||||
ocpi_enable();
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP_OTG
|
||||
#ifdef CONFIG_USB_OTG
|
||||
if (need_transceiver) {
|
||||
ohci->transceiver = otg_get_transceiver();
|
||||
if (ohci->transceiver) {
|
||||
|
|
|
@ -161,7 +161,7 @@ static int usb_console_setup(struct console *co, char *options)
|
|||
if (serial->type->set_termios) {
|
||||
termios->c_cflag = cflag;
|
||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
serial->type->set_termios(NULL, port, &dummy);
|
||||
serial->type->set_termios(tty, port, &dummy);
|
||||
|
||||
port->port.tty = NULL;
|
||||
kfree(termios);
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
|
||||
|
||||
#define BALLOON_CLASS_NAME "memory"
|
||||
#define BALLOON_CLASS_NAME "xen_memory"
|
||||
|
||||
struct balloon_stats {
|
||||
/* We aim for 'current allocation' == 'target allocation'. */
|
||||
|
|
|
@ -1279,6 +1279,12 @@ static int nfs_parse_mount_options(char *raw,
|
|||
}
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n",
|
||||
errors, (errors == 1 ? "" : "s"));
|
||||
if (!sloppy)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
out_nomem:
|
||||
|
|
|
@ -302,18 +302,6 @@ long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs)
|
|||
int subtract_lebs;
|
||||
long long available;
|
||||
|
||||
/*
|
||||
* Force the amount available to the total size reported if the used
|
||||
* space is zero.
|
||||
*/
|
||||
if (c->lst.total_used <= UBIFS_INO_NODE_SZ &&
|
||||
c->budg_data_growth + c->budg_dd_growth == 0) {
|
||||
/* Do the same calculation as for c->block_cnt */
|
||||
available = c->main_lebs - 2;
|
||||
available *= c->leb_size - c->dark_wm;
|
||||
return available;
|
||||
}
|
||||
|
||||
available = c->main_bytes - c->lst.total_used;
|
||||
|
||||
/*
|
||||
|
@ -714,34 +702,106 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
|
|||
}
|
||||
|
||||
/**
|
||||
* ubifs_budg_get_free_space - return amount of free space.
|
||||
* ubifs_reported_space - calculate reported free space.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @free: amount of free space
|
||||
*
|
||||
* This function calculates amount of free space which will be reported to
|
||||
* user-space. User-space application tend to expect that if the file-system
|
||||
* (e.g., via the 'statfs()' call) reports that it has N bytes available, they
|
||||
* are able to write a file of size N. UBIFS attaches node headers to each data
|
||||
* node and it has to write indexind nodes as well. This introduces additional
|
||||
* overhead, and UBIFS it has to report sligtly less free space to meet the
|
||||
* above expectetion.
|
||||
*
|
||||
* This function assumes free space is made up of uncompressed data nodes and
|
||||
* full index nodes (one per data node, tripled because we always allow enough
|
||||
* space to write the index thrice).
|
||||
*
|
||||
* Note, the calculation is pessimistic, which means that most of the time
|
||||
* UBIFS reports less space than it actually has.
|
||||
*/
|
||||
long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
|
||||
{
|
||||
int divisor, factor, f;
|
||||
|
||||
/*
|
||||
* Reported space size is @free * X, where X is UBIFS block size
|
||||
* divided by UBIFS block size + all overhead one data block
|
||||
* introduces. The overhead is the node header + indexing overhead.
|
||||
*
|
||||
* Indexing overhead calculations are based on the following formula:
|
||||
* I = N/(f - 1) + 1, where I - number of indexing nodes, N - number
|
||||
* of data nodes, f - fanout. Because effective UBIFS fanout is twice
|
||||
* as less than maximum fanout, we assume that each data node
|
||||
* introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes.
|
||||
* Note, the multiplier 3 is because UBIFS reseves thrice as more space
|
||||
* for the index.
|
||||
*/
|
||||
f = c->fanout > 3 ? c->fanout >> 1 : 2;
|
||||
factor = UBIFS_BLOCK_SIZE;
|
||||
divisor = UBIFS_MAX_DATA_NODE_SZ;
|
||||
divisor += (c->max_idx_node_sz * 3) / (f - 1);
|
||||
free *= factor;
|
||||
do_div(free, divisor);
|
||||
return free;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_get_free_space - return amount of free space.
|
||||
* @c: UBIFS file-system description object
|
||||
*
|
||||
* This function returns amount of free space on the file-system.
|
||||
* This function calculates amount of free space to report to user-space.
|
||||
*
|
||||
* Because UBIFS may introduce substantial overhead (the index, node headers,
|
||||
* alighment, wastage at the end of eraseblocks, etc), it cannot report real
|
||||
* amount of free flash space it has (well, because not all dirty space is
|
||||
* reclamable, UBIFS does not actually know the real amount). If UBIFS did so,
|
||||
* it would bread user expectetion about what free space is. Users seem to
|
||||
* accustomed to assume that if the file-system reports N bytes of free space,
|
||||
* they would be able to fit a file of N bytes to the FS. This almost works for
|
||||
* traditional file-systems, because they have way less overhead than UBIFS.
|
||||
* So, to keep users happy, UBIFS tries to take the overhead into account.
|
||||
*/
|
||||
long long ubifs_budg_get_free_space(struct ubifs_info *c)
|
||||
long long ubifs_get_free_space(struct ubifs_info *c)
|
||||
{
|
||||
int min_idx_lebs, rsvd_idx_lebs;
|
||||
int min_idx_lebs, rsvd_idx_lebs, lebs;
|
||||
long long available, outstanding, free;
|
||||
|
||||
/* Do exactly the same calculations as in 'do_budget_space()' */
|
||||
spin_lock(&c->space_lock);
|
||||
min_idx_lebs = ubifs_calc_min_idx_lebs(c);
|
||||
outstanding = c->budg_data_growth + c->budg_dd_growth;
|
||||
|
||||
/*
|
||||
* Force the amount available to the total size reported if the used
|
||||
* space is zero.
|
||||
*/
|
||||
if (c->lst.total_used <= UBIFS_INO_NODE_SZ && !outstanding) {
|
||||
spin_unlock(&c->space_lock);
|
||||
return (long long)c->block_cnt << UBIFS_BLOCK_SHIFT;
|
||||
}
|
||||
|
||||
available = ubifs_calc_available(c, min_idx_lebs);
|
||||
|
||||
/*
|
||||
* When reporting free space to user-space, UBIFS guarantees that it is
|
||||
* possible to write a file of free space size. This means that for
|
||||
* empty LEBs we may use more precise calculations than
|
||||
* 'ubifs_calc_available()' is using. Namely, we know that in empty
|
||||
* LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm.
|
||||
* Thus, amend the available space.
|
||||
*
|
||||
* Note, the calculations below are similar to what we have in
|
||||
* 'do_budget_space()', so refer there for comments.
|
||||
*/
|
||||
if (min_idx_lebs > c->lst.idx_lebs)
|
||||
rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
|
||||
else
|
||||
rsvd_idx_lebs = 0;
|
||||
|
||||
if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt
|
||||
- c->lst.taken_empty_lebs) {
|
||||
spin_unlock(&c->space_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
available = ubifs_calc_available(c, min_idx_lebs);
|
||||
outstanding = c->budg_data_growth + c->budg_dd_growth;
|
||||
c->min_idx_lebs = min_idx_lebs;
|
||||
lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
|
||||
c->lst.taken_empty_lebs;
|
||||
lebs -= rsvd_idx_lebs;
|
||||
available += lebs * (c->dark_wm - c->leb_overhead);
|
||||
spin_unlock(&c->space_lock);
|
||||
|
||||
if (available > outstanding)
|
||||
|
|
|
@ -587,7 +587,6 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
if (err) {
|
||||
if (err != -ENOSPC)
|
||||
return err;
|
||||
err = 0;
|
||||
budgeted = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -793,7 +793,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
|
|||
int err;
|
||||
struct ubifs_budget_req req;
|
||||
loff_t old_size = inode->i_size, new_size = attr->ia_size;
|
||||
int offset = new_size & (UBIFS_BLOCK_SIZE - 1);
|
||||
int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
|
||||
dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size);
|
||||
|
@ -811,8 +811,15 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
|
|||
/* A funny way to budget for truncation node */
|
||||
req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ;
|
||||
err = ubifs_budget_space(c, &req);
|
||||
if (err)
|
||||
return err;
|
||||
if (err) {
|
||||
/*
|
||||
* Treat truncations to zero as deletion and always allow them,
|
||||
* just like we do for '->unlink()'.
|
||||
*/
|
||||
if (new_size || err != -ENOSPC)
|
||||
return err;
|
||||
budgeted = 0;
|
||||
}
|
||||
|
||||
err = vmtruncate(inode, new_size);
|
||||
if (err)
|
||||
|
@ -869,7 +876,12 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
|
|||
err = ubifs_jnl_truncate(c, inode, old_size, new_size);
|
||||
mutex_unlock(&ui->ui_mutex);
|
||||
out_budg:
|
||||
ubifs_release_budget(c, &req);
|
||||
if (budgeted)
|
||||
ubifs_release_budget(c, &req);
|
||||
else {
|
||||
c->nospace = c->nospace_rp = 0;
|
||||
smp_wmb();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,14 +211,8 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
|
|||
* dirty index heap, and it falls-back to LPT scanning if the heaps are empty
|
||||
* or do not have an LEB which satisfies the @min_space criteria.
|
||||
*
|
||||
* Note:
|
||||
* o LEBs which have less than dead watermark of dirty space are never picked
|
||||
* by this function;
|
||||
*
|
||||
* Returns zero and the LEB properties of
|
||||
* found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a
|
||||
* negative error code in case of other failures. The returned LEB is marked as
|
||||
* "taken".
|
||||
* Note, LEBs which have less than dead watermark of free + dirty space are
|
||||
* never picked by this function.
|
||||
*
|
||||
* The additional @pick_free argument controls if this function has to return a
|
||||
* free or freeable LEB if one is present. For example, GC must to set it to %1,
|
||||
|
@ -231,6 +225,10 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
|
|||
*
|
||||
* In addition @pick_free is set to %2 by the recovery process in order to
|
||||
* recover gc_lnum in which case an index LEB must not be returned.
|
||||
*
|
||||
* This function returns zero and the LEB properties of found dirty LEB in case
|
||||
* of success, %-ENOSPC if no dirty LEB was found and a negative error code in
|
||||
* case of other failures. The returned LEB is marked as "taken".
|
||||
*/
|
||||
int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
|
||||
int min_space, int pick_free)
|
||||
|
@ -245,7 +243,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
|
|||
int lebs, rsvd_idx_lebs = 0;
|
||||
|
||||
spin_lock(&c->space_lock);
|
||||
lebs = c->lst.empty_lebs;
|
||||
lebs = c->lst.empty_lebs + c->idx_gc_cnt;
|
||||
lebs += c->freeable_cnt - c->lst.taken_empty_lebs;
|
||||
|
||||
/*
|
||||
|
@ -317,7 +315,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
|
|||
lp = idx_lp;
|
||||
|
||||
if (lp) {
|
||||
ubifs_assert(lp->dirty >= c->dead_wm);
|
||||
ubifs_assert(lp->free + lp->dirty >= c->dead_wm);
|
||||
goto found;
|
||||
}
|
||||
|
||||
|
|
|
@ -344,6 +344,12 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
/* Allow for races with TNC */
|
||||
c->gced_lnum = lnum;
|
||||
smp_wmb();
|
||||
c->gc_seq += 1;
|
||||
smp_wmb();
|
||||
|
||||
if (c->gc_lnum == -1) {
|
||||
c->gc_lnum = lnum;
|
||||
err = LEB_RETAINED;
|
||||
|
|
|
@ -283,38 +283,6 @@ static inline void *ubifs_idx_key(const struct ubifs_info *c,
|
|||
return (void *)((struct ubifs_branch *)idx->branches)->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_reported_space - calculate reported free space.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @free: amount of free space
|
||||
*
|
||||
* This function calculates amount of free space which will be reported to
|
||||
* user-space. User-space application tend to expect that if the file-system
|
||||
* (e.g., via the 'statfs()' call) reports that it has N bytes available, they
|
||||
* are able to write a file of size N. UBIFS attaches node headers to each data
|
||||
* node and it has to write indexind nodes as well. This introduces additional
|
||||
* overhead, and UBIFS it has to report sligtly less free space to meet the
|
||||
* above expectetion.
|
||||
*
|
||||
* This function assumes free space is made up of uncompressed data nodes and
|
||||
* full index nodes (one per data node, doubled because we always allow enough
|
||||
* space to write the index twice).
|
||||
*
|
||||
* Note, the calculation is pessimistic, which means that most of the time
|
||||
* UBIFS reports less space than it actually has.
|
||||
*/
|
||||
static inline long long ubifs_reported_space(const struct ubifs_info *c,
|
||||
uint64_t free)
|
||||
{
|
||||
int divisor, factor;
|
||||
|
||||
divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3);
|
||||
factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
|
||||
do_div(free, divisor);
|
||||
|
||||
return free * factor;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_current_time - round current time to time granularity.
|
||||
* @inode: inode
|
||||
|
@ -325,4 +293,21 @@ static inline struct timespec ubifs_current_time(struct inode *inode)
|
|||
current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_tnc_lookup - look up a file-system node.
|
||||
* @c: UBIFS file-system description object
|
||||
* @key: node key to lookup
|
||||
* @node: the node is returned here
|
||||
*
|
||||
* This function look up and reads node with key @key. The caller has to make
|
||||
* sure the @node buffer is large enough to fit the node. Returns zero in case
|
||||
* of success, %-ENOENT if the node was not found, and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
static inline int ubifs_tnc_lookup(struct ubifs_info *c,
|
||||
const union ubifs_key *key, void *node)
|
||||
{
|
||||
return ubifs_tnc_locate(c, key, node, NULL, NULL);
|
||||
}
|
||||
|
||||
#endif /* __UBIFS_MISC_H__ */
|
||||
|
|
|
@ -370,8 +370,9 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
{
|
||||
struct ubifs_info *c = dentry->d_sb->s_fs_info;
|
||||
unsigned long long free;
|
||||
__le32 *uuid = (__le32 *)c->uuid;
|
||||
|
||||
free = ubifs_budg_get_free_space(c);
|
||||
free = ubifs_get_free_space(c);
|
||||
dbg_gen("free space %lld bytes (%lld blocks)",
|
||||
free, free >> UBIFS_BLOCK_SHIFT);
|
||||
|
||||
|
@ -386,7 +387,8 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
buf->f_files = 0;
|
||||
buf->f_ffree = 0;
|
||||
buf->f_namelen = UBIFS_MAX_NLEN;
|
||||
|
||||
buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]);
|
||||
buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -530,6 +532,12 @@ static int init_constants_early(struct ubifs_info *c)
|
|||
c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
|
||||
c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
|
||||
|
||||
/*
|
||||
* Calculate how many bytes would be wasted at the end of LEB if it was
|
||||
* fully filled with data nodes of maximum size. This is used in
|
||||
* calculations when reporting free space.
|
||||
*/
|
||||
c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -647,13 +655,11 @@ static int init_constants_late(struct ubifs_info *c)
|
|||
* internally because it does not make much sense for UBIFS, but it is
|
||||
* necessary to report something for the 'statfs()' call.
|
||||
*
|
||||
* Subtract the LEB reserved for GC and the LEB which is reserved for
|
||||
* deletions.
|
||||
*
|
||||
* Review 'ubifs_calc_available()' if changing this calculation.
|
||||
* Subtract the LEB reserved for GC, the LEB which is reserved for
|
||||
* deletions, and assume only one journal head is available.
|
||||
*/
|
||||
tmp64 = c->main_lebs - 2;
|
||||
tmp64 *= (uint64_t)c->leb_size - c->dark_wm;
|
||||
tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1;
|
||||
tmp64 *= (uint64_t)c->leb_size - c->leb_overhead;
|
||||
tmp64 = ubifs_reported_space(c, tmp64);
|
||||
c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
|
||||
|
||||
|
|
116
fs/ubifs/tnc.c
116
fs/ubifs/tnc.c
|
@ -506,7 +506,7 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
|
|||
if (keys_cmp(c, key, &node_key) != 0)
|
||||
ret = 0;
|
||||
}
|
||||
if (ret == 0)
|
||||
if (ret == 0 && c->replaying)
|
||||
dbg_mnt("dangling branch LEB %d:%d len %d, key %s",
|
||||
zbr->lnum, zbr->offs, zbr->len, DBGKEY(key));
|
||||
return ret;
|
||||
|
@ -1382,50 +1382,39 @@ static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key,
|
|||
}
|
||||
|
||||
/**
|
||||
* ubifs_tnc_lookup - look up a file-system node.
|
||||
* maybe_leb_gced - determine if a LEB may have been garbage collected.
|
||||
* @c: UBIFS file-system description object
|
||||
* @key: node key to lookup
|
||||
* @node: the node is returned here
|
||||
* @lnum: LEB number
|
||||
* @gc_seq1: garbage collection sequence number
|
||||
*
|
||||
* This function look up and reads node with key @key. The caller has to make
|
||||
* sure the @node buffer is large enough to fit the node. Returns zero in case
|
||||
* of success, %-ENOENT if the node was not found, and a negative error code in
|
||||
* case of failure.
|
||||
* This function determines if @lnum may have been garbage collected since
|
||||
* sequence number @gc_seq1. If it may have been then %1 is returned, otherwise
|
||||
* %0 is returned.
|
||||
*/
|
||||
int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
|
||||
void *node)
|
||||
static int maybe_leb_gced(struct ubifs_info *c, int lnum, int gc_seq1)
|
||||
{
|
||||
int found, n, err;
|
||||
struct ubifs_znode *znode;
|
||||
struct ubifs_zbranch zbr, *zt;
|
||||
int gc_seq2, gced_lnum;
|
||||
|
||||
mutex_lock(&c->tnc_mutex);
|
||||
found = ubifs_lookup_level0(c, key, &znode, &n);
|
||||
if (!found) {
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
} else if (found < 0) {
|
||||
err = found;
|
||||
goto out;
|
||||
}
|
||||
zt = &znode->zbranch[n];
|
||||
if (is_hash_key(c, key)) {
|
||||
/*
|
||||
* In this case the leaf node cache gets used, so we pass the
|
||||
* address of the zbranch and keep the mutex locked
|
||||
*/
|
||||
err = tnc_read_node_nm(c, zt, node);
|
||||
goto out;
|
||||
}
|
||||
zbr = znode->zbranch[n];
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
|
||||
err = ubifs_tnc_read_node(c, &zbr, node);
|
||||
return err;
|
||||
|
||||
out:
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
return err;
|
||||
gced_lnum = c->gced_lnum;
|
||||
smp_rmb();
|
||||
gc_seq2 = c->gc_seq;
|
||||
/* Same seq means no GC */
|
||||
if (gc_seq1 == gc_seq2)
|
||||
return 0;
|
||||
/* Different by more than 1 means we don't know */
|
||||
if (gc_seq1 + 1 != gc_seq2)
|
||||
return 1;
|
||||
/*
|
||||
* We have seen the sequence number has increased by 1. Now we need to
|
||||
* be sure we read the right LEB number, so read it again.
|
||||
*/
|
||||
smp_rmb();
|
||||
if (gced_lnum != c->gced_lnum)
|
||||
return 1;
|
||||
/* Finally we can check lnum */
|
||||
if (gced_lnum == lnum)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1436,16 +1425,19 @@ out:
|
|||
* @lnum: LEB number is returned here
|
||||
* @offs: offset is returned here
|
||||
*
|
||||
* This function is the same as 'ubifs_tnc_lookup()' but it returns the node
|
||||
* location also. See 'ubifs_tnc_lookup()'.
|
||||
* This function look up and reads node with key @key. The caller has to make
|
||||
* sure the @node buffer is large enough to fit the node. Returns zero in case
|
||||
* of success, %-ENOENT if the node was not found, and a negative error code in
|
||||
* case of failure. The node location can be returned in @lnum and @offs.
|
||||
*/
|
||||
int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
|
||||
void *node, int *lnum, int *offs)
|
||||
{
|
||||
int found, n, err;
|
||||
int found, n, err, safely = 0, gc_seq1;
|
||||
struct ubifs_znode *znode;
|
||||
struct ubifs_zbranch zbr, *zt;
|
||||
|
||||
again:
|
||||
mutex_lock(&c->tnc_mutex);
|
||||
found = ubifs_lookup_level0(c, key, &znode, &n);
|
||||
if (!found) {
|
||||
|
@ -1456,24 +1448,43 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
|
|||
goto out;
|
||||
}
|
||||
zt = &znode->zbranch[n];
|
||||
if (lnum) {
|
||||
*lnum = zt->lnum;
|
||||
*offs = zt->offs;
|
||||
}
|
||||
if (is_hash_key(c, key)) {
|
||||
/*
|
||||
* In this case the leaf node cache gets used, so we pass the
|
||||
* address of the zbranch and keep the mutex locked
|
||||
*/
|
||||
*lnum = zt->lnum;
|
||||
*offs = zt->offs;
|
||||
err = tnc_read_node_nm(c, zt, node);
|
||||
goto out;
|
||||
}
|
||||
if (safely) {
|
||||
err = ubifs_tnc_read_node(c, zt, node);
|
||||
goto out;
|
||||
}
|
||||
/* Drop the TNC mutex prematurely and race with garbage collection */
|
||||
zbr = znode->zbranch[n];
|
||||
gc_seq1 = c->gc_seq;
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
|
||||
*lnum = zbr.lnum;
|
||||
*offs = zbr.offs;
|
||||
if (ubifs_get_wbuf(c, zbr.lnum)) {
|
||||
/* We do not GC journal heads */
|
||||
err = ubifs_tnc_read_node(c, &zbr, node);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ubifs_tnc_read_node(c, &zbr, node);
|
||||
return err;
|
||||
err = fallible_read_node(c, key, &zbr, node);
|
||||
if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) {
|
||||
/*
|
||||
* The node may have been GC'ed out from under us so try again
|
||||
* while keeping the TNC mutex locked.
|
||||
*/
|
||||
safely = 1;
|
||||
goto again;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out:
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
|
@ -1498,7 +1509,6 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
|
|||
{
|
||||
int found, n, err;
|
||||
struct ubifs_znode *znode;
|
||||
struct ubifs_zbranch zbr;
|
||||
|
||||
dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key));
|
||||
mutex_lock(&c->tnc_mutex);
|
||||
|
@ -1522,11 +1532,7 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
zbr = znode->zbranch[n];
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
|
||||
err = tnc_read_node_nm(c, &zbr, node);
|
||||
return err;
|
||||
err = tnc_read_node_nm(c, &znode->zbranch[n], node);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&c->tnc_mutex);
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
#define UBIFS_SK_LEN 8
|
||||
|
||||
/* Minimum index tree fanout */
|
||||
#define UBIFS_MIN_FANOUT 2
|
||||
#define UBIFS_MIN_FANOUT 3
|
||||
|
||||
/* Maximum number of levels in UBIFS indexing B-tree */
|
||||
#define UBIFS_MAX_LEVELS 512
|
||||
|
|
|
@ -995,6 +995,9 @@ struct ubifs_mount_opts {
|
|||
* @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary
|
||||
* @max_inode_sz: maximum possible inode size in bytes
|
||||
* @max_znode_sz: size of znode in bytes
|
||||
*
|
||||
* @leb_overhead: how many bytes are wasted in an LEB when it is filled with
|
||||
* data nodes of maximum size - used in free space reporting
|
||||
* @dead_wm: LEB dead space watermark
|
||||
* @dark_wm: LEB dark space watermark
|
||||
* @block_cnt: count of 4KiB blocks on the FS
|
||||
|
@ -1028,6 +1031,8 @@ struct ubifs_mount_opts {
|
|||
* @sbuf: a buffer of LEB size used by GC and replay for scanning
|
||||
* @idx_gc: list of index LEBs that have been garbage collected
|
||||
* @idx_gc_cnt: number of elements on the idx_gc list
|
||||
* @gc_seq: incremented for every non-index LEB garbage collected
|
||||
* @gced_lnum: last non-index LEB that was garbage collected
|
||||
*
|
||||
* @infos_list: links all 'ubifs_info' objects
|
||||
* @umount_mutex: serializes shrinker and un-mount
|
||||
|
@ -1224,6 +1229,8 @@ struct ubifs_info {
|
|||
int max_idx_node_sz;
|
||||
long long max_inode_sz;
|
||||
int max_znode_sz;
|
||||
|
||||
int leb_overhead;
|
||||
int dead_wm;
|
||||
int dark_wm;
|
||||
int block_cnt;
|
||||
|
@ -1257,6 +1264,8 @@ struct ubifs_info {
|
|||
void *sbuf;
|
||||
struct list_head idx_gc;
|
||||
int idx_gc_cnt;
|
||||
volatile int gc_seq;
|
||||
volatile int gced_lnum;
|
||||
|
||||
struct list_head infos_list;
|
||||
struct mutex umount_mutex;
|
||||
|
@ -1434,9 +1443,10 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
|
|||
struct ubifs_budget_req *req);
|
||||
void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
|
||||
struct ubifs_budget_req *req);
|
||||
long long ubifs_budg_get_free_space(struct ubifs_info *c);
|
||||
long long ubifs_get_free_space(struct ubifs_info *c);
|
||||
int ubifs_calc_min_idx_lebs(struct ubifs_info *c);
|
||||
void ubifs_convert_page_budget(struct ubifs_info *c);
|
||||
long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free);
|
||||
long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs);
|
||||
|
||||
/* find.c */
|
||||
|
@ -1451,8 +1461,6 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c);
|
|||
/* tnc.c */
|
||||
int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
|
||||
struct ubifs_znode **zn, int *n);
|
||||
int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
|
||||
void *node);
|
||||
int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
|
||||
void *node, const struct qstr *nm);
|
||||
int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
|
||||
|
|
|
@ -14,4 +14,10 @@ extern char __kprobes_text_start[], __kprobes_text_end[];
|
|||
extern char __initdata_begin[], __initdata_end[];
|
||||
extern char __start_rodata[], __end_rodata[];
|
||||
|
||||
/* function descriptor handling (if any). Override
|
||||
* in asm/sections.h */
|
||||
#ifndef dereference_function_descriptor
|
||||
#define dereference_function_descriptor(p) (p)
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_GENERIC_SECTIONS_H_ */
|
||||
|
|
|
@ -63,6 +63,7 @@ static inline void flush_icache_page(struct vm_area_struct *vma,
|
|||
}
|
||||
|
||||
extern void (*flush_icache_range)(unsigned long start, unsigned long end);
|
||||
extern void (*local_flush_icache_range)(unsigned long start, unsigned long end);
|
||||
|
||||
extern void (*__flush_cache_vmap)(void);
|
||||
|
||||
|
|
|
@ -4,4 +4,9 @@
|
|||
/* nothing to see, move along */
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#undef dereference_function_descriptor
|
||||
void *dereference_function_descriptor(void *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,14 +72,15 @@
|
|||
#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */
|
||||
#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
|
||||
#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
|
||||
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
|
||||
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
|
||||
#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */
|
||||
#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */
|
||||
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
|
||||
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
|
||||
#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */
|
||||
#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */
|
||||
#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
|
||||
#define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */
|
||||
#define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */
|
||||
#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */
|
||||
#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */
|
||||
#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
|
||||
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
|
||||
|
|
|
@ -41,6 +41,12 @@
|
|||
# define NEED_3DNOW 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_X86_P6_NOP) || defined(CONFIG_X86_64)
|
||||
# define NEED_NOPL (1<<(X86_FEATURE_NOPL & 31))
|
||||
#else
|
||||
# define NEED_NOPL 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#define NEED_PSE 0
|
||||
#define NEED_MSR (1<<(X86_FEATURE_MSR & 31))
|
||||
|
@ -67,7 +73,7 @@
|
|||
#define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
|
||||
|
||||
#define REQUIRED_MASK2 0
|
||||
#define REQUIRED_MASK3 0
|
||||
#define REQUIRED_MASK3 (NEED_NOPL)
|
||||
#define REQUIRED_MASK4 0
|
||||
#define REQUIRED_MASK5 0
|
||||
#define REQUIRED_MASK6 0
|
||||
|
|
|
@ -127,6 +127,8 @@ extern int clockevents_register_notifier(struct notifier_block *nb);
|
|||
extern int clockevents_program_event(struct clock_event_device *dev,
|
||||
ktime_t expires, ktime_t now);
|
||||
|
||||
extern void clockevents_handle_noop(struct clock_event_device *dev);
|
||||
|
||||
#ifdef CONFIG_GENERIC_CLOCKEVENTS
|
||||
extern void clockevents_notify(unsigned long reason, void *arg);
|
||||
#else
|
||||
|
|
|
@ -160,7 +160,7 @@ static inline int current_cpuset_is_being_rebound(void)
|
|||
|
||||
static inline void rebuild_sched_domains(void)
|
||||
{
|
||||
partition_sched_domains(0, NULL, NULL);
|
||||
partition_sched_domains(1, NULL, NULL);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_CPUSETS */
|
||||
|
|
|
@ -325,7 +325,8 @@ int hci_conn_del(struct hci_conn *conn);
|
|||
void hci_conn_hash_flush(struct hci_dev *hdev);
|
||||
void hci_conn_check_pending(struct hci_dev *hdev);
|
||||
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn);
|
||||
int hci_conn_auth(struct hci_conn *conn);
|
||||
int hci_conn_encrypt(struct hci_conn *conn);
|
||||
int hci_conn_change_link_key(struct hci_conn *conn);
|
||||
|
|
|
@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
|
|||
extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
|
||||
struct inet_timewait_death_row *twdr);
|
||||
|
||||
extern void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
|
||||
struct inet_timewait_death_row *twdr, int family);
|
||||
|
||||
static inline
|
||||
struct net *twsk_net(const struct inet_timewait_sock *twsk)
|
||||
{
|
||||
|
|
318
kernel/cpuset.c
318
kernel/cpuset.c
|
@ -14,6 +14,8 @@
|
|||
* 2003-10-22 Updates by Stephen Hemminger.
|
||||
* 2004 May-July Rework by Paul Jackson.
|
||||
* 2006 Rework by Paul Menage to use generic cgroups
|
||||
* 2008 Rework of the scheduler domains and CPU hotplug handling
|
||||
* by Max Krasnyansky
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of the Linux
|
||||
|
@ -236,9 +238,11 @@ static struct cpuset top_cpuset = {
|
|||
|
||||
static DEFINE_MUTEX(callback_mutex);
|
||||
|
||||
/* This is ugly, but preserves the userspace API for existing cpuset
|
||||
/*
|
||||
* This is ugly, but preserves the userspace API for existing cpuset
|
||||
* users. If someone tries to mount the "cpuset" filesystem, we
|
||||
* silently switch it to mount "cgroup" instead */
|
||||
* silently switch it to mount "cgroup" instead
|
||||
*/
|
||||
static int cpuset_get_sb(struct file_system_type *fs_type,
|
||||
int flags, const char *unused_dev_name,
|
||||
void *data, struct vfsmount *mnt)
|
||||
|
@ -473,10 +477,9 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
|
|||
}
|
||||
|
||||
/*
|
||||
* Helper routine for rebuild_sched_domains().
|
||||
* Helper routine for generate_sched_domains().
|
||||
* Do cpusets a, b have overlapping cpus_allowed masks?
|
||||
*/
|
||||
|
||||
static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
|
||||
{
|
||||
return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
|
||||
|
@ -518,26 +521,15 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
|
|||
}
|
||||
|
||||
/*
|
||||
* rebuild_sched_domains()
|
||||
* generate_sched_domains()
|
||||
*
|
||||
* This routine will be called to rebuild the scheduler's dynamic
|
||||
* sched domains:
|
||||
* - if the flag 'sched_load_balance' of any cpuset with non-empty
|
||||
* 'cpus' changes,
|
||||
* - or if the 'cpus' allowed changes in any cpuset which has that
|
||||
* flag enabled,
|
||||
* - or if the 'sched_relax_domain_level' of any cpuset which has
|
||||
* that flag enabled and with non-empty 'cpus' changes,
|
||||
* - or if any cpuset with non-empty 'cpus' is removed,
|
||||
* - or if a cpu gets offlined.
|
||||
*
|
||||
* This routine builds a partial partition of the systems CPUs
|
||||
* (the set of non-overlappping cpumask_t's in the array 'part'
|
||||
* below), and passes that partial partition to the kernel/sched.c
|
||||
* partition_sched_domains() routine, which will rebuild the
|
||||
* schedulers load balancing domains (sched domains) as specified
|
||||
* by that partial partition. A 'partial partition' is a set of
|
||||
* non-overlapping subsets whose union is a subset of that set.
|
||||
* This function builds a partial partition of the systems CPUs
|
||||
* A 'partial partition' is a set of non-overlapping subsets whose
|
||||
* union is a subset of that set.
|
||||
* The output of this function needs to be passed to kernel/sched.c
|
||||
* partition_sched_domains() routine, which will rebuild the scheduler's
|
||||
* load balancing domains (sched domains) as specified by that partial
|
||||
* partition.
|
||||
*
|
||||
* See "What is sched_load_balance" in Documentation/cpusets.txt
|
||||
* for a background explanation of this.
|
||||
|
@ -547,13 +539,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
|
|||
* domains when operating in the severe memory shortage situations
|
||||
* that could cause allocation failures below.
|
||||
*
|
||||
* Call with cgroup_mutex held. May take callback_mutex during
|
||||
* call due to the kfifo_alloc() and kmalloc() calls. May nest
|
||||
* a call to the get_online_cpus()/put_online_cpus() pair.
|
||||
* Must not be called holding callback_mutex, because we must not
|
||||
* call get_online_cpus() while holding callback_mutex. Elsewhere
|
||||
* the kernel nests callback_mutex inside get_online_cpus() calls.
|
||||
* So the reverse nesting would risk an ABBA deadlock.
|
||||
* Must be called with cgroup_lock held.
|
||||
*
|
||||
* The three key local variables below are:
|
||||
* q - a linked-list queue of cpuset pointers, used to implement a
|
||||
|
@ -588,10 +574,10 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
|
|||
* element of the partition (one sched domain) to be passed to
|
||||
* partition_sched_domains().
|
||||
*/
|
||||
|
||||
void rebuild_sched_domains(void)
|
||||
static int generate_sched_domains(cpumask_t **domains,
|
||||
struct sched_domain_attr **attributes)
|
||||
{
|
||||
LIST_HEAD(q); /* queue of cpusets to be scanned*/
|
||||
LIST_HEAD(q); /* queue of cpusets to be scanned */
|
||||
struct cpuset *cp; /* scans q */
|
||||
struct cpuset **csa; /* array of all cpuset ptrs */
|
||||
int csn; /* how many cpuset ptrs in csa so far */
|
||||
|
@ -601,23 +587,26 @@ void rebuild_sched_domains(void)
|
|||
int ndoms; /* number of sched domains in result */
|
||||
int nslot; /* next empty doms[] cpumask_t slot */
|
||||
|
||||
csa = NULL;
|
||||
ndoms = 0;
|
||||
doms = NULL;
|
||||
dattr = NULL;
|
||||
csa = NULL;
|
||||
|
||||
/* Special case for the 99% of systems with one, full, sched domain */
|
||||
if (is_sched_load_balance(&top_cpuset)) {
|
||||
ndoms = 1;
|
||||
doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
|
||||
if (!doms)
|
||||
goto rebuild;
|
||||
goto done;
|
||||
|
||||
dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL);
|
||||
if (dattr) {
|
||||
*dattr = SD_ATTR_INIT;
|
||||
update_domain_attr_tree(dattr, &top_cpuset);
|
||||
}
|
||||
*doms = top_cpuset.cpus_allowed;
|
||||
goto rebuild;
|
||||
|
||||
ndoms = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL);
|
||||
|
@ -680,61 +669,141 @@ restart:
|
|||
}
|
||||
}
|
||||
|
||||
/* Convert <csn, csa> to <ndoms, doms> */
|
||||
/*
|
||||
* Now we know how many domains to create.
|
||||
* Convert <csn, csa> to <ndoms, doms> and populate cpu masks.
|
||||
*/
|
||||
doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
|
||||
if (!doms)
|
||||
goto rebuild;
|
||||
if (!doms) {
|
||||
ndoms = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* The rest of the code, including the scheduler, can deal with
|
||||
* dattr==NULL case. No need to abort if alloc fails.
|
||||
*/
|
||||
dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL);
|
||||
|
||||
for (nslot = 0, i = 0; i < csn; i++) {
|
||||
struct cpuset *a = csa[i];
|
||||
cpumask_t *dp;
|
||||
int apn = a->pn;
|
||||
|
||||
if (apn >= 0) {
|
||||
cpumask_t *dp = doms + nslot;
|
||||
|
||||
if (nslot == ndoms) {
|
||||
static int warnings = 10;
|
||||
if (warnings) {
|
||||
printk(KERN_WARNING
|
||||
"rebuild_sched_domains confused:"
|
||||
" nslot %d, ndoms %d, csn %d, i %d,"
|
||||
" apn %d\n",
|
||||
nslot, ndoms, csn, i, apn);
|
||||
warnings--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
cpus_clear(*dp);
|
||||
if (dattr)
|
||||
*(dattr + nslot) = SD_ATTR_INIT;
|
||||
for (j = i; j < csn; j++) {
|
||||
struct cpuset *b = csa[j];
|
||||
|
||||
if (apn == b->pn) {
|
||||
cpus_or(*dp, *dp, b->cpus_allowed);
|
||||
b->pn = -1;
|
||||
if (dattr)
|
||||
update_domain_attr_tree(dattr
|
||||
+ nslot, b);
|
||||
}
|
||||
}
|
||||
nslot++;
|
||||
if (apn < 0) {
|
||||
/* Skip completed partitions */
|
||||
continue;
|
||||
}
|
||||
|
||||
dp = doms + nslot;
|
||||
|
||||
if (nslot == ndoms) {
|
||||
static int warnings = 10;
|
||||
if (warnings) {
|
||||
printk(KERN_WARNING
|
||||
"rebuild_sched_domains confused:"
|
||||
" nslot %d, ndoms %d, csn %d, i %d,"
|
||||
" apn %d\n",
|
||||
nslot, ndoms, csn, i, apn);
|
||||
warnings--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
cpus_clear(*dp);
|
||||
if (dattr)
|
||||
*(dattr + nslot) = SD_ATTR_INIT;
|
||||
for (j = i; j < csn; j++) {
|
||||
struct cpuset *b = csa[j];
|
||||
|
||||
if (apn == b->pn) {
|
||||
cpus_or(*dp, *dp, b->cpus_allowed);
|
||||
if (dattr)
|
||||
update_domain_attr_tree(dattr + nslot, b);
|
||||
|
||||
/* Done with this partition */
|
||||
b->pn = -1;
|
||||
}
|
||||
}
|
||||
nslot++;
|
||||
}
|
||||
BUG_ON(nslot != ndoms);
|
||||
|
||||
rebuild:
|
||||
/* Have scheduler rebuild sched domains */
|
||||
get_online_cpus();
|
||||
partition_sched_domains(ndoms, doms, dattr);
|
||||
put_online_cpus();
|
||||
|
||||
done:
|
||||
kfree(csa);
|
||||
/* Don't kfree(doms) -- partition_sched_domains() does that. */
|
||||
/* Don't kfree(dattr) -- partition_sched_domains() does that. */
|
||||
|
||||
*domains = doms;
|
||||
*attributes = dattr;
|
||||
return ndoms;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rebuild scheduler domains.
|
||||
*
|
||||
* Call with neither cgroup_mutex held nor within get_online_cpus().
|
||||
* Takes both cgroup_mutex and get_online_cpus().
|
||||
*
|
||||
* Cannot be directly called from cpuset code handling changes
|
||||
* to the cpuset pseudo-filesystem, because it cannot be called
|
||||
* from code that already holds cgroup_mutex.
|
||||
*/
|
||||
static void do_rebuild_sched_domains(struct work_struct *unused)
|
||||
{
|
||||
struct sched_domain_attr *attr;
|
||||
cpumask_t *doms;
|
||||
int ndoms;
|
||||
|
||||
get_online_cpus();
|
||||
|
||||
/* Generate domain masks and attrs */
|
||||
cgroup_lock();
|
||||
ndoms = generate_sched_domains(&doms, &attr);
|
||||
cgroup_unlock();
|
||||
|
||||
/* Have scheduler rebuild the domains */
|
||||
partition_sched_domains(ndoms, doms, attr);
|
||||
|
||||
put_online_cpus();
|
||||
}
|
||||
|
||||
static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains);
|
||||
|
||||
/*
|
||||
* Rebuild scheduler domains, asynchronously via workqueue.
|
||||
*
|
||||
* If the flag 'sched_load_balance' of any cpuset with non-empty
|
||||
* 'cpus' changes, or if the 'cpus' allowed changes in any cpuset
|
||||
* which has that flag enabled, or if any cpuset with a non-empty
|
||||
* 'cpus' is removed, then call this routine to rebuild the
|
||||
* scheduler's dynamic sched domains.
|
||||
*
|
||||
* The rebuild_sched_domains() and partition_sched_domains()
|
||||
* routines must nest cgroup_lock() inside get_online_cpus(),
|
||||
* but such cpuset changes as these must nest that locking the
|
||||
* other way, holding cgroup_lock() for much of the code.
|
||||
*
|
||||
* So in order to avoid an ABBA deadlock, the cpuset code handling
|
||||
* these user changes delegates the actual sched domain rebuilding
|
||||
* to a separate workqueue thread, which ends up processing the
|
||||
* above do_rebuild_sched_domains() function.
|
||||
*/
|
||||
static void async_rebuild_sched_domains(void)
|
||||
{
|
||||
schedule_work(&rebuild_sched_domains_work);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accomplishes the same scheduler domain rebuild as the above
|
||||
* async_rebuild_sched_domains(), however it directly calls the
|
||||
* rebuild routine synchronously rather than calling it via an
|
||||
* asynchronous work thread.
|
||||
*
|
||||
* This can only be called from code that is not holding
|
||||
* cgroup_mutex (not nested in a cgroup_lock() call.)
|
||||
*/
|
||||
void rebuild_sched_domains(void)
|
||||
{
|
||||
do_rebuild_sched_domains(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -863,7 +932,7 @@ static int update_cpumask(struct cpuset *cs, const char *buf)
|
|||
return retval;
|
||||
|
||||
if (is_load_balanced)
|
||||
rebuild_sched_domains();
|
||||
async_rebuild_sched_domains();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1090,7 +1159,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
|
|||
if (val != cs->relax_domain_level) {
|
||||
cs->relax_domain_level = val;
|
||||
if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs))
|
||||
rebuild_sched_domains();
|
||||
async_rebuild_sched_domains();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1131,7 +1200,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
|
|||
mutex_unlock(&callback_mutex);
|
||||
|
||||
if (cpus_nonempty && balance_flag_changed)
|
||||
rebuild_sched_domains();
|
||||
async_rebuild_sched_domains();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1492,6 +1561,9 @@ static u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft)
|
|||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Unreachable but makes gcc happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft)
|
||||
|
@ -1504,6 +1576,9 @@ static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft)
|
|||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Unrechable but makes gcc happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1692,15 +1767,9 @@ static struct cgroup_subsys_state *cpuset_create(
|
|||
}
|
||||
|
||||
/*
|
||||
* Locking note on the strange update_flag() call below:
|
||||
*
|
||||
* If the cpuset being removed has its flag 'sched_load_balance'
|
||||
* enabled, then simulate turning sched_load_balance off, which
|
||||
* will call rebuild_sched_domains(). The get_online_cpus()
|
||||
* call in rebuild_sched_domains() must not be made while holding
|
||||
* callback_mutex. Elsewhere the kernel nests callback_mutex inside
|
||||
* get_online_cpus() calls. So the reverse nesting would risk an
|
||||
* ABBA deadlock.
|
||||
* will call async_rebuild_sched_domains().
|
||||
*/
|
||||
|
||||
static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
|
||||
|
@ -1719,7 +1788,7 @@ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
|
|||
struct cgroup_subsys cpuset_subsys = {
|
||||
.name = "cpuset",
|
||||
.create = cpuset_create,
|
||||
.destroy = cpuset_destroy,
|
||||
.destroy = cpuset_destroy,
|
||||
.can_attach = cpuset_can_attach,
|
||||
.attach = cpuset_attach,
|
||||
.populate = cpuset_populate,
|
||||
|
@ -1811,7 +1880,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to)
|
|||
}
|
||||
|
||||
/*
|
||||
* If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs
|
||||
* If CPU and/or memory hotplug handlers, below, unplug any CPUs
|
||||
* or memory nodes, we need to walk over the cpuset hierarchy,
|
||||
* removing that CPU or node from all cpusets. If this removes the
|
||||
* last CPU or node from a cpuset, then move the tasks in the empty
|
||||
|
@ -1902,35 +1971,6 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The cpus_allowed and mems_allowed nodemasks in the top_cpuset track
|
||||
* cpu_online_map and node_states[N_HIGH_MEMORY]. Force the top cpuset to
|
||||
* track what's online after any CPU or memory node hotplug or unplug event.
|
||||
*
|
||||
* Since there are two callers of this routine, one for CPU hotplug
|
||||
* events and one for memory node hotplug events, we could have coded
|
||||
* two separate routines here. We code it as a single common routine
|
||||
* in order to minimize text size.
|
||||
*/
|
||||
|
||||
static void common_cpu_mem_hotplug_unplug(int rebuild_sd)
|
||||
{
|
||||
cgroup_lock();
|
||||
|
||||
top_cpuset.cpus_allowed = cpu_online_map;
|
||||
top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
|
||||
scan_for_empty_cpusets(&top_cpuset);
|
||||
|
||||
/*
|
||||
* Scheduler destroys domains on hotplug events.
|
||||
* Rebuild them based on the current settings.
|
||||
*/
|
||||
if (rebuild_sd)
|
||||
rebuild_sched_domains();
|
||||
|
||||
cgroup_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* The top_cpuset tracks what CPUs and Memory Nodes are online,
|
||||
* period. This is necessary in order to make cpusets transparent
|
||||
|
@ -1939,40 +1979,52 @@ static void common_cpu_mem_hotplug_unplug(int rebuild_sd)
|
|||
*
|
||||
* This routine ensures that top_cpuset.cpus_allowed tracks
|
||||
* cpu_online_map on each CPU hotplug (cpuhp) event.
|
||||
*
|
||||
* Called within get_online_cpus(). Needs to call cgroup_lock()
|
||||
* before calling generate_sched_domains().
|
||||
*/
|
||||
|
||||
static int cpuset_handle_cpuhp(struct notifier_block *unused_nb,
|
||||
static int cpuset_track_online_cpus(struct notifier_block *unused_nb,
|
||||
unsigned long phase, void *unused_cpu)
|
||||
{
|
||||
struct sched_domain_attr *attr;
|
||||
cpumask_t *doms;
|
||||
int ndoms;
|
||||
|
||||
switch (phase) {
|
||||
case CPU_UP_CANCELED:
|
||||
case CPU_UP_CANCELED_FROZEN:
|
||||
case CPU_DOWN_FAILED:
|
||||
case CPU_DOWN_FAILED_FROZEN:
|
||||
case CPU_ONLINE:
|
||||
case CPU_ONLINE_FROZEN:
|
||||
case CPU_DEAD:
|
||||
case CPU_DEAD_FROZEN:
|
||||
common_cpu_mem_hotplug_unplug(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
cgroup_lock();
|
||||
top_cpuset.cpus_allowed = cpu_online_map;
|
||||
scan_for_empty_cpusets(&top_cpuset);
|
||||
ndoms = generate_sched_domains(&doms, &attr);
|
||||
cgroup_unlock();
|
||||
|
||||
/* Have scheduler rebuild the domains */
|
||||
partition_sched_domains(ndoms, doms, attr);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
/*
|
||||
* Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
|
||||
* Call this routine anytime after you change
|
||||
* node_states[N_HIGH_MEMORY].
|
||||
* See also the previous routine cpuset_handle_cpuhp().
|
||||
* Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
|
||||
* See also the previous routine cpuset_track_online_cpus().
|
||||
*/
|
||||
|
||||
void cpuset_track_online_nodes(void)
|
||||
{
|
||||
common_cpu_mem_hotplug_unplug(0);
|
||||
cgroup_lock();
|
||||
top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
|
||||
scan_for_empty_cpusets(&top_cpuset);
|
||||
cgroup_unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1987,7 +2039,7 @@ void __init cpuset_init_smp(void)
|
|||
top_cpuset.cpus_allowed = cpu_online_map;
|
||||
top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
|
||||
|
||||
hotcpu_notifier(cpuset_handle_cpuhp, 0);
|
||||
hotcpu_notifier(cpuset_track_online_cpus, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7746,24 +7746,27 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
|
|||
* and partition_sched_domains() will fallback to the single partition
|
||||
* 'fallback_doms', it also forces the domains to be rebuilt.
|
||||
*
|
||||
* If doms_new==NULL it will be replaced with cpu_online_map.
|
||||
* ndoms_new==0 is a special case for destroying existing domains.
|
||||
* It will not create the default domain.
|
||||
*
|
||||
* Call with hotplug lock held
|
||||
*/
|
||||
void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
|
||||
struct sched_domain_attr *dattr_new)
|
||||
{
|
||||
int i, j;
|
||||
int i, j, n;
|
||||
|
||||
mutex_lock(&sched_domains_mutex);
|
||||
|
||||
/* always unregister in case we don't destroy any domains */
|
||||
unregister_sched_domain_sysctl();
|
||||
|
||||
if (doms_new == NULL)
|
||||
ndoms_new = 0;
|
||||
n = doms_new ? ndoms_new : 0;
|
||||
|
||||
/* Destroy deleted domains */
|
||||
for (i = 0; i < ndoms_cur; i++) {
|
||||
for (j = 0; j < ndoms_new; j++) {
|
||||
for (j = 0; j < n; j++) {
|
||||
if (cpus_equal(doms_cur[i], doms_new[j])
|
||||
&& dattrs_equal(dattr_cur, i, dattr_new, j))
|
||||
goto match1;
|
||||
|
@ -7776,7 +7779,6 @@ match1:
|
|||
|
||||
if (doms_new == NULL) {
|
||||
ndoms_cur = 0;
|
||||
ndoms_new = 1;
|
||||
doms_new = &fallback_doms;
|
||||
cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
|
||||
dattr_new = NULL;
|
||||
|
@ -7813,8 +7815,13 @@ match2:
|
|||
int arch_reinit_sched_domains(void)
|
||||
{
|
||||
get_online_cpus();
|
||||
|
||||
/* Destroy domains first to force the rebuild */
|
||||
partition_sched_domains(0, NULL, NULL);
|
||||
|
||||
rebuild_sched_domains();
|
||||
put_online_cpus();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -7898,7 +7905,7 @@ static int update_sched_domains(struct notifier_block *nfb,
|
|||
case CPU_ONLINE_FROZEN:
|
||||
case CPU_DEAD:
|
||||
case CPU_DEAD_FROZEN:
|
||||
partition_sched_domains(0, NULL, NULL);
|
||||
partition_sched_domains(1, NULL, NULL);
|
||||
return NOTIFY_OK;
|
||||
|
||||
default:
|
||||
|
|
|
@ -177,7 +177,7 @@ void clockevents_register_device(struct clock_event_device *dev)
|
|||
/*
|
||||
* Noop handler when we shut down an event device
|
||||
*/
|
||||
static void clockevents_handle_noop(struct clock_event_device *dev)
|
||||
void clockevents_handle_noop(struct clock_event_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,6 @@ void clockevents_exchange_device(struct clock_event_device *old,
|
|||
* released list and do a notify add later.
|
||||
*/
|
||||
if (old) {
|
||||
old->event_handler = clockevents_handle_noop;
|
||||
clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
|
||||
list_del(&old->list);
|
||||
list_add(&old->list, &clockevents_released);
|
||||
|
|
|
@ -245,7 +245,7 @@ static void sync_cmos_clock(unsigned long dummy)
|
|||
if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
|
||||
fail = update_persistent_clock(now);
|
||||
|
||||
next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;
|
||||
next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
|
||||
if (next.tv_nsec <= 0)
|
||||
next.tv_nsec += NSEC_PER_SEC;
|
||||
|
||||
|
|
|
@ -175,6 +175,8 @@ static void tick_do_periodic_broadcast(void)
|
|||
*/
|
||||
static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
|
||||
{
|
||||
ktime_t next;
|
||||
|
||||
tick_do_periodic_broadcast();
|
||||
|
||||
/*
|
||||
|
@ -185,10 +187,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
|
|||
|
||||
/*
|
||||
* Setup the next period for devices, which do not have
|
||||
* periodic mode:
|
||||
* periodic mode. We read dev->next_event first and add to it
|
||||
* when the event alrady expired. clockevents_program_event()
|
||||
* sets dev->next_event only when the event is really
|
||||
* programmed to the device.
|
||||
*/
|
||||
for (;;) {
|
||||
ktime_t next = ktime_add(dev->next_event, tick_period);
|
||||
for (next = dev->next_event; ;) {
|
||||
next = ktime_add(next, tick_period);
|
||||
|
||||
if (!clockevents_program_event(dev, next, ktime_get()))
|
||||
return;
|
||||
|
@ -205,7 +210,7 @@ static void tick_do_broadcast_on_off(void *why)
|
|||
struct clock_event_device *bc, *dev;
|
||||
struct tick_device *td;
|
||||
unsigned long flags, *reason = why;
|
||||
int cpu;
|
||||
int cpu, bc_stopped;
|
||||
|
||||
spin_lock_irqsave(&tick_broadcast_lock, flags);
|
||||
|
||||
|
@ -223,6 +228,8 @@ static void tick_do_broadcast_on_off(void *why)
|
|||
if (!tick_device_is_functional(dev))
|
||||
goto out;
|
||||
|
||||
bc_stopped = cpus_empty(tick_broadcast_mask);
|
||||
|
||||
switch (*reason) {
|
||||
case CLOCK_EVT_NOTIFY_BROADCAST_ON:
|
||||
case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
|
||||
|
@ -245,9 +252,10 @@ static void tick_do_broadcast_on_off(void *why)
|
|||
break;
|
||||
}
|
||||
|
||||
if (cpus_empty(tick_broadcast_mask))
|
||||
clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
|
||||
else {
|
||||
if (cpus_empty(tick_broadcast_mask)) {
|
||||
if (!bc_stopped)
|
||||
clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
|
||||
} else if (bc_stopped) {
|
||||
if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
|
||||
tick_broadcast_start_periodic(bc);
|
||||
else
|
||||
|
@ -364,16 +372,8 @@ cpumask_t *tick_get_broadcast_oneshot_mask(void)
|
|||
static int tick_broadcast_set_event(ktime_t expires, int force)
|
||||
{
|
||||
struct clock_event_device *bc = tick_broadcast_device.evtdev;
|
||||
ktime_t now = ktime_get();
|
||||
int res;
|
||||
|
||||
for(;;) {
|
||||
res = clockevents_program_event(bc, expires, now);
|
||||
if (!res || !force)
|
||||
return res;
|
||||
now = ktime_get();
|
||||
expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
|
||||
}
|
||||
return tick_dev_program_event(bc, expires, force);
|
||||
}
|
||||
|
||||
int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
|
||||
|
@ -491,14 +491,52 @@ static void tick_broadcast_clear_oneshot(int cpu)
|
|||
cpu_clear(cpu, tick_broadcast_oneshot_mask);
|
||||
}
|
||||
|
||||
static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
|
||||
{
|
||||
struct tick_device *td;
|
||||
int cpu;
|
||||
|
||||
for_each_cpu_mask_nr(cpu, *mask) {
|
||||
td = &per_cpu(tick_cpu_device, cpu);
|
||||
if (td->evtdev)
|
||||
td->evtdev->next_event = expires;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tick_broadcast_setup_oneshot - setup the broadcast device
|
||||
*/
|
||||
void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
|
||||
{
|
||||
bc->event_handler = tick_handle_oneshot_broadcast;
|
||||
clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
|
||||
bc->next_event.tv64 = KTIME_MAX;
|
||||
/* Set it up only once ! */
|
||||
if (bc->event_handler != tick_handle_oneshot_broadcast) {
|
||||
int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
|
||||
int cpu = smp_processor_id();
|
||||
cpumask_t mask;
|
||||
|
||||
bc->event_handler = tick_handle_oneshot_broadcast;
|
||||
clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
|
||||
|
||||
/* Take the do_timer update */
|
||||
tick_do_timer_cpu = cpu;
|
||||
|
||||
/*
|
||||
* We must be careful here. There might be other CPUs
|
||||
* waiting for periodic broadcast. We need to set the
|
||||
* oneshot_mask bits for those and program the
|
||||
* broadcast device to fire.
|
||||
*/
|
||||
mask = tick_broadcast_mask;
|
||||
cpu_clear(cpu, mask);
|
||||
cpus_or(tick_broadcast_oneshot_mask,
|
||||
tick_broadcast_oneshot_mask, mask);
|
||||
|
||||
if (was_periodic && !cpus_empty(mask)) {
|
||||
tick_broadcast_init_next_event(&mask, tick_next_period);
|
||||
tick_broadcast_set_event(tick_next_period, 1);
|
||||
} else
|
||||
bc->next_event.tv64 = KTIME_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -161,6 +161,7 @@ static void tick_setup_device(struct tick_device *td,
|
|||
} else {
|
||||
handler = td->evtdev->event_handler;
|
||||
next_event = td->evtdev->next_event;
|
||||
td->evtdev->event_handler = clockevents_handle_noop;
|
||||
}
|
||||
|
||||
td->evtdev = newdev;
|
||||
|
|
|
@ -17,6 +17,8 @@ extern void tick_handle_periodic(struct clock_event_device *dev);
|
|||
extern void tick_setup_oneshot(struct clock_event_device *newdev,
|
||||
void (*handler)(struct clock_event_device *),
|
||||
ktime_t nextevt);
|
||||
extern int tick_dev_program_event(struct clock_event_device *dev,
|
||||
ktime_t expires, int force);
|
||||
extern int tick_program_event(ktime_t expires, int force);
|
||||
extern void tick_oneshot_notify(void);
|
||||
extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
|
||||
|
|
|
@ -22,22 +22,54 @@
|
|||
|
||||
#include "tick-internal.h"
|
||||
|
||||
/**
|
||||
* tick_program_event internal worker function
|
||||
*/
|
||||
int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
|
||||
int force)
|
||||
{
|
||||
ktime_t now = ktime_get();
|
||||
int i;
|
||||
|
||||
for (i = 0;;) {
|
||||
int ret = clockevents_program_event(dev, expires, now);
|
||||
|
||||
if (!ret || !force)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We tried 2 times to program the device with the given
|
||||
* min_delta_ns. If that's not working then we double it
|
||||
* and emit a warning.
|
||||
*/
|
||||
if (++i > 2) {
|
||||
/* Increase the min. delta and try again */
|
||||
if (!dev->min_delta_ns)
|
||||
dev->min_delta_ns = 5000;
|
||||
else
|
||||
dev->min_delta_ns += dev->min_delta_ns >> 1;
|
||||
|
||||
printk(KERN_WARNING
|
||||
"CE: %s increasing min_delta_ns to %lu nsec\n",
|
||||
dev->name ? dev->name : "?",
|
||||
dev->min_delta_ns << 1);
|
||||
|
||||
i = 0;
|
||||
}
|
||||
|
||||
now = ktime_get();
|
||||
expires = ktime_add_ns(now, dev->min_delta_ns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tick_program_event
|
||||
*/
|
||||
int tick_program_event(ktime_t expires, int force)
|
||||
{
|
||||
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
|
||||
ktime_t now = ktime_get();
|
||||
|
||||
while (1) {
|
||||
int ret = clockevents_program_event(dev, expires, now);
|
||||
|
||||
if (!ret || !force)
|
||||
return ret;
|
||||
now = ktime_get();
|
||||
expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
|
||||
}
|
||||
return tick_dev_program_event(dev, expires, force);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +93,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev,
|
|||
{
|
||||
newdev->event_handler = handler;
|
||||
clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
|
||||
clockevents_program_event(newdev, next_event, ktime_get());
|
||||
tick_dev_program_event(newdev, next_event, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <asm/page.h> /* for PAGE_SIZE */
|
||||
#include <asm/div64.h>
|
||||
#include <asm/sections.h> /* for dereference_function_descriptor() */
|
||||
|
||||
/* Works only for digits and letters, but small and fast */
|
||||
#define TOLOWER(x) ((x) | 0x20)
|
||||
|
@ -513,16 +514,6 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio
|
|||
return buf;
|
||||
}
|
||||
|
||||
static inline void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
|
||||
void *p;
|
||||
if (!probe_kernel_address(ptr, p))
|
||||
ptr = p;
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags)
|
||||
{
|
||||
unsigned long value = (unsigned long) ptr;
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.12"
|
||||
#define VERSION "2.13"
|
||||
|
||||
/* Bluetooth sockets */
|
||||
#define BT_MAX_PROTO 8
|
||||
|
|
|
@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route);
|
|||
|
||||
/* Create SCO or ACL connection.
|
||||
* Device _must_ be locked */
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
|
||||
{
|
||||
struct hci_conn *acl;
|
||||
struct hci_conn *sco;
|
||||
|
@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
|||
|
||||
hci_conn_hold(acl);
|
||||
|
||||
if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
|
||||
if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
|
||||
acl->auth_type = auth_type;
|
||||
hci_acl_connect(acl);
|
||||
}
|
||||
|
||||
if (type == ACL_LINK)
|
||||
return acl;
|
||||
|
@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
|||
}
|
||||
EXPORT_SYMBOL(hci_connect);
|
||||
|
||||
/* Check link security requirement */
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
|
||||
!(conn->link_mode & HCI_LM_ENCRYPT))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(hci_conn_check_link_mode);
|
||||
|
||||
/* Authenticate remote device */
|
||||
int hci_conn_auth(struct hci_conn *conn)
|
||||
{
|
||||
|
@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn)
|
|||
|
||||
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
|
||||
if (!(conn->auth_type & 0x01)) {
|
||||
conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
|
||||
conn->auth_type |= 0x01;
|
||||
conn->link_mode &= ~HCI_LM_AUTH;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
|
|||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (!ev->status && hdev->ssp_mode > 0 &&
|
||||
conn->ssp_mode > 0) {
|
||||
if (conn->out) {
|
||||
struct hci_cp_auth_requested cp;
|
||||
cp.handle = ev->handle;
|
||||
hci_send_cmd(hdev,
|
||||
HCI_OP_AUTH_REQUESTED,
|
||||
conn->ssp_mode > 0 && conn->out) {
|
||||
struct hci_cp_auth_requested cp;
|
||||
cp.handle = ev->handle;
|
||||
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
} else {
|
||||
conn->state = BT_CONNECTED;
|
||||
hci_proto_connect_cfm(conn, ev->status);
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.10"
|
||||
#define VERSION "2.11"
|
||||
|
||||
static u32 l2cap_feat_mask = 0x0000;
|
||||
|
||||
|
@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk)
|
|||
struct l2cap_conn *conn;
|
||||
struct hci_conn *hcon;
|
||||
struct hci_dev *hdev;
|
||||
__u8 auth_type;
|
||||
int err = 0;
|
||||
|
||||
BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
|
||||
|
@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk)
|
|||
|
||||
err = -ENOMEM;
|
||||
|
||||
hcon = hci_connect(hdev, ACL_LINK, dst);
|
||||
if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH ||
|
||||
l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT ||
|
||||
l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
|
||||
if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
|
||||
auth_type = HCI_AT_NO_BONDING_MITM;
|
||||
else
|
||||
auth_type = HCI_AT_GENERAL_BONDING_MITM;
|
||||
} else {
|
||||
if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
|
||||
auth_type = HCI_AT_NO_BONDING;
|
||||
else
|
||||
auth_type = HCI_AT_GENERAL_BONDING;
|
||||
}
|
||||
|
||||
hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
|
||||
if (!hcon)
|
||||
goto done;
|
||||
|
||||
|
@ -1553,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
|
||||
struct l2cap_conn_rsp rsp;
|
||||
struct sock *sk, *parent;
|
||||
int result, status = 0;
|
||||
int result, status = L2CAP_CS_NO_INFO;
|
||||
|
||||
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
|
||||
__le16 psm = req->psm;
|
||||
__le16 psm = req->psm;
|
||||
|
||||
BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
|
||||
|
||||
|
@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||
goto sendresp;
|
||||
}
|
||||
|
||||
/* Check if the ACL is secure enough (if not SDP) */
|
||||
if (psm != cpu_to_le16(0x0001) &&
|
||||
!hci_conn_check_link_mode(conn->hcon)) {
|
||||
result = L2CAP_CR_SEC_BLOCK;
|
||||
goto response;
|
||||
}
|
||||
|
||||
result = L2CAP_CR_NO_MEM;
|
||||
|
||||
/* Check for backlog size */
|
||||
|
@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
|
|||
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
||||
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
|
||||
rsp.result = cpu_to_le16(result);
|
||||
rsp.status = cpu_to_le16(0);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
|
||||
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
}
|
||||
|
@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|||
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
||||
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
|
||||
rsp.result = cpu_to_le16(result);
|
||||
rsp.status = cpu_to_le16(0);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
|
||||
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk)
|
|||
else
|
||||
type = SCO_LINK;
|
||||
|
||||
hcon = hci_connect(hdev, type, dst);
|
||||
hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING);
|
||||
if (!hcon)
|
||||
goto done;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue