Merge branches 'core/futexes', 'core/locking', 'core/rcu' and 'linus' into core/urgent

This commit is contained in:
Ingo Molnar 2009-01-06 09:32:11 +01:00
commit fdbc0450df
453 changed files with 32825 additions and 12272 deletions

View File

@ -31,7 +31,6 @@ Features which OCFS2 does not support yet:
- quotas - quotas
- Directory change notification (F_NOTIFY) - Directory change notification (F_NOTIFY)
- Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
- POSIX ACLs
Mount options Mount options
============= =============
@ -79,3 +78,5 @@ inode64 Indicates that Ocfs2 is allowed to create inodes at
bits of significance. bits of significance.
user_xattr (*) Enables Extended User Attributes. user_xattr (*) Enables Extended User Attributes.
nouser_xattr Disables Extended User Attributes. nouser_xattr Disables Extended User Attributes.
acl Enables POSIX Access Control Lists support.
noacl (*) Disables POSIX Access Control Lists support.

View File

@ -4015,10 +4015,12 @@ L: alsa-devel@alsa-project.org (subscribers-only)
W: http://alsa-project.org/main/index.php/ASoC W: http://alsa-project.org/main/index.php/ASoC
S: Supported S: Supported
SPARC (sparc32) SPARC + UltraSPARC (sparc/sparc64)
P: William L. Irwin P: David S. Miller
M: wli@holomorphy.com M: davem@davemloft.net
L: sparclinux@vger.kernel.org L: sparclinux@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
S: Maintained S: Maintained
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
@ -4302,13 +4304,6 @@ M: dushistov@mail.ru
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
UltraSPARC (sparc64)
P: David S. Miller
M: davem@davemloft.net
L: sparclinux@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
S: Maintained
ULTRA-WIDEBAND (UWB) SUBSYSTEM: ULTRA-WIDEBAND (UWB) SUBSYSTEM:
P: David Vrabel P: David Vrabel
M: david.vrabel@csr.com M: david.vrabel@csr.com

View File

@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = {
}; };
static struct clk i2chs2_fck = { static struct clk i2chs2_fck = {
.name = "i2chs_fck", .name = "i2c_fck",
.id = 2, .id = 2,
.parent = &func_96m_ck, .parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X, .flags = CLOCK_IN_OMAP243X,
@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = {
}; };
static struct clk i2chs1_fck = { static struct clk i2chs1_fck = {
.name = "i2chs_fck", .name = "i2c_fck",
.id = 1, .id = 1,
.parent = &func_96m_ck, .parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X, .flags = CLOCK_IN_OMAP243X,

View File

@ -23,8 +23,10 @@ struct mod_arch_specific
{ {
unsigned long got_offset, got_count, got_max; unsigned long got_offset, got_count, got_max;
unsigned long fdesc_offset, fdesc_count, fdesc_max; unsigned long fdesc_offset, fdesc_count, fdesc_max;
unsigned long stub_offset, stub_count, stub_max; struct {
unsigned long init_stub_offset, init_stub_count, init_stub_max; unsigned long stub_offset;
unsigned int stub_entries;
} *section;
int unwind_section; int unwind_section;
struct unwind_table *unwind; struct unwind_table *unwind;
}; };

View File

@ -6,6 +6,7 @@
* *
* Linux/PA-RISC Project (http://www.parisc-linux.org/) * Linux/PA-RISC Project (http://www.parisc-linux.org/)
* Copyright (C) 2003 Randolph Chung <tausq at debian . org> * Copyright (C) 2003 Randolph Chung <tausq at debian . org>
* Copyright (C) 2008 Helge Deller <deller@gmx.de>
* *
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -24,6 +25,19 @@
* *
* *
* Notes: * Notes:
* - PLT stub handling
* On 32bit (and sometimes 64bit) and with big kernel modules like xfs or
* ipv6 the relocation types R_PARISC_PCREL17F and R_PARISC_PCREL22F may
* fail to reach their PLT stub if we only create one big stub array for
* all sections at the beginning of the core or init section.
* Instead we now insert individual PLT stub entries directly in front of
* of the code sections where the stubs are actually called.
* This reduces the distance between the PCREL location and the stub entry
* so that the relocations can be fulfilled.
* While calculating the final layout of the kernel module in memory, the
* kernel module loader calls arch_mod_section_prepend() to request the
* to be reserved amount of memory in front of each individual section.
*
* - SEGREL32 handling * - SEGREL32 handling
* We are not doing SEGREL32 handling correctly. According to the ABI, we * We are not doing SEGREL32 handling correctly. According to the ABI, we
* should do a value offset, like this: * should do a value offset, like this:
@ -58,9 +72,13 @@
#define DEBUGP(fmt...) #define DEBUGP(fmt...)
#endif #endif
#define RELOC_REACHABLE(val, bits) \
(( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \
0 : 1)
#define CHECK_RELOC(val, bits) \ #define CHECK_RELOC(val, bits) \
if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ if (!RELOC_REACHABLE(val, bits)) { \
( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
me->name, strtab + sym->st_name, (unsigned long)val, bits); \ me->name, strtab + sym->st_name, (unsigned long)val, bits); \
return -ENOEXEC; \ return -ENOEXEC; \
@ -92,13 +110,6 @@ static inline int in_local(struct module *me, void *loc)
return in_init(me, loc) || in_core(me, loc); return in_init(me, loc) || in_core(me, loc);
} }
static inline int in_local_section(struct module *me, void *loc, void *dot)
{
return (in_init(me, loc) && in_init(me, dot)) ||
(in_core(me, loc) && in_core(me, dot));
}
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
struct got_entry { struct got_entry {
Elf32_Addr addr; Elf32_Addr addr;
@ -258,23 +269,42 @@ static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
/* Free memory returned from module_alloc */ /* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region) void module_free(struct module *mod, void *module_region)
{ {
kfree(mod->arch.section);
mod->arch.section = NULL;
vfree(module_region); vfree(module_region);
/* FIXME: If module_region == mod->init_region, trim exception /* FIXME: If module_region == mod->init_region, trim exception
table entries. */ table entries. */
} }
/* Additional bytes needed in front of individual sections */
unsigned int arch_mod_section_prepend(struct module *mod,
unsigned int section)
{
/* size needed for all stubs of this section (including
* one additional for correct alignment of the stubs) */
return (mod->arch.section[section].stub_entries + 1)
* sizeof(struct stub_entry);
}
#define CONST #define CONST
int module_frob_arch_sections(CONST Elf_Ehdr *hdr, int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
CONST Elf_Shdr *sechdrs, CONST Elf_Shdr *sechdrs,
CONST char *secstrings, CONST char *secstrings,
struct module *me) struct module *me)
{ {
unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0; unsigned long gots = 0, fdescs = 0, len;
unsigned int i; unsigned int i;
len = hdr->e_shnum * sizeof(me->arch.section[0]);
me->arch.section = kzalloc(len, GFP_KERNEL);
if (!me->arch.section)
return -ENOMEM;
for (i = 1; i < hdr->e_shnum; i++) { for (i = 1; i < hdr->e_shnum; i++) {
const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; const Elf_Rela *rels = (void *)sechdrs[i].sh_addr;
unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
unsigned int count, s;
if (strncmp(secstrings + sechdrs[i].sh_name, if (strncmp(secstrings + sechdrs[i].sh_name,
".PARISC.unwind", 14) == 0) ".PARISC.unwind", 14) == 0)
@ -290,11 +320,23 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
*/ */
gots += count_gots(rels, nrels); gots += count_gots(rels, nrels);
fdescs += count_fdescs(rels, nrels); fdescs += count_fdescs(rels, nrels);
if(strncmp(secstrings + sechdrs[i].sh_name,
".rela.init", 10) == 0) /* XXX: By sorting the relocs and finding duplicate entries
init_stubs += count_stubs(rels, nrels); * we could reduce the number of necessary stubs and save
else * some memory. */
stubs += count_stubs(rels, nrels); count = count_stubs(rels, nrels);
if (!count)
continue;
/* so we need relocation stubs. reserve necessary memory. */
/* sh_info gives the section for which we need to add stubs. */
s = sechdrs[i].sh_info;
/* each code section should only have one relocation section */
WARN_ON(me->arch.section[s].stub_entries);
/* store number of stubs we need for this section */
me->arch.section[s].stub_entries += count;
} }
/* align things a bit */ /* align things a bit */
@ -306,18 +348,8 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
me->arch.fdesc_offset = me->core_size; me->arch.fdesc_offset = me->core_size;
me->core_size += fdescs * sizeof(Elf_Fdesc); me->core_size += fdescs * sizeof(Elf_Fdesc);
me->core_size = ALIGN(me->core_size, 16);
me->arch.stub_offset = me->core_size;
me->core_size += stubs * sizeof(struct stub_entry);
me->init_size = ALIGN(me->init_size, 16);
me->arch.init_stub_offset = me->init_size;
me->init_size += init_stubs * sizeof(struct stub_entry);
me->arch.got_max = gots; me->arch.got_max = gots;
me->arch.fdesc_max = fdescs; me->arch.fdesc_max = fdescs;
me->arch.stub_max = stubs;
me->arch.init_stub_max = init_stubs;
return 0; return 0;
} }
@ -380,23 +412,27 @@ enum elf_stub_type {
}; };
static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
enum elf_stub_type stub_type, int init_section) enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec)
{ {
unsigned long i;
struct stub_entry *stub; struct stub_entry *stub;
if(init_section) { /* initialize stub_offset to point in front of the section */
i = me->arch.init_stub_count++; if (!me->arch.section[targetsec].stub_offset) {
BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); loc0 -= (me->arch.section[targetsec].stub_entries + 1) *
stub = me->module_init + me->arch.init_stub_offset + sizeof(struct stub_entry);
i * sizeof(struct stub_entry); /* get correct alignment for the stubs */
} else { loc0 = ALIGN(loc0, sizeof(struct stub_entry));
i = me->arch.stub_count++; me->arch.section[targetsec].stub_offset = loc0;
BUG_ON(me->arch.stub_count > me->arch.stub_max);
stub = me->module_core + me->arch.stub_offset +
i * sizeof(struct stub_entry);
} }
/* get address of stub entry */
stub = (void *) me->arch.section[targetsec].stub_offset;
me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry);
/* do not write outside available stub area */
BUG_ON(0 == me->arch.section[targetsec].stub_entries--);
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
/* for 32-bit the stub looks like this: /* for 32-bit the stub looks like this:
* ldil L'XXX,%r1 * ldil L'XXX,%r1
@ -489,15 +525,19 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf32_Addr val; Elf32_Addr val;
Elf32_Sword addend; Elf32_Sword addend;
Elf32_Addr dot; Elf32_Addr dot;
Elf_Addr loc0;
unsigned int targetsec = sechdrs[relsec].sh_info;
//unsigned long dp = (unsigned long)$global$; //unsigned long dp = (unsigned long)$global$;
register unsigned long dp asm ("r27"); register unsigned long dp asm ("r27");
DEBUGP("Applying relocate section %u to %u\n", relsec, DEBUGP("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info); targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */ /* This is where to make the change */
loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset; + rel[i].r_offset;
/* This is the start of the target section */
loc0 = sechdrs[targetsec].sh_addr;
/* This is the symbol it is referring to */ /* This is the symbol it is referring to */
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rel[i].r_info); + ELF32_R_SYM(rel[i].r_info);
@ -569,19 +609,32 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break; break;
case R_PARISC_PCREL17F: case R_PARISC_PCREL17F:
/* 17-bit PC relative address */ /* 17-bit PC relative address */
val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); /* calculate direct call offset */
val += addend;
val = (val - dot - 8)/4; val = (val - dot - 8)/4;
CHECK_RELOC(val, 17) if (!RELOC_REACHABLE(val, 17)) {
/* direct distance too far, create
* stub entry instead */
val = get_stub(me, sym->st_value, addend,
ELF_STUB_DIRECT, loc0, targetsec);
val = (val - dot - 8)/4;
CHECK_RELOC(val, 17);
}
*loc = (*loc & ~0x1f1ffd) | reassemble_17(val); *loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
break; break;
case R_PARISC_PCREL22F: case R_PARISC_PCREL22F:
/* 22-bit PC relative address; only defined for pa20 */ /* 22-bit PC relative address; only defined for pa20 */
val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); /* calculate direct call offset */
DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", val += addend;
strtab + sym->st_name, (unsigned long)loc, addend,
val)
val = (val - dot - 8)/4; val = (val - dot - 8)/4;
CHECK_RELOC(val, 22); if (!RELOC_REACHABLE(val, 22)) {
/* direct distance too far, create
* stub entry instead */
val = get_stub(me, sym->st_value, addend,
ELF_STUB_DIRECT, loc0, targetsec);
val = (val - dot - 8)/4;
CHECK_RELOC(val, 22);
}
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break; break;
@ -610,13 +663,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf64_Addr val; Elf64_Addr val;
Elf64_Sxword addend; Elf64_Sxword addend;
Elf64_Addr dot; Elf64_Addr dot;
Elf_Addr loc0;
unsigned int targetsec = sechdrs[relsec].sh_info;
DEBUGP("Applying relocate section %u to %u\n", relsec, DEBUGP("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info); targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */ /* This is where to make the change */
loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset; + rel[i].r_offset;
/* This is the start of the target section */
loc0 = sechdrs[targetsec].sh_addr;
/* This is the symbol it is referring to */ /* This is the symbol it is referring to */
sym = (Elf64_Sym *)sechdrs[symindex].sh_addr sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
+ ELF64_R_SYM(rel[i].r_info); + ELF64_R_SYM(rel[i].r_info);
@ -672,42 +729,40 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
strtab + sym->st_name, strtab + sym->st_name,
loc, val); loc, val);
val += addend;
/* can we reach it locally? */ /* can we reach it locally? */
if(!in_local_section(me, (void *)val, (void *)dot)) { if (in_local(me, (void *)val)) {
/* this is the case where the symbol is local
if (in_local(me, (void *)val)) * to the module, but in a different section,
/* this is the case where the * so stub the jump in case it's more than 22
* symbol is local to the * bits away */
* module, but in a different val = (val - dot - 8)/4;
* section, so stub the jump if (!RELOC_REACHABLE(val, 22)) {
* in case it's more than 22 /* direct distance too far, create
* bits away */ * stub entry instead */
val = get_stub(me, val, addend, ELF_STUB_DIRECT, val = get_stub(me, sym->st_value,
in_init(me, loc)); addend, ELF_STUB_DIRECT,
else if (strncmp(strtab + sym->st_name, "$$", 2) loc0, targetsec);
} else {
/* Ok, we can reach it directly. */
val = sym->st_value;
val += addend;
}
} else {
val = sym->st_value;
if (strncmp(strtab + sym->st_name, "$$", 2)
== 0) == 0)
val = get_stub(me, val, addend, ELF_STUB_MILLI, val = get_stub(me, val, addend, ELF_STUB_MILLI,
in_init(me, loc)); loc0, targetsec);
else else
val = get_stub(me, val, addend, ELF_STUB_GOT, val = get_stub(me, val, addend, ELF_STUB_GOT,
in_init(me, loc)); loc0, targetsec);
} }
DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
strtab + sym->st_name, loc, sym->st_value, strtab + sym->st_name, loc, sym->st_value,
addend, val); addend, val);
/* FIXME: local symbols work as long as the
* core and init pieces aren't separated too
* far. If this is ever broken, you will trip
* the check below. The way to fix it would
* be to generate local stubs to go between init
* and core */
if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 ||
(Elf64_Sxword)(val - dot - 8) < -0x800000) {
printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n",
me->name, strtab + sym->st_name);
return -ENOEXEC;
}
val = (val - dot - 8)/4; val = (val - dot - 8)/4;
CHECK_RELOC(val, 22);
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break; break;
case R_PARISC_DIR64: case R_PARISC_DIR64:
@ -794,12 +849,8 @@ int module_finalize(const Elf_Ehdr *hdr,
addr = (u32 *)entry->addr; addr = (u32 *)entry->addr;
printk("INSNS: %x %x %x %x\n", printk("INSNS: %x %x %x %x\n",
addr[0], addr[1], addr[2], addr[3]); addr[0], addr[1], addr[2], addr[3]);
printk("stubs used %ld, stubs max %ld\n" printk("got entries used %ld, gots max %ld\n"
"init_stubs used %ld, init stubs max %ld\n"
"got entries used %ld, gots max %ld\n"
"fdescs used %ld, fdescs max %ld\n", "fdescs used %ld, fdescs max %ld\n",
me->arch.stub_count, me->arch.stub_max,
me->arch.init_stub_count, me->arch.init_stub_max,
me->arch.got_count, me->arch.got_max, me->arch.got_count, me->arch.got_max,
me->arch.fdesc_count, me->arch.fdesc_max); me->arch.fdesc_count, me->arch.fdesc_max);
#endif #endif
@ -829,7 +880,10 @@ int module_finalize(const Elf_Ehdr *hdr,
me->name, me->arch.got_count, MAX_GOTS); me->name, me->arch.got_count, MAX_GOTS);
return -EINVAL; return -EINVAL;
} }
kfree(me->arch.section);
me->arch.section = NULL;
/* no symbol table */ /* no symbol table */
if(symhdr == NULL) if(symhdr == NULL)
return 0; return 0;

View File

@ -97,7 +97,6 @@ spufs_new_inode(struct super_block *sb, int mode)
inode->i_mode = mode; inode->i_mode = mode;
inode->i_uid = current_fsuid(); inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid(); inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
out: out:
return inode; return inode;

View File

@ -106,7 +106,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
ret->i_mode = mode; ret->i_mode = mode;
ret->i_uid = hypfs_info->uid; ret->i_uid = hypfs_info->uid;
ret->i_gid = hypfs_info->gid; ret->i_gid = hypfs_info->gid;
ret->i_blocks = 0;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
if (mode & S_IFDIR) if (mode & S_IFDIR)
ret->i_nlink = 2; ret->i_nlink = 2;

View File

@ -4,6 +4,17 @@
mainmenu "Linux/SPARC Kernel Configuration" mainmenu "Linux/SPARC Kernel Configuration"
config 64BIT
bool "64-bit kernel" if ARCH = "sparc"
default ARCH = "sparc64"
help
SPARC is a family of RISC microprocessors designed and marketed by
Sun Microsystems, incorporated. They are very widely found in Sun
workstations and clones.
Say yes to build a 64-bit kernel - formerly known as sparc64
Say no to build a 32-bit kernel - formerly known as sparc
config SPARC config SPARC
bool bool
default y default y
@ -15,22 +26,11 @@ config SPARC
select RTC_CLASS select RTC_CLASS
select RTC_DRV_M48T59 select RTC_DRV_M48T59
# Identify this as a Sparc32 build
config SPARC32 config SPARC32
bool def_bool !64BIT
default y if ARCH = "sparc"
help
SPARC is a family of RISC microprocessors designed and marketed by
Sun Microsystems, incorporated. They are very widely found in Sun
workstations and clones. This port covers the original 32-bit SPARC;
it is old and stable and usually considered one of the "big three"
along with the Intel and Alpha ports. The UltraLinux project
maintains both the SPARC32 and SPARC64 ports; its web page is
available at <http://www.ultralinux.org/>.
config SPARC64 config SPARC64
bool def_bool 64BIT
default y if ARCH = "sparc64"
select ARCH_SUPPORTS_MSI select ARCH_SUPPORTS_MSI
select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACER
select HAVE_KRETPROBES select HAVE_KRETPROBES
@ -53,9 +53,6 @@ config BITS
default 32 if SPARC32 default 32 if SPARC32
default 64 if SPARC64 default 64 if SPARC64
config 64BIT
def_bool y if SPARC64
config GENERIC_TIME config GENERIC_TIME
bool bool
default y if SPARC64 default y if SPARC64
@ -188,14 +185,6 @@ config ARCH_MAY_HAVE_PC_FDC
bool bool
default y default y
config ARCH_HAS_ILOG2_U32
bool
default n
config ARCH_HAS_ILOG2_U64
bool
default n
config EMULATED_CMPXCHG config EMULATED_CMPXCHG
bool bool
default y if SPARC32 default y if SPARC32
@ -442,26 +431,6 @@ config SERIAL_CONSOLE
endmenu endmenu
menu "Bus options (PCI etc.)" menu "Bus options (PCI etc.)"
config ISA
bool
help
ISA is found on Espresso only and is not supported currently.
config ISAPNP
bool
help
ISAPNP is not supported
config EISA
bool
help
EISA is not supported.
config MCA
bool
help
MCA is not supported.
config SBUS config SBUS
bool bool
default y default y

View File

@ -1,27 +1,27 @@
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.28-rc4 # Linux kernel version: 2.6.28
# Mon Nov 10 12:35:09 2008 # Fri Jan 2 18:14:26 2009
# #
CONFIG_SPARC=y CONFIG_SPARC=y
CONFIG_SPARC64=y CONFIG_SPARC64=y
CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc64_defconfig"
CONFIG_BITS=64
CONFIG_64BIT=y
CONFIG_GENERIC_TIME=y CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_IOMMU_HELPER=y CONFIG_IOMMU_HELPER=y
CONFIG_QUICKLIST=y CONFIG_QUICKLIST=y
CONFIG_STACKTRACE_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_AUDIT_ARCH=y CONFIG_AUDIT_ARCH=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_MMU=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y CONFIG_OF=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
# #
@ -86,6 +86,7 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y CONFIG_SLUB=y
# CONFIG_SLOB is not set # CONFIG_SLOB is not set
CONFIG_PROFILING=y CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set # CONFIG_MARKERS is not set
CONFIG_OPROFILE=m CONFIG_OPROFILE=m
CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_OPROFILE=y
@ -127,34 +128,40 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set # CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y CONFIG_CLASSIC_RCU=y
# CONFIG_TREE_RCU is not set
# CONFIG_PREEMPT_RCU is not set
# CONFIG_TREE_RCU_TRACE is not set
# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set # CONFIG_FREEZER is not set
# #
# Processor type and features # Processor type and features
# #
CONFIG_SPARC64_PAGE_SIZE_8KB=y CONFIG_SMP=y
# CONFIG_SPARC64_PAGE_SIZE_64KB is not set CONFIG_NR_CPUS=64
CONFIG_SECCOMP=y
CONFIG_HZ_100=y CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set # CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set # CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set # CONFIG_HZ_1000 is not set
CONFIG_HZ=100 CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y CONFIG_SCHED_HRTICK=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_SPARC64_SMP=y
CONFIG_SPARC64_PAGE_SIZE_8KB=y
# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
CONFIG_SECCOMP=y
CONFIG_HOTPLUG_CPU=y CONFIG_HOTPLUG_CPU=y
CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS=y
CONFIG_TICK_ONESHOT=y CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_SMP=y
CONFIG_NR_CPUS=64
# CONFIG_CPU_FREQ is not set # CONFIG_CPU_FREQ is not set
CONFIG_US3_MC=y CONFIG_US3_MC=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HUGETLB_PAGE_SIZE_4MB=y CONFIG_HUGETLB_PAGE_SIZE_4MB=y
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set # CONFIG_HUGETLB_PAGE_SIZE_512K is not set
# CONFIG_HUGETLB_PAGE_SIZE_64K is not set # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
@ -183,10 +190,18 @@ CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=0 CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=1 CONFIG_NR_QUICK=1
CONFIG_UNEVICTABLE_LRU=y CONFIG_UNEVICTABLE_LRU=y
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_CMDLINE_BOOL is not set
#
# Bus options (PCI etc.)
#
CONFIG_SBUS=y CONFIG_SBUS=y
CONFIG_SBUSCHAR=y CONFIG_SBUSCHAR=y
CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
CONFIG_SUN_LDOMS=y CONFIG_SUN_LDOMS=y
CONFIG_PCI=y CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y CONFIG_PCI_DOMAINS=y
@ -195,7 +210,9 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY is not set # CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set # CONFIG_PCI_DEBUG is not set
# CONFIG_PCCARD is not set
CONFIG_SUN_OPENPROMFS=m CONFIG_SUN_OPENPROMFS=m
CONFIG_SPARC64_PCI=y
# #
# Executable file formats # Executable file formats
@ -207,17 +224,13 @@ CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m CONFIG_BINFMT_MISC=m
CONFIG_COMPAT=y CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y CONFIG_SYSVIPC_COMPAT=y
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_CMDLINE_BOOL is not set
CONFIG_NET=y CONFIG_NET=y
# #
# Networking options # Networking options
# #
# CONFIG_NET_NS is not set
CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y CONFIG_UNIX=y
@ -314,6 +327,7 @@ CONFIG_VLAN_8021Q=m
# CONFIG_ECONET is not set # CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set # CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set # CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
# #
# Network testing # Network testing
@ -330,8 +344,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set # CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set # CONFIG_WIRELESS_EXT is not set
# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set # CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set # CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set # CONFIG_NET_9P is not set
@ -378,8 +392,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set # CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set # CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set # CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set # CONFIG_HP_ILO is not set
# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y CONFIG_HAVE_IDE=y
CONFIG_IDE=y CONFIG_IDE=y
@ -387,6 +403,7 @@ CONFIG_IDE=y
# Please see Documentation/ide/ide.txt for help/info on IDE drives # Please see Documentation/ide/ide.txt for help/info on IDE drives
# #
CONFIG_IDE_TIMINGS=y CONFIG_IDE_TIMINGS=y
CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set # CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y CONFIG_IDE_GD_ATA=y
@ -394,7 +411,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set # CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y CONFIG_IDE_PROC_FS=y
@ -477,6 +493,7 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set # CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set # CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_ACARD is not set
@ -490,6 +507,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set # CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_IPS is not set
@ -564,6 +583,9 @@ CONFIG_PHYLIB=m
# CONFIG_BROADCOM_PHY is not set # CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set # CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set # CONFIG_REALTEK_PHY is not set
# CONFIG_NATIONAL_PHY is not set
# CONFIG_STE10XP is not set
# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_MDIO_BITBANG is not set # CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y CONFIG_NET_ETHERNET=y
CONFIG_MII=m CONFIG_MII=m
@ -590,7 +612,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set # CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set # CONFIG_FORCEDETH is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set # CONFIG_E100 is not set
# CONFIG_FEALNX is not set # CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set # CONFIG_NATSEMI is not set
@ -600,6 +621,7 @@ CONFIG_NET_PCI=y
# CONFIG_R6040 is not set # CONFIG_R6040 is not set
# CONFIG_SIS900 is not set # CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set # CONFIG_EPIC100 is not set
# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set # CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set # CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set # CONFIG_VIA_RHINE is not set
@ -629,6 +651,7 @@ CONFIG_BNX2=m
# CONFIG_JME is not set # CONFIG_JME is not set
CONFIG_NETDEV_10000=y CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T1 is not set
CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set # CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set # CONFIG_ENIC is not set
# CONFIG_IXGBE is not set # CONFIG_IXGBE is not set
@ -778,6 +801,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set # CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set # CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m CONFIG_HW_RANDOM=m
@ -870,6 +894,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set # CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_ATXP1 is not set
@ -919,11 +944,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set # CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set # CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set # CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
# #
# Sonics Silicon Backplane # Sonics Silicon Backplane
# #
CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set # CONFIG_SSB is not set
# #
@ -1071,6 +1096,7 @@ CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set # CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y CONFIG_SND_VERBOSE_PROCFS=y
@ -1242,11 +1268,11 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_TMC is not set # CONFIG_USB_TMC is not set
# #
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
# #
# #
# may also be needed; see USB_STORAGE Help for more information # see USB_STORAGE Help for more information
# #
CONFIG_USB_STORAGE=m CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DEBUG is not set
@ -1337,6 +1363,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set
# #
# SPI RTC drivers # SPI RTC drivers
@ -1365,7 +1392,6 @@ CONFIG_RTC_DRV_STARFIRE=y
# CONFIG_DMADEVICES is not set # CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set # CONFIG_UIO is not set
# CONFIG_STAGING is not set # CONFIG_STAGING is not set
CONFIG_STAGING_EXCLUDE_BUILD=y
# #
# Misc Linux/SPARC drivers # Misc Linux/SPARC drivers
@ -1544,6 +1570,7 @@ CONFIG_SCHEDSTATS=y
# CONFIG_LOCK_STAT is not set # CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_INFO is not set
@ -1552,6 +1579,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
@ -1560,8 +1588,12 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set # CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set # CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
# #
# Tracers # Tracers
@ -1571,7 +1603,9 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set # CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set # CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set # CONFIG_STACK_TRACER is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set # CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y CONFIG_HAVE_ARCH_KGDB=y
@ -1600,11 +1634,16 @@ CONFIG_CRYPTO=y
# #
# CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_CRYPTD is not set

View File

@ -1,21 +1,6 @@
# User exported sparc header files # User exported sparc header files
include include/asm-generic/Kbuild.asm include include/asm-generic/Kbuild.asm
header-y += ipcbuf_32.h
header-y += ipcbuf_64.h
header-y += posix_types_32.h
header-y += posix_types_64.h
header-y += ptrace_32.h
header-y += ptrace_64.h
header-y += sigcontext_32.h
header-y += sigcontext_64.h
header-y += siginfo_32.h
header-y += siginfo_64.h
header-y += signal_32.h
header-y += signal_64.h
header-y += stat_32.h
header-y += stat_64.h
header-y += apc.h header-y += apc.h
header-y += asi.h header-y += asi.h
header-y += display7seg.h header-y += display7seg.h
@ -23,16 +8,11 @@ header-y += envctrl.h
header-y += fbio.h header-y += fbio.h
header-y += jsflash.h header-y += jsflash.h
header-y += openprom.h header-y += openprom.h
header-y += openprom_32.h
header-y += openprom_64.h
header-y += openpromio.h header-y += openpromio.h
header-y += perfctr.h header-y += perfctr.h
header-y += psrcompat.h header-y += psrcompat.h
header-y += psr.h header-y += psr.h
header-y += pstate.h header-y += pstate.h
header-y += reg.h
header-y += reg_32.h
header-y += reg_64.h
header-y += traps.h header-y += traps.h
header-y += uctx.h header-y += uctx.h
header-y += utrap.h header-y += utrap.h

View File

@ -1,16 +1,12 @@
#ifndef _SPARC_BYTEORDER_H #ifndef _SPARC_BYTEORDER_H
#define _SPARC_BYTEORDER_H #define _SPARC_BYTEORDER_H
#include <asm/types.h> #include <linux/types.h>
#include <asm/asi.h> #include <asm/asi.h>
#define __BIG_ENDIAN #define __BIG_ENDIAN
#ifdef CONFIG_SPARC32 #if defined(__sparc__) && defined(__arch64__)
#define __SWAB_64_THRU_32__
#endif
#ifdef CONFIG_SPARC64
static inline __u16 __arch_swab16p(const __u16 *addr) static inline __u16 __arch_swab16p(const __u16 *addr)
{ {
__u16 ret; __u16 ret;
@ -44,7 +40,9 @@ static inline __u64 __arch_swab64p(const __u64 *addr)
} }
#define __arch_swab64p __arch_swab64p #define __arch_swab64p __arch_swab64p
#endif /* CONFIG_SPARC64 */ #else
#define __SWAB_64_THRU_32__
#endif /* defined(__sparc__) && defined(__arch64__) */
#include <linux/byteorder.h> #include <linux/byteorder.h>

View File

@ -1,8 +1,32 @@
#ifndef ___ASM_SPARC_IPCBUF_H #ifndef __SPARC_IPCBUF_H
#define ___ASM_SPARC_IPCBUF_H #define __SPARC_IPCBUF_H
#if defined(__sparc__) && defined(__arch64__)
#include <asm/ipcbuf_64.h> /*
#else * The ipc64_perm structure for sparc/sparc64 architecture.
#include <asm/ipcbuf_32.h> * Note extra padding because this structure is passed back and forth
#endif * between kernel and user space.
*
* Pad space is left for:
* - 32-bit seq
* - on sparc for 32 bit mode (it is 32 bit on sparc64)
* - 2 miscellaneous 64-bit values
*/
struct ipc64_perm
{
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
#ifndef __arch64__
unsigned short __pad0;
#endif #endif
__kernel_mode_t mode;
unsigned short __pad1;
unsigned short seq;
unsigned long long __unused1;
unsigned long long __unused2;
};
#endif /* __SPARC_IPCBUF_H */

View File

@ -1,31 +0,0 @@
#ifndef _SPARC_IPCBUF_H
#define _SPARC_IPCBUF_H
/*
* The ipc64_perm structure for sparc architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 32-bit mode
* - 32-bit seq
* - 2 miscellaneous 64-bit values (so that this structure matches
* sparc64 ipc64_perm)
*/
struct ipc64_perm
{
__kernel_key_t key;
__kernel_uid32_t uid;
__kernel_gid32_t gid;
__kernel_uid32_t cuid;
__kernel_gid32_t cgid;
unsigned short __pad1;
__kernel_mode_t mode;
unsigned short __pad2;
unsigned short seq;
unsigned long long __unused1;
unsigned long long __unused2;
};
#endif /* _SPARC_IPCBUF_H */

View File

@ -1,28 +0,0 @@
#ifndef _SPARC64_IPCBUF_H
#define _SPARC64_IPCBUF_H
/*
* The ipc64_perm structure for sparc64 architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 32-bit seq
* - 2 miscellaneous 64-bit values
*/
struct ipc64_perm
{
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
__kernel_mode_t mode;
unsigned short __pad1;
unsigned short seq;
unsigned long __unused1;
unsigned long __unused2;
};
#endif /* _SPARC64_IPCBUF_H */

View File

@ -8,7 +8,7 @@
#define _SPARC_JSFLASH_H #define _SPARC_JSFLASH_H
#ifndef _SPARC_TYPES_H #ifndef _SPARC_TYPES_H
#include <asm/types.h> #include <linux/types.h>
#endif #endif
/* /*

View File

@ -1,8 +1,277 @@
#ifndef ___ASM_SPARC_OPENPROM_H #ifndef __SPARC_OPENPROM_H
#define ___ASM_SPARC_OPENPROM_H #define __SPARC_OPENPROM_H
/* openprom.h: Prom structures and defines for access to the OPENBOOT
* prom routines and data areas.
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
*/
/* Empirical constants... */
#define LINUX_OPPROM_MAGIC 0x10010407
#ifndef __ASSEMBLY__
/* V0 prom device operations. */
struct linux_dev_v0_funcs {
int (*v0_devopen)(char *device_str);
int (*v0_devclose)(int dev_desc);
int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
};
/* V2 and later prom device operations. */
struct linux_dev_v2_funcs {
int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
void (*v2_dumb_mem_free)(char *va, unsigned sz);
/* To map devices into virtual I/O space. */
char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
void (*v2_dumb_munmap)(char *virta, unsigned size);
int (*v2_dev_open)(char *devpath);
void (*v2_dev_close)(int d);
int (*v2_dev_read)(int d, char *buf, int nbytes);
int (*v2_dev_write)(int d, char *buf, int nbytes);
int (*v2_dev_seek)(int d, int hi, int lo);
/* Never issued (multistage load support) */
void (*v2_wheee2)(void);
void (*v2_wheee3)(void);
};
struct linux_mlist_v0 {
struct linux_mlist_v0 *theres_more;
unsigned int start_adr;
unsigned num_bytes;
};
struct linux_mem_v0 {
struct linux_mlist_v0 **v0_totphys;
struct linux_mlist_v0 **v0_prommap;
struct linux_mlist_v0 **v0_available; /* What we can use */
};
/* Arguments sent to the kernel from the boot prompt. */
struct linux_arguments_v0 {
char *argv[8];
char args[100];
char boot_dev[2];
int boot_dev_ctrl;
int boot_dev_unit;
int dev_partition;
char *kernel_file_name;
void *aieee1; /* XXX */
};
/* V2 and up boot things. */
struct linux_bootargs_v2 {
char **bootpath;
char **bootargs;
int *fd_stdin;
int *fd_stdout;
};
/* The top level PROM vector. */
struct linux_romvec {
/* Version numbers. */
unsigned int pv_magic_cookie;
unsigned int pv_romvers;
unsigned int pv_plugin_revision;
unsigned int pv_printrev;
/* Version 0 memory descriptors. */
struct linux_mem_v0 pv_v0mem;
/* Node operations. */
struct linux_nodeops *pv_nodeops;
char **pv_bootstr;
struct linux_dev_v0_funcs pv_v0devops;
char *pv_stdin;
char *pv_stdout;
#define PROMDEV_KBD 0 /* input from keyboard */
#define PROMDEV_SCREEN 0 /* output to screen */
#define PROMDEV_TTYA 1 /* in/out to ttya */
#define PROMDEV_TTYB 2 /* in/out to ttyb */
/* Blocking getchar/putchar. NOT REENTRANT! (grr) */
int (*pv_getchar)(void);
void (*pv_putchar)(int ch);
/* Non-blocking variants. */
int (*pv_nbgetchar)(void);
int (*pv_nbputchar)(int ch);
void (*pv_putstr)(char *str, int len);
/* Miscellany. */
void (*pv_reboot)(char *bootstr);
void (*pv_printf)(__const__ char *fmt, ...);
void (*pv_abort)(void);
__volatile__ int *pv_ticks;
void (*pv_halt)(void);
void (**pv_synchook)(void);
/* Evaluate a forth string, not different proto for V0 and V2->up. */
union {
void (*v0_eval)(int len, char *str);
void (*v2_eval)(char *str);
} pv_fortheval;
struct linux_arguments_v0 **pv_v0bootargs;
/* Get ether address. */
unsigned int (*pv_enaddr)(int d, char *enaddr);
struct linux_bootargs_v2 pv_v2bootargs;
struct linux_dev_v2_funcs pv_v2devops;
int filler[15];
/* This one is sun4c/sun4 only. */
void (*pv_setctxt)(int ctxt, char *va, int pmeg);
/* Prom version 3 Multiprocessor routines. This stuff is crazy.
* No joke. Calling these when there is only one cpu probably
* crashes the machine, have to test this. :-)
*/
/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
* 'thiscontext' executing at address 'prog_counter'
*/
int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
int thiscontext, char *prog_counter);
/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
* until a resume cpu call is made.
*/
int (*v3_cpustop)(unsigned int whichcpu);
/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
* resume cpu call is made.
*/
int (*v3_cpuidle)(unsigned int whichcpu);
/* v3_cpuresume() will resume processor 'whichcpu' executing
* starting with whatever 'pc' and 'npc' were left at the
* last 'idle' or 'stop' call.
*/
int (*v3_cpuresume)(unsigned int whichcpu);
};
/* Routines for traversing the prom device tree. */
struct linux_nodeops {
int (*no_nextnode)(int node);
int (*no_child)(int node);
int (*no_proplen)(int node, const char *name);
int (*no_getprop)(int node, const char *name, char *val);
int (*no_setprop)(int node, const char *name, char *val, int len);
char * (*no_nextprop)(int node, char *name);
};
/* More fun PROM structures for device probing. */
#if defined(__sparc__) && defined(__arch64__) #if defined(__sparc__) && defined(__arch64__)
#include <asm/openprom_64.h> #define PROMREG_MAX 24
#define PROMVADDR_MAX 16
#define PROMINTR_MAX 32
#else #else
#include <asm/openprom_32.h> #define PROMREG_MAX 16
#define PROMVADDR_MAX 16
#define PROMINTR_MAX 15
#endif #endif
struct linux_prom_registers {
unsigned int which_io; /* hi part of physical address */
unsigned int phys_addr; /* The physical address of this register */
unsigned int reg_size; /* How many bytes does this register take up? */
};
struct linux_prom64_registers {
unsigned long phys_addr;
unsigned long reg_size;
};
struct linux_prom_irqs {
int pri; /* IRQ priority */
int vector; /* This is foobar, what does it do? */
};
/* Element of the "ranges" vector */
struct linux_prom_ranges {
unsigned int ot_child_space;
unsigned int ot_child_base; /* Bus feels this */
unsigned int ot_parent_space;
unsigned int ot_parent_base; /* CPU looks from here */
unsigned int or_size;
};
/*
* Ranges and reg properties are a bit different for PCI.
*/
#if defined(__sparc__) && defined(__arch64__)
struct linux_prom_pci_registers {
unsigned int phys_hi;
unsigned int phys_mid;
unsigned int phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
#else
struct linux_prom_pci_registers {
/*
* We don't know what information this field contain.
* We guess, PCI device function is in bits 15:8
* So, ...
*/
unsigned int which_io; /* Let it be which_io */
unsigned int phys_hi;
unsigned int phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
#endif #endif
struct linux_prom_pci_ranges {
unsigned int child_phys_hi; /* Only certain bits are encoded here. */
unsigned int child_phys_mid;
unsigned int child_phys_lo;
unsigned int parent_phys_hi;
unsigned int parent_phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
struct linux_prom_pci_intmap {
unsigned int phys_hi;
unsigned int phys_mid;
unsigned int phys_lo;
unsigned int interrupt;
int cnode;
unsigned int cinterrupt;
};
struct linux_prom_pci_intmask {
unsigned int phys_hi;
unsigned int phys_mid;
unsigned int phys_lo;
unsigned int interrupt;
};
#endif /* !(__ASSEMBLY__) */
#endif /* !(__SPARC_OPENPROM_H) */

View File

@ -1,255 +0,0 @@
#ifndef __SPARC_OPENPROM_H
#define __SPARC_OPENPROM_H
/* openprom.h: Prom structures and defines for access to the OPENBOOT
* prom routines and data areas.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
/* Empirical constants... */
#define LINUX_OPPROM_MAGIC 0x10010407
#ifndef __ASSEMBLY__
/* V0 prom device operations. */
struct linux_dev_v0_funcs {
int (*v0_devopen)(char *device_str);
int (*v0_devclose)(int dev_desc);
int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
};
/* V2 and later prom device operations. */
struct linux_dev_v2_funcs {
int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
void (*v2_dumb_mem_free)(char *va, unsigned sz);
/* To map devices into virtual I/O space. */
char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
void (*v2_dumb_munmap)(char *virta, unsigned size);
int (*v2_dev_open)(char *devpath);
void (*v2_dev_close)(int d);
int (*v2_dev_read)(int d, char *buf, int nbytes);
int (*v2_dev_write)(int d, char *buf, int nbytes);
int (*v2_dev_seek)(int d, int hi, int lo);
/* Never issued (multistage load support) */
void (*v2_wheee2)(void);
void (*v2_wheee3)(void);
};
struct linux_mlist_v0 {
struct linux_mlist_v0 *theres_more;
char *start_adr;
unsigned num_bytes;
};
struct linux_mem_v0 {
struct linux_mlist_v0 **v0_totphys;
struct linux_mlist_v0 **v0_prommap;
struct linux_mlist_v0 **v0_available; /* What we can use */
};
/* Arguments sent to the kernel from the boot prompt. */
struct linux_arguments_v0 {
char *argv[8];
char args[100];
char boot_dev[2];
int boot_dev_ctrl;
int boot_dev_unit;
int dev_partition;
char *kernel_file_name;
void *aieee1; /* XXX */
};
/* V2 and up boot things. */
struct linux_bootargs_v2 {
char **bootpath;
char **bootargs;
int *fd_stdin;
int *fd_stdout;
};
/* The top level PROM vector. */
struct linux_romvec {
/* Version numbers. */
unsigned int pv_magic_cookie;
unsigned int pv_romvers;
unsigned int pv_plugin_revision;
unsigned int pv_printrev;
/* Version 0 memory descriptors. */
struct linux_mem_v0 pv_v0mem;
/* Node operations. */
struct linux_nodeops *pv_nodeops;
char **pv_bootstr;
struct linux_dev_v0_funcs pv_v0devops;
char *pv_stdin;
char *pv_stdout;
#define PROMDEV_KBD 0 /* input from keyboard */
#define PROMDEV_SCREEN 0 /* output to screen */
#define PROMDEV_TTYA 1 /* in/out to ttya */
#define PROMDEV_TTYB 2 /* in/out to ttyb */
/* Blocking getchar/putchar. NOT REENTRANT! (grr) */
int (*pv_getchar)(void);
void (*pv_putchar)(int ch);
/* Non-blocking variants. */
int (*pv_nbgetchar)(void);
int (*pv_nbputchar)(int ch);
void (*pv_putstr)(char *str, int len);
/* Miscellany. */
void (*pv_reboot)(char *bootstr);
void (*pv_printf)(__const__ char *fmt, ...);
void (*pv_abort)(void);
__volatile__ int *pv_ticks;
void (*pv_halt)(void);
void (**pv_synchook)(void);
/* Evaluate a forth string, not different proto for V0 and V2->up. */
union {
void (*v0_eval)(int len, char *str);
void (*v2_eval)(char *str);
} pv_fortheval;
struct linux_arguments_v0 **pv_v0bootargs;
/* Get ether address. */
unsigned int (*pv_enaddr)(int d, char *enaddr);
struct linux_bootargs_v2 pv_v2bootargs;
struct linux_dev_v2_funcs pv_v2devops;
int filler[15];
/* This one is sun4c/sun4 only. */
void (*pv_setctxt)(int ctxt, char *va, int pmeg);
/* Prom version 3 Multiprocessor routines. This stuff is crazy.
* No joke. Calling these when there is only one cpu probably
* crashes the machine, have to test this. :-)
*/
/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
* 'thiscontext' executing at address 'prog_counter'
*/
int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
int thiscontext, char *prog_counter);
/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
* until a resume cpu call is made.
*/
int (*v3_cpustop)(unsigned int whichcpu);
/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
* resume cpu call is made.
*/
int (*v3_cpuidle)(unsigned int whichcpu);
/* v3_cpuresume() will resume processor 'whichcpu' executing
* starting with whatever 'pc' and 'npc' were left at the
* last 'idle' or 'stop' call.
*/
int (*v3_cpuresume)(unsigned int whichcpu);
};
/* Routines for traversing the prom device tree. */
struct linux_nodeops {
int (*no_nextnode)(int node);
int (*no_child)(int node);
int (*no_proplen)(int node, const char *name);
int (*no_getprop)(int node, const char *name, char *val);
int (*no_setprop)(int node, const char *name, char *val, int len);
char * (*no_nextprop)(int node, char *name);
};
/* More fun PROM structures for device probing. */
#define PROMREG_MAX 16
#define PROMVADDR_MAX 16
#define PROMINTR_MAX 15
struct linux_prom_registers {
unsigned int which_io; /* is this in OBIO space? */
unsigned int phys_addr; /* The physical address of this register */
unsigned int reg_size; /* How many bytes does this register take up? */
};
struct linux_prom_irqs {
int pri; /* IRQ priority */
int vector; /* This is foobar, what does it do? */
};
/* Element of the "ranges" vector */
struct linux_prom_ranges {
unsigned int ot_child_space;
unsigned int ot_child_base; /* Bus feels this */
unsigned int ot_parent_space;
unsigned int ot_parent_base; /* CPU looks from here */
unsigned int or_size;
};
/* Ranges and reg properties are a bit different for PCI. */
struct linux_prom_pci_registers {
/*
* We don't know what information this field contain.
* We guess, PCI device function is in bits 15:8
* So, ...
*/
unsigned int which_io; /* Let it be which_io */
unsigned int phys_hi;
unsigned int phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
struct linux_prom_pci_ranges {
unsigned int child_phys_hi; /* Only certain bits are encoded here. */
unsigned int child_phys_mid;
unsigned int child_phys_lo;
unsigned int parent_phys_hi;
unsigned int parent_phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
struct linux_prom_pci_assigned_addresses {
unsigned int which_io;
unsigned int phys_hi;
unsigned int phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
struct linux_prom_ebus_ranges {
unsigned int child_phys_hi;
unsigned int child_phys_lo;
unsigned int parent_phys_hi;
unsigned int parent_phys_mid;
unsigned int parent_phys_lo;
unsigned int size;
};
#endif /* !(__ASSEMBLY__) */
#endif /* !(__SPARC_OPENPROM_H) */

View File

@ -1,280 +0,0 @@
#ifndef __SPARC64_OPENPROM_H
#define __SPARC64_OPENPROM_H
/* openprom.h: Prom structures and defines for access to the OPENBOOT
* prom routines and data areas.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
#ifndef __ASSEMBLY__
/* V0 prom device operations. */
struct linux_dev_v0_funcs {
int (*v0_devopen)(char *device_str);
int (*v0_devclose)(int dev_desc);
int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
};
/* V2 and later prom device operations. */
struct linux_dev_v2_funcs {
int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
void (*v2_dumb_mem_free)(char *va, unsigned sz);
/* To map devices into virtual I/O space. */
char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
void (*v2_dumb_munmap)(char *virta, unsigned size);
int (*v2_dev_open)(char *devpath);
void (*v2_dev_close)(int d);
int (*v2_dev_read)(int d, char *buf, int nbytes);
int (*v2_dev_write)(int d, char *buf, int nbytes);
int (*v2_dev_seek)(int d, int hi, int lo);
/* Never issued (multistage load support) */
void (*v2_wheee2)(void);
void (*v2_wheee3)(void);
};
struct linux_mlist_v0 {
struct linux_mlist_v0 *theres_more;
unsigned start_adr;
unsigned num_bytes;
};
struct linux_mem_v0 {
struct linux_mlist_v0 **v0_totphys;
struct linux_mlist_v0 **v0_prommap;
struct linux_mlist_v0 **v0_available; /* What we can use */
};
/* Arguments sent to the kernel from the boot prompt. */
struct linux_arguments_v0 {
char *argv[8];
char args[100];
char boot_dev[2];
int boot_dev_ctrl;
int boot_dev_unit;
int dev_partition;
char *kernel_file_name;
void *aieee1; /* XXX */
};
/* V2 and up boot things. */
struct linux_bootargs_v2 {
char **bootpath;
char **bootargs;
int *fd_stdin;
int *fd_stdout;
};
/* The top level PROM vector. */
struct linux_romvec {
/* Version numbers. */
unsigned int pv_magic_cookie;
unsigned int pv_romvers;
unsigned int pv_plugin_revision;
unsigned int pv_printrev;
/* Version 0 memory descriptors. */
struct linux_mem_v0 pv_v0mem;
/* Node operations. */
struct linux_nodeops *pv_nodeops;
char **pv_bootstr;
struct linux_dev_v0_funcs pv_v0devops;
char *pv_stdin;
char *pv_stdout;
#define PROMDEV_KBD 0 /* input from keyboard */
#define PROMDEV_SCREEN 0 /* output to screen */
#define PROMDEV_TTYA 1 /* in/out to ttya */
#define PROMDEV_TTYB 2 /* in/out to ttyb */
/* Blocking getchar/putchar. NOT REENTRANT! (grr) */
int (*pv_getchar)(void);
void (*pv_putchar)(int ch);
/* Non-blocking variants. */
int (*pv_nbgetchar)(void);
int (*pv_nbputchar)(int ch);
void (*pv_putstr)(char *str, int len);
/* Miscellany. */
void (*pv_reboot)(char *bootstr);
void (*pv_printf)(__const__ char *fmt, ...);
void (*pv_abort)(void);
__volatile__ int *pv_ticks;
void (*pv_halt)(void);
void (**pv_synchook)(void);
/* Evaluate a forth string, not different proto for V0 and V2->up. */
union {
void (*v0_eval)(int len, char *str);
void (*v2_eval)(char *str);
} pv_fortheval;
struct linux_arguments_v0 **pv_v0bootargs;
/* Get ether address. */
unsigned int (*pv_enaddr)(int d, char *enaddr);
struct linux_bootargs_v2 pv_v2bootargs;
struct linux_dev_v2_funcs pv_v2devops;
int filler[15];
/* This one is sun4c/sun4 only. */
void (*pv_setctxt)(int ctxt, char *va, int pmeg);
/* Prom version 3 Multiprocessor routines. This stuff is crazy.
* No joke. Calling these when there is only one cpu probably
* crashes the machine, have to test this. :-)
*/
/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
* 'thiscontext' executing at address 'prog_counter'
*/
int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
int thiscontext, char *prog_counter);
/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
* until a resume cpu call is made.
*/
int (*v3_cpustop)(unsigned int whichcpu);
/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
* resume cpu call is made.
*/
int (*v3_cpuidle)(unsigned int whichcpu);
/* v3_cpuresume() will resume processor 'whichcpu' executing
* starting with whatever 'pc' and 'npc' were left at the
* last 'idle' or 'stop' call.
*/
int (*v3_cpuresume)(unsigned int whichcpu);
};
/* Routines for traversing the prom device tree. */
struct linux_nodeops {
int (*no_nextnode)(int node);
int (*no_child)(int node);
int (*no_proplen)(int node, char *name);
int (*no_getprop)(int node, char *name, char *val);
int (*no_setprop)(int node, char *name, char *val, int len);
char * (*no_nextprop)(int node, char *name);
};
/* More fun PROM structures for device probing. */
#define PROMREG_MAX 24
#define PROMVADDR_MAX 16
#define PROMINTR_MAX 32
struct linux_prom_registers {
unsigned which_io; /* hi part of physical address */
unsigned phys_addr; /* The physical address of this register */
int reg_size; /* How many bytes does this register take up? */
};
struct linux_prom64_registers {
unsigned long phys_addr;
unsigned long reg_size;
};
struct linux_prom_irqs {
int pri; /* IRQ priority */
int vector; /* This is foobar, what does it do? */
};
/* Element of the "ranges" vector */
struct linux_prom_ranges {
unsigned int ot_child_space;
unsigned int ot_child_base; /* Bus feels this */
unsigned int ot_parent_space;
unsigned int ot_parent_base; /* CPU looks from here */
unsigned int or_size;
};
struct linux_prom64_ranges {
unsigned long ot_child_base; /* Bus feels this */
unsigned long ot_parent_base; /* CPU looks from here */
unsigned long or_size;
};
/* Ranges and reg properties are a bit different for PCI. */
struct linux_prom_pci_registers {
unsigned int phys_hi;
unsigned int phys_mid;
unsigned int phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
struct linux_prom_pci_ranges {
unsigned int child_phys_hi; /* Only certain bits are encoded here. */
unsigned int child_phys_mid;
unsigned int child_phys_lo;
unsigned int parent_phys_hi;
unsigned int parent_phys_lo;
unsigned int size_hi;
unsigned int size_lo;
};
struct linux_prom_pci_intmap {
unsigned int phys_hi;
unsigned int phys_mid;
unsigned int phys_lo;
unsigned int interrupt;
int cnode;
unsigned int cinterrupt;
};
struct linux_prom_pci_intmask {
unsigned int phys_hi;
unsigned int phys_mid;
unsigned int phys_lo;
unsigned int interrupt;
};
struct linux_prom_ebus_ranges {
unsigned int child_phys_hi;
unsigned int child_phys_lo;
unsigned int parent_phys_hi;
unsigned int parent_phys_mid;
unsigned int parent_phys_lo;
unsigned int size;
};
struct linux_prom_ebus_intmap {
unsigned int phys_hi;
unsigned int phys_lo;
unsigned int interrupt;
int cnode;
unsigned int cinterrupt;
};
struct linux_prom_ebus_intmask {
unsigned int phys_hi;
unsigned int phys_lo;
unsigned int interrupt;
};
#endif /* !(__ASSEMBLY__) */
#endif /* !(__SPARC64_OPENPROM_H) */

View File

@ -1,8 +1,155 @@
#ifndef ___ASM_SPARC_POSIX_TYPES_H /*
#define ___ASM_SPARC_POSIX_TYPES_H * This file is generally used by user-level software, so you need to
* be a little careful about namespace pollution etc. Also, we cannot
* assume GCC is being used.
*/
#ifndef __SPARC_POSIX_TYPES_H
#define __SPARC_POSIX_TYPES_H
#if defined(__sparc__) && defined(__arch64__) #if defined(__sparc__) && defined(__arch64__)
#include <asm/posix_types_64.h> /* sparc 64 bit */
typedef unsigned long __kernel_size_t;
typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_clock_t;
typedef int __kernel_pid_t;
typedef int __kernel_ipc_pid_t;
typedef unsigned int __kernel_uid_t;
typedef unsigned int __kernel_gid_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned int __kernel_mode_t;
typedef unsigned short __kernel_umode_t;
typedef unsigned int __kernel_nlink_t;
typedef int __kernel_daddr_t;
typedef long __kernel_off_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
typedef int __kernel_clockid_t;
typedef int __kernel_timer_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
typedef __kernel_uid_t __kernel_uid32_t;
typedef __kernel_gid_t __kernel_gid32_t;
typedef unsigned int __kernel_old_dev_t;
/* Note this piece of asymmetry from the v9 ABI. */
typedef int __kernel_suseconds_t;
#else #else
#include <asm/posix_types_32.h> /* sparc 32 bit */
#endif
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef long int __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t;
typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_umode_t;
typedef short __kernel_nlink_t;
typedef long __kernel_daddr_t;
typedef long __kernel_off_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
typedef unsigned short __kernel_old_dev_t;
typedef int __kernel_clockid_t;
typedef int __kernel_timer_t;
#endif /* defined(__sparc__) && defined(__arch64__) */
#ifdef __GNUC__
typedef long long __kernel_loff_t;
#endif #endif
typedef struct {
int val[2];
} __kernel_fsid_t;
#ifdef __KERNEL__
#undef __FD_SET
static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
}
#undef __FD_CLR
static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
}
#undef __FD_ISSET
static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
}
/*
* This will unroll the loop for the normal constant cases (8 or 32 longs,
* for 256 and 1024-bit fd_sets respectively)
*/
#undef __FD_ZERO
static inline void __FD_ZERO(__kernel_fd_set *p)
{
unsigned long *tmp = p->fds_bits;
int i;
if (__builtin_constant_p(__FDSET_LONGS)) {
switch (__FDSET_LONGS) {
case 32:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
return;
case 16:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
return;
case 8:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
return;
case 4:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
return;
}
}
i = __FDSET_LONGS;
while (i) {
i--;
*tmp = 0;
tmp++;
}
}
#endif /* __KERNEL__ */
#endif /* __SPARC_POSIX_TYPES_H */

View File

@ -1,118 +0,0 @@
#ifndef __ARCH_SPARC_POSIX_TYPES_H
#define __ARCH_SPARC_POSIX_TYPES_H
/*
* This file is generally used by user-level software, so you need to
* be a little careful about namespace pollution etc. Also, we cannot
* assume GCC is being used.
*/
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef long int __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t;
typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_umode_t;
typedef short __kernel_nlink_t;
typedef long __kernel_daddr_t;
typedef long __kernel_off_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
typedef unsigned short __kernel_old_dev_t;
typedef int __kernel_clockid_t;
typedef int __kernel_timer_t;
#ifdef __GNUC__
typedef long long __kernel_loff_t;
#endif
typedef struct {
int val[2];
} __kernel_fsid_t;
#if defined(__KERNEL__)
#undef __FD_SET
static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
}
#undef __FD_CLR
static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
}
#undef __FD_ISSET
static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
}
/*
* This will unroll the loop for the normal constant cases (8 or 32 longs,
* for 256 and 1024-bit fd_sets respectively)
*/
#undef __FD_ZERO
static inline void __FD_ZERO(__kernel_fd_set *p)
{
unsigned long *tmp = p->fds_bits;
int i;
if (__builtin_constant_p(__FDSET_LONGS)) {
switch (__FDSET_LONGS) {
case 32:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
return;
case 16:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
return;
case 8:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
return;
case 4:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
return;
}
}
i = __FDSET_LONGS;
while (i) {
i--;
*tmp = 0;
tmp++;
}
}
#endif /* defined(__KERNEL__) */
#endif /* !(__ARCH_SPARC_POSIX_TYPES_H) */

View File

@ -1,122 +0,0 @@
#ifndef __ARCH_SPARC64_POSIX_TYPES_H
#define __ARCH_SPARC64_POSIX_TYPES_H
/*
* This file is generally used by user-level software, so you need to
* be a little careful about namespace pollution etc. Also, we cannot
* assume GCC is being used.
*/
typedef unsigned long __kernel_size_t;
typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_clock_t;
typedef int __kernel_pid_t;
typedef int __kernel_ipc_pid_t;
typedef unsigned int __kernel_uid_t;
typedef unsigned int __kernel_gid_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned int __kernel_mode_t;
typedef unsigned short __kernel_umode_t;
typedef unsigned int __kernel_nlink_t;
typedef int __kernel_daddr_t;
typedef long __kernel_off_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
typedef int __kernel_clockid_t;
typedef int __kernel_timer_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
typedef __kernel_uid_t __kernel_uid32_t;
typedef __kernel_gid_t __kernel_gid32_t;
typedef unsigned int __kernel_old_dev_t;
/* Note this piece of asymmetry from the v9 ABI. */
typedef int __kernel_suseconds_t;
#ifdef __GNUC__
typedef long long __kernel_loff_t;
#endif
typedef struct {
int val[2];
} __kernel_fsid_t;
#if defined(__KERNEL__)
#undef __FD_SET
static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
}
#undef __FD_CLR
static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
}
#undef __FD_ISSET
static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
{
unsigned long _tmp = fd / __NFDBITS;
unsigned long _rem = fd % __NFDBITS;
return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
}
/*
* This will unroll the loop for the normal constant cases (8 or 32 longs,
* for 256 and 1024-bit fd_sets respectively)
*/
#undef __FD_ZERO
static inline void __FD_ZERO(__kernel_fd_set *p)
{
unsigned long *tmp = p->fds_bits;
int i;
if (__builtin_constant_p(__FDSET_LONGS)) {
switch (__FDSET_LONGS) {
case 32:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
return;
case 16:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
return;
case 8:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
return;
case 4:
tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
return;
}
}
i = __FDSET_LONGS;
while (i) {
i--;
*tmp = 0;
tmp++;
}
}
#endif /* defined(__KERNEL__) */
#endif /* !(__ARCH_SPARC64_POSIX_TYPES_H) */

View File

@ -99,7 +99,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
"st\t%%g0, [%0 + %3 + 0x3c]" "st\t%%g0, [%0 + %3 + 0x3c]"
: /* no outputs */ : /* no outputs */
: "r" (regs), : "r" (regs),
"r" (sp - sizeof(struct reg_window)), "r" (sp - sizeof(struct reg_window32)),
"r" (zero), "r" (zero),
"i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0])) "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))
: "memory"); : "memory");

View File

@ -1,8 +1,448 @@
#ifndef ___ASM_SPARC_PTRACE_H #ifndef __SPARC_PTRACE_H
#define ___ASM_SPARC_PTRACE_H #define __SPARC_PTRACE_H
#if defined(__sparc__) && defined(__arch64__) #if defined(__sparc__) && defined(__arch64__)
#include <asm/ptrace_64.h> /* 64 bit sparc */
#include <asm/pstate.h>
/* This struct defines the way the registers are stored on the
* stack during a system call and basically all traps.
*/
/* This magic value must have the low 9 bits clear,
* as that is where we encode the %tt value, see below.
*/
#define PT_REGS_MAGIC 0x57ac6c00
#ifndef __ASSEMBLY__
#include <linux/types.h>
struct pt_regs {
unsigned long u_regs[16]; /* globals and ins */
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned int y;
/* We encode a magic number, PT_REGS_MAGIC, along
* with the %tt (trap type) register value at trap
* entry time. The magic number allows us to identify
* accurately a trap stack frame in the stack
* unwinder, and the %tt value allows us to test
* things like "in a system call" etc. for an arbitray
* process.
*
* The PT_REGS_MAGIC is choosen such that it can be
* loaded completely using just a sethi instruction.
*/
unsigned int magic;
};
struct pt_regs32 {
unsigned int psr;
unsigned int pc;
unsigned int npc;
unsigned int y;
unsigned int u_regs[16]; /* globals and ins */
};
/* A V9 register window */
struct reg_window {
unsigned long locals[8];
unsigned long ins[8];
};
/* A 32-bit register window. */
struct reg_window32 {
unsigned int locals[8];
unsigned int ins[8];
};
/* A V9 Sparc stack frame */
struct sparc_stackf {
unsigned long locals[8];
unsigned long ins[6];
struct sparc_stackf *fp;
unsigned long callers_pc;
char *structptr;
unsigned long xargs[6];
unsigned long xxargs[1];
};
/* A 32-bit Sparc stack frame */
struct sparc_stackf32 {
unsigned int locals[8];
unsigned int ins[6];
unsigned int fp;
unsigned int callers_pc;
unsigned int structptr;
unsigned int xargs[6];
unsigned int xxargs[1];
};
struct sparc_trapf {
unsigned long locals[8];
unsigned long ins[8];
unsigned long _unused;
struct pt_regs *regs;
};
#endif /* (!__ASSEMBLY__) */
#else #else
#include <asm/ptrace_32.h> /* 32 bit sparc */
#include <asm/psr.h>
/* This struct defines the way the registers are stored on the
* stack during a system call and basically all traps.
*/
#ifndef __ASSEMBLY__
struct pt_regs {
unsigned long psr;
unsigned long pc;
unsigned long npc;
unsigned long y;
unsigned long u_regs[16]; /* globals and ins */
};
/* A 32-bit register window. */
struct reg_window32 {
unsigned long locals[8];
unsigned long ins[8];
};
/* A Sparc stack frame */
struct sparc_stackf {
unsigned long locals[8];
unsigned long ins[6];
struct sparc_stackf *fp;
unsigned long callers_pc;
char *structptr;
unsigned long xargs[6];
unsigned long xxargs[1];
};
#endif /* (!__ASSEMBLY__) */
#endif /* (defined(__sparc__) && defined(__arch64__))*/
#ifndef __ASSEMBLY__
#define TRACEREG_SZ sizeof(struct pt_regs)
#define STACKFRAME_SZ sizeof(struct sparc_stackf)
#define TRACEREG32_SZ sizeof(struct pt_regs32)
#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
#endif /* (!__ASSEMBLY__) */
#define UREG_G0 0
#define UREG_G1 1
#define UREG_G2 2
#define UREG_G3 3
#define UREG_G4 4
#define UREG_G5 5
#define UREG_G6 6
#define UREG_G7 7
#define UREG_I0 8
#define UREG_I1 9
#define UREG_I2 10
#define UREG_I3 11
#define UREG_I4 12
#define UREG_I5 13
#define UREG_I6 14
#define UREG_I7 15
#define UREG_FP UREG_I6
#define UREG_RETPC UREG_I7
#if defined(__sparc__) && defined(__arch64__)
/* 64 bit sparc */
#ifndef __ASSEMBLY__
#ifdef __KERNEL__
#include <linux/threads.h>
#include <asm/system.h>
static inline int pt_regs_trap_type(struct pt_regs *regs)
{
return regs->magic & 0x1ff;
}
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->tstate & TSTATE_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->tstate &= ~TSTATE_SYSCALL);
}
#define arch_ptrace_stop_needed(exit_code, info) \
({ flush_user_windows(); \
get_thread_wsaved() != 0; \
})
#define arch_ptrace_stop(exit_code, info) \
synchronize_user_stack()
struct global_reg_snapshot {
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned long o7;
unsigned long i7;
unsigned long rpc;
struct thread_info *thread;
unsigned long pad1;
};
extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
#define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \
} while (0)
#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
#define instruction_pointer(regs) ((regs)->tpc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
#ifdef CONFIG_SMP
extern unsigned long profile_pc(struct pt_regs *);
#else
#define profile_pc(regs) instruction_pointer(regs)
#endif #endif
extern void show_regs(struct pt_regs *);
#endif /* (__KERNEL__) */
#else /* __ASSEMBLY__ */
/* For assembly code. */
#define TRACEREG_SZ 0xa0
#define STACKFRAME_SZ 0xc0
#define TRACEREG32_SZ 0x50
#define STACKFRAME32_SZ 0x60
#endif /* __ASSEMBLY__ */
#else /* (defined(__sparc__) && defined(__arch64__)) */
/* 32 bit sparc */
#ifndef __ASSEMBLY__
#ifdef __KERNEL__
#include <asm/system.h>
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->psr & PSR_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->psr &= ~PSR_SYSCALL);
}
#define arch_ptrace_stop_needed(exit_code, info) \
({ flush_user_windows(); \
current_thread_info()->w_saved != 0; \
})
#define arch_ptrace_stop(exit_code, info) \
synchronize_user_stack()
#define user_mode(regs) (!((regs)->psr & PSR_PS))
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
unsigned long profile_pc(struct pt_regs *);
extern void show_regs(struct pt_regs *);
#endif /* (__KERNEL__) */
#else /* (!__ASSEMBLY__) */
/* For assembly code. */
#define TRACEREG_SZ 0x50
#define STACKFRAME_SZ 0x60
#endif /* (!__ASSEMBLY__) */
#endif /* (defined(__sparc__) && defined(__arch64__)) */
#ifdef __KERNEL__
#define STACK_BIAS 2047
#endif #endif
/* These are for pt_regs. */
#define PT_V9_G0 0x00
#define PT_V9_G1 0x08
#define PT_V9_G2 0x10
#define PT_V9_G3 0x18
#define PT_V9_G4 0x20
#define PT_V9_G5 0x28
#define PT_V9_G6 0x30
#define PT_V9_G7 0x38
#define PT_V9_I0 0x40
#define PT_V9_I1 0x48
#define PT_V9_I2 0x50
#define PT_V9_I3 0x58
#define PT_V9_I4 0x60
#define PT_V9_I5 0x68
#define PT_V9_I6 0x70
#define PT_V9_FP PT_V9_I6
#define PT_V9_I7 0x78
#define PT_V9_TSTATE 0x80
#define PT_V9_TPC 0x88
#define PT_V9_TNPC 0x90
#define PT_V9_Y 0x98
#define PT_V9_MAGIC 0x9c
#define PT_TSTATE PT_V9_TSTATE
#define PT_TPC PT_V9_TPC
#define PT_TNPC PT_V9_TNPC
/* These for pt_regs32. */
#define PT_PSR 0x0
#define PT_PC 0x4
#define PT_NPC 0x8
#define PT_Y 0xc
#define PT_G0 0x10
#define PT_WIM PT_G0
#define PT_G1 0x14
#define PT_G2 0x18
#define PT_G3 0x1c
#define PT_G4 0x20
#define PT_G5 0x24
#define PT_G6 0x28
#define PT_G7 0x2c
#define PT_I0 0x30
#define PT_I1 0x34
#define PT_I2 0x38
#define PT_I3 0x3c
#define PT_I4 0x40
#define PT_I5 0x44
#define PT_I6 0x48
#define PT_FP PT_I6
#define PT_I7 0x4c
/* Reg_window offsets */
#define RW_V9_L0 0x00
#define RW_V9_L1 0x08
#define RW_V9_L2 0x10
#define RW_V9_L3 0x18
#define RW_V9_L4 0x20
#define RW_V9_L5 0x28
#define RW_V9_L6 0x30
#define RW_V9_L7 0x38
#define RW_V9_I0 0x40
#define RW_V9_I1 0x48
#define RW_V9_I2 0x50
#define RW_V9_I3 0x58
#define RW_V9_I4 0x60
#define RW_V9_I5 0x68
#define RW_V9_I6 0x70
#define RW_V9_I7 0x78
#define RW_L0 0x00
#define RW_L1 0x04
#define RW_L2 0x08
#define RW_L3 0x0c
#define RW_L4 0x10
#define RW_L5 0x14
#define RW_L6 0x18
#define RW_L7 0x1c
#define RW_I0 0x20
#define RW_I1 0x24
#define RW_I2 0x28
#define RW_I3 0x2c
#define RW_I4 0x30
#define RW_I5 0x34
#define RW_I6 0x38
#define RW_I7 0x3c
/* Stack_frame offsets */
#define SF_V9_L0 0x00
#define SF_V9_L1 0x08
#define SF_V9_L2 0x10
#define SF_V9_L3 0x18
#define SF_V9_L4 0x20
#define SF_V9_L5 0x28
#define SF_V9_L6 0x30
#define SF_V9_L7 0x38
#define SF_V9_I0 0x40
#define SF_V9_I1 0x48
#define SF_V9_I2 0x50
#define SF_V9_I3 0x58
#define SF_V9_I4 0x60
#define SF_V9_I5 0x68
#define SF_V9_FP 0x70
#define SF_V9_PC 0x78
#define SF_V9_RETP 0x80
#define SF_V9_XARG0 0x88
#define SF_V9_XARG1 0x90
#define SF_V9_XARG2 0x98
#define SF_V9_XARG3 0xa0
#define SF_V9_XARG4 0xa8
#define SF_V9_XARG5 0xb0
#define SF_V9_XXARG 0xb8
#define SF_L0 0x00
#define SF_L1 0x04
#define SF_L2 0x08
#define SF_L3 0x0c
#define SF_L4 0x10
#define SF_L5 0x14
#define SF_L6 0x18
#define SF_L7 0x1c
#define SF_I0 0x20
#define SF_I1 0x24
#define SF_I2 0x28
#define SF_I3 0x2c
#define SF_I4 0x30
#define SF_I5 0x34
#define SF_FP 0x38
#define SF_PC 0x3c
#define SF_RETP 0x40
#define SF_XARG0 0x44
#define SF_XARG1 0x48
#define SF_XARG2 0x4c
#define SF_XARG3 0x50
#define SF_XARG4 0x54
#define SF_XARG5 0x58
#define SF_XXARG 0x5c
#ifdef __KERNEL__
/* global_reg_snapshot offsets */
#define GR_SNAP_TSTATE 0x00
#define GR_SNAP_TPC 0x08
#define GR_SNAP_TNPC 0x10
#define GR_SNAP_O7 0x18
#define GR_SNAP_I7 0x20
#define GR_SNAP_RPC 0x28
#define GR_SNAP_THREAD 0x30
#define GR_SNAP_PAD1 0x38
#endif /* __KERNEL__ */
/* Stuff for the ptrace system call */
#define PTRACE_SPARC_DETACH 11
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
#define PTRACE_READDATA 16
#define PTRACE_WRITEDATA 17
#define PTRACE_READTEXT 18
#define PTRACE_WRITETEXT 19
#define PTRACE_GETFPAREGS 20
#define PTRACE_SETFPAREGS 21
/* There are for debugging 64-bit processes, either from a 32 or 64 bit
* parent. Thus their complements are for debugging 32-bit processes only.
*/
#define PTRACE_GETREGS64 22
#define PTRACE_SETREGS64 23
/* PTRACE_SYSCALL is 24 */
#define PTRACE_GETFPREGS64 25
#define PTRACE_SETFPREGS64 26
#endif /* !(__SPARC_PTRACE_H) */

View File

@ -1,186 +0,0 @@
#ifndef _SPARC_PTRACE_H
#define _SPARC_PTRACE_H
#include <asm/psr.h>
/* This struct defines the way the registers are stored on the
* stack during a system call and basically all traps.
*/
#ifndef __ASSEMBLY__
#include <linux/types.h>
struct pt_regs {
unsigned long psr;
unsigned long pc;
unsigned long npc;
unsigned long y;
unsigned long u_regs[16]; /* globals and ins */
};
#define UREG_G0 0
#define UREG_G1 1
#define UREG_G2 2
#define UREG_G3 3
#define UREG_G4 4
#define UREG_G5 5
#define UREG_G6 6
#define UREG_G7 7
#define UREG_I0 8
#define UREG_I1 9
#define UREG_I2 10
#define UREG_I3 11
#define UREG_I4 12
#define UREG_I5 13
#define UREG_I6 14
#define UREG_I7 15
#define UREG_WIM UREG_G0
#define UREG_FADDR UREG_G0
#define UREG_FP UREG_I6
#define UREG_RETPC UREG_I7
/* A register window */
struct reg_window {
unsigned long locals[8];
unsigned long ins[8];
};
/* A Sparc stack frame */
struct sparc_stackf {
unsigned long locals[8];
unsigned long ins[6];
struct sparc_stackf *fp;
unsigned long callers_pc;
char *structptr;
unsigned long xargs[6];
unsigned long xxargs[1];
};
#define TRACEREG_SZ sizeof(struct pt_regs)
#define STACKFRAME_SZ sizeof(struct sparc_stackf)
#ifdef __KERNEL__
#include <asm/system.h>
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->psr & PSR_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->psr &= ~PSR_SYSCALL);
}
#define arch_ptrace_stop_needed(exit_code, info) \
({ flush_user_windows(); \
current_thread_info()->w_saved != 0; \
})
#define arch_ptrace_stop(exit_code, info) \
synchronize_user_stack()
#define user_mode(regs) (!((regs)->psr & PSR_PS))
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
unsigned long profile_pc(struct pt_regs *);
extern void show_regs(struct pt_regs *);
#endif
#else /* __ASSEMBLY__ */
/* For assembly code. */
#define TRACEREG_SZ 0x50
#define STACKFRAME_SZ 0x60
#endif
/*
* The asm-offsets.h is a generated file, so we cannot include it.
* It may be OK for glibc headers, but it's utterly pointless for C code.
* The assembly code using those offsets has to include it explicitly.
*/
/* #include <asm/asm-offsets.h> */
/* These are for pt_regs. */
#define PT_PSR 0x0
#define PT_PC 0x4
#define PT_NPC 0x8
#define PT_Y 0xc
#define PT_G0 0x10
#define PT_WIM PT_G0
#define PT_G1 0x14
#define PT_G2 0x18
#define PT_G3 0x1c
#define PT_G4 0x20
#define PT_G5 0x24
#define PT_G6 0x28
#define PT_G7 0x2c
#define PT_I0 0x30
#define PT_I1 0x34
#define PT_I2 0x38
#define PT_I3 0x3c
#define PT_I4 0x40
#define PT_I5 0x44
#define PT_I6 0x48
#define PT_FP PT_I6
#define PT_I7 0x4c
/* Reg_window offsets */
#define RW_L0 0x00
#define RW_L1 0x04
#define RW_L2 0x08
#define RW_L3 0x0c
#define RW_L4 0x10
#define RW_L5 0x14
#define RW_L6 0x18
#define RW_L7 0x1c
#define RW_I0 0x20
#define RW_I1 0x24
#define RW_I2 0x28
#define RW_I3 0x2c
#define RW_I4 0x30
#define RW_I5 0x34
#define RW_I6 0x38
#define RW_I7 0x3c
/* Stack_frame offsets */
#define SF_L0 0x00
#define SF_L1 0x04
#define SF_L2 0x08
#define SF_L3 0x0c
#define SF_L4 0x10
#define SF_L5 0x14
#define SF_L6 0x18
#define SF_L7 0x1c
#define SF_I0 0x20
#define SF_I1 0x24
#define SF_I2 0x28
#define SF_I3 0x2c
#define SF_I4 0x30
#define SF_I5 0x34
#define SF_FP 0x38
#define SF_PC 0x3c
#define SF_RETP 0x40
#define SF_XARG0 0x44
#define SF_XARG1 0x48
#define SF_XARG2 0x4c
#define SF_XARG3 0x50
#define SF_XARG4 0x54
#define SF_XARG5 0x58
#define SF_XXARG 0x5c
/* Stuff for the ptrace system call */
#define PTRACE_SPARC_DETACH 11
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
#define PTRACE_READDATA 16
#define PTRACE_WRITEDATA 17
#define PTRACE_READTEXT 18
#define PTRACE_WRITETEXT 19
#define PTRACE_GETFPAREGS 20
#define PTRACE_SETFPAREGS 21
#endif /* !(_SPARC_PTRACE_H) */

View File

@ -1,356 +0,0 @@
#ifndef _SPARC64_PTRACE_H
#define _SPARC64_PTRACE_H
#include <asm/pstate.h>
/* This struct defines the way the registers are stored on the
* stack during a system call and basically all traps.
*/
/* This magic value must have the low 9 bits clear,
* as that is where we encode the %tt value, see below.
*/
#define PT_REGS_MAGIC 0x57ac6c00
#ifndef __ASSEMBLY__
#include <linux/types.h>
struct pt_regs {
unsigned long u_regs[16]; /* globals and ins */
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned int y;
/* We encode a magic number, PT_REGS_MAGIC, along
* with the %tt (trap type) register value at trap
* entry time. The magic number allows us to identify
* accurately a trap stack frame in the stack
* unwinder, and the %tt value allows us to test
* things like "in a system call" etc. for an arbitray
* process.
*
* The PT_REGS_MAGIC is choosen such that it can be
* loaded completely using just a sethi instruction.
*/
unsigned int magic;
};
struct pt_regs32 {
unsigned int psr;
unsigned int pc;
unsigned int npc;
unsigned int y;
unsigned int u_regs[16]; /* globals and ins */
};
#define UREG_G0 0
#define UREG_G1 1
#define UREG_G2 2
#define UREG_G3 3
#define UREG_G4 4
#define UREG_G5 5
#define UREG_G6 6
#define UREG_G7 7
#define UREG_I0 8
#define UREG_I1 9
#define UREG_I2 10
#define UREG_I3 11
#define UREG_I4 12
#define UREG_I5 13
#define UREG_I6 14
#define UREG_I7 15
#define UREG_FP UREG_I6
#define UREG_RETPC UREG_I7
/* A V9 register window */
struct reg_window {
unsigned long locals[8];
unsigned long ins[8];
};
/* A 32-bit register window. */
struct reg_window32 {
unsigned int locals[8];
unsigned int ins[8];
};
/* A V9 Sparc stack frame */
struct sparc_stackf {
unsigned long locals[8];
unsigned long ins[6];
struct sparc_stackf *fp;
unsigned long callers_pc;
char *structptr;
unsigned long xargs[6];
unsigned long xxargs[1];
};
/* A 32-bit Sparc stack frame */
struct sparc_stackf32 {
unsigned int locals[8];
unsigned int ins[6];
unsigned int fp;
unsigned int callers_pc;
unsigned int structptr;
unsigned int xargs[6];
unsigned int xxargs[1];
};
struct sparc_trapf {
unsigned long locals[8];
unsigned long ins[8];
unsigned long _unused;
struct pt_regs *regs;
};
#define TRACEREG_SZ sizeof(struct pt_regs)
#define STACKFRAME_SZ sizeof(struct sparc_stackf)
#define TRACEREG32_SZ sizeof(struct pt_regs32)
#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
#ifdef __KERNEL__
#include <linux/threads.h>
#include <asm/system.h>
static inline int pt_regs_trap_type(struct pt_regs *regs)
{
return regs->magic & 0x1ff;
}
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->tstate & TSTATE_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->tstate &= ~TSTATE_SYSCALL);
}
#define arch_ptrace_stop_needed(exit_code, info) \
({ flush_user_windows(); \
get_thread_wsaved() != 0; \
})
#define arch_ptrace_stop(exit_code, info) \
synchronize_user_stack()
struct global_reg_snapshot {
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned long o7;
unsigned long i7;
unsigned long rpc;
struct thread_info *thread;
unsigned long pad1;
};
extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
#define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \
} while (0)
#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
#define instruction_pointer(regs) ((regs)->tpc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
#ifdef CONFIG_SMP
extern unsigned long profile_pc(struct pt_regs *);
#else
#define profile_pc(regs) instruction_pointer(regs)
#endif
extern void show_regs(struct pt_regs *);
#endif
#else /* __ASSEMBLY__ */
/* For assembly code. */
#define TRACEREG_SZ 0xa0
#define STACKFRAME_SZ 0xc0
#define TRACEREG32_SZ 0x50
#define STACKFRAME32_SZ 0x60
#endif
#ifdef __KERNEL__
#define STACK_BIAS 2047
#endif
/* These are for pt_regs. */
#define PT_V9_G0 0x00
#define PT_V9_G1 0x08
#define PT_V9_G2 0x10
#define PT_V9_G3 0x18
#define PT_V9_G4 0x20
#define PT_V9_G5 0x28
#define PT_V9_G6 0x30
#define PT_V9_G7 0x38
#define PT_V9_I0 0x40
#define PT_V9_I1 0x48
#define PT_V9_I2 0x50
#define PT_V9_I3 0x58
#define PT_V9_I4 0x60
#define PT_V9_I5 0x68
#define PT_V9_I6 0x70
#define PT_V9_FP PT_V9_I6
#define PT_V9_I7 0x78
#define PT_V9_TSTATE 0x80
#define PT_V9_TPC 0x88
#define PT_V9_TNPC 0x90
#define PT_V9_Y 0x98
#define PT_V9_MAGIC 0x9c
#define PT_TSTATE PT_V9_TSTATE
#define PT_TPC PT_V9_TPC
#define PT_TNPC PT_V9_TNPC
/* These for pt_regs32. */
#define PT_PSR 0x0
#define PT_PC 0x4
#define PT_NPC 0x8
#define PT_Y 0xc
#define PT_G0 0x10
#define PT_WIM PT_G0
#define PT_G1 0x14
#define PT_G2 0x18
#define PT_G3 0x1c
#define PT_G4 0x20
#define PT_G5 0x24
#define PT_G6 0x28
#define PT_G7 0x2c
#define PT_I0 0x30
#define PT_I1 0x34
#define PT_I2 0x38
#define PT_I3 0x3c
#define PT_I4 0x40
#define PT_I5 0x44
#define PT_I6 0x48
#define PT_FP PT_I6
#define PT_I7 0x4c
/* Reg_window offsets */
#define RW_V9_L0 0x00
#define RW_V9_L1 0x08
#define RW_V9_L2 0x10
#define RW_V9_L3 0x18
#define RW_V9_L4 0x20
#define RW_V9_L5 0x28
#define RW_V9_L6 0x30
#define RW_V9_L7 0x38
#define RW_V9_I0 0x40
#define RW_V9_I1 0x48
#define RW_V9_I2 0x50
#define RW_V9_I3 0x58
#define RW_V9_I4 0x60
#define RW_V9_I5 0x68
#define RW_V9_I6 0x70
#define RW_V9_I7 0x78
#define RW_L0 0x00
#define RW_L1 0x04
#define RW_L2 0x08
#define RW_L3 0x0c
#define RW_L4 0x10
#define RW_L5 0x14
#define RW_L6 0x18
#define RW_L7 0x1c
#define RW_I0 0x20
#define RW_I1 0x24
#define RW_I2 0x28
#define RW_I3 0x2c
#define RW_I4 0x30
#define RW_I5 0x34
#define RW_I6 0x38
#define RW_I7 0x3c
/* Stack_frame offsets */
#define SF_V9_L0 0x00
#define SF_V9_L1 0x08
#define SF_V9_L2 0x10
#define SF_V9_L3 0x18
#define SF_V9_L4 0x20
#define SF_V9_L5 0x28
#define SF_V9_L6 0x30
#define SF_V9_L7 0x38
#define SF_V9_I0 0x40
#define SF_V9_I1 0x48
#define SF_V9_I2 0x50
#define SF_V9_I3 0x58
#define SF_V9_I4 0x60
#define SF_V9_I5 0x68
#define SF_V9_FP 0x70
#define SF_V9_PC 0x78
#define SF_V9_RETP 0x80
#define SF_V9_XARG0 0x88
#define SF_V9_XARG1 0x90
#define SF_V9_XARG2 0x98
#define SF_V9_XARG3 0xa0
#define SF_V9_XARG4 0xa8
#define SF_V9_XARG5 0xb0
#define SF_V9_XXARG 0xb8
#define SF_L0 0x00
#define SF_L1 0x04
#define SF_L2 0x08
#define SF_L3 0x0c
#define SF_L4 0x10
#define SF_L5 0x14
#define SF_L6 0x18
#define SF_L7 0x1c
#define SF_I0 0x20
#define SF_I1 0x24
#define SF_I2 0x28
#define SF_I3 0x2c
#define SF_I4 0x30
#define SF_I5 0x34
#define SF_FP 0x38
#define SF_PC 0x3c
#define SF_RETP 0x40
#define SF_XARG0 0x44
#define SF_XARG1 0x48
#define SF_XARG2 0x4c
#define SF_XARG3 0x50
#define SF_XARG4 0x54
#define SF_XARG5 0x58
#define SF_XXARG 0x5c
#ifdef __KERNEL__
/* global_reg_snapshot offsets */
#define GR_SNAP_TSTATE 0x00
#define GR_SNAP_TPC 0x08
#define GR_SNAP_TNPC 0x10
#define GR_SNAP_O7 0x18
#define GR_SNAP_I7 0x20
#define GR_SNAP_RPC 0x28
#define GR_SNAP_THREAD 0x30
#define GR_SNAP_PAD1 0x38
#endif /* __KERNEL__ */
/* Stuff for the ptrace system call */
#define PTRACE_SPARC_DETACH 11
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
#define PTRACE_READDATA 16
#define PTRACE_WRITEDATA 17
#define PTRACE_READTEXT 18
#define PTRACE_WRITETEXT 19
#define PTRACE_GETFPAREGS 20
#define PTRACE_SETFPAREGS 21
/* There are for debugging 64-bit processes, either from a 32 or 64 bit
* parent. Thus their complements are for debugging 32-bit processes only.
*/
#define PTRACE_GETREGS64 22
#define PTRACE_SETREGS64 23
/* PTRACE_SYSCALL is 24 */
#define PTRACE_GETFPREGS64 25
#define PTRACE_SETFPREGS64 26
#endif /* !(_SPARC64_PTRACE_H) */

View File

@ -1,8 +0,0 @@
#ifndef ___ASM_SPARC_REG_H
#define ___ASM_SPARC_REG_H
#if defined(__sparc__) && defined(__arch64__)
#include <asm/reg_64.h>
#else
#include <asm/reg_32.h>
#endif
#endif

View File

@ -1,79 +0,0 @@
/*
* linux/include/asm/reg.h
* Layout of the registers as expected by gdb on the Sparc
* we should replace the user.h definitions with those in
* this file, we don't even use the other
* -miguel
*
* The names of the structures, constants and aliases in this file
* have the same names as the sunos ones, some programs rely on these
* names (gdb for example).
*
*/
#ifndef __SPARC_REG_H
#define __SPARC_REG_H
struct regs {
int r_psr;
#define r_ps r_psr
int r_pc;
int r_npc;
int r_y;
int r_g1;
int r_g2;
int r_g3;
int r_g4;
int r_g5;
int r_g6;
int r_g7;
int r_o0;
int r_o1;
int r_o2;
int r_o3;
int r_o4;
int r_o5;
int r_o6;
int r_o7;
};
struct fpq {
unsigned long *addr;
unsigned long instr;
};
struct fq {
union {
double whole;
struct fpq fpq;
} FQu;
};
#define FPU_REGS_TYPE unsigned int
#define FPU_FSR_TYPE unsigned
struct fp_status {
union {
FPU_REGS_TYPE Fpu_regs[32];
double Fpu_dregs[16];
} fpu_fr;
FPU_FSR_TYPE Fpu_fsr;
unsigned Fpu_flags;
unsigned Fpu_extra;
unsigned Fpu_qcnt;
struct fq Fpu_q[16];
};
#define fpu_regs f_fpstatus.fpu_fr.Fpu_regs
#define fpu_dregs f_fpstatus.fpu_fr.Fpu_dregs
#define fpu_fsr f_fpstatus.Fpu_fsr
#define fpu_flags f_fpstatus.Fpu_flags
#define fpu_extra f_fpstatus.Fpu_extra
#define fpu_q f_fpstatus.Fpu_q
#define fpu_qcnt f_fpstatus.Fpu_qcnt
struct fpu {
struct fp_status f_fpstatus;
};
#endif /* __SPARC_REG_H */

View File

@ -1,56 +0,0 @@
/*
* linux/asm/reg.h
* Layout of the registers as expected by gdb on the Sparc
* we should replace the user.h definitions with those in
* this file, we don't even use the other
* -miguel
*
* The names of the structures, constants and aliases in this file
* have the same names as the sunos ones, some programs rely on these
* names (gdb for example).
*
*/
#ifndef __SPARC64_REG_H
#define __SPARC64_REG_H
struct regs {
unsigned long r_g1;
unsigned long r_g2;
unsigned long r_g3;
unsigned long r_g4;
unsigned long r_g5;
unsigned long r_g6;
unsigned long r_g7;
unsigned long r_o0;
unsigned long r_o1;
unsigned long r_o2;
unsigned long r_o3;
unsigned long r_o4;
unsigned long r_o5;
unsigned long r_o6;
unsigned long r_o7;
unsigned long __pad;
unsigned long r_tstate;
unsigned long r_tpc;
unsigned long r_tnpc;
unsigned int r_y;
unsigned int r_fprs;
};
#define FPU_REGS_TYPE unsigned int
#define FPU_FSR_TYPE unsigned long
struct fp_status {
unsigned long fpu_fr[32];
unsigned long Fpu_fsr;
};
struct fpu {
struct fp_status f_fpstatus;
};
#define fpu_regs f_fpstatus.fpu_fr
#define fpu_fsr f_fpstatus.Fpu_fsr
#endif /* __SPARC64_REG_H */

View File

@ -1,8 +1,96 @@
#ifndef ___ASM_SPARC_SIGCONTEXT_H #ifndef __SPARC_SIGCONTEXT_H
#define ___ASM_SPARC_SIGCONTEXT_H #define __SPARC_SIGCONTEXT_H
#if defined(__sparc__) && defined(__arch64__)
#include <asm/sigcontext_64.h> #ifdef __KERNEL__
#include <asm/ptrace.h>
#ifndef __ASSEMBLY__
#define __SUNOS_MAXWIN 31
/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
struct sigcontext32 {
int sigc_onstack; /* state to restore */
int sigc_mask; /* sigmask to restore */
int sigc_sp; /* stack pointer */
int sigc_pc; /* program counter */
int sigc_npc; /* next program counter */
int sigc_psr; /* for condition codes etc */
int sigc_g1; /* User uses these two registers */
int sigc_o0; /* within the trampoline code. */
/* Now comes information regarding the users window set
* at the time of the signal.
*/
int sigc_oswins; /* outstanding windows */
/* stack ptrs for each regwin buf */
unsigned sigc_spbuf[__SUNOS_MAXWIN];
/* Windows to restore after signal */
struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
};
/* This is what we use for 32bit new non-rt signals. */
typedef struct {
struct {
unsigned int psr;
unsigned int pc;
unsigned int npc;
unsigned int y;
unsigned int u_regs[16]; /* globals and ins */
} si_regs;
int si_mask;
} __siginfo32_t;
#ifdef CONFIG_SPARC64
typedef struct {
unsigned int si_float_regs [64];
unsigned long si_fsr;
unsigned long si_gsr;
unsigned long si_fprs;
} __siginfo_fpu_t;
/* This is what SunOS doesn't, so we have to write this alone
and do it properly. */
struct sigcontext {
/* The size of this array has to match SI_MAX_SIZE from siginfo.h */
char sigc_info[128];
struct {
unsigned long u_regs[16]; /* globals and ins */
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned int y;
unsigned int fprs;
} sigc_regs;
__siginfo_fpu_t * sigc_fpu_save;
struct {
void * ss_sp;
int ss_flags;
unsigned long ss_size;
} sigc_stack;
unsigned long sigc_mask;
};
#else #else
#include <asm/sigcontext_32.h>
#endif typedef struct {
#endif unsigned long si_float_regs [32];
unsigned long si_fsr;
unsigned long si_fpqdepth;
struct {
unsigned long *insn_addr;
unsigned long insn;
} si_fpqueue [16];
} __siginfo_fpu_t;
#endif /* (CONFIG_SPARC64) */
#endif /* !(__ASSEMBLY__) */
#endif /* (__KERNEL__) */
#endif /* !(__SPARC_SIGCONTEXT_H) */

View File

@ -1,62 +0,0 @@
#ifndef __SPARC_SIGCONTEXT_H
#define __SPARC_SIGCONTEXT_H
#ifdef __KERNEL__
#include <asm/ptrace.h>
#ifndef __ASSEMBLY__
#define __SUNOS_MAXWIN 31
/* This is what SunOS does, so shall I. */
struct sigcontext {
int sigc_onstack; /* state to restore */
int sigc_mask; /* sigmask to restore */
int sigc_sp; /* stack pointer */
int sigc_pc; /* program counter */
int sigc_npc; /* next program counter */
int sigc_psr; /* for condition codes etc */
int sigc_g1; /* User uses these two registers */
int sigc_o0; /* within the trampoline code. */
/* Now comes information regarding the users window set
* at the time of the signal.
*/
int sigc_oswins; /* outstanding windows */
/* stack ptrs for each regwin buf */
char *sigc_spbuf[__SUNOS_MAXWIN];
/* Windows to restore after signal */
struct {
unsigned long locals[8];
unsigned long ins[8];
} sigc_wbuf[__SUNOS_MAXWIN];
};
typedef struct {
struct {
unsigned long psr;
unsigned long pc;
unsigned long npc;
unsigned long y;
unsigned long u_regs[16]; /* globals and ins */
} si_regs;
int si_mask;
} __siginfo_t;
typedef struct {
unsigned long si_float_regs [32];
unsigned long si_fsr;
unsigned long si_fpqdepth;
struct {
unsigned long *insn_addr;
unsigned long insn;
} si_fpqueue [16];
} __siginfo_fpu_t;
#endif /* !(__ASSEMBLY__) */
#endif /* (__KERNEL__) */
#endif /* !(__SPARC_SIGCONTEXT_H) */

View File

@ -1,87 +0,0 @@
#ifndef __SPARC64_SIGCONTEXT_H
#define __SPARC64_SIGCONTEXT_H
#ifdef __KERNEL__
#include <asm/ptrace.h>
#endif
#ifndef __ASSEMBLY__
#ifdef __KERNEL__
#define __SUNOS_MAXWIN 31
/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
struct sigcontext32 {
int sigc_onstack; /* state to restore */
int sigc_mask; /* sigmask to restore */
int sigc_sp; /* stack pointer */
int sigc_pc; /* program counter */
int sigc_npc; /* next program counter */
int sigc_psr; /* for condition codes etc */
int sigc_g1; /* User uses these two registers */
int sigc_o0; /* within the trampoline code. */
/* Now comes information regarding the users window set
* at the time of the signal.
*/
int sigc_oswins; /* outstanding windows */
/* stack ptrs for each regwin buf */
unsigned sigc_spbuf[__SUNOS_MAXWIN];
/* Windows to restore after signal */
struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
};
#endif
#ifdef __KERNEL__
/* This is what we use for 32bit new non-rt signals. */
typedef struct {
struct {
unsigned int psr;
unsigned int pc;
unsigned int npc;
unsigned int y;
unsigned int u_regs[16]; /* globals and ins */
} si_regs;
int si_mask;
} __siginfo32_t;
#endif
typedef struct {
unsigned int si_float_regs [64];
unsigned long si_fsr;
unsigned long si_gsr;
unsigned long si_fprs;
} __siginfo_fpu_t;
/* This is what SunOS doesn't, so we have to write this alone
and do it properly. */
struct sigcontext {
/* The size of this array has to match SI_MAX_SIZE from siginfo.h */
char sigc_info[128];
struct {
unsigned long u_regs[16]; /* globals and ins */
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
unsigned int y;
unsigned int fprs;
} sigc_regs;
__siginfo_fpu_t * sigc_fpu_save;
struct {
void * ss_sp;
int ss_flags;
unsigned long ss_size;
} sigc_stack;
unsigned long sigc_mask;
};
#endif /* !(__ASSEMBLY__) */
#endif /* !(__SPARC64_SIGCONTEXT_H) */

View File

@ -1,8 +1,37 @@
#ifndef ___ASM_SPARC_SIGINFO_H #ifndef __SPARC_SIGINFO_H
#define ___ASM_SPARC_SIGINFO_H #define __SPARC_SIGINFO_H
#if defined(__sparc__) && defined(__arch64__) #if defined(__sparc__) && defined(__arch64__)
#include <asm/siginfo_64.h>
#else #define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
#include <asm/siginfo_32.h> #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
#endif #define __ARCH_SI_BAND_T int
#endif
#endif /* defined(__sparc__) && defined(__arch64__) */
#define __ARCH_SI_TRAPNO
#include <asm-generic/siginfo.h>
#ifdef __KERNEL__
#include <linux/compat.h>
#ifdef CONFIG_COMPAT
struct compat_siginfo;
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#define SI_NOINFO 32767 /* no information in siginfo_t */
/*
* SIGEMT si_codes
*/
#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
#define NSIGEMT 1
#endif /* !(__SPARC_SIGINFO_H) */

View File

@ -1,17 +0,0 @@
#ifndef _SPARC_SIGINFO_H
#define _SPARC_SIGINFO_H
#define __ARCH_SI_UID_T unsigned int
#define __ARCH_SI_TRAPNO
#include <asm-generic/siginfo.h>
#define SI_NOINFO 32767 /* no information in siginfo_t */
/*
* SIGEMT si_codes
*/
#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
#define NSIGEMT 1
#endif /* !(_SPARC_SIGINFO_H) */

View File

@ -1,32 +0,0 @@
#ifndef _SPARC64_SIGINFO_H
#define _SPARC64_SIGINFO_H
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
#define __ARCH_SI_TRAPNO
#define __ARCH_SI_BAND_T int
#include <asm-generic/siginfo.h>
#ifdef __KERNEL__
#include <linux/compat.h>
#ifdef CONFIG_COMPAT
struct compat_siginfo;
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#define SI_NOINFO 32767 /* no information in siginfo_t */
/*
* SIGEMT si_codes
*/
#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
#define NSIGEMT 1
#endif

View File

@ -1,8 +1,210 @@
#ifndef ___ASM_SPARC_SIGNAL_H #ifndef __SPARC_SIGNAL_H
#define ___ASM_SPARC_SIGNAL_H #define __SPARC_SIGNAL_H
#if defined(__sparc__) && defined(__arch64__)
#include <asm/signal_64.h> #include <asm/sigcontext.h>
#include <linux/compiler.h>
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <linux/personality.h>
#include <linux/types.h>
#endif
#endif
/* On the Sparc the signal handlers get passed a 'sub-signal' code
* for certain signal types, which we document here.
*/
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SUBSIG_STACK 0
#define SUBSIG_ILLINST 2
#define SUBSIG_PRIVINST 3
#define SUBSIG_BADTRAP(t) (0x80 + (t))
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGEMT 7
#define SUBSIG_TAG 10
#define SIGFPE 8
#define SUBSIG_FPDISABLED 0x400
#define SUBSIG_FPERROR 0x404
#define SUBSIG_FPINTOVFL 0x001
#define SUBSIG_FPSTSIG 0x002
#define SUBSIG_IDIVZERO 0x014
#define SUBSIG_FPINEXACT 0x0c4
#define SUBSIG_FPDIVZERO 0x0c8
#define SUBSIG_FPUNFLOW 0x0cc
#define SUBSIG_FPOPERROR 0x0d0
#define SUBSIG_FPOVFLOW 0x0d4
#define SIGKILL 9
#define SIGBUS 10
#define SUBSIG_BUSTIMEOUT 1
#define SUBSIG_ALIGNMENT 2
#define SUBSIG_MISCERROR 5
#define SIGSEGV 11
#define SUBSIG_NOMAPPING 3
#define SUBSIG_PROTECTION 4
#define SUBSIG_SEGERROR 5
#define SIGSYS 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGURG 16
/* SunOS values which deviate from the Linux/i386 ones */
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGIO 23
#define SIGPOLL SIGIO /* SysV name for SIGIO */
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGLOST 29
#define SIGPWR SIGLOST
#define SIGUSR1 30
#define SIGUSR2 31
/* Most things should be clean enough to redefine this at will, if care
is taken to make libc match. */
#define __OLD_NSIG 32
#define __NEW_NSIG 64
#define _NSIG_BPW 64
#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
#define SIGRTMIN 32
#define SIGRTMAX __NEW_NSIG
#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
#define _NSIG __NEW_NSIG
#define __new_sigset_t sigset_t
#define __new_sigaction sigaction
#define __new_sigaction32 sigaction32
#define __old_sigset_t old_sigset_t
#define __old_sigaction old_sigaction
#define __old_sigaction32 old_sigaction32
#else #else
#include <asm/signal_32.h> #define _NSIG __OLD_NSIG
#define NSIG _NSIG
#define __old_sigset_t sigset_t
#define __old_sigaction sigaction
#define __old_sigaction32 sigaction32
#endif #endif
#ifndef __ASSEMBLY__
typedef unsigned long __old_sigset_t; /* at least 32 bits */
typedef struct {
unsigned long sig[_NSIG_WORDS];
} __new_sigset_t;
/* A SunOS sigstack */
struct sigstack {
/* XXX 32-bit pointers pinhead XXX */
char *the_stack;
int cur_status;
};
/* Sigvec flags */
#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
#define _SV_INTR 2u /* Sig return should not restart system call */
#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
/*
* sa_flags values: SA_STACK is not currently supported, but will allow the
* usage of signal stacks by using the (now obsolete) sa_restorer field in
* the sigaction structure as a stack pointer. This is now possible due to
* the changes in signal handling. LBT 010493.
* SA_RESTART flag to get restarting signals (which were the default long ago)
*/
#define SA_NOCLDSTOP _SV_IGNCHILD
#define SA_STACK _SV_SSTACK
#define SA_ONSTACK _SV_SSTACK
#define SA_RESTART _SV_INTR
#define SA_ONESHOT _SV_RESET
#define SA_NOMASK 0x20u
#define SA_NOCLDWAIT 0x100u
#define SA_SIGINFO 0x200u
#define SIG_BLOCK 0x01 /* for blocking signals */
#define SIG_UNBLOCK 0x02 /* for unblocking signals */
#define SIG_SETMASK 0x04 /* for setting the signal mask */
/*
* sigaltstack controls
*/
#define SS_ONSTACK 1
#define SS_DISABLE 2
#define MINSIGSTKSZ 4096
#define SIGSTKSZ 16384
#ifdef __KERNEL__
/*
* DJHR
* SA_STATIC_ALLOC is used for the sparc32 system to indicate that this
* interrupt handler's irq structure should be statically allocated
* by the request_irq routine.
* The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
* of interrupt usage and that sucks. Also without a flag like this
* it may be possible for the free_irq routine to attempt to free
* statically allocated data.. which is NOT GOOD.
*
*/
#define SA_STATIC_ALLOC 0x8000
#endif #endif
#include <asm-generic/signal.h>
struct __new_sigaction {
__sighandler_t sa_handler;
unsigned long sa_flags;
__sigrestore_t sa_restorer; /* not used by Linux/SPARC yet */
__new_sigset_t sa_mask;
};
struct __old_sigaction {
__sighandler_t sa_handler;
__old_sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void); /* not used by Linux/SPARC yet */
};
typedef struct sigaltstack {
void __user *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
#ifdef __KERNEL__
struct k_sigaction {
struct __new_sigaction sa;
void __user *ka_restorer;
};
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* !(__KERNEL__) */
#endif /* !(__ASSEMBLY__) */
#endif /* !(__SPARC_SIGNAL_H) */

View File

@ -1,207 +0,0 @@
#ifndef _ASMSPARC_SIGNAL_H
#define _ASMSPARC_SIGNAL_H
#include <asm/sigcontext.h>
#include <linux/compiler.h>
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <linux/personality.h>
#include <linux/types.h>
#endif
#endif
/* On the Sparc the signal handlers get passed a 'sub-signal' code
* for certain signal types, which we document here.
*/
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SUBSIG_STACK 0
#define SUBSIG_ILLINST 2
#define SUBSIG_PRIVINST 3
#define SUBSIG_BADTRAP(t) (0x80 + (t))
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGEMT 7
#define SUBSIG_TAG 10
#define SIGFPE 8
#define SUBSIG_FPDISABLED 0x400
#define SUBSIG_FPERROR 0x404
#define SUBSIG_FPINTOVFL 0x001
#define SUBSIG_FPSTSIG 0x002
#define SUBSIG_IDIVZERO 0x014
#define SUBSIG_FPINEXACT 0x0c4
#define SUBSIG_FPDIVZERO 0x0c8
#define SUBSIG_FPUNFLOW 0x0cc
#define SUBSIG_FPOPERROR 0x0d0
#define SUBSIG_FPOVFLOW 0x0d4
#define SIGKILL 9
#define SIGBUS 10
#define SUBSIG_BUSTIMEOUT 1
#define SUBSIG_ALIGNMENT 2
#define SUBSIG_MISCERROR 5
#define SIGSEGV 11
#define SUBSIG_NOMAPPING 3
#define SUBSIG_PROTECTION 4
#define SUBSIG_SEGERROR 5
#define SIGSYS 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGURG 16
/* SunOS values which deviate from the Linux/i386 ones */
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGIO 23
#define SIGPOLL SIGIO /* SysV name for SIGIO */
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGLOST 29
#define SIGPWR SIGLOST
#define SIGUSR1 30
#define SIGUSR2 31
/* Most things should be clean enough to redefine this at will, if care
* is taken to make libc match.
*/
#define __OLD_NSIG 32
#define __NEW_NSIG 64
#define _NSIG_BPW 32
#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
#define SIGRTMIN 32
#define SIGRTMAX __NEW_NSIG
#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
#define _NSIG __NEW_NSIG
#define __new_sigset_t sigset_t
#define __new_sigaction sigaction
#define __old_sigset_t old_sigset_t
#define __old_sigaction old_sigaction
#else
#define _NSIG __OLD_NSIG
#define __old_sigset_t sigset_t
#define __old_sigaction sigaction
#endif
#ifndef __ASSEMBLY__
typedef unsigned long __old_sigset_t;
typedef struct {
unsigned long sig[_NSIG_WORDS];
} __new_sigset_t;
#ifdef __KERNEL__
/* A SunOS sigstack */
struct sigstack {
char *the_stack;
int cur_status;
};
#endif
/* Sigvec flags */
#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
#define _SV_INTR 2u /* Sig return should not restart system call */
#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
/*
* sa_flags values: SA_STACK is not currently supported, but will allow the
* usage of signal stacks by using the (now obsolete) sa_restorer field in
* the sigaction structure as a stack pointer. This is now possible due to
* the changes in signal handling. LBT 010493.
* SA_RESTART flag to get restarting signals (which were the default long ago)
*/
#define SA_NOCLDSTOP _SV_IGNCHILD
#define SA_STACK _SV_SSTACK
#define SA_ONSTACK _SV_SSTACK
#define SA_RESTART _SV_INTR
#define SA_ONESHOT _SV_RESET
#define SA_NOMASK 0x20u
#define SA_NOCLDWAIT 0x100u
#define SA_SIGINFO 0x200u
#define SIG_BLOCK 0x01 /* for blocking signals */
#define SIG_UNBLOCK 0x02 /* for unblocking signals */
#define SIG_SETMASK 0x04 /* for setting the signal mask */
/*
* sigaltstack controls
*/
#define SS_ONSTACK 1
#define SS_DISABLE 2
#define MINSIGSTKSZ 4096
#define SIGSTKSZ 16384
#ifdef __KERNEL__
/*
* DJHR
* SA_STATIC_ALLOC is used for the SPARC system to indicate that this
* interrupt handler's irq structure should be statically allocated
* by the request_irq routine.
* The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
* of interrupt usage and that sucks. Also without a flag like this
* it may be possible for the free_irq routine to attempt to free
* statically allocated data.. which is NOT GOOD.
*
*/
#define SA_STATIC_ALLOC 0x8000
#endif
#include <asm-generic/signal.h>
#ifdef __KERNEL__
struct __new_sigaction {
__sighandler_t sa_handler;
unsigned long sa_flags;
void (*sa_restorer)(void); /* Not used by Linux/SPARC */
__new_sigset_t sa_mask;
};
struct k_sigaction {
struct __new_sigaction sa;
void __user *ka_restorer;
};
struct __old_sigaction {
__sighandler_t sa_handler;
__old_sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer) (void); /* not used by Linux/SPARC */
};
typedef struct sigaltstack {
void __user *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* !(__KERNEL__) */
#endif /* !(__ASSEMBLY__) */
#endif /* !(_ASMSPARC_SIGNAL_H) */

View File

@ -1,194 +0,0 @@
#ifndef _ASMSPARC64_SIGNAL_H
#define _ASMSPARC64_SIGNAL_H
#include <asm/sigcontext.h>
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <linux/personality.h>
#include <linux/types.h>
#endif
#endif
/* On the Sparc the signal handlers get passed a 'sub-signal' code
* for certain signal types, which we document here.
*/
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SUBSIG_STACK 0
#define SUBSIG_ILLINST 2
#define SUBSIG_PRIVINST 3
#define SUBSIG_BADTRAP(t) (0x80 + (t))
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGEMT 7
#define SUBSIG_TAG 10
#define SIGFPE 8
#define SUBSIG_FPDISABLED 0x400
#define SUBSIG_FPERROR 0x404
#define SUBSIG_FPINTOVFL 0x001
#define SUBSIG_FPSTSIG 0x002
#define SUBSIG_IDIVZERO 0x014
#define SUBSIG_FPINEXACT 0x0c4
#define SUBSIG_FPDIVZERO 0x0c8
#define SUBSIG_FPUNFLOW 0x0cc
#define SUBSIG_FPOPERROR 0x0d0
#define SUBSIG_FPOVFLOW 0x0d4
#define SIGKILL 9
#define SIGBUS 10
#define SUBSIG_BUSTIMEOUT 1
#define SUBSIG_ALIGNMENT 2
#define SUBSIG_MISCERROR 5
#define SIGSEGV 11
#define SUBSIG_NOMAPPING 3
#define SUBSIG_PROTECTION 4
#define SUBSIG_SEGERROR 5
#define SIGSYS 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGURG 16
/* SunOS values which deviate from the Linux/i386 ones */
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGIO 23
#define SIGPOLL SIGIO /* SysV name for SIGIO */
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGLOST 29
#define SIGPWR SIGLOST
#define SIGUSR1 30
#define SIGUSR2 31
/* Most things should be clean enough to redefine this at will, if care
is taken to make libc match. */
#define __OLD_NSIG 32
#define __NEW_NSIG 64
#define _NSIG_BPW 64
#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
#define SIGRTMIN 32
#define SIGRTMAX __NEW_NSIG
#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
#define _NSIG __NEW_NSIG
#define __new_sigset_t sigset_t
#define __new_sigaction sigaction
#define __new_sigaction32 sigaction32
#define __old_sigset_t old_sigset_t
#define __old_sigaction old_sigaction
#define __old_sigaction32 old_sigaction32
#else
#define _NSIG __OLD_NSIG
#define NSIG _NSIG
#define __old_sigset_t sigset_t
#define __old_sigaction sigaction
#define __old_sigaction32 sigaction32
#endif
#ifndef __ASSEMBLY__
typedef unsigned long __old_sigset_t; /* at least 32 bits */
typedef struct {
unsigned long sig[_NSIG_WORDS];
} __new_sigset_t;
/* A SunOS sigstack */
struct sigstack {
/* XXX 32-bit pointers pinhead XXX */
char *the_stack;
int cur_status;
};
/* Sigvec flags */
#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
#define _SV_INTR 2u /* Sig return should not restart system call */
#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
/*
* sa_flags values: SA_STACK is not currently supported, but will allow the
* usage of signal stacks by using the (now obsolete) sa_restorer field in
* the sigaction structure as a stack pointer. This is now possible due to
* the changes in signal handling. LBT 010493.
* SA_RESTART flag to get restarting signals (which were the default long ago)
*/
#define SA_NOCLDSTOP _SV_IGNCHILD
#define SA_STACK _SV_SSTACK
#define SA_ONSTACK _SV_SSTACK
#define SA_RESTART _SV_INTR
#define SA_ONESHOT _SV_RESET
#define SA_NOMASK 0x20u
#define SA_NOCLDWAIT 0x100u
#define SA_SIGINFO 0x200u
#define SIG_BLOCK 0x01 /* for blocking signals */
#define SIG_UNBLOCK 0x02 /* for unblocking signals */
#define SIG_SETMASK 0x04 /* for setting the signal mask */
/*
* sigaltstack controls
*/
#define SS_ONSTACK 1
#define SS_DISABLE 2
#define MINSIGSTKSZ 4096
#define SIGSTKSZ 16384
#include <asm-generic/signal.h>
struct __new_sigaction {
__sighandler_t sa_handler;
unsigned long sa_flags;
__sigrestore_t sa_restorer; /* not used by Linux/SPARC yet */
__new_sigset_t sa_mask;
};
struct __old_sigaction {
__sighandler_t sa_handler;
__old_sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void); /* not used by Linux/SPARC yet */
};
typedef struct sigaltstack {
void __user *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
#ifdef __KERNEL__
struct k_sigaction {
struct __new_sigaction sa;
void __user *ka_restorer;
};
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* !(__KERNEL__) */
#endif /* !(__ASSEMBLY__) */
#endif /* !(_ASMSPARC64_SIGNAL_H) */

View File

@ -170,7 +170,4 @@ void smp_setup_cpu_possible_map(void);
#define smp_setup_cpu_possible_map() do { } while (0) #define smp_setup_cpu_possible_map() do { } while (0)
#endif /* !(SMP) */ #endif /* !(SMP) */
#define NO_PROC_ID 0xFF
#endif /* !(_SPARC_SMP_H) */ #endif /* !(_SPARC_SMP_H) */

View File

@ -1,8 +1,107 @@
#ifndef ___ASM_SPARC_STAT_H #ifndef __SPARC_STAT_H
#define ___ASM_SPARC_STAT_H #define __SPARC_STAT_H
#include <linux/types.h>
#if defined(__sparc__) && defined(__arch64__) #if defined(__sparc__) && defined(__arch64__)
#include <asm/stat_64.h> /* 64 bit sparc */
struct stat {
unsigned st_dev;
ino_t st_ino;
mode_t st_mode;
short st_nlink;
uid_t st_uid;
gid_t st_gid;
unsigned st_rdev;
off_t st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
off_t st_blksize;
off_t st_blocks;
unsigned long __unused4[2];
};
struct stat64 {
unsigned long st_dev;
unsigned long st_ino;
unsigned long st_nlink;
unsigned int st_mode;
unsigned int st_uid;
unsigned int st_gid;
unsigned int __pad0;
unsigned long st_rdev;
long st_size;
long st_blksize;
long st_blocks;
unsigned long st_atime;
unsigned long st_atime_nsec;
unsigned long st_mtime;
unsigned long st_mtime_nsec;
unsigned long st_ctime;
unsigned long st_ctime_nsec;
long __unused[3];
};
#else #else
#include <asm/stat_32.h> /* 32 bit sparc */
#endif struct stat {
#endif unsigned short st_dev;
ino_t st_ino;
mode_t st_mode;
short st_nlink;
uid_t st_uid;
gid_t st_gid;
unsigned short st_rdev;
off_t st_size;
time_t st_atime;
unsigned long st_atime_nsec;
time_t st_mtime;
unsigned long st_mtime_nsec;
time_t st_ctime;
unsigned long st_ctime_nsec;
off_t st_blksize;
off_t st_blocks;
unsigned long __unused4[2];
};
#define STAT_HAVE_NSEC 1
struct stat64 {
unsigned long long st_dev;
unsigned long long st_ino;
unsigned int st_mode;
unsigned int st_nlink;
unsigned int st_uid;
unsigned int st_gid;
unsigned long long st_rdev;
unsigned char __pad3[8];
long long st_size;
unsigned int st_blksize;
unsigned char __pad4[8];
unsigned int st_blocks;
unsigned int st_atime;
unsigned int st_atime_nsec;
unsigned int st_mtime;
unsigned int st_mtime_nsec;
unsigned int st_ctime;
unsigned int st_ctime_nsec;
unsigned int __unused4;
unsigned int __unused5;
};
#endif /* defined(__sparc__) && defined(__arch64__) */
#endif /* __SPARC_STAT_H */

View File

@ -1,76 +0,0 @@
#ifndef _SPARC_STAT_H
#define _SPARC_STAT_H
#include <linux/types.h>
struct __old_kernel_stat {
unsigned short st_dev;
unsigned short st_ino;
unsigned short st_mode;
unsigned short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
unsigned long st_size;
unsigned long st_atime;
unsigned long st_mtime;
unsigned long st_ctime;
};
struct stat {
unsigned short st_dev;
unsigned long st_ino;
unsigned short st_mode;
short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
long st_size;
long st_atime;
unsigned long st_atime_nsec;
long st_mtime;
unsigned long st_mtime_nsec;
long st_ctime;
unsigned long st_ctime_nsec;
long st_blksize;
long st_blocks;
unsigned long __unused4[2];
};
#define STAT_HAVE_NSEC 1
struct stat64 {
unsigned long long st_dev;
unsigned long long st_ino;
unsigned int st_mode;
unsigned int st_nlink;
unsigned int st_uid;
unsigned int st_gid;
unsigned long long st_rdev;
unsigned char __pad3[8];
long long st_size;
unsigned int st_blksize;
unsigned char __pad4[8];
unsigned int st_blocks;
unsigned int st_atime;
unsigned int st_atime_nsec;
unsigned int st_mtime;
unsigned int st_mtime_nsec;
unsigned int st_ctime;
unsigned int st_ctime_nsec;
unsigned int __unused4;
unsigned int __unused5;
};
#endif

View File

@ -1,47 +0,0 @@
#ifndef _SPARC64_STAT_H
#define _SPARC64_STAT_H
#include <linux/types.h>
struct stat {
unsigned st_dev;
ino_t st_ino;
mode_t st_mode;
short st_nlink;
uid_t st_uid;
gid_t st_gid;
unsigned st_rdev;
off_t st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
off_t st_blksize;
off_t st_blocks;
unsigned long __unused4[2];
};
struct stat64 {
unsigned long st_dev;
unsigned long st_ino;
unsigned long st_nlink;
unsigned int st_mode;
unsigned int st_uid;
unsigned int st_gid;
unsigned int __pad0;
unsigned long st_rdev;
long st_size;
long st_blksize;
long st_blocks;
unsigned long st_atime;
unsigned long st_atime_nsec;
unsigned long st_mtime;
unsigned long st_mtime_nsec;
unsigned long st_ctime;
unsigned long st_ctime_nsec;
long __unused[3];
};
#endif

View File

@ -45,7 +45,7 @@ struct thread_info {
/* A place to store user windows and stack pointers /* A place to store user windows and stack pointers
* when the stack needs inspection. * when the stack needs inspection.
*/ */
struct reg_window reg_window[NSWINS]; /* align for ldd! */ struct reg_window32 reg_window[NSWINS]; /* align for ldd! */
unsigned long rwbuf_stkptrs[NSWINS]; unsigned long rwbuf_stkptrs[NSWINS];
unsigned long w_saved; unsigned long w_saved;

View File

@ -10,7 +10,7 @@
#define NUM_SPARC_TRAPS 255 #define NUM_SPARC_TRAPS 255
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef __KERNEL__
/* This is for V8 compliant Sparc CPUS */ /* This is for V8 compliant Sparc CPUS */
struct tt_entry { struct tt_entry {
unsigned long inst_one; unsigned long inst_one;
@ -22,14 +22,7 @@ struct tt_entry {
/* We set this to _start in system setup. */ /* We set this to _start in system setup. */
extern struct tt_entry *sparc_ttable; extern struct tt_entry *sparc_ttable;
static inline unsigned long get_tbr(void) #endif /* (__KERNEL__) */
{
unsigned long tbr;
__asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (tbr));
return tbr;
}
#endif /* !(__ASSEMBLY__) */ #endif /* !(__ASSEMBLY__) */
/* For patching the trap table at boot time, we need to know how to /* For patching the trap table at boot time, we need to know how to

View File

@ -669,7 +669,9 @@ void __init init_IRQ(void)
btfixup(); btfixup();
} }
#ifdef CONFIG_PROC_FS
void init_irq_proc(void) void init_irq_proc(void)
{ {
/* For now, nothing... */ /* For now, nothing... */
} }
#endif /* CONFIG_PROC_FS */

View File

@ -14,14 +14,14 @@ extern unsigned long trapbase;
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{ {
struct reg_window *win; struct reg_window32 *win;
int i; int i;
gdb_regs[GDB_G0] = 0; gdb_regs[GDB_G0] = 0;
for (i = 0; i < 15; i++) for (i = 0; i < 15; i++)
gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i]; gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
win = (struct reg_window *) regs->u_regs[UREG_FP]; win = (struct reg_window32 *) regs->u_regs[UREG_FP];
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
gdb_regs[GDB_L0 + i] = win->locals[i]; gdb_regs[GDB_L0 + i] = win->locals[i];
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
@ -43,7 +43,7 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{ {
struct thread_info *t = task_thread_info(p); struct thread_info *t = task_thread_info(p);
struct reg_window *win; struct reg_window32 *win;
int i; int i;
for (i = GDB_G0; i < GDB_G6; i++) for (i = GDB_G0; i < GDB_G6; i++)
@ -55,7 +55,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
gdb_regs[GDB_SP] = t->ksp; gdb_regs[GDB_SP] = t->ksp;
gdb_regs[GDB_O7] = 0; gdb_regs[GDB_O7] = 0;
win = (struct reg_window *) t->ksp; win = (struct reg_window32 *) t->ksp;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
gdb_regs[GDB_L0 + i] = win->locals[i]; gdb_regs[GDB_L0 + i] = win->locals[i];
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
@ -77,7 +77,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{ {
struct reg_window *win; struct reg_window32 *win;
int i; int i;
for (i = 0; i < 15; i++) for (i = 0; i < 15; i++)
@ -96,7 +96,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
regs->npc = gdb_regs[GDB_NPC]; regs->npc = gdb_regs[GDB_NPC];
regs->y = gdb_regs[GDB_Y]; regs->y = gdb_regs[GDB_Y];
win = (struct reg_window *) regs->u_regs[UREG_FP]; win = (struct reg_window32 *) regs->u_regs[UREG_FP];
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
win->locals[i] = gdb_regs[GDB_L0 + i]; win->locals[i] = gdb_regs[GDB_L0 + i];
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)

View File

@ -60,7 +60,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
} }
#define fetch_reg(reg, regs) ({ \ #define fetch_reg(reg, regs) ({ \
struct reg_window __user *win; \ struct reg_window32 __user *win; \
register unsigned long ret; \ register unsigned long ret; \
\ \
if (!(reg)) ret = 0; \ if (!(reg)) ret = 0; \
@ -68,7 +68,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
ret = regs->u_regs[(reg)]; \ ret = regs->u_regs[(reg)]; \
} else { \ } else { \
/* Ho hum, the slightly complicated case. */ \ /* Ho hum, the slightly complicated case. */ \
win = (struct reg_window __user *)regs->u_regs[UREG_FP];\ win = (struct reg_window32 __user *)regs->u_regs[UREG_FP];\
if (get_user (ret, &win->locals[(reg) - 16])) return -1;\ if (get_user (ret, &win->locals[(reg) - 16])) return -1;\
} \ } \
ret; \ ret; \
@ -77,7 +77,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
static inline int static inline int
store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs) store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
{ {
struct reg_window __user *win; struct reg_window32 __user *win;
if (!reg) if (!reg)
return 0; return 0;
@ -86,7 +86,7 @@ store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
return 0; return 0;
} else { } else {
/* need to use put_user() in this case: */ /* need to use put_user() in this case: */
win = (struct reg_window __user *) regs->u_regs[UREG_FP]; win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
return (put_user(result, &win->locals[reg - 16])); return (put_user(result, &win->locals[reg - 16]));
} }
} }

View File

@ -307,10 +307,7 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm)
/* We really mean to ignore the return result here. Two /* We really mean to ignore the return result here. Two
* PCI controller share the same interrupt numbers and * PCI controller share the same interrupt numbers and
* drive the same front-end hardware. Whichever of the * drive the same front-end hardware.
* two get in here first will register the IRQ handler
* the second will just error out since we do not pass in
* IRQF_SHARED.
*/ */
err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED,
"PSYCHO_UE", pbm); "PSYCHO_UE", pbm);

View File

@ -180,13 +180,13 @@ static DEFINE_SPINLOCK(sparc_backtrace_lock);
void __show_backtrace(unsigned long fp) void __show_backtrace(unsigned long fp)
{ {
struct reg_window *rw; struct reg_window32 *rw;
unsigned long flags; unsigned long flags;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
spin_lock_irqsave(&sparc_backtrace_lock, flags); spin_lock_irqsave(&sparc_backtrace_lock, flags);
rw = (struct reg_window *)fp; rw = (struct reg_window32 *)fp;
while(rw && (((unsigned long) rw) >= PAGE_OFFSET) && while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
!(((unsigned long) rw) & 0x7)) { !(((unsigned long) rw) & 0x7)) {
printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] " printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
@ -196,7 +196,7 @@ void __show_backtrace(unsigned long fp)
rw->ins[6], rw->ins[6],
rw->ins[7]); rw->ins[7]);
printk("%pS\n", (void *) rw->ins[7]); printk("%pS\n", (void *) rw->ins[7]);
rw = (struct reg_window *) rw->ins[6]; rw = (struct reg_window32 *) rw->ins[6];
} }
spin_unlock_irqrestore(&sparc_backtrace_lock, flags); spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
} }
@ -258,7 +258,7 @@ void show_stackframe(struct sparc_stackf *sf)
void show_regs(struct pt_regs *r) void show_regs(struct pt_regs *r)
{ {
struct reg_window *rw = (struct reg_window *) r->u_regs[14]; struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14];
printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n", printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n",
r->psr, r->pc, r->npc, r->y, print_tainted()); r->psr, r->pc, r->npc, r->y, print_tainted());
@ -287,7 +287,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
{ {
unsigned long pc, fp; unsigned long pc, fp;
unsigned long task_base; unsigned long task_base;
struct reg_window *rw; struct reg_window32 *rw;
int count = 0; int count = 0;
if (tsk != NULL) if (tsk != NULL)
@ -301,7 +301,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
if (fp < (task_base + sizeof(struct thread_info)) || if (fp < (task_base + sizeof(struct thread_info)) ||
fp >= (task_base + (PAGE_SIZE << 1))) fp >= (task_base + (PAGE_SIZE << 1)))
break; break;
rw = (struct reg_window *) fp; rw = (struct reg_window32 *) fp;
pc = rw->ins[7]; pc = rw->ins[7];
printk("[%08lx : ", pc); printk("[%08lx : ", pc);
printk("%pS ] ", (void *) pc); printk("%pS ] ", (void *) pc);
@ -679,7 +679,7 @@ unsigned long get_wchan(struct task_struct *task)
unsigned long pc, fp, bias = 0; unsigned long pc, fp, bias = 0;
unsigned long task_base = (unsigned long) task; unsigned long task_base = (unsigned long) task;
unsigned long ret = 0; unsigned long ret = 0;
struct reg_window *rw; struct reg_window32 *rw;
int count = 0; int count = 0;
if (!task || task == current || if (!task || task == current ||
@ -692,7 +692,7 @@ unsigned long get_wchan(struct task_struct *task)
if (fp < (task_base + sizeof(struct thread_info)) || if (fp < (task_base + sizeof(struct thread_info)) ||
fp >= (task_base + (2 * PAGE_SIZE))) fp >= (task_base + (2 * PAGE_SIZE)))
break; break;
rw = (struct reg_window *) fp; rw = (struct reg_window32 *) fp;
pc = rw->ins[7]; pc = rw->ins[7];
if (!in_sched_functions(pc)) { if (!in_sched_functions(pc)) {
ret = pc; ret = pc;

View File

@ -155,20 +155,12 @@ static struct property * __init build_one_prop(phandle node, char *prev,
p->value = prom_early_alloc(special_len); p->value = prom_early_alloc(special_len);
memcpy(p->value, special_val, special_len); memcpy(p->value, special_val, special_len);
} else { } else {
#ifdef CONFIG_SPARC32
if (prev == NULL) { if (prev == NULL) {
name = prom_firstprop(node, NULL); name = prom_firstprop(node, p->name);
} else { } else {
name = prom_nextprop(node, prev, NULL); name = prom_nextprop(node, prev, p->name);
} }
#else
if (prev == NULL) {
prom_firstprop(node, p->name);
} else {
prom_nextprop(node, prev, p->name);
}
name = p->name;
#endif
if (strlen(name) == 0) { if (strlen(name) == 0) {
tmp = p; tmp = p;
return NULL; return NULL;

View File

@ -34,7 +34,7 @@ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
struct signal_frame { struct signal_frame {
struct sparc_stackf ss; struct sparc_stackf ss;
__siginfo_t info; __siginfo32_t info;
__siginfo_fpu_t __user *fpu_save; __siginfo_fpu_t __user *fpu_save;
unsigned long insns[2] __attribute__ ((aligned (8))); unsigned long insns[2] __attribute__ ((aligned (8)));
unsigned int extramask[_NSIG_WORDS - 1]; unsigned int extramask[_NSIG_WORDS - 1];
@ -351,7 +351,7 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __copy_to_user(sf->extramask, &oldset->sig[1], err |= __copy_to_user(sf->extramask, &oldset->sig[1],
(_NSIG_WORDS - 1) * sizeof(unsigned int)); (_NSIG_WORDS - 1) * sizeof(unsigned int));
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
sizeof(struct reg_window)); sizeof(struct reg_window32));
if (err) if (err)
goto sigsegv; goto sigsegv;
@ -433,7 +433,7 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
sizeof(struct reg_window)); sizeof(struct reg_window32));
err |= copy_siginfo_to_user(&sf->info, info); err |= copy_siginfo_to_user(&sf->info, info);

View File

@ -67,7 +67,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
__RESTORE; __RESTORE; __RESTORE; __RESTORE; __RESTORE; __RESTORE; __RESTORE; __RESTORE;
{ {
struct reg_window *rw = (struct reg_window *)regs->u_regs[UREG_FP]; struct reg_window32 *rw = (struct reg_window32 *)regs->u_regs[UREG_FP];
/* Stop the back trace when we hit userland or we /* Stop the back trace when we hit userland or we
* find some badly aligned kernel stack. Set an upper * find some badly aligned kernel stack. Set an upper
@ -79,7 +79,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
!(((unsigned long) rw) & 0x7)) { !(((unsigned long) rw) & 0x7)) {
printk("Caller[%08lx]: %pS\n", rw->ins[7], printk("Caller[%08lx]: %pS\n", rw->ins[7],
(void *) rw->ins[7]); (void *) rw->ins[7]);
rw = (struct reg_window *)rw->ins[6]; rw = (struct reg_window32 *)rw->ins[6];
} }
} }
printk("Instruction DUMP:"); printk("Instruction DUMP:");

View File

@ -97,26 +97,26 @@ static inline int sign_extend_imm13(int imm)
static inline unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) static inline unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
{ {
struct reg_window *win; struct reg_window32 *win;
if(reg < 16) if(reg < 16)
return (!reg ? 0 : regs->u_regs[reg]); return (!reg ? 0 : regs->u_regs[reg]);
/* Ho hum, the slightly complicated case. */ /* Ho hum, the slightly complicated case. */
win = (struct reg_window *) regs->u_regs[UREG_FP]; win = (struct reg_window32 *) regs->u_regs[UREG_FP];
return win->locals[reg - 16]; /* yes, I know what this does... */ return win->locals[reg - 16]; /* yes, I know what this does... */
} }
static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *regs) static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *regs)
{ {
struct reg_window __user *win; struct reg_window32 __user *win;
unsigned long ret; unsigned long ret;
if (reg < 16) if (reg < 16)
return (!reg ? 0 : regs->u_regs[reg]); return (!reg ? 0 : regs->u_regs[reg]);
/* Ho hum, the slightly complicated case. */ /* Ho hum, the slightly complicated case. */
win = (struct reg_window __user *) regs->u_regs[UREG_FP]; win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
if ((unsigned long)win & 3) if ((unsigned long)win & 3)
return -1; return -1;
@ -129,11 +129,11 @@ static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *reg
static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
{ {
struct reg_window *win; struct reg_window32 *win;
if(reg < 16) if(reg < 16)
return &regs->u_regs[reg]; return &regs->u_regs[reg];
win = (struct reg_window *) regs->u_regs[UREG_FP]; win = (struct reg_window32 *) regs->u_regs[UREG_FP];
return &win->locals[reg - 16]; return &win->locals[reg - 16];
} }

View File

@ -42,7 +42,7 @@ static inline void shift_window_buffer(int first_win, int last_win, struct threa
for(i = first_win; i < last_win; i++) { for(i = first_win; i < last_win; i++) {
tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1]; tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1];
memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window)); memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window32));
} }
} }
@ -70,7 +70,7 @@ void synchronize_user_stack(void)
/* Ok, let it rip. */ /* Ok, let it rip. */
if (copy_to_user((char __user *) sp, &tp->reg_window[window], if (copy_to_user((char __user *) sp, &tp->reg_window[window],
sizeof(struct reg_window))) sizeof(struct reg_window32)))
continue; continue;
shift_window_buffer(window, tp->w_saved - 1, tp); shift_window_buffer(window, tp->w_saved - 1, tp);
@ -119,7 +119,7 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)
if ((sp & 7) || if ((sp & 7) ||
copy_to_user((char __user *) sp, &tp->reg_window[window], copy_to_user((char __user *) sp, &tp->reg_window[window],
sizeof(struct reg_window))) sizeof(struct reg_window32)))
do_exit(SIGILL); do_exit(SIGILL);
} }
tp->w_saved = 0; tp->w_saved = 0;

View File

@ -22,10 +22,11 @@ MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/shared/skas
include $(srctree)/$(ARCH_DIR)/Makefile-skas include $(srctree)/$(ARCH_DIR)/Makefile-skas
ARCH_INCLUDE := -I$(srctree)/$(ARCH_DIR)/include/shared SHARED_HEADERS := $(ARCH_DIR)/include/shared
ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS)
ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared
ifneq ($(KBUILD_SRC),) ifneq ($(KBUILD_SRC),)
ARCH_INCLUDE += -I$(ARCH_DIR)/include/shared # for two generated files ARCH_INCLUDE += -I$(SHARED_HEADERS)
endif endif
KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH) KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
@ -85,8 +86,8 @@ endef
KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH) KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
archprepare: $(ARCH_DIR)/include/shared/user_constants.h archprepare: $(SHARED_HEADERS)/user_constants.h
prepare: $(ARCH_DIR)/include/shared/kern_constants.h archprepare: $(SHARED_HEADERS)/kern_constants.h
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@ -119,17 +120,13 @@ endef
# When cleaning we don't include .config, so we don't include # When cleaning we don't include .config, so we don't include
# TT or skas makefiles and don't clean skas_ptregs.h. # TT or skas makefiles and don't clean skas_ptregs.h.
CLEAN_FILES += linux x.i gmon.out \ CLEAN_FILES += linux x.i gmon.out \
$(ARCH_DIR)/include/shared/user_constants.h \ $(SHARED_HEADERS)/user_constants.h \
$(ARCH_DIR)/include/shared/kern_constants.h $(SHARED_HEADERS)/kern_constants.h
archclean: archclean:
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-o -name '*.gcov' \) -type f -print | xargs rm -f -o -name '*.gcov' \) -type f -print | xargs rm -f
$(objtree)/$(ARCH_DIR)/include/shared:
@echo ' MKDIR $@'
$(Q)mkdir -p $@
# Generated files # Generated files
$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
@ -148,11 +145,11 @@ define filechk_gen-asm-offsets
echo ""; ) echo ""; )
endef endef
$(ARCH_DIR)/include/shared/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s $(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
$(call filechk,gen-asm-offsets) $(call filechk,gen-asm-offsets)
$(ARCH_DIR)/include/shared/kern_constants.h: $(objtree)/$(ARCH_DIR)/include/shared $(SHARED_HEADERS)/kern_constants.h:
@echo ' SYMLINK $@' $(Q)mkdir -p $(dir $@)
$(Q)ln -sf ../../../../include/asm/asm-offsets.h $@ $(Q)echo '#include "../../../../include/asm/asm-offsets.h"' >$@
export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH

View File

@ -11,21 +11,21 @@ extern int get_signals(void);
extern void block_signals(void); extern void block_signals(void);
extern void unblock_signals(void); extern void unblock_signals(void);
#define raw_local_save_flags(flags) do { typecheck(unsigned long, flags); \ #define local_save_flags(flags) do { typecheck(unsigned long, flags); \
(flags) = get_signals(); } while(0) (flags) = get_signals(); } while(0)
#define raw_local_irq_restore(flags) do { typecheck(unsigned long, flags); \ #define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
set_signals(flags); } while(0) set_signals(flags); } while(0)
#define raw_local_irq_save(flags) do { raw_local_save_flags(flags); \ #define local_irq_save(flags) do { local_save_flags(flags); \
raw_local_irq_disable(); } while(0) local_irq_disable(); } while(0)
#define raw_local_irq_enable() unblock_signals() #define local_irq_enable() unblock_signals()
#define raw_local_irq_disable() block_signals() #define local_irq_disable() block_signals()
#define irqs_disabled() \ #define irqs_disabled() \
({ \ ({ \
unsigned long flags; \ unsigned long flags; \
raw_local_save_flags(flags); \ local_save_flags(flags); \
(flags == 0); \ (flags == 0); \
}) })

View File

@ -408,7 +408,7 @@ config X86_MINIMUM_CPU_FAMILY
config X86_DEBUGCTLMSR config X86_DEBUGCTLMSR
def_bool y def_bool y
depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) && !UML
menuconfig PROCESSOR_SELECT menuconfig PROCESSOR_SELECT
bool "Supported processor vendors" if EMBEDDED bool "Supported processor vendors" if EMBEDDED

View File

@ -160,6 +160,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
switch (c->x86_model) { switch (c->x86_model) {
case 0x0E: /* Core */ case 0x0E: /* Core */
case 0x0F: /* Core Duo */ case 0x0F: /* Core Duo */
case 0x16: /* Celeron Core */
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE); return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE);
case 0x0D: /* Pentium M (Dothan) */ case 0x0D: /* Pentium M (Dothan) */
@ -171,7 +172,9 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
} }
if (c->x86 != 0xF) { if (c->x86 != 0xF) {
printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <cpufreq@vger.kernel.org>\n"); if (!cpu_has(c, X86_FEATURE_EST))
printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. "
"Please send an e-mail to <cpufreq@vger.kernel.org>\n");
return 0; return 0;
} }
@ -274,6 +277,7 @@ static struct cpufreq_driver p4clockmod_driver = {
.name = "p4-clockmod", .name = "p4-clockmod",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.attr = p4clockmod_attr, .attr = p4clockmod_attr,
.hide_interface = 1,
}; };

View File

@ -459,9 +459,7 @@ static int centrino_verify (struct cpufreq_policy *policy)
* Sets a new CPUFreq policy. * Sets a new CPUFreq policy.
*/ */
struct allmasks { struct allmasks {
cpumask_t online_policy_cpus;
cpumask_t saved_mask; cpumask_t saved_mask;
cpumask_t set_mask;
cpumask_t covered_cpus; cpumask_t covered_cpus;
}; };
@ -475,9 +473,7 @@ static int centrino_target (struct cpufreq_policy *policy,
int retval = 0; int retval = 0;
unsigned int j, k, first_cpu, tmp; unsigned int j, k, first_cpu, tmp;
CPUMASK_ALLOC(allmasks); CPUMASK_ALLOC(allmasks);
CPUMASK_PTR(online_policy_cpus, allmasks);
CPUMASK_PTR(saved_mask, allmasks); CPUMASK_PTR(saved_mask, allmasks);
CPUMASK_PTR(set_mask, allmasks);
CPUMASK_PTR(covered_cpus, allmasks); CPUMASK_PTR(covered_cpus, allmasks);
if (unlikely(allmasks == NULL)) if (unlikely(allmasks == NULL))
@ -497,30 +493,28 @@ static int centrino_target (struct cpufreq_policy *policy,
goto out; goto out;
} }
#ifdef CONFIG_HOTPLUG_CPU
/* cpufreq holds the hotplug lock, so we are safe from here on */
cpus_and(*online_policy_cpus, cpu_online_map, policy->cpus);
#else
*online_policy_cpus = policy->cpus;
#endif
*saved_mask = current->cpus_allowed; *saved_mask = current->cpus_allowed;
first_cpu = 1; first_cpu = 1;
cpus_clear(*covered_cpus); cpus_clear(*covered_cpus);
for_each_cpu_mask_nr(j, *online_policy_cpus) { for_each_cpu_mask_nr(j, policy->cpus) {
const cpumask_t *mask;
/* cpufreq holds the hotplug lock, so we are safe here */
if (!cpu_online(j))
continue;
/* /*
* Support for SMP systems. * Support for SMP systems.
* Make sure we are running on CPU that wants to change freq * Make sure we are running on CPU that wants to change freq
*/ */
cpus_clear(*set_mask);
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
cpus_or(*set_mask, *set_mask, *online_policy_cpus); mask = &policy->cpus;
else else
cpu_set(j, *set_mask); mask = &cpumask_of_cpu(j);
set_cpus_allowed_ptr(current, set_mask); set_cpus_allowed_ptr(current, mask);
preempt_disable(); preempt_disable();
if (unlikely(!cpu_isset(smp_processor_id(), *set_mask))) { if (unlikely(!cpu_isset(smp_processor_id(), *mask))) {
dprintk("couldn't limit to CPUs in this domain\n"); dprintk("couldn't limit to CPUs in this domain\n");
retval = -EAGAIN; retval = -EAGAIN;
if (first_cpu) { if (first_cpu) {
@ -548,7 +542,9 @@ static int centrino_target (struct cpufreq_policy *policy,
dprintk("target=%dkHz old=%d new=%d msr=%04x\n", dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
target_freq, freqs.old, freqs.new, msr); target_freq, freqs.old, freqs.new, msr);
for_each_cpu_mask_nr(k, *online_policy_cpus) { for_each_cpu_mask_nr(k, policy->cpus) {
if (!cpu_online(k))
continue;
freqs.cpu = k; freqs.cpu = k;
cpufreq_notify_transition(&freqs, cpufreq_notify_transition(&freqs,
CPUFREQ_PRECHANGE); CPUFREQ_PRECHANGE);
@ -571,7 +567,9 @@ static int centrino_target (struct cpufreq_policy *policy,
preempt_enable(); preempt_enable();
} }
for_each_cpu_mask_nr(k, *online_policy_cpus) { for_each_cpu_mask_nr(k, policy->cpus) {
if (!cpu_online(k))
continue;
freqs.cpu = k; freqs.cpu = k;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
} }
@ -584,18 +582,17 @@ static int centrino_target (struct cpufreq_policy *policy,
* Best effort undo.. * Best effort undo..
*/ */
if (!cpus_empty(*covered_cpus)) for_each_cpu_mask_nr(j, *covered_cpus) {
for_each_cpu_mask_nr(j, *covered_cpus) { set_cpus_allowed_ptr(current, &cpumask_of_cpu(j));
set_cpus_allowed_ptr(current, wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
&cpumask_of_cpu(j)); }
wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
}
tmp = freqs.new; tmp = freqs.new;
freqs.new = freqs.old; freqs.new = freqs.old;
freqs.old = tmp; freqs.old = tmp;
for_each_cpu_mask_nr(j, *online_policy_cpus) { for_each_cpu_mask_nr(j, policy->cpus) {
freqs.cpu = j; if (!cpu_online(j))
continue;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
} }

View File

@ -139,6 +139,15 @@ static unsigned int pentium_core_get_frequency(void)
case 3: case 3:
fsb = 166667; fsb = 166667;
break; break;
case 2:
fsb = 200000;
break;
case 0:
fsb = 266667;
break;
case 4:
fsb = 333333;
break;
default: default:
printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value"); printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value");
} }

View File

@ -754,6 +754,11 @@ static struct kobj_type ktype_cpufreq = {
.release = cpufreq_sysfs_release, .release = cpufreq_sysfs_release,
}; };
static struct kobj_type ktype_empty_cpufreq = {
.sysfs_ops = &sysfs_ops,
.release = cpufreq_sysfs_release,
};
/** /**
* cpufreq_add_dev - add a CPU device * cpufreq_add_dev - add a CPU device
@ -822,8 +827,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
dprintk("initialization failed\n"); dprintk("initialization failed\n");
goto err_out; goto err_out;
} }
policy->user_policy.min = policy->cpuinfo.min_freq; policy->user_policy.min = policy->min;
policy->user_policy.max = policy->cpuinfo.max_freq; policy->user_policy.max = policy->max;
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_START, policy); CPUFREQ_START, policy);
@ -876,26 +881,36 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
/* prepare interface data */ /* prepare interface data */
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, if (!cpufreq_driver->hide_interface) {
"cpufreq"); ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
if (ret) &sys_dev->kobj, "cpufreq");
goto err_out_driver_exit; if (ret)
goto err_out_driver_exit;
/* set up files for this cpu device */ /* set up files for this cpu device */
drv_attr = cpufreq_driver->attr; drv_attr = cpufreq_driver->attr;
while ((drv_attr) && (*drv_attr)) { while ((drv_attr) && (*drv_attr)) {
ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); ret = sysfs_create_file(&policy->kobj,
if (ret) &((*drv_attr)->attr));
goto err_out_driver_exit; if (ret)
drv_attr++; goto err_out_driver_exit;
} drv_attr++;
if (cpufreq_driver->get) { }
ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); if (cpufreq_driver->get) {
if (ret) ret = sysfs_create_file(&policy->kobj,
goto err_out_driver_exit; &cpuinfo_cur_freq.attr);
} if (ret)
if (cpufreq_driver->target) { goto err_out_driver_exit;
ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); }
if (cpufreq_driver->target) {
ret = sysfs_create_file(&policy->kobj,
&scaling_cur_freq.attr);
if (ret)
goto err_out_driver_exit;
}
} else {
ret = kobject_init_and_add(&policy->kobj, &ktype_empty_cpufreq,
&sys_dev->kobj, "cpufreq");
if (ret) if (ret)
goto err_out_driver_exit; goto err_out_driver_exit;
} }

View File

@ -85,14 +85,14 @@ config HID_COMPAT
config HID_A4TECH config HID_A4TECH
tristate "A4 tech" if EMBEDDED tristate "A4 tech" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for A4 tech X5 and WOP-35 / Trust 450L mice. Support for A4 tech X5 and WOP-35 / Trust 450L mice.
config HID_APPLE config HID_APPLE
tristate "Apple" if EMBEDDED tristate "Apple" if EMBEDDED
depends on (USB_HID || BT_HIDP) depends on (USB_HID || BT_HIDP)
default y default !EMBEDDED
---help--- ---help---
Support for some Apple devices which less or more break Support for some Apple devices which less or more break
HID specification. HID specification.
@ -103,64 +103,49 @@ config HID_APPLE
config HID_BELKIN config HID_BELKIN
tristate "Belkin" if EMBEDDED tristate "Belkin" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Belkin Flip KVM and Wireless keyboard. Support for Belkin Flip KVM and Wireless keyboard.
config HID_BRIGHT
tristate "Bright" if EMBEDDED
depends on USB_HID
default y
---help---
Support for Bright ABNT-2 keyboard.
config HID_CHERRY config HID_CHERRY
tristate "Cherry" if EMBEDDED tristate "Cherry" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Cherry Cymotion keyboard. Support for Cherry Cymotion keyboard.
config HID_CHICONY config HID_CHICONY
tristate "Chicony" if EMBEDDED tristate "Chicony" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Chicony Tactical pad. Support for Chicony Tactical pad.
config HID_CYPRESS config HID_CYPRESS
tristate "Cypress" if EMBEDDED tristate "Cypress" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for cypress mouse and barcode readers. Support for cypress mouse and barcode readers.
config HID_DELL
tristate "Dell" if EMBEDDED
depends on USB_HID
default y
---help---
Support for quirky Dell HID hardware that require
special LED handling (W7658 and SK8115 models)
config HID_EZKEY config HID_EZKEY
tristate "Ezkey" if EMBEDDED tristate "Ezkey" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Ezkey BTC 8193 keyboard. Support for Ezkey BTC 8193 keyboard.
config HID_GYRATION config HID_GYRATION
tristate "Gyration" if EMBEDDED tristate "Gyration" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Gyration remote control. Support for Gyration remote control.
config HID_LOGITECH config HID_LOGITECH
tristate "Logitech" if EMBEDDED tristate "Logitech" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Logitech devices that are not fully compliant with HID standard. Support for Logitech devices that are not fully compliant with HID standard.
@ -191,21 +176,28 @@ config LOGIRUMBLEPAD2_FF
config HID_MICROSOFT config HID_MICROSOFT
tristate "Microsoft" if EMBEDDED tristate "Microsoft" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Microsoft devices that are not fully compliant with HID standard. Support for Microsoft devices that are not fully compliant with HID standard.
config HID_MONTEREY config HID_MONTEREY
tristate "Monterey" if EMBEDDED tristate "Monterey" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Monterey Genius KB29E. Support for Monterey Genius KB29E.
config HID_NTRIG
tristate "NTrig" if EMBEDDED
depends on USB_HID
default !EMBEDDED
---help---
Support for N-Trig touch screen.
config HID_PANTHERLORD config HID_PANTHERLORD
tristate "Pantherlord devices support" if EMBEDDED tristate "Pantherlord devices support" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for PantherLord/GreenAsia based device support. Support for PantherLord/GreenAsia based device support.
@ -220,31 +212,47 @@ config PANTHERLORD_FF
config HID_PETALYNX config HID_PETALYNX
tristate "Petalynx" if EMBEDDED tristate "Petalynx" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Petalynx Maxter remote control. Support for Petalynx Maxter remote control.
config HID_SAMSUNG config HID_SAMSUNG
tristate "Samsung" if EMBEDDED tristate "Samsung" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Samsung InfraRed remote control. Support for Samsung InfraRed remote control.
config HID_SONY config HID_SONY
tristate "Sony" if EMBEDDED tristate "Sony" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Sony PS3 controller. Support for Sony PS3 controller.
config HID_SUNPLUS config HID_SUNPLUS
tristate "Sunplus" if EMBEDDED tristate "Sunplus" if EMBEDDED
depends on USB_HID depends on USB_HID
default y default !EMBEDDED
---help--- ---help---
Support for Sunplus wireless desktop. Support for Sunplus wireless desktop.
config GREENASIA_FF
tristate "GreenAsia (Product ID 0x12) force feedback support"
depends on USB_HID
select INPUT_FF_MEMLESS
---help---
Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
(like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter
and want to enable force feedback support for it.
config HID_TOPSEED
tristate "TopSeed Cyberlink remote control support" if EMBEDDED
depends on USB_HID
default !EMBEDDED
---help---
Say Y if you have a TopSeed Cyberlink remote control.
config THRUSTMASTER_FF config THRUSTMASTER_FF
tristate "ThrustMaster devices support" tristate "ThrustMaster devices support"
depends on USB_HID depends on USB_HID

View File

@ -23,22 +23,23 @@ endif
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_APPLE) += hid-apple.o
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_BRIGHT) += hid-bright.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
obj-$(CONFIG_HID_DELL) += hid-dell.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SONY) += hid-sony.o obj-$(CONFIG_HID_SONY) += hid-sony.o
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_HID) += usbhid/

View File

@ -1,71 +0,0 @@
/*
* HID driver for some bright "special" devices
*
* Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
*
* Based on hid-dell driver
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
ret = hid_parse(hdev);
if (ret) {
dev_err(&hdev->dev, "parse failed\n");
goto err_free;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
dev_err(&hdev->dev, "hw start failed\n");
goto err_free;
}
usbhid_set_leds(hdev);
return 0;
err_free:
return ret;
}
static const struct hid_device_id bright_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
{ }
};
MODULE_DEVICE_TABLE(hid, bright_devices);
static struct hid_driver bright_driver = {
.name = "bright",
.id_table = bright_devices,
.probe = bright_probe,
};
static int bright_init(void)
{
return hid_register_driver(&bright_driver);
}
static void bright_exit(void)
{
hid_unregister_driver(&bright_driver);
}
module_init(bright_init);
module_exit(bright_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(bright);

View File

@ -1256,19 +1256,16 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
@ -1279,7 +1276,6 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
@ -1297,23 +1293,105 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
{ } { }
}; };
struct hid_dynid {
struct list_head list;
struct hid_device_id id;
};
/**
* store_new_id - add a new HID device ID to this driver and re-probe devices
* @driver: target device driver
* @buf: buffer for scanning device ID data
* @count: input size
*
* Adds a new dynamic hid device ID to this driver,
* and causes the driver to probe for all devices again.
*/
static ssize_t store_new_id(struct device_driver *drv, const char *buf,
size_t count)
{
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
struct hid_dynid *dynid;
__u32 bus, vendor, product;
unsigned long driver_data = 0;
int ret;
ret = sscanf(buf, "%x %x %x %lx",
&bus, &vendor, &product, &driver_data);
if (ret < 3)
return -EINVAL;
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
if (!dynid)
return -ENOMEM;
dynid->id.bus = bus;
dynid->id.vendor = vendor;
dynid->id.product = product;
dynid->id.driver_data = driver_data;
spin_lock(&hdrv->dyn_lock);
list_add_tail(&dynid->list, &hdrv->dyn_list);
spin_unlock(&hdrv->dyn_lock);
ret = 0;
if (get_driver(&hdrv->driver)) {
ret = driver_attach(&hdrv->driver);
put_driver(&hdrv->driver);
}
return ret ? : count;
}
static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
static void hid_free_dynids(struct hid_driver *hdrv)
{
struct hid_dynid *dynid, *n;
spin_lock(&hdrv->dyn_lock);
list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) {
list_del(&dynid->list);
kfree(dynid);
}
spin_unlock(&hdrv->dyn_lock);
}
static const struct hid_device_id *hid_match_device(struct hid_device *hdev,
struct hid_driver *hdrv)
{
struct hid_dynid *dynid;
spin_lock(&hdrv->dyn_lock);
list_for_each_entry(dynid, &hdrv->dyn_list, list) {
if (hid_match_one_id(hdev, &dynid->id)) {
spin_unlock(&hdrv->dyn_lock);
return &dynid->id;
}
}
spin_unlock(&hdrv->dyn_lock);
return hid_match_id(hdev, hdrv->id_table);
}
static int hid_bus_match(struct device *dev, struct device_driver *drv) static int hid_bus_match(struct device *dev, struct device_driver *drv)
{ {
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct hid_device *hdev = container_of(dev, struct hid_device, dev);
if (!hid_match_id(hdev, hdrv->id_table)) if (!hid_match_device(hdev, hdrv))
return 0; return 0;
/* generic wants all non-blacklisted */ /* generic wants all non-blacklisted */
@ -1332,7 +1410,7 @@ static int hid_device_probe(struct device *dev)
int ret = 0; int ret = 0;
if (!hdev->driver) { if (!hdev->driver) {
id = hid_match_id(hdev, hdrv->id_table); id = hid_match_device(hdev, hdrv);
if (id == NULL) if (id == NULL)
return -ENODEV; return -ENODEV;
@ -1420,6 +1498,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
@ -1577,6 +1656,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ } { }
@ -1618,9 +1700,10 @@ int hid_add_device(struct hid_device *hdev)
if (hid_ignore(hdev)) if (hid_ignore(hdev))
return -ENODEV; return -ENODEV;
/* XXX hack, any other cleaner solution < 20 bus_id bytes? */ /* XXX hack, any other cleaner solution after the driver core
sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus, * is converted to allow more than 20 bytes as the device name? */
hdev->vendor, hdev->product, atomic_inc_return(&id)); dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
hdev->vendor, hdev->product, atomic_inc_return(&id));
ret = device_add(&hdev->dev); ret = device_add(&hdev->dev);
if (!ret) if (!ret)
@ -1695,18 +1778,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device);
int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
const char *mod_name) const char *mod_name)
{ {
int ret;
hdrv->driver.name = hdrv->name; hdrv->driver.name = hdrv->name;
hdrv->driver.bus = &hid_bus_type; hdrv->driver.bus = &hid_bus_type;
hdrv->driver.owner = owner; hdrv->driver.owner = owner;
hdrv->driver.mod_name = mod_name; hdrv->driver.mod_name = mod_name;
return driver_register(&hdrv->driver); INIT_LIST_HEAD(&hdrv->dyn_list);
spin_lock_init(&hdrv->dyn_lock);
ret = driver_register(&hdrv->driver);
if (ret)
return ret;
ret = driver_create_file(&hdrv->driver, &driver_attr_new_id);
if (ret)
driver_unregister(&hdrv->driver);
return ret;
} }
EXPORT_SYMBOL_GPL(__hid_register_driver); EXPORT_SYMBOL_GPL(__hid_register_driver);
void hid_unregister_driver(struct hid_driver *hdrv) void hid_unregister_driver(struct hid_driver *hdrv)
{ {
driver_remove_file(&hdrv->driver, &driver_attr_new_id);
driver_unregister(&hdrv->driver); driver_unregister(&hdrv->driver);
hid_free_dynids(hdrv);
} }
EXPORT_SYMBOL_GPL(hid_unregister_driver); EXPORT_SYMBOL_GPL(hid_unregister_driver);

View File

@ -1,76 +0,0 @@
/*
* HID driver for some dell "special" devices
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
* Copyright (c) 2006-2007 Jiri Kosina
* Copyright (c) 2007 Paul Walmsley
* Copyright (c) 2008 Jiri Slaby
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
ret = hid_parse(hdev);
if (ret) {
dev_err(&hdev->dev, "parse failed\n");
goto err_free;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
dev_err(&hdev->dev, "hw start failed\n");
goto err_free;
}
usbhid_set_leds(hdev);
return 0;
err_free:
return ret;
}
static const struct hid_device_id dell_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
{ }
};
MODULE_DEVICE_TABLE(hid, dell_devices);
static struct hid_driver dell_driver = {
.name = "dell",
.id_table = dell_devices,
.probe = dell_probe,
};
static int dell_init(void)
{
return hid_register_driver(&dell_driver);
}
static void dell_exit(void)
{
hid_unregister_driver(&dell_driver);
}
module_init(dell_init);
module_exit(dell_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(dell);

View File

@ -43,6 +43,9 @@ static int __init hid_dummy_init(void)
#ifdef CONFIG_HID_MONTEREY_MODULE #ifdef CONFIG_HID_MONTEREY_MODULE
HID_COMPAT_CALL_DRIVER(monterey); HID_COMPAT_CALL_DRIVER(monterey);
#endif #endif
#ifdef CONFIG_HID_NTRIG_MODULE
HID_COMPAT_CALL_DRIVER(ntrig);
#endif
#ifdef CONFIG_HID_PANTHERLORD_MODULE #ifdef CONFIG_HID_PANTHERLORD_MODULE
HID_COMPAT_CALL_DRIVER(pantherlord); HID_COMPAT_CALL_DRIVER(pantherlord);
#endif #endif
@ -58,6 +61,9 @@ static int __init hid_dummy_init(void)
#ifdef CONFIG_HID_SUNPLUS_MODULE #ifdef CONFIG_HID_SUNPLUS_MODULE
HID_COMPAT_CALL_DRIVER(sunplus); HID_COMPAT_CALL_DRIVER(sunplus);
#endif #endif
#ifdef CONFIG_GREENASIA_FF_MODULE
HID_COMPAT_CALL_DRIVER(greenasia);
#endif
#ifdef CONFIG_THRUSTMASTER_FF_MODULE #ifdef CONFIG_THRUSTMASTER_FF_MODULE
HID_COMPAT_CALL_DRIVER(thrustmaster); HID_COMPAT_CALL_DRIVER(thrustmaster);
#endif #endif

185
drivers/hid/hid-gaff.c Normal file
View File

@ -0,0 +1,185 @@
/*
* Force feedback support for GreenAsia (Product ID 0x12) based devices
*
* The devices are distributed under various names and the same USB device ID
* can be used in many game controllers.
*
*
* 0e8f:0012 "GreenAsia Inc. USB Joystick "
* - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635.
*
* Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
#include "hid-ids.h"
#include "usbhid/usbhid.h"
struct gaff_device {
struct hid_report *report;
};
static int hid_gaff_play(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
struct hid_device *hid = input_get_drvdata(dev);
struct gaff_device *gaff = data;
int left, right;
left = effect->u.rumble.strong_magnitude;
right = effect->u.rumble.weak_magnitude;
dbg_hid("called with 0x%04x 0x%04x", left, right);
left = left * 0xfe / 0xffff;
right = right * 0xfe / 0xffff;
gaff->report->field[0]->value[0] = 0x51;
gaff->report->field[0]->value[1] = 0x0;
gaff->report->field[0]->value[2] = right;
gaff->report->field[0]->value[3] = 0;
gaff->report->field[0]->value[4] = left;
gaff->report->field[0]->value[5] = 0;
dbg_hid("running with 0x%02x 0x%02x", left, right);
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
gaff->report->field[0]->value[0] = 0xfa;
gaff->report->field[0]->value[1] = 0xfe;
gaff->report->field[0]->value[2] = 0x0;
gaff->report->field[0]->value[4] = 0x0;
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
return 0;
}
static int gaff_init(struct hid_device *hid)
{
struct gaff_device *gaff;
struct hid_report *report;
struct hid_input *hidinput = list_entry(hid->inputs.next,
struct hid_input, list);
struct list_head *report_list =
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct list_head *report_ptr = report_list;
struct input_dev *dev = hidinput->input;
int error;
if (list_empty(report_list)) {
dev_err(&hid->dev, "no output reports found\n");
return -ENODEV;
}
report_ptr = report_ptr->next;
report = list_entry(report_ptr, struct hid_report, list);
if (report->maxfield < 1) {
dev_err(&hid->dev, "no fields in the report\n");
return -ENODEV;
}
if (report->field[0]->report_count < 6) {
dev_err(&hid->dev, "not enough values in the field\n");
return -ENODEV;
}
gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL);
if (!gaff)
return -ENOMEM;
set_bit(FF_RUMBLE, dev->ffbit);
error = input_ff_create_memless(dev, gaff, hid_gaff_play);
if (error) {
kfree(gaff);
return error;
}
gaff->report = report;
gaff->report->field[0]->value[0] = 0x51;
gaff->report->field[0]->value[1] = 0x00;
gaff->report->field[0]->value[2] = 0x00;
gaff->report->field[0]->value[3] = 0x00;
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
gaff->report->field[0]->value[0] = 0xfa;
gaff->report->field[0]->value[1] = 0xfe;
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12"
" devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
return 0;
}
static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
dev_dbg(&hdev->dev, "Greenasia HID hardware probe...");
ret = hid_parse(hdev);
if (ret) {
dev_err(&hdev->dev, "parse failed\n");
goto err;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
if (ret) {
dev_err(&hdev->dev, "hw start failed\n");
goto err;
}
gaff_init(hdev);
return 0;
err:
return ret;
}
static const struct hid_device_id ga_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), },
{ }
};
MODULE_DEVICE_TABLE(hid, ga_devices);
static struct hid_driver ga_driver = {
.name = "greenasia",
.id_table = ga_devices,
.probe = ga_probe,
};
static int __init ga_init(void)
{
return hid_register_driver(&ga_driver);
}
static void __exit ga_exit(void)
{
hid_unregister_driver(&ga_driver);
}
module_init(ga_init);
module_exit(ga_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(greenasia);

View File

@ -107,9 +107,6 @@
#define USB_VENDOR_ID_BELKIN 0x050d #define USB_VENDOR_ID_BELKIN 0x050d
#define USB_DEVICE_ID_FLIP_KVM 0x3201 #define USB_DEVICE_ID_FLIP_KVM 0x3201
#define USB_VENDOR_ID_BRIGHT 0x1241
#define USB_DEVICE_ID_BRIGHT_ABNT2 0x1503
#define USB_VENDOR_ID_BERKSHIRE 0x0c98 #define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
@ -141,9 +138,8 @@
#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
#define USB_VENDOR_ID_DELL 0x413c #define USB_VENDOR_ID_DEALEXTREAME 0x10c5
#define USB_DEVICE_ID_DELL_W7658 0x2005 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a
#define USB_DEVICE_ID_DELL_SK8115 0x2105
#define USB_VENDOR_ID_DELORME 0x1163 #define USB_VENDOR_ID_DELORME 0x1163
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
@ -167,9 +163,6 @@
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
#define USB_VENDOR_ID_GENERIC_13BA 0x13ba
#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017
#define USB_VENDOR_ID_GLAB 0x06c2 #define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@ -292,7 +285,6 @@
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c #define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
@ -339,6 +331,9 @@
#define USB_VENDOR_ID_NEC 0x073e #define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
#define USB_VENDOR_ID_NTRIG 0x1b96
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
#define USB_VENDOR_ID_ONTRAK 0x0a07 #define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
@ -383,9 +378,15 @@
#define USB_VENDOR_ID_TOPMAX 0x0663 #define USB_VENDOR_ID_TOPMAX 0x0663
#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
#define USB_VENDOR_ID_TOPSEED 0x0766
#define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204
#define USB_VENDOR_ID_TURBOX 0x062a #define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
#define USB_VENDOR_ID_UCLOGIC 0x5543
#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042
#define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_VENDOR_ID_VERNIER 0x08f7
#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002

View File

@ -26,7 +26,6 @@
#define LG_RDESC 0x001 #define LG_RDESC 0x001
#define LG_BAD_RELATIVE_KEYS 0x002 #define LG_BAD_RELATIVE_KEYS 0x002
#define LG_DUPLICATE_USAGES 0x004 #define LG_DUPLICATE_USAGES 0x004
#define LG_RESET_LEDS 0x008
#define LG_EXPANDED_KEYMAP 0x010 #define LG_EXPANDED_KEYMAP 0x010
#define LG_IGNORE_DOUBLED_WHEEL 0x020 #define LG_IGNORE_DOUBLED_WHEEL 0x020
#define LG_WIRELESS 0x040 #define LG_WIRELESS 0x040
@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_free; goto err_free;
} }
if (quirks & LG_RESET_LEDS)
usbhid_set_leds(hdev);
if (quirks & LG_FF) if (quirks & LG_FF)
lgff_init(hdev); lgff_init(hdev);
if (quirks & LG_FF2) if (quirks & LG_FF2)
@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
.driver_data = LG_DUPLICATE_USAGES }, .driver_data = LG_DUPLICATE_USAGES },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
.driver_data = LG_RESET_LEDS },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),

82
drivers/hid/hid-ntrig.c Normal file
View File

@ -0,0 +1,82 @@
/*
* HID driver for some ntrig "special" devices
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
* Copyright (c) 2006-2007 Jiri Kosina
* Copyright (c) 2007 Paul Walmsley
* Copyright (c) 2008 Jiri Slaby
* Copyright (c) 2008 Rafi Rubin
*
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define NTRIG_DUPLICATE_USAGES 0x001
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
(usage->hid & 0xff) == 0x47) {
nt_map_key_clear(BTN_TOOL_DOUBLETAP);
return 1;
}
return 0;
}
static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if (usage->type == EV_KEY || usage->type == EV_REL
|| usage->type == EV_ABS)
clear_bit(usage->code, *bit);
return 0;
}
static const struct hid_device_id ntrig_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
.driver_data = NTRIG_DUPLICATE_USAGES },
{ }
};
MODULE_DEVICE_TABLE(hid, ntrig_devices);
static struct hid_driver ntrig_driver = {
.name = "ntrig",
.id_table = ntrig_devices,
.input_mapping = ntrig_input_mapping,
.input_mapped = ntrig_input_mapped,
};
static int ntrig_init(void)
{
return hid_register_driver(&ntrig_driver);
}
static void ntrig_exit(void)
{
hid_unregister_driver(&ntrig_driver);
}
module_init(ntrig_init);
module_exit(ntrig_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(ntrig);

View File

@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
} }
ret = sony_set_operational(hdev); ret = sony_set_operational(hdev);
if (ret) if (ret < 0)
goto err_stop; goto err_stop;
return 0; return 0;

77
drivers/hid/hid-topseed.c Normal file
View File

@ -0,0 +1,77 @@
/*
* HID driver for TopSeed Cyberlink remote
*
* Copyright (c) 2008 Lev Babiev
* based on hid-cherry driver
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
return 0;
switch (usage->hid & HID_USAGE) {
case 0x00d: ts_map_key_clear(KEY_HOME); break;
case 0x024: ts_map_key_clear(KEY_MENU); break;
case 0x025: ts_map_key_clear(KEY_TV); break;
case 0x048: ts_map_key_clear(KEY_RED); break;
case 0x047: ts_map_key_clear(KEY_GREEN); break;
case 0x049: ts_map_key_clear(KEY_YELLOW); break;
case 0x04a: ts_map_key_clear(KEY_BLUE); break;
case 0x04b: ts_map_key_clear(KEY_ANGLE); break;
case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break;
case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break;
case 0x031: ts_map_key_clear(KEY_AUDIO); break;
case 0x032: ts_map_key_clear(KEY_TEXT); break;
case 0x033: ts_map_key_clear(KEY_CHANNEL); break;
default:
return 0;
}
return 1;
}
static const struct hid_device_id ts_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
{ }
};
MODULE_DEVICE_TABLE(hid, ts_devices);
static struct hid_driver ts_driver = {
.name = "topseed",
.id_table = ts_devices,
.input_mapping = ts_input_mapping,
};
static int ts_init(void)
{
return hid_register_driver(&ts_driver);
}
static void ts_exit(void)
{
hid_unregister_driver(&ts_driver);
}
module_init(ts_init);
module_exit(ts_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(topseed);

View File

@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
list_del(&list->node); list_del(&list->node);
dev = hidraw_table[minor]; dev = hidraw_table[minor];
if (!dev->open--) { if (!--dev->open) {
if (list->hidraw->exist) if (list->hidraw->exist)
dev->hid->ll_driver->close(dev->hid); dev->hid->ll_driver->close(dev->hid);
else else
@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
break; break;
} }
default: default:
{
struct hid_device *hid = dev->hid;
if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
return -EINVAL;
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
int len;
if (!hid->name)
return 0;
len = strlen(hid->name) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
return copy_to_user(user_arg, hid->name, len) ?
-EFAULT : len;
}
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
int len;
if (!hid->phys)
return 0;
len = strlen(hid->phys) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
return copy_to_user(user_arg, hid->phys, len) ?
-EFAULT : len;
}
}
ret = -ENOTTY; ret = -ENOTTY;
} }
unlock_kernel(); unlock_kernel();
@ -329,7 +357,7 @@ int hidraw_connect(struct hid_device *hid)
goto out; goto out;
} }
dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor), dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
NULL, "%s%d", "hidraw", minor); NULL, "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) { if (IS_ERR(dev->dev)) {

View File

@ -45,7 +45,7 @@ config USB_HIDDEV
If unsure, say Y. If unsure, say Y.
menu "USB HID Boot Protocol drivers" menu "USB HID Boot Protocol drivers"
depends on USB!=n && USB_HID!=y depends on USB!=n && USB_HID!=y && EMBEDDED
config USB_KBD config USB_KBD
tristate "USB HIDBP Keyboard (simple Boot) support" tristate "USB HIDBP Keyboard (simple Boot) support"

View File

@ -4,7 +4,7 @@
* Copyright (c) 1999 Andreas Gal * Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
* Copyright (c) 2006-2007 Jiri Kosina * Copyright (c) 2006-2008 Jiri Kosina
*/ */
/* /*
@ -641,9 +641,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type,
unsigned int size; unsigned int size;
list_for_each_entry(report, &hid->report_enum[type].report_list, list) { list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
size = ((report->size - 1) >> 3) + 1; size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered;
if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
size++;
if (*max < size) if (*max < size)
*max = size; *max = size;
} }
@ -653,13 +651,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{ {
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma))) usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
return -1; &usbhid->inbuf_dma);
if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma))) usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
return -1; &usbhid->outbuf_dma);
if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma))) usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
return -1; &usbhid->cr_dma);
if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma))) usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->ctrlbuf_dma);
if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
!usbhid->ctrlbuf)
return -1; return -1;
return 0; return 0;
@ -807,7 +808,7 @@ static int usbhid_start(struct hid_device *hid)
int interval; int interval;
endpoint = &interface->endpoint[n].desc; endpoint = &interface->endpoint[n].desc;
if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ if (!usb_endpoint_xfer_int(endpoint))
continue; continue;
interval = endpoint->bInterval; interval = endpoint->bInterval;
@ -876,6 +877,15 @@ static int usbhid_start(struct hid_device *hid)
set_bit(HID_STARTED, &usbhid->iofl); set_bit(HID_STARTED, &usbhid->iofl);
/* Some keyboards don't work until their LEDs have been set.
* Since BIOSes do set the LEDs, it must be safe for any device
* that supports the keyboard boot protocol.
*/
if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
interface->desc.bInterfaceProtocol ==
USB_INTERFACE_PROTOCOL_KEYBOARD)
usbhid_set_leds(hid);
return 0; return 0;
fail: fail:

View File

@ -54,6 +54,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },

View File

@ -49,6 +49,7 @@
struct hiddev { struct hiddev {
int exist; int exist;
int open; int open;
struct mutex existancelock;
wait_queue_head_t wait; wait_queue_head_t wait;
struct hid_device *hid; struct hid_device *hid;
struct list_head list; struct list_head list;
@ -63,6 +64,7 @@ struct hiddev_list {
struct fasync_struct *fasync; struct fasync_struct *fasync;
struct hiddev *hiddev; struct hiddev *hiddev;
struct list_head node; struct list_head node;
struct mutex thread_lock;
}; };
static struct hiddev *hiddev_table[HIDDEV_MINORS]; static struct hiddev *hiddev_table[HIDDEV_MINORS];
@ -264,29 +266,48 @@ static int hiddev_release(struct inode * inode, struct file * file)
static int hiddev_open(struct inode *inode, struct file *file) static int hiddev_open(struct inode *inode, struct file *file)
{ {
struct hiddev_list *list; struct hiddev_list *list;
unsigned long flags; int res;
int i = iminor(inode) - HIDDEV_MINOR_BASE; int i = iminor(inode) - HIDDEV_MINOR_BASE;
if (i >= HIDDEV_MINORS || !hiddev_table[i]) if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i])
return -ENODEV; return -ENODEV;
if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
mutex_init(&list->thread_lock);
list->hiddev = hiddev_table[i]; list->hiddev = hiddev_table[i];
spin_lock_irqsave(&list->hiddev->list_lock, flags);
list_add_tail(&list->node, &hiddev_table[i]->list);
spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
file->private_data = list; file->private_data = list;
if (!list->hiddev->open++) /*
if (list->hiddev->exist) * no need for locking because the USB major number
usbhid_open(hiddev_table[i]->hid); * is shared which usbcore guards against disconnect
*/
if (list->hiddev->exist) {
if (!list->hiddev->open++) {
res = usbhid_open(hiddev_table[i]->hid);
if (res < 0) {
res = -EIO;
goto bail;
}
}
} else {
res = -ENODEV;
goto bail;
}
spin_lock_irq(&list->hiddev->list_lock);
list_add_tail(&list->node, &hiddev_table[i]->list);
spin_unlock_irq(&list->hiddev->list_lock);
return 0; return 0;
bail:
file->private_data = NULL;
kfree(list->hiddev);
return res;
} }
/* /*
@ -305,7 +326,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data; struct hiddev_list *list = file->private_data;
int event_size; int event_size;
int retval = 0; int retval;
event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
@ -313,10 +334,14 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
if (count < event_size) if (count < event_size)
return 0; return 0;
/* lock against other threads */
retval = mutex_lock_interruptible(&list->thread_lock);
if (retval)
return -ERESTARTSYS;
while (retval == 0) { while (retval == 0) {
if (list->head == list->tail) { if (list->head == list->tail) {
add_wait_queue(&list->hiddev->wait, &wait); prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) { while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
@ -332,35 +357,45 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
break; break;
} }
/* let O_NONBLOCK tasks run */
mutex_unlock(&list->thread_lock);
schedule(); schedule();
if (mutex_lock_interruptible(&list->thread_lock))
return -EINTR;
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
} }
finish_wait(&list->hiddev->wait, &wait);
set_current_state(TASK_RUNNING);
remove_wait_queue(&list->hiddev->wait, &wait);
} }
if (retval) if (retval) {
mutex_unlock(&list->thread_lock);
return retval; return retval;
}
while (list->head != list->tail && while (list->head != list->tail &&
retval + event_size <= count) { retval + event_size <= count) {
if ((list->flags & HIDDEV_FLAG_UREF) == 0) { if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
if (list->buffer[list->tail].field_index != if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) {
HID_FIELD_INDEX_NONE) {
struct hiddev_event event; struct hiddev_event event;
event.hid = list->buffer[list->tail].usage_code; event.hid = list->buffer[list->tail].usage_code;
event.value = list->buffer[list->tail].value; event.value = list->buffer[list->tail].value;
if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) {
mutex_unlock(&list->thread_lock);
return -EFAULT; return -EFAULT;
}
retval += sizeof(struct hiddev_event); retval += sizeof(struct hiddev_event);
} }
} else { } else {
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) { (list->flags & HIDDEV_FLAG_REPORT) != 0) {
if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) {
mutex_unlock(&list->thread_lock);
return -EFAULT; return -EFAULT;
}
retval += sizeof(struct hiddev_usage_ref); retval += sizeof(struct hiddev_usage_ref);
} }
} }
@ -368,6 +403,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
} }
} }
mutex_unlock(&list->thread_lock);
return retval; return retval;
} }
@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct hid_field *field; struct hid_field *field;
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
void __user *user_arg = (void __user *)arg; void __user *user_arg = (void __user *)arg;
int i; int i, r;
/* Called without BKL by compat methods so no BKL taken */ /* Called without BKL by compat methods so no BKL taken */
@ -619,10 +655,22 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} }
case HIDIOCGSTRING: case HIDIOCGSTRING:
return hiddev_ioctl_string(hiddev, cmd, user_arg); mutex_lock(&hiddev->existancelock);
if (!hiddev->exist)
r = hiddev_ioctl_string(hiddev, cmd, user_arg);
else
r = -ENODEV;
mutex_unlock(&hiddev->existancelock);
return r;
case HIDIOCINITREPORT: case HIDIOCINITREPORT:
mutex_lock(&hiddev->existancelock);
if (!hiddev->exist) {
mutex_unlock(&hiddev->existancelock);
return -ENODEV;
}
usbhid_init_reports(hid); usbhid_init_reports(hid);
mutex_unlock(&hiddev->existancelock);
return 0; return 0;
@ -636,8 +684,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL; return -EINVAL;
usbhid_submit_report(hid, report, USB_DIR_IN); mutex_lock(&hiddev->existancelock);
usbhid_wait_io(hid); if (hiddev->exist) {
usbhid_submit_report(hid, report, USB_DIR_IN);
usbhid_wait_io(hid);
}
mutex_unlock(&hiddev->existancelock);
return 0; return 0;
@ -651,8 +703,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL; return -EINVAL;
usbhid_submit_report(hid, report, USB_DIR_OUT); mutex_lock(&hiddev->existancelock);
usbhid_wait_io(hid); if (hiddev->exist) {
usbhid_submit_report(hid, report, USB_DIR_OUT);
usbhid_wait_io(hid);
}
mutex_unlock(&hiddev->existancelock);
return 0; return 0;
@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case HIDIOCGUSAGES: case HIDIOCGUSAGES:
case HIDIOCSUSAGES: case HIDIOCSUSAGES:
case HIDIOCGCOLLECTIONINDEX: case HIDIOCGCOLLECTIONINDEX:
return hiddev_ioctl_usage(hiddev, cmd, user_arg); mutex_lock(&hiddev->existancelock);
if (hiddev->exist)
r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
else
r = -ENODEV;
mutex_unlock(&hiddev->existancelock);
return r;
case HIDIOCGCOLLECTIONINFO: case HIDIOCGCOLLECTIONINFO:
if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
@ -808,24 +870,23 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
return -1; return -1;
init_waitqueue_head(&hiddev->wait);
INIT_LIST_HEAD(&hiddev->list);
spin_lock_init(&hiddev->list_lock);
mutex_init(&hiddev->existancelock);
hiddev->hid = hid;
hiddev->exist = 1;
retval = usb_register_dev(usbhid->intf, &hiddev_class); retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) { if (retval) {
err_hid("Not able to get a minor for this device."); err_hid("Not able to get a minor for this device.");
kfree(hiddev); kfree(hiddev);
return -1; return -1;
} else {
hid->minor = usbhid->intf->minor;
hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
} }
init_waitqueue_head(&hiddev->wait);
INIT_LIST_HEAD(&hiddev->list);
spin_lock_init(&hiddev->list_lock);
hiddev->hid = hid;
hiddev->exist = 1;
hid->minor = usbhid->intf->minor;
hid->hiddev = hiddev;
hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
return 0; return 0;
} }
@ -839,7 +900,9 @@ void hiddev_disconnect(struct hid_device *hid)
struct hiddev *hiddev = hid->hiddev; struct hiddev *hiddev = hid->hiddev;
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
mutex_lock(&hiddev->existancelock);
hiddev->exist = 0; hiddev->exist = 0;
mutex_unlock(&hiddev->existancelock);
hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
usb_deregister_dev(usbhid->intf, &hiddev_class); usb_deregister_dev(usbhid->intf, &hiddev_class);

View File

@ -40,6 +40,16 @@ int usbhid_open(struct hid_device *hid);
void usbhid_init_reports(struct hid_device *hid); void usbhid_init_reports(struct hid_device *hid);
void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
/* iofl flags */
#define HID_CTRL_RUNNING 1
#define HID_OUT_RUNNING 2
#define HID_IN_RUNNING 3
#define HID_RESET_PENDING 4
#define HID_SUSPENDED 5
#define HID_CLEAR_HALT 6
#define HID_DISCONNECTED 7
#define HID_STARTED 8
/* /*
* USB-specific HID struct, to be pointed to * USB-specific HID struct, to be pointed to
* from struct hid_device->driver_data * from struct hid_device->driver_data

View File

@ -2,13 +2,16 @@
* TI OMAP I2C master mode driver * TI OMAP I2C master mode driver
* *
* Copyright (C) 2003 MontaVista Software, Inc. * Copyright (C) 2003 MontaVista Software, Inc.
* Copyright (C) 2004 Texas Instruments.
*
* Updated to work with multiple I2C interfaces on 24xx by
* Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation * Copyright (C) 2005 Nokia Corporation
* Copyright (C) 2004 - 2007 Texas Instruments.
* *
* Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com> * Originally written by MontaVista Software, Inc.
* Additional contributions by:
* Tony Lindgren <tony@atomide.com>
* Imre Deak <imre.deak@nokia.com>
* Juha Yrjölä <juha.yrjola@solidboot.com>
* Syed Khasim <x0khasim@ti.com>
* Nishant Menon <nm@ti.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -33,8 +36,14 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h>
#include <asm/io.h> /* I2C controller revisions */
#define OMAP_I2C_REV_2 0x20
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36
#define OMAP_I2C_REV_ON_3430 0x3C
/* timeout waiting for the controller to respond */ /* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@ -43,6 +52,8 @@
#define OMAP_I2C_IE_REG 0x04 #define OMAP_I2C_IE_REG 0x04
#define OMAP_I2C_STAT_REG 0x08 #define OMAP_I2C_STAT_REG 0x08
#define OMAP_I2C_IV_REG 0x0c #define OMAP_I2C_IV_REG 0x0c
/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
#define OMAP_I2C_WE_REG 0x0c
#define OMAP_I2C_SYSS_REG 0x10 #define OMAP_I2C_SYSS_REG 0x10
#define OMAP_I2C_BUF_REG 0x14 #define OMAP_I2C_BUF_REG 0x14
#define OMAP_I2C_CNT_REG 0x18 #define OMAP_I2C_CNT_REG 0x18
@ -55,8 +66,11 @@
#define OMAP_I2C_SCLL_REG 0x34 #define OMAP_I2C_SCLL_REG 0x34
#define OMAP_I2C_SCLH_REG 0x38 #define OMAP_I2C_SCLH_REG 0x38
#define OMAP_I2C_SYSTEST_REG 0x3c #define OMAP_I2C_SYSTEST_REG 0x3c
#define OMAP_I2C_BUFSTAT_REG 0x40
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */ /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */ #define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */
#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */ #define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */
#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */ #define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */
@ -64,7 +78,8 @@
#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */ #define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */
/* I2C Status Register (OMAP_I2C_STAT): */ /* I2C Status Register (OMAP_I2C_STAT): */
#define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */ #define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */
#define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */
#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */ #define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */
#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */ #define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */
#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ #define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */
@ -76,13 +91,34 @@
#define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */ #define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */
#define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */ #define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */
/* I2C WE wakeup enable register */
#define OMAP_I2C_WE_XDR_WE (1 << 14) /* TX drain wakup */
#define OMAP_I2C_WE_RDR_WE (1 << 13) /* RX drain wakeup */
#define OMAP_I2C_WE_AAS_WE (1 << 9) /* Address as slave wakeup*/
#define OMAP_I2C_WE_BF_WE (1 << 8) /* Bus free wakeup */
#define OMAP_I2C_WE_STC_WE (1 << 6) /* Start condition wakeup */
#define OMAP_I2C_WE_GC_WE (1 << 5) /* General call wakeup */
#define OMAP_I2C_WE_DRDY_WE (1 << 3) /* TX/RX data ready wakeup */
#define OMAP_I2C_WE_ARDY_WE (1 << 2) /* Reg access ready wakeup */
#define OMAP_I2C_WE_NACK_WE (1 << 1) /* No acknowledgment wakeup */
#define OMAP_I2C_WE_AL_WE (1 << 0) /* Arbitration lost wakeup */
#define OMAP_I2C_WE_ALL (OMAP_I2C_WE_XDR_WE | OMAP_I2C_WE_RDR_WE | \
OMAP_I2C_WE_AAS_WE | OMAP_I2C_WE_BF_WE | \
OMAP_I2C_WE_STC_WE | OMAP_I2C_WE_GC_WE | \
OMAP_I2C_WE_DRDY_WE | OMAP_I2C_WE_ARDY_WE | \
OMAP_I2C_WE_NACK_WE | OMAP_I2C_WE_AL_WE)
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */ /* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */ #define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */
#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */ #define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */
#define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */
/* I2C Configuration Register (OMAP_I2C_CON): */ /* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */ #define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */ #define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
#define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */
#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */ #define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */ #define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */ #define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@ -91,6 +127,10 @@
#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */ #define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */
#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */ #define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */
/* I2C SCL time value when Master */
#define OMAP_I2C_SCLL_HSSCLL 8
#define OMAP_I2C_SCLH_HSSCLH 8
/* I2C System Test Register (OMAP_I2C_SYSTEST): */ /* I2C System Test Register (OMAP_I2C_SYSTEST): */
#ifdef DEBUG #ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */ #define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
@ -103,17 +143,19 @@
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */ #define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
#endif #endif
/* I2C System Status register (OMAP_I2C_SYSS): */ /* OCP_SYSSTATUS bit definitions */
#define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */ #define SYSS_RESETDONE_MASK (1 << 0)
/* I2C System Configuration Register (OMAP_I2C_SYSC): */ /* OCP_SYSCONFIG bit definitions */
#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */ #define SYSC_CLOCKACTIVITY_MASK (0x3 << 8)
#define SYSC_SIDLEMODE_MASK (0x3 << 3)
#define SYSC_ENAWAKEUP_MASK (1 << 2)
#define SYSC_SOFTRESET_MASK (1 << 1)
#define SYSC_AUTOIDLE_MASK (1 << 0)
#define SYSC_IDLEMODE_SMART 0x2
#define SYSC_CLOCKACTIVITY_FCLK 0x2
/* REVISIT: Use platform_data instead of module parameters */
/* Fast Mode = 400 kHz, Standard = 100 kHz */
static int clock = 100; /* Default: 100 kHz */
module_param(clock, int, 0);
MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
struct omap_i2c_dev { struct omap_i2c_dev {
struct device *dev; struct device *dev;
@ -123,11 +165,17 @@ struct omap_i2c_dev {
struct clk *fclk; /* Functional clock */ struct clk *fclk; /* Functional clock */
struct completion cmd_complete; struct completion cmd_complete;
struct resource *ioarea; struct resource *ioarea;
u32 speed; /* Speed of bus in Khz */
u16 cmd_err; u16 cmd_err;
u8 *buf; u8 *buf;
size_t buf_len; size_t buf_len;
struct i2c_adapter adapter; struct i2c_adapter adapter;
unsigned rev1:1; u8 fifo_size; /* use as flag and value
* fifo_size==0 implies no fifo
* if set, should be trsh+1
*/
u8 rev;
unsigned b_hw:1; /* bad h/w fixes */
unsigned idle:1; unsigned idle:1;
u16 iestate; /* Saved interrupt register */ u16 iestate; /* Saved interrupt register */
}; };
@ -143,9 +191,9 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
return __raw_readw(i2c_dev->base + reg); return __raw_readw(i2c_dev->base + reg);
} }
static int omap_i2c_get_clocks(struct omap_i2c_dev *dev) static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{ {
if (cpu_is_omap16xx() || cpu_is_omap24xx()) { if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
dev->iclk = clk_get(dev->dev, "i2c_ick"); dev->iclk = clk_get(dev->dev, "i2c_ick");
if (IS_ERR(dev->iclk)) { if (IS_ERR(dev->iclk)) {
dev->iclk = NULL; dev->iclk = NULL;
@ -178,25 +226,33 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
static void omap_i2c_unidle(struct omap_i2c_dev *dev) static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{ {
WARN_ON(!dev->idle);
if (dev->iclk != NULL) if (dev->iclk != NULL)
clk_enable(dev->iclk); clk_enable(dev->iclk);
clk_enable(dev->fclk); clk_enable(dev->fclk);
dev->idle = 0;
if (dev->iestate) if (dev->iestate)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
dev->idle = 0;
} }
static void omap_i2c_idle(struct omap_i2c_dev *dev) static void omap_i2c_idle(struct omap_i2c_dev *dev)
{ {
u16 iv; u16 iv;
dev->idle = 1; WARN_ON(dev->idle);
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
if (dev->rev1) if (dev->rev < OMAP_I2C_REV_2) {
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
else } else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
/* Flush posted write before the dev->idle store occurs */
omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
}
dev->idle = 1;
clk_disable(dev->fclk); clk_disable(dev->fclk);
if (dev->iclk != NULL) if (dev->iclk != NULL)
clk_disable(dev->iclk); clk_disable(dev->iclk);
@ -204,18 +260,20 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
static int omap_i2c_init(struct omap_i2c_dev *dev) static int omap_i2c_init(struct omap_i2c_dev *dev)
{ {
u16 psc = 0; u16 psc = 0, scll = 0, sclh = 0;
u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
unsigned long fclk_rate = 12000000; unsigned long fclk_rate = 12000000;
unsigned long timeout; unsigned long timeout;
unsigned long internal_clk = 0;
if (!dev->rev1) { if (dev->rev >= OMAP_I2C_REV_2) {
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST); omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
/* For some reason we need to set the EN bit before the /* For some reason we need to set the EN bit before the
* reset done bit gets set. */ * reset done bit gets set. */
timeout = jiffies + OMAP_I2C_TIMEOUT; timeout = jiffies + OMAP_I2C_TIMEOUT;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
OMAP_I2C_SYSS_RDONE)) { SYSS_RESETDONE_MASK)) {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
dev_warn(dev->dev, "timeout waiting " dev_warn(dev->dev, "timeout waiting "
"for controller reset\n"); "for controller reset\n");
@ -223,6 +281,33 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
} }
msleep(1); msleep(1);
} }
/* SYSC register is cleared by the reset; rewrite it */
if (dev->rev == OMAP_I2C_REV_ON_2430) {
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
SYSC_AUTOIDLE_MASK);
} else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
u32 v;
v = SYSC_AUTOIDLE_MASK;
v |= SYSC_ENAWAKEUP_MASK;
v |= (SYSC_IDLEMODE_SMART <<
__ffs(SYSC_SIDLEMODE_MASK));
v |= (SYSC_CLOCKACTIVITY_FCLK <<
__ffs(SYSC_CLOCKACTIVITY_MASK));
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
/*
* Enabling all wakup sources to stop I2C freezing on
* WFI instruction.
* REVISIT: Some wkup sources might not be needed.
*/
omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
OMAP_I2C_WE_ALL);
}
} }
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
@ -249,27 +334,65 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000; psc = fclk_rate / 12000000;
} }
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
/* HSI2C controller internal clk rate should be 19.2 Mhz */
internal_clk = 19200;
fclk_rate = clk_get_rate(dev->fclk) / 1000;
/* Compute prescaler divisor */
psc = fclk_rate / internal_clk;
psc = psc - 1;
/* If configured for High Speed */
if (dev->speed > 400) {
/* For first phase of HS mode */
fsscll = internal_clk / (400 * 2) - 6;
fssclh = internal_clk / (400 * 2) - 6;
/* For second phase of HS mode */
hsscll = fclk_rate / (dev->speed * 2) - 6;
hssclh = fclk_rate / (dev->speed * 2) - 6;
} else {
/* To handle F/S modes */
fsscll = internal_clk / (dev->speed * 2) - 6;
fssclh = internal_clk / (dev->speed * 2) - 6;
}
scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
} else {
/* Program desired operating rate */
fclk_rate /= (psc + 1) * 1000;
if (psc > 2)
psc = 2;
scll = fclk_rate / (dev->speed * 2) - 7 + psc;
sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
}
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
/* Program desired operating rate */ /* SCL low and high time values */
fclk_rate /= (psc + 1) * 1000; omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
if (psc > 2) omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
psc = 2;
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, if (dev->fifo_size)
fclk_rate / (clock * 2) - 7 + psc); /* Note: setup required fifo size - 1 */
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
fclk_rate / (clock * 2) - 7 + psc); (dev->fifo_size - 1) << 8 | /* RTRSH */
OMAP_I2C_BUF_RXFIF_CLR |
(dev->fifo_size - 1) | /* XTRSH */
OMAP_I2C_BUF_TXFIF_CLR);
/* Take the I2C module out of reset: */ /* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/* Enable interrupts */ /* Enable interrupts */
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
OMAP_I2C_IE_AL)); OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
return 0; return 0;
} }
@ -316,20 +439,59 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
/* Clear the FIFO Buffers */
w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
init_completion(&dev->cmd_complete); init_completion(&dev->cmd_complete);
dev->cmd_err = 0; dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
/* High speed configuration */
if (dev->speed > 400)
w |= OMAP_I2C_CON_OPMODE_HS;
if (msg->flags & I2C_M_TEN) if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA; w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD)) if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX; w |= OMAP_I2C_CON_TRX;
if (stop)
if (!dev->b_hw && stop)
w |= OMAP_I2C_CON_STP; w |= OMAP_I2C_CON_STP;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, /*
OMAP_I2C_TIMEOUT); * Don't write stt and stp together on some hardware.
*/
if (dev->b_hw && stop) {
unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
while (con & OMAP_I2C_CON_STT) {
con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
/* Let the user know if i2c is in a bad state */
if (time_after(jiffies, delay)) {
dev_err(dev->dev, "controller timed out "
"waiting for start condition to finish\n");
return -ETIMEDOUT;
}
cpu_relax();
}
w |= OMAP_I2C_CON_STP;
w &= ~OMAP_I2C_CON_STT;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
}
/*
* REVISIT: We should abort the transfer on signals, but the bus goes
* into arbitration and we're currently unable to recover from it.
*/
r = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT);
dev->buf_len = 0; dev->buf_len = 0;
if (r < 0) if (r < 0)
return r; return r;
@ -376,7 +538,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_unidle(dev); omap_i2c_unidle(dev);
if ((r = omap_i2c_wait_for_bb(dev)) < 0) r = omap_i2c_wait_for_bb(dev);
if (r < 0)
goto out; goto out;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
@ -411,6 +574,9 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
} }
/* rev1 devices are apparently only on some 15xx */
#ifdef CONFIG_ARCH_OMAP15XX
static irqreturn_t static irqreturn_t
omap_i2c_rev1_isr(int this_irq, void *dev_id) omap_i2c_rev1_isr(int this_irq, void *dev_id)
{ {
@ -465,6 +631,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
#else
#define omap_i2c_rev1_isr NULL
#endif
static irqreturn_t static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id) omap_i2c_isr(int this_irq, void *dev_id)
@ -472,7 +641,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
struct omap_i2c_dev *dev = dev_id; struct omap_i2c_dev *dev = dev_id;
u16 bits; u16 bits;
u16 stat, w; u16 stat, w;
int count = 0; int err, count = 0;
if (dev->idle) if (dev->idle)
return IRQ_NONE; return IRQ_NONE;
@ -487,39 +656,96 @@ omap_i2c_isr(int this_irq, void *dev_id)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
if (stat & OMAP_I2C_STAT_ARDY) { err = 0;
omap_i2c_complete_cmd(dev, 0); if (stat & OMAP_I2C_STAT_NACK) {
err |= OMAP_I2C_STAT_NACK;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
OMAP_I2C_CON_STP);
}
if (stat & OMAP_I2C_STAT_AL) {
dev_err(dev->dev, "Arbitration lost\n");
err |= OMAP_I2C_STAT_AL;
}
if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
OMAP_I2C_STAT_AL))
omap_i2c_complete_cmd(dev, err);
if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
u8 num_bytes = 1;
if (dev->fifo_size) {
if (stat & OMAP_I2C_STAT_RRDY)
num_bytes = dev->fifo_size;
else
num_bytes = omap_i2c_read_reg(dev,
OMAP_I2C_BUFSTAT_REG);
}
while (num_bytes) {
num_bytes--;
w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
if (dev->buf_len) {
*dev->buf++ = w;
dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
if (!cpu_is_omap2430() &&
!cpu_is_omap34xx()) {
if (dev->buf_len) {
*dev->buf++ = w >> 8;
dev->buf_len--;
}
}
} else {
if (stat & OMAP_I2C_STAT_RRDY)
dev_err(dev->dev,
"RRDY IRQ while no data"
" requested\n");
if (stat & OMAP_I2C_STAT_RDR)
dev_err(dev->dev,
"RDR IRQ while no data"
" requested\n");
break;
}
}
omap_i2c_ack_stat(dev,
stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
continue; continue;
} }
if (stat & OMAP_I2C_STAT_RRDY) { if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); u8 num_bytes = 1;
if (dev->buf_len) { if (dev->fifo_size) {
*dev->buf++ = w; if (stat & OMAP_I2C_STAT_XRDY)
dev->buf_len--; num_bytes = dev->fifo_size;
else
num_bytes = omap_i2c_read_reg(dev,
OMAP_I2C_BUFSTAT_REG);
}
while (num_bytes) {
num_bytes--;
w = 0;
if (dev->buf_len) { if (dev->buf_len) {
*dev->buf++ = w >> 8; w = *dev->buf++;
dev->buf_len--; dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
if (!cpu_is_omap2430() &&
!cpu_is_omap34xx()) {
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
}
}
} else {
if (stat & OMAP_I2C_STAT_XRDY)
dev_err(dev->dev,
"XRDY IRQ while no "
"data to send\n");
if (stat & OMAP_I2C_STAT_XDR)
dev_err(dev->dev,
"XDR IRQ while no "
"data to send\n");
break;
} }
} else omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
dev_err(dev->dev, "RRDY IRQ while no data " }
"requested\n"); omap_i2c_ack_stat(dev,
omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY); stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
continue;
}
if (stat & OMAP_I2C_STAT_XRDY) {
w = 0;
if (dev->buf_len) {
w = *dev->buf++;
dev->buf_len--;
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
}
} else
dev_err(dev->dev, "XRDY IRQ while no "
"data to send\n");
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
continue; continue;
} }
if (stat & OMAP_I2C_STAT_ROVR) { if (stat & OMAP_I2C_STAT_ROVR) {
@ -527,18 +753,9 @@ omap_i2c_isr(int this_irq, void *dev_id)
dev->cmd_err |= OMAP_I2C_STAT_ROVR; dev->cmd_err |= OMAP_I2C_STAT_ROVR;
} }
if (stat & OMAP_I2C_STAT_XUDF) { if (stat & OMAP_I2C_STAT_XUDF) {
dev_err(dev->dev, "Transmit overflow\n"); dev_err(dev->dev, "Transmit underflow\n");
dev->cmd_err |= OMAP_I2C_STAT_XUDF; dev->cmd_err |= OMAP_I2C_STAT_XUDF;
} }
if (stat & OMAP_I2C_STAT_NACK) {
omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
OMAP_I2C_CON_STP);
}
if (stat & OMAP_I2C_STAT_AL) {
dev_err(dev->dev, "Arbitration lost\n");
omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
}
} }
return count ? IRQ_HANDLED : IRQ_NONE; return count ? IRQ_HANDLED : IRQ_NONE;
@ -549,13 +766,15 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func, .functionality = omap_i2c_func,
}; };
static int static int __init
omap_i2c_probe(struct platform_device *pdev) omap_i2c_probe(struct platform_device *pdev)
{ {
struct omap_i2c_dev *dev; struct omap_i2c_dev *dev;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea; struct resource *mem, *irq, *ioarea;
irq_handler_t isr;
int r; int r;
u32 speed = 0;
/* NOTE: driver uses the static register mapping */ /* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -576,17 +795,19 @@ omap_i2c_probe(struct platform_device *pdev)
return -EBUSY; return -EBUSY;
} }
if (clock > 200)
clock = 400; /* Fast mode */
else
clock = 100; /* Standard mode */
dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL); dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
if (!dev) { if (!dev) {
r = -ENOMEM; r = -ENOMEM;
goto err_release_region; goto err_release_region;
} }
if (pdev->dev.platform_data != NULL)
speed = *(u32 *)pdev->dev.platform_data;
else
speed = 100; /* Defualt speed */
dev->speed = speed;
dev->idle = 1;
dev->dev = &pdev->dev; dev->dev = &pdev->dev;
dev->irq = irq->start; dev->irq = irq->start;
dev->base = ioremap(mem->start, mem->end - mem->start + 1); dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@ -602,22 +823,39 @@ omap_i2c_probe(struct platform_device *pdev)
omap_i2c_unidle(dev); omap_i2c_unidle(dev);
if (cpu_is_omap15xx()) dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
u16 s;
/* Set up the fifo size - Get total size */
s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
dev->fifo_size = 0x8 << s;
/*
* Set up notification threshold as half the total available
* size. This is to ensure that we can handle the status on int
* call back latencies.
*/
dev->fifo_size = (dev->fifo_size / 2);
dev->b_hw = 1; /* Enable hardware fixes */
}
/* reset ASAP, clearing any IRQs */ /* reset ASAP, clearing any IRQs */
omap_i2c_init(dev); omap_i2c_init(dev);
r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr, isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
0, pdev->name, dev); r = request_irq(dev->irq, isr, 0, pdev->name, dev);
if (r) { if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq); dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
goto err_unuse_clocks; goto err_unuse_clocks;
} }
r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
pdev->id, r >> 4, r & 0xf, clock); pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
omap_i2c_idle(dev);
adap = &dev->adapter; adap = &dev->adapter;
i2c_set_adapdata(adap, dev); i2c_set_adapdata(adap, dev);
@ -635,8 +873,6 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_free_irq; goto err_free_irq;
} }
omap_i2c_idle(dev);
return 0; return 0;
err_free_irq: err_free_irq:

View File

@ -35,11 +35,9 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <mach/hardware.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
#include <mach/regs-gpio.h>
#include <plat/regs-iic.h> #include <plat/regs-iic.h>
#include <plat/iic.h> #include <plat/iic.h>
@ -64,6 +62,7 @@ struct s3c24xx_i2c {
unsigned int msg_ptr; unsigned int msg_ptr;
unsigned int tx_setup; unsigned int tx_setup;
unsigned int irq;
enum s3c24xx_i2c_state state; enum s3c24xx_i2c_state state;
unsigned long clkrate; unsigned long clkrate;
@ -71,7 +70,6 @@ struct s3c24xx_i2c {
void __iomem *regs; void __iomem *regs;
struct clk *clk; struct clk *clk;
struct device *dev; struct device *dev;
struct resource *irq;
struct resource *ioarea; struct resource *ioarea;
struct i2c_adapter adap; struct i2c_adapter adap;
@ -80,16 +78,7 @@ struct s3c24xx_i2c {
#endif #endif
}; };
/* default platform data to use if not supplied in the platform_device /* default platform data removed, dev should always carry data. */
*/
static struct s3c2410_platform_i2c s3c24xx_i2c_default_platform = {
.flags = 0,
.slave_addr = 0x10,
.bus_freq = 100*1000,
.max_freq = 400*1000,
.sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
};
/* s3c24xx_i2c_is2440() /* s3c24xx_i2c_is2440()
* *
@ -103,21 +92,6 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
return !strcmp(pdev->name, "s3c2440-i2c"); return !strcmp(pdev->name, "s3c2440-i2c");
} }
/* s3c24xx_i2c_get_platformdata
*
* get the platform data associated with the given device, or return
* the default if there is none
*/
static inline struct s3c2410_platform_i2c *s3c24xx_i2c_get_platformdata(struct device *dev)
{
if (dev->platform_data != NULL)
return (struct s3c2410_platform_i2c *)dev->platform_data;
return &s3c24xx_i2c_default_platform;
}
/* s3c24xx_i2c_master_complete /* s3c24xx_i2c_master_complete
* *
* complete the message and wake up the caller, using the given return code, * complete the message and wake up the caller, using the given return code,
@ -130,7 +104,7 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
i2c->msg_ptr = 0; i2c->msg_ptr = 0;
i2c->msg = NULL; i2c->msg = NULL;
i2c->msg_idx ++; i2c->msg_idx++;
i2c->msg_num = 0; i2c->msg_num = 0;
if (ret) if (ret)
i2c->msg_idx = ret; i2c->msg_idx = ret;
@ -141,19 +115,17 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
{ {
unsigned long tmp; unsigned long tmp;
tmp = readl(i2c->regs + S3C2410_IICCON); tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
} }
static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c) static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
{ {
unsigned long tmp; unsigned long tmp;
tmp = readl(i2c->regs + S3C2410_IICCON); tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
} }
/* irq enable/disable functions */ /* irq enable/disable functions */
@ -161,7 +133,7 @@ static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c) static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
{ {
unsigned long tmp; unsigned long tmp;
tmp = readl(i2c->regs + S3C2410_IICCON); tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
} }
@ -169,7 +141,7 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
{ {
unsigned long tmp; unsigned long tmp;
tmp = readl(i2c->regs + S3C2410_IICCON); tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
} }
@ -177,10 +149,10 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_message_start /* s3c24xx_i2c_message_start
* *
* put the start of a message onto the bus * put the start of a message onto the bus
*/ */
static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
struct i2c_msg *msg) struct i2c_msg *msg)
{ {
unsigned int addr = (msg->addr & 0x7f) << 1; unsigned int addr = (msg->addr & 0x7f) << 1;
@ -199,15 +171,15 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
if (msg->flags & I2C_M_REV_DIR_ADDR) if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1; addr ^= 1;
// todo - check for wether ack wanted or not /* todo - check for wether ack wanted or not */
s3c24xx_i2c_enable_ack(i2c); s3c24xx_i2c_enable_ack(i2c);
iiccon = readl(i2c->regs + S3C2410_IICCON); iiccon = readl(i2c->regs + S3C2410_IICCON);
writel(stat, i2c->regs + S3C2410_IICSTAT); writel(stat, i2c->regs + S3C2410_IICSTAT);
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
writeb(addr, i2c->regs + S3C2410_IICDS); writeb(addr, i2c->regs + S3C2410_IICDS);
/* delay here to ensure the data byte has gotten onto the bus /* delay here to ensure the data byte has gotten onto the bus
* before the transaction is started */ * before the transaction is started */
@ -215,8 +187,8 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
writel(iiccon, i2c->regs + S3C2410_IICCON); writel(iiccon, i2c->regs + S3C2410_IICCON);
stat |= S3C2410_IICSTAT_START; stat |= S3C2410_IICSTAT_START;
writel(stat, i2c->regs + S3C2410_IICSTAT); writel(stat, i2c->regs + S3C2410_IICSTAT);
} }
@ -227,11 +199,11 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
dev_dbg(i2c->dev, "STOP\n"); dev_dbg(i2c->dev, "STOP\n");
/* stop the transfer */ /* stop the transfer */
iicstat &= ~ S3C2410_IICSTAT_START; iicstat &= ~S3C2410_IICSTAT_START;
writel(iicstat, i2c->regs + S3C2410_IICSTAT); writel(iicstat, i2c->regs + S3C2410_IICSTAT);
i2c->state = STATE_STOP; i2c->state = STATE_STOP;
s3c24xx_i2c_master_complete(i2c, ret); s3c24xx_i2c_master_complete(i2c, ret);
s3c24xx_i2c_disable_irq(i2c); s3c24xx_i2c_disable_irq(i2c);
} }
@ -241,7 +213,7 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
/* is_lastmsg() /* is_lastmsg()
* *
* returns TRUE if the current message is the last in the set * returns TRUE if the current message is the last in the set
*/ */
static inline int is_lastmsg(struct s3c24xx_i2c *i2c) static inline int is_lastmsg(struct s3c24xx_i2c *i2c)
@ -289,14 +261,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
case STATE_STOP: case STATE_STOP:
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
s3c24xx_i2c_disable_irq(i2c); s3c24xx_i2c_disable_irq(i2c);
goto out_ack; goto out_ack;
case STATE_START: case STATE_START:
/* last thing we did was send a start condition on the /* last thing we did was send a start condition on the
* bus, or started a new i2c message * bus, or started a new i2c message
*/ */
if (iicstat & S3C2410_IICSTAT_LASTBIT && if (iicstat & S3C2410_IICSTAT_LASTBIT &&
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { !(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
/* ack was not received... */ /* ack was not received... */
@ -322,7 +294,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
if (i2c->state == STATE_READ) if (i2c->state == STATE_READ)
goto prepare_read; goto prepare_read;
/* fall through to the write state, as we will need to /* fall through to the write state, as we will need to
* send a byte as well */ * send a byte as well */
case STATE_WRITE: case STATE_WRITE:
@ -339,7 +311,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
} }
} }
retry_write: retry_write:
if (!is_msgend(i2c)) { if (!is_msgend(i2c)) {
byte = i2c->msg->buf[i2c->msg_ptr++]; byte = i2c->msg->buf[i2c->msg_ptr++];
@ -359,9 +331,9 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
dev_dbg(i2c->dev, "WRITE: Next Message\n"); dev_dbg(i2c->dev, "WRITE: Next Message\n");
i2c->msg_ptr = 0; i2c->msg_ptr = 0;
i2c->msg_idx ++; i2c->msg_idx++;
i2c->msg++; i2c->msg++;
/* check to see if we need to do another message */ /* check to see if we need to do another message */
if (i2c->msg->flags & I2C_M_NOSTART) { if (i2c->msg->flags & I2C_M_NOSTART) {
@ -375,7 +347,6 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
goto retry_write; goto retry_write;
} else { } else {
/* send the new start */ /* send the new start */
s3c24xx_i2c_message_start(i2c, i2c->msg); s3c24xx_i2c_message_start(i2c, i2c->msg);
i2c->state = STATE_START; i2c->state = STATE_START;
@ -389,7 +360,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
break; break;
case STATE_READ: case STATE_READ:
/* we have a byte of data in the data register, do /* we have a byte of data in the data register, do
* something with it, and then work out wether we are * something with it, and then work out wether we are
* going to do any more read/write * going to do any more read/write
*/ */
@ -397,13 +368,13 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
byte = readb(i2c->regs + S3C2410_IICDS); byte = readb(i2c->regs + S3C2410_IICDS);
i2c->msg->buf[i2c->msg_ptr++] = byte; i2c->msg->buf[i2c->msg_ptr++] = byte;
prepare_read: prepare_read:
if (is_msglast(i2c)) { if (is_msglast(i2c)) {
/* last byte of buffer */ /* last byte of buffer */
if (is_lastmsg(i2c)) if (is_lastmsg(i2c))
s3c24xx_i2c_disable_ack(i2c); s3c24xx_i2c_disable_ack(i2c);
} else if (is_msgend(i2c)) { } else if (is_msgend(i2c)) {
/* ok, we've read the entire buffer, see if there /* ok, we've read the entire buffer, see if there
* is anything else we need to do */ * is anything else we need to do */
@ -429,7 +400,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
/* acknowlegde the IRQ and get back on with the work */ /* acknowlegde the IRQ and get back on with the work */
out_ack: out_ack:
tmp = readl(i2c->regs + S3C2410_IICCON); tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND; tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON); writel(tmp, i2c->regs + S3C2410_IICCON);
out: out:
@ -450,19 +421,19 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
status = readl(i2c->regs + S3C2410_IICSTAT); status = readl(i2c->regs + S3C2410_IICSTAT);
if (status & S3C2410_IICSTAT_ARBITR) { if (status & S3C2410_IICSTAT_ARBITR) {
// deal with arbitration loss /* deal with arbitration loss */
dev_err(i2c->dev, "deal with arbitration loss\n"); dev_err(i2c->dev, "deal with arbitration loss\n");
} }
if (i2c->state == STATE_IDLE) { if (i2c->state == STATE_IDLE) {
dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n");
tmp = readl(i2c->regs + S3C2410_IICCON); tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND; tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON); writel(tmp, i2c->regs + S3C2410_IICCON);
goto out; goto out;
} }
/* pretty much this leaves us with the fact that we've /* pretty much this leaves us with the fact that we've
* transmitted or received whatever byte we last sent */ * transmitted or received whatever byte we last sent */
@ -485,16 +456,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
while (timeout-- > 0) { while (timeout-- > 0) {
iicstat = readl(i2c->regs + S3C2410_IICSTAT); iicstat = readl(i2c->regs + S3C2410_IICSTAT);
if (!(iicstat & S3C2410_IICSTAT_BUSBUSY)) if (!(iicstat & S3C2410_IICSTAT_BUSBUSY))
return 0; return 0;
msleep(1); msleep(1);
} }
dev_dbg(i2c->dev, "timeout: GPEDAT is %08x\n",
__raw_readl(S3C2410_GPEDAT));
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -503,7 +471,8 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
* this starts an i2c transfer * this starts an i2c transfer
*/ */
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
struct i2c_msg *msgs, int num)
{ {
unsigned long timeout; unsigned long timeout;
int ret; int ret;
@ -529,12 +498,12 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_enable_irq(i2c);
s3c24xx_i2c_message_start(i2c, msgs); s3c24xx_i2c_message_start(i2c, msgs);
spin_unlock_irq(&i2c->lock); spin_unlock_irq(&i2c->lock);
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
ret = i2c->msg_idx; ret = i2c->msg_idx;
/* having these next two as dev_err() makes life very /* having these next two as dev_err() makes life very
* noisy when doing an i2cdetect */ * noisy when doing an i2cdetect */
if (timeout == 0) if (timeout == 0)
@ -591,19 +560,6 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
.functionality = s3c24xx_i2c_func, .functionality = s3c24xx_i2c_func,
}; };
static struct s3c24xx_i2c s3c24xx_i2c = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
.tx_setup = 50,
.adap = {
.name = "s3c2410-i2c",
.owner = THIS_MODULE,
.algo = &s3c24xx_i2c_algorithm,
.retries = 2,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
},
};
/* s3c24xx_i2c_calcdivisor /* s3c24xx_i2c_calcdivisor
* *
* return the divisor settings for a given frequency * return the divisor settings for a given frequency
@ -643,7 +599,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
{ {
int diff = freq - wanted; int diff = freq - wanted;
return (diff >= -2 && diff <= 2); return diff >= -2 && diff <= 2;
} }
/* s3c24xx_i2c_clockrate /* s3c24xx_i2c_clockrate
@ -655,7 +611,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
{ {
struct s3c2410_platform_i2c *pdata; struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
unsigned long clkin = clk_get_rate(i2c->clk); unsigned long clkin = clk_get_rate(i2c->clk);
unsigned int divs, div1; unsigned int divs, div1;
u32 iiccon; u32 iiccon;
@ -663,10 +619,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
int start, end; int start, end;
i2c->clkrate = clkin; i2c->clkrate = clkin;
pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
clkin /= 1000; /* clkin now in KHz */ clkin /= 1000; /* clkin now in KHz */
dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
@ -774,7 +728,7 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_init /* s3c24xx_i2c_init
* *
* initialise the controller, set the IO lines and frequency * initialise the controller, set the IO lines and frequency
*/ */
static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
@ -785,15 +739,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
/* get the plafrom data */ /* get the plafrom data */
pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent); pdata = i2c->dev->platform_data;
/* inititalise the gpio */ /* inititalise the gpio */
s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA); if (pdata->cfg_gpio)
s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL); pdata->cfg_gpio(to_platform_device(i2c->dev));
/* write slave address */ /* write slave address */
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
@ -831,12 +785,32 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
static int s3c24xx_i2c_probe(struct platform_device *pdev) static int s3c24xx_i2c_probe(struct platform_device *pdev)
{ {
struct s3c24xx_i2c *i2c = &s3c24xx_i2c; struct s3c24xx_i2c *i2c;
struct s3c2410_platform_i2c *pdata; struct s3c2410_platform_i2c *pdata;
struct resource *res; struct resource *res;
int ret; int ret;
pdata = s3c24xx_i2c_get_platformdata(&pdev->dev); pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
}
i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
if (!i2c) {
dev_err(&pdev->dev, "no memory for state\n");
return -ENOMEM;
}
strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;
i2c->adap.algo = &s3c24xx_i2c_algorithm;
i2c->adap.retries = 2;
i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
i2c->tx_setup = 50;
spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wait);
/* find the clock and enable it */ /* find the clock and enable it */
@ -878,7 +852,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_ioarea; goto err_ioarea;
} }
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
i2c->regs, i2c->ioarea, res);
/* setup info block for the i2c core */ /* setup info block for the i2c core */
@ -892,29 +867,23 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_iomap; goto err_iomap;
/* find the IRQ for this unit (note, this relies on the init call to /* find the IRQ for this unit (note, this relies on the init call to
* ensure no current IRQs pending * ensure no current IRQs pending
*/ */
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); i2c->irq = ret = platform_get_irq(pdev, 0);
if (res == NULL) { if (ret <= 0) {
dev_err(&pdev->dev, "cannot find IRQ\n"); dev_err(&pdev->dev, "cannot find IRQ\n");
ret = -ENOENT;
goto err_iomap; goto err_iomap;
} }
ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED, ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
pdev->name, i2c); dev_name(&pdev->dev), i2c);
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "cannot claim IRQ\n"); dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
goto err_iomap; goto err_iomap;
} }
i2c->irq = res;
dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
(unsigned long)res->start);
ret = s3c24xx_i2c_register_cpufreq(i2c); ret = s3c24xx_i2c_register_cpufreq(i2c);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
@ -944,7 +913,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
s3c24xx_i2c_deregister_cpufreq(i2c); s3c24xx_i2c_deregister_cpufreq(i2c);
err_irq: err_irq:
free_irq(i2c->irq->start, i2c); free_irq(i2c->irq, i2c);
err_iomap: err_iomap:
iounmap(i2c->regs); iounmap(i2c->regs);
@ -958,6 +927,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
clk_put(i2c->clk); clk_put(i2c->clk);
err_noclk: err_noclk:
kfree(i2c);
return ret; return ret;
} }
@ -973,7 +943,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
s3c24xx_i2c_deregister_cpufreq(i2c); s3c24xx_i2c_deregister_cpufreq(i2c);
i2c_del_adapter(&i2c->adap); i2c_del_adapter(&i2c->adap);
free_irq(i2c->irq->start, i2c); free_irq(i2c->irq, i2c);
clk_disable(i2c->clk); clk_disable(i2c->clk);
clk_put(i2c->clk); clk_put(i2c->clk);
@ -982,6 +952,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
release_resource(i2c->ioarea); release_resource(i2c->ioarea);
kfree(i2c->ioarea); kfree(i2c->ioarea);
kfree(i2c);
return 0; return 0;
} }

View File

@ -126,19 +126,6 @@ config ISP1301_OMAP
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called isp1301_omap. will be called isp1301_omap.
config TPS65010
tristate "TPS6501x Power Management chips"
depends on GPIOLIB
default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
help
If you say yes here you get support for the TPS6501x series of
Power Management chips. These include voltage regulators,
lithium ion/polymer battery charging, and other features that
are often used in portable devices like cell phones and cameras.
This driver can also be built as a module. If so, the module
will be called tps65010.
config SENSORS_MAX6875 config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor" tristate "Maxim MAX6875 Power supply supervisor"
depends on EXPERIMENTAL depends on EXPERIMENTAL
@ -164,16 +151,6 @@ config SENSORS_TSL2550
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called tsl2550. will be called tsl2550.
config MENELAUS
bool "TWL92330/Menelaus PM chip"
depends on I2C=y && ARCH_OMAP24XX
help
If you say yes here you get support for the Texas Instruments
TWL92330/Menelaus Power Management chip. This include voltage
regulators, Dual slot memory card tranceivers, real-time clock
and other features that are often used in portable devices like
cell phones and PDAs.
config MCU_MPC8349EMITX config MCU_MPC8349EMITX
tristate "MPC8349E-mITX MCU driver" tristate "MPC8349E-mITX MCU driver"
depends on I2C && PPC_83xx depends on I2C && PPC_83xx

View File

@ -19,8 +19,6 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o obj-$(CONFIG_PCF8575) += pcf8575.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o

View File

@ -57,9 +57,6 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
} }
inode->i_mode = mode; inode->i_mode = mode;
inode->i_uid = 0;
inode->i_gid = 0;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_private = data; inode->i_private = data;
if ((mode & S_IFMT) == S_IFDIR) { if ((mode & S_IFMT) == S_IFDIR) {

View File

@ -1519,7 +1519,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
int digit2 = 0; int digit2 = 0;
if (!isdigit(*s)) return -3; if (!isdigit(*s)) return -3;
while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; } while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
if (digit1 <= 0 && digit1 > 30) return -4; if (digit1 <= 0 || digit1 > 30) return -4;
if (*s == 0 || *s == ',' || *s == ' ') { if (*s == 0 || *s == ',' || *s == ' ') {
bmask |= (1 << digit1); bmask |= (1 << digit1);
digit1 = 0; digit1 = 0;
@ -1530,7 +1530,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
s++; s++;
if (!isdigit(*s)) return -3; if (!isdigit(*s)) return -3;
while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; } while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
if (digit2 <= 0 && digit2 > 30) return -4; if (digit2 <= 0 || digit2 > 30) return -4;
if (*s == 0 || *s == ',' || *s == ' ') { if (*s == 0 || *s == ',' || *s == ' ') {
if (digit1 > digit2) if (digit1 > digit2)
for (i = digit2; i <= digit1 ; i++) for (i = digit2; i <= digit1 ; i++)

View File

@ -111,8 +111,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent)
goto fail; goto fail;
inode->i_ino = 1; inode->i_ino = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0;
inode->i_uid = inode->i_gid = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &simple_dir_inode_operations; inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;

View File

@ -3,9 +3,10 @@
# #
dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
dm-ioctl.o dm-io.o dm-kcopyd.o dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o
dm-multipath-objs := dm-path-selector.o dm-mpath.o dm-multipath-objs := dm-path-selector.o dm-mpath.o
dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-snap-transient.o \
dm-snap-persistent.o
dm-mirror-objs := dm-raid1.o dm-mirror-objs := dm-raid1.o
md-mod-objs := md.o bitmap.o md-mod-objs := md.o bitmap.o
raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \

View File

@ -1322,11 +1322,7 @@ static int __init dm_crypt_init(void)
static void __exit dm_crypt_exit(void) static void __exit dm_crypt_exit(void)
{ {
int r = dm_unregister_target(&crypt_target); dm_unregister_target(&crypt_target);
if (r < 0)
DMERR("unregister failed %d", r);
kmem_cache_destroy(_crypt_io_pool); kmem_cache_destroy(_crypt_io_pool);
} }

View File

@ -364,11 +364,7 @@ bad_queue:
static void __exit dm_delay_exit(void) static void __exit dm_delay_exit(void)
{ {
int r = dm_unregister_target(&delay_target); dm_unregister_target(&delay_target);
if (r < 0)
DMERR("unregister failed %d", r);
kmem_cache_destroy(delayed_cache); kmem_cache_destroy(delayed_cache);
destroy_workqueue(kdelayd_wq); destroy_workqueue(kdelayd_wq);
} }

View File

@ -1,756 +1,45 @@
/* /*
* dm-exception-store.c
*
* Copyright (C) 2001-2002 Sistina Software (UK) Limited. * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
* Copyright (C) 2006 Red Hat GmbH * Copyright (C) 2006-2008 Red Hat GmbH
* *
* This file is released under the GPL. * This file is released under the GPL.
*/ */
#include "dm-snap.h" #include "dm-exception-store.h"
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dm-io.h>
#include <linux/dm-kcopyd.h>
#define DM_MSG_PREFIX "snapshots" #define DM_MSG_PREFIX "snapshot exception stores"
#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
/*----------------------------------------------------------------- int dm_exception_store_init(void)
* Persistent snapshots, by persistent we mean that the snapshot
* will survive a reboot.
*---------------------------------------------------------------*/
/*
* We need to store a record of which parts of the origin have
* been copied to the snapshot device. The snapshot code
* requires that we copy exception chunks to chunk aligned areas
* of the COW store. It makes sense therefore, to store the
* metadata in chunk size blocks.
*
* There is no backward or forward compatibility implemented,
* snapshots with different disk versions than the kernel will
* not be usable. It is expected that "lvcreate" will blank out
* the start of a fresh COW device before calling the snapshot
* constructor.
*
* The first chunk of the COW device just contains the header.
* After this there is a chunk filled with exception metadata,
* followed by as many exception chunks as can fit in the
* metadata areas.
*
* All on disk structures are in little-endian format. The end
* of the exceptions info is indicated by an exception with a
* new_chunk of 0, which is invalid since it would point to the
* header chunk.
*/
/*
* Magic for persistent snapshots: "SnAp" - Feeble isn't it.
*/
#define SNAP_MAGIC 0x70416e53
/*
* The on-disk version of the metadata.
*/
#define SNAPSHOT_DISK_VERSION 1
struct disk_header {
uint32_t magic;
/*
* Is this snapshot valid. There is no way of recovering
* an invalid snapshot.
*/
uint32_t valid;
/*
* Simple, incrementing version. no backward
* compatibility.
*/
uint32_t version;
/* In sectors */
uint32_t chunk_size;
};
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
struct commit_callback {
void (*callback)(void *, int success);
void *context;
};
/*
* The top level structure for a persistent exception store.
*/
struct pstore {
struct dm_snapshot *snap; /* up pointer to my snapshot */
int version;
int valid;
uint32_t exceptions_per_area;
/*
* Now that we have an asynchronous kcopyd there is no
* need for large chunk sizes, so it wont hurt to have a
* whole chunks worth of metadata in memory at once.
*/
void *area;
/*
* An area of zeros used to clear the next area.
*/
void *zero_area;
/*
* Used to keep track of which metadata area the data in
* 'chunk' refers to.
*/
chunk_t current_area;
/*
* The next free chunk for an exception.
*/
chunk_t next_free;
/*
* The index of next free exception in the current
* metadata area.
*/
uint32_t current_committed;
atomic_t pending_count;
uint32_t callback_count;
struct commit_callback *callbacks;
struct dm_io_client *io_client;
struct workqueue_struct *metadata_wq;
};
static unsigned sectors_to_pages(unsigned sectors)
{
return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
}
static int alloc_area(struct pstore *ps)
{
int r = -ENOMEM;
size_t len;
len = ps->snap->chunk_size << SECTOR_SHIFT;
/*
* Allocate the chunk_size block of memory that will hold
* a single metadata area.
*/
ps->area = vmalloc(len);
if (!ps->area)
return r;
ps->zero_area = vmalloc(len);
if (!ps->zero_area) {
vfree(ps->area);
return r;
}
memset(ps->zero_area, 0, len);
return 0;
}
static void free_area(struct pstore *ps)
{
vfree(ps->area);
ps->area = NULL;
vfree(ps->zero_area);
ps->zero_area = NULL;
}
struct mdata_req {
struct dm_io_region *where;
struct dm_io_request *io_req;
struct work_struct work;
int result;
};
static void do_metadata(struct work_struct *work)
{
struct mdata_req *req = container_of(work, struct mdata_req, work);
req->result = dm_io(req->io_req, 1, req->where, NULL);
}
/*
* Read or write a chunk aligned and sized block of data from a device.
*/
static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
{
struct dm_io_region where = {
.bdev = ps->snap->cow->bdev,
.sector = ps->snap->chunk_size * chunk,
.count = ps->snap->chunk_size,
};
struct dm_io_request io_req = {
.bi_rw = rw,
.mem.type = DM_IO_VMA,
.mem.ptr.vma = ps->area,
.client = ps->io_client,
.notify.fn = NULL,
};
struct mdata_req req;
if (!metadata)
return dm_io(&io_req, 1, &where, NULL);
req.where = &where;
req.io_req = &io_req;
/*
* Issue the synchronous I/O from a different thread
* to avoid generic_make_request recursion.
*/
INIT_WORK(&req.work, do_metadata);
queue_work(ps->metadata_wq, &req.work);
flush_workqueue(ps->metadata_wq);
return req.result;
}
/*
* Convert a metadata area index to a chunk index.
*/
static chunk_t area_location(struct pstore *ps, chunk_t area)
{
return 1 + ((ps->exceptions_per_area + 1) * area);
}
/*
* Read or write a metadata area. Remembering to skip the first
* chunk which holds the header.
*/
static int area_io(struct pstore *ps, int rw)
{ {
int r; int r;
chunk_t chunk;
chunk = area_location(ps, ps->current_area); r = dm_transient_snapshot_init();
if (r) {
DMERR("Unable to register transient exception store type.");
goto transient_fail;
}
r = chunk_io(ps, chunk, rw, 0); r = dm_persistent_snapshot_init();
if (r) if (r) {
return r; DMERR("Unable to register persistent exception store type");
goto persistent_fail;
}
return 0; return 0;
}
static void zero_memory_area(struct pstore *ps) persistent_fail:
{ dm_persistent_snapshot_exit();
memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); transient_fail:
}
static int zero_disk_area(struct pstore *ps, chunk_t area)
{
struct dm_io_region where = {
.bdev = ps->snap->cow->bdev,
.sector = ps->snap->chunk_size * area_location(ps, area),
.count = ps->snap->chunk_size,
};
struct dm_io_request io_req = {
.bi_rw = WRITE,
.mem.type = DM_IO_VMA,
.mem.ptr.vma = ps->zero_area,
.client = ps->io_client,
.notify.fn = NULL,
};
return dm_io(&io_req, 1, &where, NULL);
}
static int read_header(struct pstore *ps, int *new_snapshot)
{
int r;
struct disk_header *dh;
chunk_t chunk_size;
int chunk_size_supplied = 1;
/*
* Use default chunk size (or hardsect_size, if larger) if none supplied
*/
if (!ps->snap->chunk_size) {
ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
bdev_hardsect_size(ps->snap->cow->bdev) >> 9);
ps->snap->chunk_mask = ps->snap->chunk_size - 1;
ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1;
chunk_size_supplied = 0;
}
ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
chunk_size));
if (IS_ERR(ps->io_client))
return PTR_ERR(ps->io_client);
r = alloc_area(ps);
if (r)
return r;
r = chunk_io(ps, 0, READ, 1);
if (r)
goto bad;
dh = (struct disk_header *) ps->area;
if (le32_to_cpu(dh->magic) == 0) {
*new_snapshot = 1;
return 0;
}
if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
DMWARN("Invalid or corrupt snapshot");
r = -ENXIO;
goto bad;
}
*new_snapshot = 0;
ps->valid = le32_to_cpu(dh->valid);
ps->version = le32_to_cpu(dh->version);
chunk_size = le32_to_cpu(dh->chunk_size);
if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size)
return 0;
DMWARN("chunk size %llu in device metadata overrides "
"table chunk size of %llu.",
(unsigned long long)chunk_size,
(unsigned long long)ps->snap->chunk_size);
/* We had a bogus chunk_size. Fix stuff up. */
free_area(ps);
ps->snap->chunk_size = chunk_size;
ps->snap->chunk_mask = chunk_size - 1;
ps->snap->chunk_shift = ffs(chunk_size) - 1;
r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
ps->io_client);
if (r)
return r;
r = alloc_area(ps);
return r;
bad:
free_area(ps);
return r; return r;
} }
static int write_header(struct pstore *ps) void dm_exception_store_exit(void)
{ {
struct disk_header *dh; dm_persistent_snapshot_exit();
dm_transient_snapshot_exit();
memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
dh = (struct disk_header *) ps->area;
dh->magic = cpu_to_le32(SNAP_MAGIC);
dh->valid = cpu_to_le32(ps->valid);
dh->version = cpu_to_le32(ps->version);
dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
return chunk_io(ps, 0, WRITE, 1);
}
/*
* Access functions for the disk exceptions, these do the endian conversions.
*/
static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
{
BUG_ON(index >= ps->exceptions_per_area);
return ((struct disk_exception *) ps->area) + index;
}
static void read_exception(struct pstore *ps,
uint32_t index, struct disk_exception *result)
{
struct disk_exception *e = get_exception(ps, index);
/* copy it */
result->old_chunk = le64_to_cpu(e->old_chunk);
result->new_chunk = le64_to_cpu(e->new_chunk);
}
static void write_exception(struct pstore *ps,
uint32_t index, struct disk_exception *de)
{
struct disk_exception *e = get_exception(ps, index);
/* copy it */
e->old_chunk = cpu_to_le64(de->old_chunk);
e->new_chunk = cpu_to_le64(de->new_chunk);
}
/*
* Registers the exceptions that are present in the current area.
* 'full' is filled in to indicate if the area has been
* filled.
*/
static int insert_exceptions(struct pstore *ps, int *full)
{
int r;
unsigned int i;
struct disk_exception de;
/* presume the area is full */
*full = 1;
for (i = 0; i < ps->exceptions_per_area; i++) {
read_exception(ps, i, &de);
/*
* If the new_chunk is pointing at the start of
* the COW device, where the first metadata area
* is we know that we've hit the end of the
* exceptions. Therefore the area is not full.
*/
if (de.new_chunk == 0LL) {
ps->current_committed = i;
*full = 0;
break;
}
/*
* Keep track of the start of the free chunks.
*/
if (ps->next_free <= de.new_chunk)
ps->next_free = de.new_chunk + 1;
/*
* Otherwise we add the exception to the snapshot.
*/
r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk);
if (r)
return r;
}
return 0;
}
static int read_exceptions(struct pstore *ps)
{
int r, full = 1;
/*
* Keeping reading chunks and inserting exceptions until
* we find a partially full area.
*/
for (ps->current_area = 0; full; ps->current_area++) {
r = area_io(ps, READ);
if (r)
return r;
r = insert_exceptions(ps, &full);
if (r)
return r;
}
ps->current_area--;
return 0;
}
static struct pstore *get_info(struct exception_store *store)
{
return (struct pstore *) store->context;
}
static void persistent_fraction_full(struct exception_store *store,
sector_t *numerator, sector_t *denominator)
{
*numerator = get_info(store)->next_free * store->snap->chunk_size;
*denominator = get_dev_size(store->snap->cow->bdev);
}
static void persistent_destroy(struct exception_store *store)
{
struct pstore *ps = get_info(store);
destroy_workqueue(ps->metadata_wq);
dm_io_client_destroy(ps->io_client);
vfree(ps->callbacks);
free_area(ps);
kfree(ps);
}
static int persistent_read_metadata(struct exception_store *store)
{
int r, uninitialized_var(new_snapshot);
struct pstore *ps = get_info(store);
/*
* Read the snapshot header.
*/
r = read_header(ps, &new_snapshot);
if (r)
return r;
/*
* Now we know correct chunk_size, complete the initialisation.
*/
ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
sizeof(struct disk_exception);
ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
sizeof(*ps->callbacks));
if (!ps->callbacks)
return -ENOMEM;
/*
* Do we need to setup a new snapshot ?
*/
if (new_snapshot) {
r = write_header(ps);
if (r) {
DMWARN("write_header failed");
return r;
}
ps->current_area = 0;
zero_memory_area(ps);
r = zero_disk_area(ps, 0);
if (r) {
DMWARN("zero_disk_area(0) failed");
return r;
}
} else {
/*
* Sanity checks.
*/
if (ps->version != SNAPSHOT_DISK_VERSION) {
DMWARN("unable to handle snapshot disk version %d",
ps->version);
return -EINVAL;
}
/*
* Metadata are valid, but snapshot is invalidated
*/
if (!ps->valid)
return 1;
/*
* Read the metadata.
*/
r = read_exceptions(ps);
if (r)
return r;
}
return 0;
}
static int persistent_prepare(struct exception_store *store,
struct dm_snap_exception *e)
{
struct pstore *ps = get_info(store);
uint32_t stride;
chunk_t next_free;
sector_t size = get_dev_size(store->snap->cow->bdev);
/* Is there enough room ? */
if (size < ((ps->next_free + 1) * store->snap->chunk_size))
return -ENOSPC;
e->new_chunk = ps->next_free;
/*
* Move onto the next free pending, making sure to take
* into account the location of the metadata chunks.
*/
stride = (ps->exceptions_per_area + 1);
next_free = ++ps->next_free;
if (sector_div(next_free, stride) == 1)
ps->next_free++;
atomic_inc(&ps->pending_count);
return 0;
}
static void persistent_commit(struct exception_store *store,
struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context)
{
unsigned int i;
struct pstore *ps = get_info(store);
struct disk_exception de;
struct commit_callback *cb;
de.old_chunk = e->old_chunk;
de.new_chunk = e->new_chunk;
write_exception(ps, ps->current_committed++, &de);
/*
* Add the callback to the back of the array. This code
* is the only place where the callback array is
* manipulated, and we know that it will never be called
* multiple times concurrently.
*/
cb = ps->callbacks + ps->callback_count++;
cb->callback = callback;
cb->context = callback_context;
/*
* If there are exceptions in flight and we have not yet
* filled this metadata area there's nothing more to do.
*/
if (!atomic_dec_and_test(&ps->pending_count) &&
(ps->current_committed != ps->exceptions_per_area))
return;
/*
* If we completely filled the current area, then wipe the next one.
*/
if ((ps->current_committed == ps->exceptions_per_area) &&
zero_disk_area(ps, ps->current_area + 1))
ps->valid = 0;
/*
* Commit exceptions to disk.
*/
if (ps->valid && area_io(ps, WRITE))
ps->valid = 0;
/*
* Advance to the next area if this one is full.
*/
if (ps->current_committed == ps->exceptions_per_area) {
ps->current_committed = 0;
ps->current_area++;
zero_memory_area(ps);
}
for (i = 0; i < ps->callback_count; i++) {
cb = ps->callbacks + i;
cb->callback(cb->context, ps->valid);
}
ps->callback_count = 0;
}
static void persistent_drop(struct exception_store *store)
{
struct pstore *ps = get_info(store);
ps->valid = 0;
if (write_header(ps))
DMWARN("write header failed");
}
int dm_create_persistent(struct exception_store *store)
{
struct pstore *ps;
/* allocate the pstore */
ps = kmalloc(sizeof(*ps), GFP_KERNEL);
if (!ps)
return -ENOMEM;
ps->snap = store->snap;
ps->valid = 1;
ps->version = SNAPSHOT_DISK_VERSION;
ps->area = NULL;
ps->next_free = 2; /* skipping the header and first area */
ps->current_committed = 0;
ps->callback_count = 0;
atomic_set(&ps->pending_count, 0);
ps->callbacks = NULL;
ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
if (!ps->metadata_wq) {
kfree(ps);
DMERR("couldn't start header metadata update thread");
return -ENOMEM;
}
store->destroy = persistent_destroy;
store->read_metadata = persistent_read_metadata;
store->prepare_exception = persistent_prepare;
store->commit_exception = persistent_commit;
store->drop_snapshot = persistent_drop;
store->fraction_full = persistent_fraction_full;
store->context = ps;
return 0;
}
/*-----------------------------------------------------------------
* Implementation of the store for non-persistent snapshots.
*---------------------------------------------------------------*/
struct transient_c {
sector_t next_free;
};
static void transient_destroy(struct exception_store *store)
{
kfree(store->context);
}
static int transient_read_metadata(struct exception_store *store)
{
return 0;
}
static int transient_prepare(struct exception_store *store,
struct dm_snap_exception *e)
{
struct transient_c *tc = (struct transient_c *) store->context;
sector_t size = get_dev_size(store->snap->cow->bdev);
if (size < (tc->next_free + store->snap->chunk_size))
return -1;
e->new_chunk = sector_to_chunk(store->snap, tc->next_free);
tc->next_free += store->snap->chunk_size;
return 0;
}
static void transient_commit(struct exception_store *store,
struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context)
{
/* Just succeed */
callback(callback_context, 1);
}
static void transient_fraction_full(struct exception_store *store,
sector_t *numerator, sector_t *denominator)
{
*numerator = ((struct transient_c *) store->context)->next_free;
*denominator = get_dev_size(store->snap->cow->bdev);
}
int dm_create_transient(struct exception_store *store)
{
struct transient_c *tc;
store->destroy = transient_destroy;
store->read_metadata = transient_read_metadata;
store->prepare_exception = transient_prepare;
store->commit_exception = transient_commit;
store->drop_snapshot = NULL;
store->fraction_full = transient_fraction_full;
tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
if (!tc)
return -ENOMEM;
tc->next_free = 0;
store->context = tc;
return 0;
} }

View File

@ -0,0 +1,148 @@
/*
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
* Copyright (C) 2008 Red Hat, Inc. All rights reserved.
*
* Device-mapper snapshot exception store.
*
* This file is released under the GPL.
*/
#ifndef _LINUX_DM_EXCEPTION_STORE
#define _LINUX_DM_EXCEPTION_STORE
#include <linux/blkdev.h>
#include <linux/device-mapper.h>
/*
* The snapshot code deals with largish chunks of the disk at a
* time. Typically 32k - 512k.
*/
typedef sector_t chunk_t;
/*
* An exception is used where an old chunk of data has been
* replaced by a new one.
* If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
* of chunks that follow contiguously. Remaining bits hold the number of the
* chunk within the device.
*/
struct dm_snap_exception {
struct list_head hash_list;
chunk_t old_chunk;
chunk_t new_chunk;
};
/*
* Abstraction to handle the meta/layout of exception stores (the
* COW device).
*/
struct dm_exception_store {
/*
* Destroys this object when you've finished with it.
*/
void (*destroy) (struct dm_exception_store *store);
/*
* The target shouldn't read the COW device until this is
* called. As exceptions are read from the COW, they are
* reported back via the callback.
*/
int (*read_metadata) (struct dm_exception_store *store,
int (*callback)(void *callback_context,
chunk_t old, chunk_t new),
void *callback_context);
/*
* Find somewhere to store the next exception.
*/
int (*prepare_exception) (struct dm_exception_store *store,
struct dm_snap_exception *e);
/*
* Update the metadata with this exception.
*/
void (*commit_exception) (struct dm_exception_store *store,
struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context);
/*
* The snapshot is invalid, note this in the metadata.
*/
void (*drop_snapshot) (struct dm_exception_store *store);
int (*status) (struct dm_exception_store *store, status_type_t status,
char *result, unsigned int maxlen);
/*
* Return how full the snapshot is.
*/
void (*fraction_full) (struct dm_exception_store *store,
sector_t *numerator,
sector_t *denominator);
struct dm_snapshot *snap;
void *context;
};
/*
* Funtions to manipulate consecutive chunks
*/
# if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
# define DM_CHUNK_CONSECUTIVE_BITS 8
# define DM_CHUNK_NUMBER_BITS 56
static inline chunk_t dm_chunk_number(chunk_t chunk)
{
return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
}
static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
{
return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
}
static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
{
e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
BUG_ON(!dm_consecutive_chunk_count(e));
}
# else
# define DM_CHUNK_CONSECUTIVE_BITS 0
static inline chunk_t dm_chunk_number(chunk_t chunk)
{
return chunk;
}
static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
{
return 0;
}
static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
{
}
# endif
int dm_exception_store_init(void);
void dm_exception_store_exit(void);
/*
* Two exception store implementations.
*/
int dm_persistent_snapshot_init(void);
void dm_persistent_snapshot_exit(void);
int dm_transient_snapshot_init(void);
void dm_transient_snapshot_exit(void);
int dm_create_persistent(struct dm_exception_store *store);
int dm_create_transient(struct dm_exception_store *store);
#endif /* _LINUX_DM_EXCEPTION_STORE */

View File

@ -233,7 +233,7 @@ static void __hash_remove(struct hash_cell *hc)
} }
if (hc->new_map) if (hc->new_map)
dm_table_put(hc->new_map); dm_table_destroy(hc->new_map);
dm_put(hc->md); dm_put(hc->md);
free_cell(hc); free_cell(hc);
} }
@ -827,8 +827,8 @@ static int do_resume(struct dm_ioctl *param)
r = dm_swap_table(md, new_map); r = dm_swap_table(md, new_map);
if (r) { if (r) {
dm_table_destroy(new_map);
dm_put(md); dm_put(md);
dm_table_put(new_map);
return r; return r;
} }
@ -836,8 +836,6 @@ static int do_resume(struct dm_ioctl *param)
set_disk_ro(dm_disk(md), 0); set_disk_ro(dm_disk(md), 0);
else else
set_disk_ro(dm_disk(md), 1); set_disk_ro(dm_disk(md), 1);
dm_table_put(new_map);
} }
if (dm_suspended(md)) if (dm_suspended(md))
@ -1080,7 +1078,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
} }
if (hc->new_map) if (hc->new_map)
dm_table_put(hc->new_map); dm_table_destroy(hc->new_map);
hc->new_map = t; hc->new_map = t;
up_write(&_hash_lock); up_write(&_hash_lock);
@ -1109,7 +1107,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size)
} }
if (hc->new_map) { if (hc->new_map) {
dm_table_put(hc->new_map); dm_table_destroy(hc->new_map);
hc->new_map = NULL; hc->new_map = NULL;
} }
@ -1550,8 +1548,10 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid)
goto out; goto out;
} }
strcpy(name, hc->name); if (name)
strcpy(uuid, hc->uuid ? : ""); strcpy(name, hc->name);
if (uuid)
strcpy(uuid, hc->uuid ? : "");
out: out:
up_read(&_hash_lock); up_read(&_hash_lock);

View File

@ -142,6 +142,7 @@ static struct target_type linear_target = {
.status = linear_status, .status = linear_status,
.ioctl = linear_ioctl, .ioctl = linear_ioctl,
.merge = linear_merge, .merge = linear_merge,
.features = DM_TARGET_SUPPORTS_BARRIERS,
}; };
int __init dm_linear_init(void) int __init dm_linear_init(void)
@ -156,8 +157,5 @@ int __init dm_linear_init(void)
void dm_linear_exit(void) void dm_linear_exit(void)
{ {
int r = dm_unregister_target(&linear_target); dm_unregister_target(&linear_target);
if (r < 0)
DMERR("unregister failed %d", r);
} }

View File

@ -326,8 +326,6 @@ static void header_from_disk(struct log_header *core, struct log_header *disk)
static int rw_header(struct log_c *lc, int rw) static int rw_header(struct log_c *lc, int rw)
{ {
lc->io_req.bi_rw = rw; lc->io_req.bi_rw = rw;
lc->io_req.mem.ptr.vma = lc->disk_header;
lc->io_req.notify.fn = NULL;
return dm_io(&lc->io_req, 1, &lc->header_location, NULL); return dm_io(&lc->io_req, 1, &lc->header_location, NULL);
} }
@ -362,10 +360,15 @@ static int read_header(struct log_c *log)
return 0; return 0;
} }
static inline int write_header(struct log_c *log) static int _check_region_size(struct dm_target *ti, uint32_t region_size)
{ {
header_to_disk(&log->header, log->disk_header); if (region_size < 2 || region_size > ti->len)
return rw_header(log, WRITE); return 0;
if (!is_power_of_2(region_size))
return 0;
return 1;
} }
/*---------------------------------------------------------------- /*----------------------------------------------------------------
@ -403,8 +406,9 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
} }
} }
if (sscanf(argv[0], "%u", &region_size) != 1) { if (sscanf(argv[0], "%u", &region_size) != 1 ||
DMWARN("invalid region size string"); !_check_region_size(ti, region_size)) {
DMWARN("invalid region size %s", argv[0]);
return -EINVAL; return -EINVAL;
} }
@ -453,8 +457,18 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
*/ */
buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) +
bitset_size, ti->limits.hardsect_size); bitset_size, ti->limits.hardsect_size);
if (buf_size > dev->bdev->bd_inode->i_size) {
DMWARN("log device %s too small: need %llu bytes",
dev->name, (unsigned long long)buf_size);
kfree(lc);
return -EINVAL;
}
lc->header_location.count = buf_size >> SECTOR_SHIFT; lc->header_location.count = buf_size >> SECTOR_SHIFT;
lc->io_req.mem.type = DM_IO_VMA; lc->io_req.mem.type = DM_IO_VMA;
lc->io_req.notify.fn = NULL;
lc->io_req.client = dm_io_client_create(dm_div_up(buf_size, lc->io_req.client = dm_io_client_create(dm_div_up(buf_size,
PAGE_SIZE)); PAGE_SIZE));
if (IS_ERR(lc->io_req.client)) { if (IS_ERR(lc->io_req.client)) {
@ -467,10 +481,12 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
lc->disk_header = vmalloc(buf_size); lc->disk_header = vmalloc(buf_size);
if (!lc->disk_header) { if (!lc->disk_header) {
DMWARN("couldn't allocate disk log buffer"); DMWARN("couldn't allocate disk log buffer");
dm_io_client_destroy(lc->io_req.client);
kfree(lc); kfree(lc);
return -ENOMEM; return -ENOMEM;
} }
lc->io_req.mem.ptr.vma = lc->disk_header;
lc->clean_bits = (void *)lc->disk_header + lc->clean_bits = (void *)lc->disk_header +
(LOG_OFFSET << SECTOR_SHIFT); (LOG_OFFSET << SECTOR_SHIFT);
} }
@ -482,6 +498,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
DMWARN("couldn't allocate sync bitset"); DMWARN("couldn't allocate sync bitset");
if (!dev) if (!dev)
vfree(lc->clean_bits); vfree(lc->clean_bits);
else
dm_io_client_destroy(lc->io_req.client);
vfree(lc->disk_header); vfree(lc->disk_header);
kfree(lc); kfree(lc);
return -ENOMEM; return -ENOMEM;
@ -495,6 +513,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
vfree(lc->sync_bits); vfree(lc->sync_bits);
if (!dev) if (!dev)
vfree(lc->clean_bits); vfree(lc->clean_bits);
else
dm_io_client_destroy(lc->io_req.client);
vfree(lc->disk_header); vfree(lc->disk_header);
kfree(lc); kfree(lc);
return -ENOMEM; return -ENOMEM;
@ -631,8 +651,10 @@ static int disk_resume(struct dm_dirty_log *log)
/* set the correct number of regions in the header */ /* set the correct number of regions in the header */
lc->header.nr_regions = lc->region_count; lc->header.nr_regions = lc->region_count;
header_to_disk(&lc->header, lc->disk_header);
/* write the new header */ /* write the new header */
r = write_header(lc); r = rw_header(lc, WRITE);
if (r) { if (r) {
DMWARN("%s: Failed to write header on dirty region log device", DMWARN("%s: Failed to write header on dirty region log device",
lc->log_dev->name); lc->log_dev->name);
@ -682,7 +704,7 @@ static int disk_flush(struct dm_dirty_log *log)
if (!lc->touched) if (!lc->touched)
return 0; return 0;
r = write_header(lc); r = rw_header(lc, WRITE);
if (r) if (r)
fail_log_device(lc); fail_log_device(lc);
else else

View File

@ -889,7 +889,7 @@ static int fail_path(struct pgpath *pgpath)
dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti, dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
pgpath->path.dev->name, m->nr_valid_paths); pgpath->path.dev->name, m->nr_valid_paths);
queue_work(kmultipathd, &m->trigger_event); schedule_work(&m->trigger_event);
queue_work(kmultipathd, &pgpath->deactivate_path); queue_work(kmultipathd, &pgpath->deactivate_path);
out: out:
@ -932,7 +932,7 @@ static int reinstate_path(struct pgpath *pgpath)
dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti, dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
pgpath->path.dev->name, m->nr_valid_paths); pgpath->path.dev->name, m->nr_valid_paths);
queue_work(kmultipathd, &m->trigger_event); schedule_work(&m->trigger_event);
out: out:
spin_unlock_irqrestore(&m->lock, flags); spin_unlock_irqrestore(&m->lock, flags);
@ -976,7 +976,7 @@ static void bypass_pg(struct multipath *m, struct priority_group *pg,
spin_unlock_irqrestore(&m->lock, flags); spin_unlock_irqrestore(&m->lock, flags);
queue_work(kmultipathd, &m->trigger_event); schedule_work(&m->trigger_event);
} }
/* /*
@ -1006,7 +1006,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
} }
spin_unlock_irqrestore(&m->lock, flags); spin_unlock_irqrestore(&m->lock, flags);
queue_work(kmultipathd, &m->trigger_event); schedule_work(&m->trigger_event);
return 0; return 0;
} }
@ -1495,14 +1495,10 @@ static int __init dm_multipath_init(void)
static void __exit dm_multipath_exit(void) static void __exit dm_multipath_exit(void)
{ {
int r;
destroy_workqueue(kmpath_handlerd); destroy_workqueue(kmpath_handlerd);
destroy_workqueue(kmultipathd); destroy_workqueue(kmultipathd);
r = dm_unregister_target(&multipath_target); dm_unregister_target(&multipath_target);
if (r < 0)
DMERR("target unregister failed %d", r);
kmem_cache_destroy(_mpio_cache); kmem_cache_destroy(_mpio_cache);
} }

View File

@ -197,9 +197,6 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
struct mirror_set *ms = m->ms; struct mirror_set *ms = m->ms;
struct mirror *new; struct mirror *new;
if (!errors_handled(ms))
return;
/* /*
* error_count is used for nothing more than a * error_count is used for nothing more than a
* simple way to tell if a device has encountered * simple way to tell if a device has encountered
@ -210,6 +207,9 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
if (test_and_set_bit(error_type, &m->error_type)) if (test_and_set_bit(error_type, &m->error_type))
return; return;
if (!errors_handled(ms))
return;
if (m != get_default_mirror(ms)) if (m != get_default_mirror(ms))
goto out; goto out;
@ -808,12 +808,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
kfree(ms); kfree(ms);
} }
static inline int _check_region_size(struct dm_target *ti, uint32_t size)
{
return !(size % (PAGE_SIZE >> 9) || !is_power_of_2(size) ||
size > ti->len);
}
static int get_mirror(struct mirror_set *ms, struct dm_target *ti, static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
unsigned int mirror, char **argv) unsigned int mirror, char **argv)
{ {
@ -872,12 +866,6 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
return NULL; return NULL;
} }
if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
ti->error = "Invalid region size";
dm_dirty_log_destroy(dl);
return NULL;
}
return dl; return dl;
} }
@ -1300,11 +1288,7 @@ static int __init dm_mirror_init(void)
static void __exit dm_mirror_exit(void) static void __exit dm_mirror_exit(void)
{ {
int r; dm_unregister_target(&mirror_target);
r = dm_unregister_target(&mirror_target);
if (r < 0)
DMERR("unregister failed %d", r);
} }
/* Module hooks */ /* Module hooks */

View File

@ -0,0 +1,704 @@
/*
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
* Copyright (C) 2006-2008 Red Hat GmbH
*
* This file is released under the GPL.
*/
#include "dm-exception-store.h"
#include "dm-snap.h"
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/dm-io.h>
#define DM_MSG_PREFIX "persistent snapshot"
#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
/*-----------------------------------------------------------------
* Persistent snapshots, by persistent we mean that the snapshot
* will survive a reboot.
*---------------------------------------------------------------*/
/*
* We need to store a record of which parts of the origin have
* been copied to the snapshot device. The snapshot code
* requires that we copy exception chunks to chunk aligned areas
* of the COW store. It makes sense therefore, to store the
* metadata in chunk size blocks.
*
* There is no backward or forward compatibility implemented,
* snapshots with different disk versions than the kernel will
* not be usable. It is expected that "lvcreate" will blank out
* the start of a fresh COW device before calling the snapshot
* constructor.
*
* The first chunk of the COW device just contains the header.
* After this there is a chunk filled with exception metadata,
* followed by as many exception chunks as can fit in the
* metadata areas.
*
* All on disk structures are in little-endian format. The end
* of the exceptions info is indicated by an exception with a
* new_chunk of 0, which is invalid since it would point to the
* header chunk.
*/
/*
* Magic for persistent snapshots: "SnAp" - Feeble isn't it.
*/
#define SNAP_MAGIC 0x70416e53
/*
* The on-disk version of the metadata.
*/
#define SNAPSHOT_DISK_VERSION 1
struct disk_header {
uint32_t magic;
/*
* Is this snapshot valid. There is no way of recovering
* an invalid snapshot.
*/
uint32_t valid;
/*
* Simple, incrementing version. no backward
* compatibility.
*/
uint32_t version;
/* In sectors */
uint32_t chunk_size;
};
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
struct commit_callback {
void (*callback)(void *, int success);
void *context;
};
/*
* The top level structure for a persistent exception store.
*/
struct pstore {
struct dm_snapshot *snap; /* up pointer to my snapshot */
int version;
int valid;
uint32_t exceptions_per_area;
/*
* Now that we have an asynchronous kcopyd there is no
* need for large chunk sizes, so it wont hurt to have a
* whole chunks worth of metadata in memory at once.
*/
void *area;
/*
* An area of zeros used to clear the next area.
*/
void *zero_area;
/*
* Used to keep track of which metadata area the data in
* 'chunk' refers to.
*/
chunk_t current_area;
/*
* The next free chunk for an exception.
*/
chunk_t next_free;
/*
* The index of next free exception in the current
* metadata area.
*/
uint32_t current_committed;
atomic_t pending_count;
uint32_t callback_count;
struct commit_callback *callbacks;
struct dm_io_client *io_client;
struct workqueue_struct *metadata_wq;
};
static unsigned sectors_to_pages(unsigned sectors)
{
return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
}
static int alloc_area(struct pstore *ps)
{
int r = -ENOMEM;
size_t len;
len = ps->snap->chunk_size << SECTOR_SHIFT;
/*
* Allocate the chunk_size block of memory that will hold
* a single metadata area.
*/
ps->area = vmalloc(len);
if (!ps->area)
return r;
ps->zero_area = vmalloc(len);
if (!ps->zero_area) {
vfree(ps->area);
return r;
}
memset(ps->zero_area, 0, len);
return 0;
}
static void free_area(struct pstore *ps)
{
vfree(ps->area);
ps->area = NULL;
vfree(ps->zero_area);
ps->zero_area = NULL;
}
struct mdata_req {
struct dm_io_region *where;
struct dm_io_request *io_req;
struct work_struct work;
int result;
};
static void do_metadata(struct work_struct *work)
{
struct mdata_req *req = container_of(work, struct mdata_req, work);
req->result = dm_io(req->io_req, 1, req->where, NULL);
}
/*
* Read or write a chunk aligned and sized block of data from a device.
*/
static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
{
struct dm_io_region where = {
.bdev = ps->snap->cow->bdev,
.sector = ps->snap->chunk_size * chunk,
.count = ps->snap->chunk_size,
};
struct dm_io_request io_req = {
.bi_rw = rw,
.mem.type = DM_IO_VMA,
.mem.ptr.vma = ps->area,
.client = ps->io_client,
.notify.fn = NULL,
};
struct mdata_req req;
if (!metadata)
return dm_io(&io_req, 1, &where, NULL);
req.where = &where;
req.io_req = &io_req;
/*
* Issue the synchronous I/O from a different thread
* to avoid generic_make_request recursion.
*/
INIT_WORK(&req.work, do_metadata);
queue_work(ps->metadata_wq, &req.work);
flush_workqueue(ps->metadata_wq);
return req.result;
}
/*
* Convert a metadata area index to a chunk index.
*/
static chunk_t area_location(struct pstore *ps, chunk_t area)
{
return 1 + ((ps->exceptions_per_area + 1) * area);
}
/*
* Read or write a metadata area. Remembering to skip the first
* chunk which holds the header.
*/
static int area_io(struct pstore *ps, int rw)
{
int r;
chunk_t chunk;
chunk = area_location(ps, ps->current_area);
r = chunk_io(ps, chunk, rw, 0);
if (r)
return r;
return 0;
}
static void zero_memory_area(struct pstore *ps)
{
memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
}
static int zero_disk_area(struct pstore *ps, chunk_t area)
{
struct dm_io_region where = {
.bdev = ps->snap->cow->bdev,
.sector = ps->snap->chunk_size * area_location(ps, area),
.count = ps->snap->chunk_size,
};
struct dm_io_request io_req = {
.bi_rw = WRITE,
.mem.type = DM_IO_VMA,
.mem.ptr.vma = ps->zero_area,
.client = ps->io_client,
.notify.fn = NULL,
};
return dm_io(&io_req, 1, &where, NULL);
}
static int read_header(struct pstore *ps, int *new_snapshot)
{
int r;
struct disk_header *dh;
chunk_t chunk_size;
int chunk_size_supplied = 1;
/*
* Use default chunk size (or hardsect_size, if larger) if none supplied
*/
if (!ps->snap->chunk_size) {
ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
bdev_hardsect_size(ps->snap->cow->bdev) >> 9);
ps->snap->chunk_mask = ps->snap->chunk_size - 1;
ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1;
chunk_size_supplied = 0;
}
ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
chunk_size));
if (IS_ERR(ps->io_client))
return PTR_ERR(ps->io_client);
r = alloc_area(ps);
if (r)
return r;
r = chunk_io(ps, 0, READ, 1);
if (r)
goto bad;
dh = (struct disk_header *) ps->area;
if (le32_to_cpu(dh->magic) == 0) {
*new_snapshot = 1;
return 0;
}
if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
DMWARN("Invalid or corrupt snapshot");
r = -ENXIO;
goto bad;
}
*new_snapshot = 0;
ps->valid = le32_to_cpu(dh->valid);
ps->version = le32_to_cpu(dh->version);
chunk_size = le32_to_cpu(dh->chunk_size);
if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size)
return 0;
DMWARN("chunk size %llu in device metadata overrides "
"table chunk size of %llu.",
(unsigned long long)chunk_size,
(unsigned long long)ps->snap->chunk_size);
/* We had a bogus chunk_size. Fix stuff up. */
free_area(ps);
ps->snap->chunk_size = chunk_size;
ps->snap->chunk_mask = chunk_size - 1;
ps->snap->chunk_shift = ffs(chunk_size) - 1;
r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
ps->io_client);
if (r)
return r;
r = alloc_area(ps);
return r;
bad:
free_area(ps);
return r;
}
static int write_header(struct pstore *ps)
{
struct disk_header *dh;
memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
dh = (struct disk_header *) ps->area;
dh->magic = cpu_to_le32(SNAP_MAGIC);
dh->valid = cpu_to_le32(ps->valid);
dh->version = cpu_to_le32(ps->version);
dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
return chunk_io(ps, 0, WRITE, 1);
}
/*
* Access functions for the disk exceptions, these do the endian conversions.
*/
static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
{
BUG_ON(index >= ps->exceptions_per_area);
return ((struct disk_exception *) ps->area) + index;
}
static void read_exception(struct pstore *ps,
uint32_t index, struct disk_exception *result)
{
struct disk_exception *e = get_exception(ps, index);
/* copy it */
result->old_chunk = le64_to_cpu(e->old_chunk);
result->new_chunk = le64_to_cpu(e->new_chunk);
}
static void write_exception(struct pstore *ps,
uint32_t index, struct disk_exception *de)
{
struct disk_exception *e = get_exception(ps, index);
/* copy it */
e->old_chunk = cpu_to_le64(de->old_chunk);
e->new_chunk = cpu_to_le64(de->new_chunk);
}
/*
* Registers the exceptions that are present in the current area.
* 'full' is filled in to indicate if the area has been
* filled.
*/
static int insert_exceptions(struct pstore *ps,
int (*callback)(void *callback_context,
chunk_t old, chunk_t new),
void *callback_context,
int *full)
{
int r;
unsigned int i;
struct disk_exception de;
/* presume the area is full */
*full = 1;
for (i = 0; i < ps->exceptions_per_area; i++) {
read_exception(ps, i, &de);
/*
* If the new_chunk is pointing at the start of
* the COW device, where the first metadata area
* is we know that we've hit the end of the
* exceptions. Therefore the area is not full.
*/
if (de.new_chunk == 0LL) {
ps->current_committed = i;
*full = 0;
break;
}
/*
* Keep track of the start of the free chunks.
*/
if (ps->next_free <= de.new_chunk)
ps->next_free = de.new_chunk + 1;
/*
* Otherwise we add the exception to the snapshot.
*/
r = callback(callback_context, de.old_chunk, de.new_chunk);
if (r)
return r;
}
return 0;
}
static int read_exceptions(struct pstore *ps,
int (*callback)(void *callback_context, chunk_t old,
chunk_t new),
void *callback_context)
{
int r, full = 1;
/*
* Keeping reading chunks and inserting exceptions until
* we find a partially full area.
*/
for (ps->current_area = 0; full; ps->current_area++) {
r = area_io(ps, READ);
if (r)
return r;
r = insert_exceptions(ps, callback, callback_context, &full);
if (r)
return r;
}
ps->current_area--;
return 0;
}
static struct pstore *get_info(struct dm_exception_store *store)
{
return (struct pstore *) store->context;
}
static void persistent_fraction_full(struct dm_exception_store *store,
sector_t *numerator, sector_t *denominator)
{
*numerator = get_info(store)->next_free * store->snap->chunk_size;
*denominator = get_dev_size(store->snap->cow->bdev);
}
static void persistent_destroy(struct dm_exception_store *store)
{
struct pstore *ps = get_info(store);
destroy_workqueue(ps->metadata_wq);
dm_io_client_destroy(ps->io_client);
vfree(ps->callbacks);
free_area(ps);
kfree(ps);
}
static int persistent_read_metadata(struct dm_exception_store *store,
int (*callback)(void *callback_context,
chunk_t old, chunk_t new),
void *callback_context)
{
int r, uninitialized_var(new_snapshot);
struct pstore *ps = get_info(store);
/*
* Read the snapshot header.
*/
r = read_header(ps, &new_snapshot);
if (r)
return r;
/*
* Now we know correct chunk_size, complete the initialisation.
*/
ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
sizeof(struct disk_exception);
ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
sizeof(*ps->callbacks));
if (!ps->callbacks)
return -ENOMEM;
/*
* Do we need to setup a new snapshot ?
*/
if (new_snapshot) {
r = write_header(ps);
if (r) {
DMWARN("write_header failed");
return r;
}
ps->current_area = 0;
zero_memory_area(ps);
r = zero_disk_area(ps, 0);
if (r) {
DMWARN("zero_disk_area(0) failed");
return r;
}
} else {
/*
* Sanity checks.
*/
if (ps->version != SNAPSHOT_DISK_VERSION) {
DMWARN("unable to handle snapshot disk version %d",
ps->version);
return -EINVAL;
}
/*
* Metadata are valid, but snapshot is invalidated
*/
if (!ps->valid)
return 1;
/*
* Read the metadata.
*/
r = read_exceptions(ps, callback, callback_context);
if (r)
return r;
}
return 0;
}
static int persistent_prepare_exception(struct dm_exception_store *store,
struct dm_snap_exception *e)
{
struct pstore *ps = get_info(store);
uint32_t stride;
chunk_t next_free;
sector_t size = get_dev_size(store->snap->cow->bdev);
/* Is there enough room ? */
if (size < ((ps->next_free + 1) * store->snap->chunk_size))
return -ENOSPC;
e->new_chunk = ps->next_free;
/*
* Move onto the next free pending, making sure to take
* into account the location of the metadata chunks.
*/
stride = (ps->exceptions_per_area + 1);
next_free = ++ps->next_free;
if (sector_div(next_free, stride) == 1)
ps->next_free++;
atomic_inc(&ps->pending_count);
return 0;
}
static void persistent_commit_exception(struct dm_exception_store *store,
struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context)
{
unsigned int i;
struct pstore *ps = get_info(store);
struct disk_exception de;
struct commit_callback *cb;
de.old_chunk = e->old_chunk;
de.new_chunk = e->new_chunk;
write_exception(ps, ps->current_committed++, &de);
/*
* Add the callback to the back of the array. This code
* is the only place where the callback array is
* manipulated, and we know that it will never be called
* multiple times concurrently.
*/
cb = ps->callbacks + ps->callback_count++;
cb->callback = callback;
cb->context = callback_context;
/*
* If there are exceptions in flight and we have not yet
* filled this metadata area there's nothing more to do.
*/
if (!atomic_dec_and_test(&ps->pending_count) &&
(ps->current_committed != ps->exceptions_per_area))
return;
/*
* If we completely filled the current area, then wipe the next one.
*/
if ((ps->current_committed == ps->exceptions_per_area) &&
zero_disk_area(ps, ps->current_area + 1))
ps->valid = 0;
/*
* Commit exceptions to disk.
*/
if (ps->valid && area_io(ps, WRITE))
ps->valid = 0;
/*
* Advance to the next area if this one is full.
*/
if (ps->current_committed == ps->exceptions_per_area) {
ps->current_committed = 0;
ps->current_area++;
zero_memory_area(ps);
}
for (i = 0; i < ps->callback_count; i++) {
cb = ps->callbacks + i;
cb->callback(cb->context, ps->valid);
}
ps->callback_count = 0;
}
static void persistent_drop_snapshot(struct dm_exception_store *store)
{
struct pstore *ps = get_info(store);
ps->valid = 0;
if (write_header(ps))
DMWARN("write header failed");
}
int dm_create_persistent(struct dm_exception_store *store)
{
struct pstore *ps;
/* allocate the pstore */
ps = kmalloc(sizeof(*ps), GFP_KERNEL);
if (!ps)
return -ENOMEM;
ps->snap = store->snap;
ps->valid = 1;
ps->version = SNAPSHOT_DISK_VERSION;
ps->area = NULL;
ps->next_free = 2; /* skipping the header and first area */
ps->current_committed = 0;
ps->callback_count = 0;
atomic_set(&ps->pending_count, 0);
ps->callbacks = NULL;
ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
if (!ps->metadata_wq) {
kfree(ps);
DMERR("couldn't start header metadata update thread");
return -ENOMEM;
}
store->destroy = persistent_destroy;
store->read_metadata = persistent_read_metadata;
store->prepare_exception = persistent_prepare_exception;
store->commit_exception = persistent_commit_exception;
store->drop_snapshot = persistent_drop_snapshot;
store->fraction_full = persistent_fraction_full;
store->context = ps;
return 0;
}
int dm_persistent_snapshot_init(void)
{
return 0;
}
void dm_persistent_snapshot_exit(void)
{
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
* Copyright (C) 2006-2008 Red Hat GmbH
*
* This file is released under the GPL.
*/
#include "dm-exception-store.h"
#include "dm-snap.h"
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/dm-io.h>
#define DM_MSG_PREFIX "transient snapshot"
/*-----------------------------------------------------------------
* Implementation of the store for non-persistent snapshots.
*---------------------------------------------------------------*/
struct transient_c {
sector_t next_free;
};
static void transient_destroy(struct dm_exception_store *store)
{
kfree(store->context);
}
static int transient_read_metadata(struct dm_exception_store *store,
int (*callback)(void *callback_context,
chunk_t old, chunk_t new),
void *callback_context)
{
return 0;
}
static int transient_prepare_exception(struct dm_exception_store *store,
struct dm_snap_exception *e)
{
struct transient_c *tc = (struct transient_c *) store->context;
sector_t size = get_dev_size(store->snap->cow->bdev);
if (size < (tc->next_free + store->snap->chunk_size))
return -1;
e->new_chunk = sector_to_chunk(store->snap, tc->next_free);
tc->next_free += store->snap->chunk_size;
return 0;
}
static void transient_commit_exception(struct dm_exception_store *store,
struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context)
{
/* Just succeed */
callback(callback_context, 1);
}
static void transient_fraction_full(struct dm_exception_store *store,
sector_t *numerator, sector_t *denominator)
{
*numerator = ((struct transient_c *) store->context)->next_free;
*denominator = get_dev_size(store->snap->cow->bdev);
}
int dm_create_transient(struct dm_exception_store *store)
{
struct transient_c *tc;
store->destroy = transient_destroy;
store->read_metadata = transient_read_metadata;
store->prepare_exception = transient_prepare_exception;
store->commit_exception = transient_commit_exception;
store->drop_snapshot = NULL;
store->fraction_full = transient_fraction_full;
tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
if (!tc)
return -ENOMEM;
tc->next_free = 0;
store->context = tc;
return 0;
}
int dm_transient_snapshot_init(void)
{
return 0;
}
void dm_transient_snapshot_exit(void)
{
}

View File

@ -9,6 +9,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/device-mapper.h> #include <linux/device-mapper.h>
#include <linux/delay.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
@ -20,6 +21,7 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/dm-kcopyd.h> #include <linux/dm-kcopyd.h>
#include "dm-exception-store.h"
#include "dm-snap.h" #include "dm-snap.h"
#include "dm-bio-list.h" #include "dm-bio-list.h"
@ -428,8 +430,13 @@ out:
list_add(&new_e->hash_list, e ? &e->hash_list : l); list_add(&new_e->hash_list, e ? &e->hash_list : l);
} }
int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new) /*
* Callback used by the exception stores to load exceptions when
* initialising.
*/
static int dm_add_exception(void *context, chunk_t old, chunk_t new)
{ {
struct dm_snapshot *s = context;
struct dm_snap_exception *e; struct dm_snap_exception *e;
e = alloc_exception(); e = alloc_exception();
@ -658,7 +665,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
spin_lock_init(&s->tracked_chunk_lock); spin_lock_init(&s->tracked_chunk_lock);
/* Metadata must only be loaded into one table at once */ /* Metadata must only be loaded into one table at once */
r = s->store.read_metadata(&s->store); r = s->store.read_metadata(&s->store, dm_add_exception, (void *)s);
if (r < 0) { if (r < 0) {
ti->error = "Failed to read snapshot metadata"; ti->error = "Failed to read snapshot metadata";
goto bad_load_and_register; goto bad_load_and_register;
@ -735,7 +742,7 @@ static void snapshot_dtr(struct dm_target *ti)
unregister_snapshot(s); unregister_snapshot(s);
while (atomic_read(&s->pending_exceptions_count)) while (atomic_read(&s->pending_exceptions_count))
yield(); msleep(1);
/* /*
* Ensure instructions in mempool_destroy aren't reordered * Ensure instructions in mempool_destroy aren't reordered
* before atomic_read. * before atomic_read.
@ -888,10 +895,10 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
/* /*
* Check for conflicting reads. This is extremely improbable, * Check for conflicting reads. This is extremely improbable,
* so yield() is sufficient and there is no need for a wait queue. * so msleep(1) is sufficient and there is no need for a wait queue.
*/ */
while (__chunk_is_tracked(s, pe->e.old_chunk)) while (__chunk_is_tracked(s, pe->e.old_chunk))
yield(); msleep(1);
/* /*
* Add a proper exception, and remove the * Add a proper exception, and remove the
@ -1404,6 +1411,12 @@ static int __init dm_snapshot_init(void)
{ {
int r; int r;
r = dm_exception_store_init();
if (r) {
DMERR("Failed to initialize exception stores");
return r;
}
r = dm_register_target(&snapshot_target); r = dm_register_target(&snapshot_target);
if (r) { if (r) {
DMERR("snapshot target register failed %d", r); DMERR("snapshot target register failed %d", r);
@ -1452,39 +1465,34 @@ static int __init dm_snapshot_init(void)
return 0; return 0;
bad_pending_pool: bad_pending_pool:
kmem_cache_destroy(tracked_chunk_cache); kmem_cache_destroy(tracked_chunk_cache);
bad5: bad5:
kmem_cache_destroy(pending_cache); kmem_cache_destroy(pending_cache);
bad4: bad4:
kmem_cache_destroy(exception_cache); kmem_cache_destroy(exception_cache);
bad3: bad3:
exit_origin_hash(); exit_origin_hash();
bad2: bad2:
dm_unregister_target(&origin_target); dm_unregister_target(&origin_target);
bad1: bad1:
dm_unregister_target(&snapshot_target); dm_unregister_target(&snapshot_target);
return r; return r;
} }
static void __exit dm_snapshot_exit(void) static void __exit dm_snapshot_exit(void)
{ {
int r;
destroy_workqueue(ksnapd); destroy_workqueue(ksnapd);
r = dm_unregister_target(&snapshot_target); dm_unregister_target(&snapshot_target);
if (r) dm_unregister_target(&origin_target);
DMERR("snapshot unregister failed %d", r);
r = dm_unregister_target(&origin_target);
if (r)
DMERR("origin unregister failed %d", r);
exit_origin_hash(); exit_origin_hash();
kmem_cache_destroy(pending_cache); kmem_cache_destroy(pending_cache);
kmem_cache_destroy(exception_cache); kmem_cache_destroy(exception_cache);
kmem_cache_destroy(tracked_chunk_cache); kmem_cache_destroy(tracked_chunk_cache);
dm_exception_store_exit();
} }
/* Module hooks */ /* Module hooks */

View File

@ -1,6 +1,4 @@
/* /*
* dm-snapshot.c
*
* Copyright (C) 2001-2002 Sistina Software (UK) Limited. * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
* *
* This file is released under the GPL. * This file is released under the GPL.
@ -10,6 +8,7 @@
#define DM_SNAPSHOT_H #define DM_SNAPSHOT_H
#include <linux/device-mapper.h> #include <linux/device-mapper.h>
#include "dm-exception-store.h"
#include "dm-bio-list.h" #include "dm-bio-list.h"
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
@ -20,116 +19,6 @@ struct exception_table {
struct list_head *table; struct list_head *table;
}; };
/*
* The snapshot code deals with largish chunks of the disk at a
* time. Typically 32k - 512k.
*/
typedef sector_t chunk_t;
/*
* An exception is used where an old chunk of data has been
* replaced by a new one.
* If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
* of chunks that follow contiguously. Remaining bits hold the number of the
* chunk within the device.
*/
struct dm_snap_exception {
struct list_head hash_list;
chunk_t old_chunk;
chunk_t new_chunk;
};
/*
* Funtions to manipulate consecutive chunks
*/
# if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
# define DM_CHUNK_CONSECUTIVE_BITS 8
# define DM_CHUNK_NUMBER_BITS 56
static inline chunk_t dm_chunk_number(chunk_t chunk)
{
return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
}
static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
{
return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
}
static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
{
e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
BUG_ON(!dm_consecutive_chunk_count(e));
}
# else
# define DM_CHUNK_CONSECUTIVE_BITS 0
static inline chunk_t dm_chunk_number(chunk_t chunk)
{
return chunk;
}
static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
{
return 0;
}
static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
{
}
# endif
/*
* Abstraction to handle the meta/layout of exception stores (the
* COW device).
*/
struct exception_store {
/*
* Destroys this object when you've finished with it.
*/
void (*destroy) (struct exception_store *store);
/*
* The target shouldn't read the COW device until this is
* called.
*/
int (*read_metadata) (struct exception_store *store);
/*
* Find somewhere to store the next exception.
*/
int (*prepare_exception) (struct exception_store *store,
struct dm_snap_exception *e);
/*
* Update the metadata with this exception.
*/
void (*commit_exception) (struct exception_store *store,
struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context);
/*
* The snapshot is invalid, note this in the metadata.
*/
void (*drop_snapshot) (struct exception_store *store);
/*
* Return how full the snapshot is.
*/
void (*fraction_full) (struct exception_store *store,
sector_t *numerator,
sector_t *denominator);
struct dm_snapshot *snap;
void *context;
};
#define DM_TRACKED_CHUNK_HASH_SIZE 16 #define DM_TRACKED_CHUNK_HASH_SIZE 16
#define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \ #define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \
(DM_TRACKED_CHUNK_HASH_SIZE - 1)) (DM_TRACKED_CHUNK_HASH_SIZE - 1))
@ -172,7 +61,7 @@ struct dm_snapshot {
spinlock_t pe_lock; spinlock_t pe_lock;
/* The on disk metadata handler */ /* The on disk metadata handler */
struct exception_store store; struct dm_exception_store store;
struct dm_kcopyd_client *kcopyd_client; struct dm_kcopyd_client *kcopyd_client;
@ -186,20 +75,6 @@ struct dm_snapshot {
struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
}; };
/*
* Used by the exception stores to load exceptions hen
* initialising.
*/
int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new);
/*
* Constructor and destructor for the default persistent
* store.
*/
int dm_create_persistent(struct exception_store *store);
int dm_create_transient(struct exception_store *store);
/* /*
* Return the number of sectors in the device. * Return the number of sectors in the device.
*/ */

View File

@ -337,9 +337,7 @@ int __init dm_stripe_init(void)
void dm_stripe_exit(void) void dm_stripe_exit(void)
{ {
if (dm_unregister_target(&stripe_target)) dm_unregister_target(&stripe_target);
DMWARN("target unregistration failed");
destroy_workqueue(kstriped); destroy_workqueue(kstriped);
return; return;

Some files were not shown because too many files have changed in this diff Show More