mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
Merge branches 'core/futexes', 'core/locking', 'core/rcu' and 'linus' into core/urgent
This commit is contained in:
commit
fdbc0450df
@ -31,7 +31,6 @@ Features which OCFS2 does not support yet:
|
||||
- quotas
|
||||
- Directory change notification (F_NOTIFY)
|
||||
- Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
|
||||
- POSIX ACLs
|
||||
|
||||
Mount options
|
||||
=============
|
||||
@ -79,3 +78,5 @@ inode64 Indicates that Ocfs2 is allowed to create inodes at
|
||||
bits of significance.
|
||||
user_xattr (*) Enables Extended User Attributes.
|
||||
nouser_xattr Disables Extended User Attributes.
|
||||
acl Enables POSIX Access Control Lists support.
|
||||
noacl (*) Disables POSIX Access Control Lists support.
|
||||
|
15
MAINTAINERS
15
MAINTAINERS
@ -4015,10 +4015,12 @@ L: alsa-devel@alsa-project.org (subscribers-only)
|
||||
W: http://alsa-project.org/main/index.php/ASoC
|
||||
S: Supported
|
||||
|
||||
SPARC (sparc32)
|
||||
P: William L. Irwin
|
||||
M: wli@holomorphy.com
|
||||
SPARC + UltraSPARC (sparc/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
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
|
||||
S: Maintained
|
||||
|
||||
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
|
||||
@ -4302,13 +4304,6 @@ M: dushistov@mail.ru
|
||||
L: linux-kernel@vger.kernel.org
|
||||
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:
|
||||
P: David Vrabel
|
||||
M: david.vrabel@csr.com
|
||||
|
@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = {
|
||||
};
|
||||
|
||||
static struct clk i2chs2_fck = {
|
||||
.name = "i2chs_fck",
|
||||
.name = "i2c_fck",
|
||||
.id = 2,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = {
|
||||
};
|
||||
|
||||
static struct clk i2chs1_fck = {
|
||||
.name = "i2chs_fck",
|
||||
.name = "i2c_fck",
|
||||
.id = 1,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
|
@ -23,8 +23,10 @@ struct mod_arch_specific
|
||||
{
|
||||
unsigned long got_offset, got_count, got_max;
|
||||
unsigned long fdesc_offset, fdesc_count, fdesc_max;
|
||||
unsigned long stub_offset, stub_count, stub_max;
|
||||
unsigned long init_stub_offset, init_stub_count, init_stub_max;
|
||||
struct {
|
||||
unsigned long stub_offset;
|
||||
unsigned int stub_entries;
|
||||
} *section;
|
||||
int unwind_section;
|
||||
struct unwind_table *unwind;
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.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
|
||||
@ -24,6 +25,19 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* We are not doing SEGREL32 handling correctly. According to the ABI, we
|
||||
* should do a value offset, like this:
|
||||
@ -58,9 +72,13 @@
|
||||
#define DEBUGP(fmt...)
|
||||
#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) \
|
||||
if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
|
||||
( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
|
||||
if (!RELOC_REACHABLE(val, bits)) { \
|
||||
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); \
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
struct got_entry {
|
||||
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 */
|
||||
void module_free(struct module *mod, void *module_region)
|
||||
{
|
||||
kfree(mod->arch.section);
|
||||
mod->arch.section = NULL;
|
||||
|
||||
vfree(module_region);
|
||||
/* FIXME: If module_region == mod->init_region, trim exception
|
||||
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
|
||||
int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
|
||||
CONST Elf_Shdr *sechdrs,
|
||||
CONST char *secstrings,
|
||||
struct module *me)
|
||||
{
|
||||
unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0;
|
||||
unsigned long gots = 0, fdescs = 0, len;
|
||||
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++) {
|
||||
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 int count, s;
|
||||
|
||||
if (strncmp(secstrings + sechdrs[i].sh_name,
|
||||
".PARISC.unwind", 14) == 0)
|
||||
@ -290,11 +320,23 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
|
||||
*/
|
||||
gots += count_gots(rels, nrels);
|
||||
fdescs += count_fdescs(rels, nrels);
|
||||
if(strncmp(secstrings + sechdrs[i].sh_name,
|
||||
".rela.init", 10) == 0)
|
||||
init_stubs += count_stubs(rels, nrels);
|
||||
else
|
||||
stubs += count_stubs(rels, nrels);
|
||||
|
||||
/* XXX: By sorting the relocs and finding duplicate entries
|
||||
* we could reduce the number of necessary stubs and save
|
||||
* some memory. */
|
||||
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 */
|
||||
@ -306,18 +348,8 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
|
||||
me->arch.fdesc_offset = me->core_size;
|
||||
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.fdesc_max = fdescs;
|
||||
me->arch.stub_max = stubs;
|
||||
me->arch.init_stub_max = init_stubs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -380,23 +412,27 @@ enum elf_stub_type {
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
if(init_section) {
|
||||
i = me->arch.init_stub_count++;
|
||||
BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
|
||||
stub = me->module_init + me->arch.init_stub_offset +
|
||||
i * sizeof(struct stub_entry);
|
||||
} else {
|
||||
i = me->arch.stub_count++;
|
||||
BUG_ON(me->arch.stub_count > me->arch.stub_max);
|
||||
stub = me->module_core + me->arch.stub_offset +
|
||||
i * sizeof(struct stub_entry);
|
||||
/* initialize stub_offset to point in front of the section */
|
||||
if (!me->arch.section[targetsec].stub_offset) {
|
||||
loc0 -= (me->arch.section[targetsec].stub_entries + 1) *
|
||||
sizeof(struct stub_entry);
|
||||
/* get correct alignment for the stubs */
|
||||
loc0 = ALIGN(loc0, sizeof(struct stub_entry));
|
||||
me->arch.section[targetsec].stub_offset = loc0;
|
||||
}
|
||||
|
||||
/* 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
|
||||
/* for 32-bit the stub looks like this:
|
||||
* ldil L'XXX,%r1
|
||||
@ -489,15 +525,19 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
|
||||
Elf32_Addr val;
|
||||
Elf32_Sword addend;
|
||||
Elf32_Addr dot;
|
||||
Elf_Addr loc0;
|
||||
unsigned int targetsec = sechdrs[relsec].sh_info;
|
||||
//unsigned long dp = (unsigned long)$global$;
|
||||
register unsigned long dp asm ("r27");
|
||||
|
||||
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++) {
|
||||
/* 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;
|
||||
/* This is the start of the target section */
|
||||
loc0 = sechdrs[targetsec].sh_addr;
|
||||
/* This is the symbol it is referring to */
|
||||
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF32_R_SYM(rel[i].r_info);
|
||||
@ -569,19 +609,32 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
|
||||
break;
|
||||
case R_PARISC_PCREL17F:
|
||||
/* 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;
|
||||
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);
|
||||
break;
|
||||
case R_PARISC_PCREL22F:
|
||||
/* 22-bit PC relative address; only defined for pa20 */
|
||||
val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
|
||||
DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n",
|
||||
strtab + sym->st_name, (unsigned long)loc, addend,
|
||||
val)
|
||||
/* calculate direct call offset */
|
||||
val += addend;
|
||||
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);
|
||||
break;
|
||||
|
||||
@ -610,13 +663,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
|
||||
Elf64_Addr val;
|
||||
Elf64_Sxword addend;
|
||||
Elf64_Addr dot;
|
||||
Elf_Addr loc0;
|
||||
unsigned int targetsec = sechdrs[relsec].sh_info;
|
||||
|
||||
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++) {
|
||||
/* 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;
|
||||
/* This is the start of the target section */
|
||||
loc0 = sechdrs[targetsec].sh_addr;
|
||||
/* This is the symbol it is referring to */
|
||||
sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
|
||||
+ 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",
|
||||
strtab + sym->st_name,
|
||||
loc, val);
|
||||
val += addend;
|
||||
/* 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 to the
|
||||
* module, but in a different
|
||||
* section, so stub the jump
|
||||
* in case it's more than 22
|
||||
* bits away */
|
||||
val = get_stub(me, val, addend, ELF_STUB_DIRECT,
|
||||
in_init(me, loc));
|
||||
else if (strncmp(strtab + sym->st_name, "$$", 2)
|
||||
if (in_local(me, (void *)val)) {
|
||||
/* this is the case where the symbol is local
|
||||
* to the module, but in a different section,
|
||||
* so stub the jump in case it's more than 22
|
||||
* bits away */
|
||||
val = (val - dot - 8)/4;
|
||||
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);
|
||||
} 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)
|
||||
val = get_stub(me, val, addend, ELF_STUB_MILLI,
|
||||
in_init(me, loc));
|
||||
loc0, targetsec);
|
||||
else
|
||||
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",
|
||||
strtab + sym->st_name, loc, sym->st_value,
|
||||
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;
|
||||
CHECK_RELOC(val, 22);
|
||||
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
|
||||
break;
|
||||
case R_PARISC_DIR64:
|
||||
@ -794,12 +849,8 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
addr = (u32 *)entry->addr;
|
||||
printk("INSNS: %x %x %x %x\n",
|
||||
addr[0], addr[1], addr[2], addr[3]);
|
||||
printk("stubs used %ld, stubs max %ld\n"
|
||||
"init_stubs used %ld, init stubs max %ld\n"
|
||||
"got entries used %ld, gots max %ld\n"
|
||||
printk("got entries used %ld, gots 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.fdesc_count, me->arch.fdesc_max);
|
||||
#endif
|
||||
@ -829,7 +880,10 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
me->name, me->arch.got_count, MAX_GOTS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
kfree(me->arch.section);
|
||||
me->arch.section = NULL;
|
||||
|
||||
/* no symbol table */
|
||||
if(symhdr == NULL)
|
||||
return 0;
|
||||
|
@ -97,7 +97,6 @@ spufs_new_inode(struct super_block *sb, int mode)
|
||||
inode->i_mode = mode;
|
||||
inode->i_uid = current_fsuid();
|
||||
inode->i_gid = current_fsgid();
|
||||
inode->i_blocks = 0;
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
||||
out:
|
||||
return inode;
|
||||
|
@ -106,7 +106,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
|
||||
ret->i_mode = mode;
|
||||
ret->i_uid = hypfs_info->uid;
|
||||
ret->i_gid = hypfs_info->gid;
|
||||
ret->i_blocks = 0;
|
||||
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
|
||||
if (mode & S_IFDIR)
|
||||
ret->i_nlink = 2;
|
||||
|
@ -4,6 +4,17 @@
|
||||
|
||||
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
|
||||
bool
|
||||
default y
|
||||
@ -15,22 +26,11 @@ config SPARC
|
||||
select RTC_CLASS
|
||||
select RTC_DRV_M48T59
|
||||
|
||||
# Identify this as a Sparc32 build
|
||||
config SPARC32
|
||||
bool
|
||||
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/>.
|
||||
def_bool !64BIT
|
||||
|
||||
config SPARC64
|
||||
bool
|
||||
default y if ARCH = "sparc64"
|
||||
def_bool 64BIT
|
||||
select ARCH_SUPPORTS_MSI
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_KRETPROBES
|
||||
@ -53,9 +53,6 @@ config BITS
|
||||
default 32 if SPARC32
|
||||
default 64 if SPARC64
|
||||
|
||||
config 64BIT
|
||||
def_bool y if SPARC64
|
||||
|
||||
config GENERIC_TIME
|
||||
bool
|
||||
default y if SPARC64
|
||||
@ -188,14 +185,6 @@ config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
default y
|
||||
|
||||
config ARCH_HAS_ILOG2_U32
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_HAS_ILOG2_U64
|
||||
bool
|
||||
default n
|
||||
|
||||
config EMULATED_CMPXCHG
|
||||
bool
|
||||
default y if SPARC32
|
||||
@ -442,26 +431,6 @@ config SERIAL_CONSOLE
|
||||
endmenu
|
||||
|
||||
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
|
||||
bool
|
||||
default y
|
||||
|
@ -1,27 +1,27 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.28-rc4
|
||||
# Mon Nov 10 12:35:09 2008
|
||||
# Linux kernel version: 2.6.28
|
||||
# Fri Jan 2 18:14:26 2009
|
||||
#
|
||||
CONFIG_SPARC=y
|
||||
CONFIG_SPARC64=y
|
||||
CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc64_defconfig"
|
||||
CONFIG_BITS=64
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_GENERIC_TIME=y
|
||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_MMU=y
|
||||
CONFIG_IOMMU_HELPER=y
|
||||
CONFIG_QUICKLIST=y
|
||||
CONFIG_STACKTRACE_SUPPORT=y
|
||||
CONFIG_LOCKDEP_SUPPORT=y
|
||||
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
|
||||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
|
||||
CONFIG_AUDIT_ARCH=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_OF=y
|
||||
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
|
||||
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
|
||||
|
||||
#
|
||||
@ -86,6 +86,7 @@ CONFIG_SLUB_DEBUG=y
|
||||
CONFIG_SLUB=y
|
||||
# CONFIG_SLOB is not set
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_TRACEPOINTS=y
|
||||
# CONFIG_MARKERS is not set
|
||||
CONFIG_OPROFILE=m
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
@ -127,34 +128,40 @@ CONFIG_DEFAULT_AS=y
|
||||
# CONFIG_DEFAULT_NOOP is not set
|
||||
CONFIG_DEFAULT_IOSCHED="anticipatory"
|
||||
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
|
||||
|
||||
#
|
||||
# Processor type and features
|
||||
#
|
||||
CONFIG_SPARC64_PAGE_SIZE_8KB=y
|
||||
# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=64
|
||||
CONFIG_HZ_100=y
|
||||
# CONFIG_HZ_250 is not set
|
||||
# CONFIG_HZ_300 is not set
|
||||
# CONFIG_HZ_1000 is not set
|
||||
CONFIG_HZ=100
|
||||
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_GENERIC_HARDIRQS=y
|
||||
CONFIG_TICK_ONESHOT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=64
|
||||
# CONFIG_CPU_FREQ is not set
|
||||
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_512K 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_NR_QUICK=1
|
||||
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_SBUSCHAR=y
|
||||
CONFIG_SUN_AUXIO=y
|
||||
CONFIG_SUN_IO=y
|
||||
CONFIG_SUN_LDOMS=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
@ -195,7 +210,9 @@ CONFIG_ARCH_SUPPORTS_MSI=y
|
||||
CONFIG_PCI_MSI=y
|
||||
# CONFIG_PCI_LEGACY is not set
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
# CONFIG_PCCARD is not set
|
||||
CONFIG_SUN_OPENPROMFS=m
|
||||
CONFIG_SPARC64_PCI=y
|
||||
|
||||
#
|
||||
# Executable file formats
|
||||
@ -207,17 +224,13 @@ CONFIG_COMPAT_BINFMT_ELF=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_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
|
||||
|
||||
#
|
||||
# Networking options
|
||||
#
|
||||
# CONFIG_NET_NS is not set
|
||||
CONFIG_COMPAT_NET_DEV_OPS=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_PACKET_MMAP=y
|
||||
CONFIG_UNIX=y
|
||||
@ -314,6 +327,7 @@ CONFIG_VLAN_8021Q=m
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
# CONFIG_NET_SCHED is not set
|
||||
# CONFIG_DCB is not set
|
||||
|
||||
#
|
||||
# Network testing
|
||||
@ -330,8 +344,8 @@ CONFIG_WIRELESS=y
|
||||
# CONFIG_CFG80211 is not set
|
||||
CONFIG_WIRELESS_OLD_REGULATORY=y
|
||||
# CONFIG_WIRELESS_EXT is not set
|
||||
# CONFIG_LIB80211 is not set
|
||||
# CONFIG_MAC80211 is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
# CONFIG_RFKILL is not set
|
||||
# CONFIG_NET_9P is not set
|
||||
|
||||
@ -378,8 +392,10 @@ CONFIG_MISC_DEVICES=y
|
||||
# CONFIG_EEPROM_93CX6 is not set
|
||||
# CONFIG_SGI_IOC4 is not set
|
||||
# CONFIG_TIFM_CORE is not set
|
||||
# CONFIG_ICS932S401 is not set
|
||||
# CONFIG_ENCLOSURE_SERVICES is not set
|
||||
# CONFIG_HP_ILO is not set
|
||||
# CONFIG_C2PORT is not set
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_IDE=y
|
||||
|
||||
@ -387,6 +403,7 @@ CONFIG_IDE=y
|
||||
# Please see Documentation/ide/ide.txt for help/info on IDE drives
|
||||
#
|
||||
CONFIG_IDE_TIMINGS=y
|
||||
CONFIG_IDE_ATAPI=y
|
||||
# CONFIG_BLK_DEV_IDE_SATA is not set
|
||||
CONFIG_IDE_GD=y
|
||||
CONFIG_IDE_GD_ATA=y
|
||||
@ -394,7 +411,6 @@ CONFIG_IDE_GD_ATA=y
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
|
||||
# CONFIG_BLK_DEV_IDETAPE is not set
|
||||
# CONFIG_BLK_DEV_IDESCSI is not set
|
||||
# CONFIG_IDE_TASK_IOCTL is not set
|
||||
CONFIG_IDE_PROC_FS=y
|
||||
|
||||
@ -477,6 +493,7 @@ CONFIG_SCSI_FC_ATTRS=y
|
||||
# CONFIG_SCSI_SRP_ATTRS is not set
|
||||
CONFIG_SCSI_LOWLEVEL=y
|
||||
# CONFIG_ISCSI_TCP is not set
|
||||
# CONFIG_SCSI_CXGB3_ISCSI is not set
|
||||
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
|
||||
# CONFIG_SCSI_3W_9XXX 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_SAS 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_FUTURE_DOMAIN is not set
|
||||
# CONFIG_SCSI_IPS is not set
|
||||
@ -564,6 +583,9 @@ CONFIG_PHYLIB=m
|
||||
# CONFIG_BROADCOM_PHY is not set
|
||||
# CONFIG_ICPLUS_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_NET_ETHERNET=y
|
||||
CONFIG_MII=m
|
||||
@ -590,7 +612,6 @@ CONFIG_NET_PCI=y
|
||||
# CONFIG_ADAPTEC_STARFIRE is not set
|
||||
# CONFIG_B44 is not set
|
||||
# CONFIG_FORCEDETH is not set
|
||||
# CONFIG_EEPRO100 is not set
|
||||
# CONFIG_E100 is not set
|
||||
# CONFIG_FEALNX is not set
|
||||
# CONFIG_NATSEMI is not set
|
||||
@ -600,6 +621,7 @@ CONFIG_NET_PCI=y
|
||||
# CONFIG_R6040 is not set
|
||||
# CONFIG_SIS900 is not set
|
||||
# CONFIG_EPIC100 is not set
|
||||
# CONFIG_SMSC9420 is not set
|
||||
# CONFIG_SUNDANCE is not set
|
||||
# CONFIG_TLAN is not set
|
||||
# CONFIG_VIA_RHINE is not set
|
||||
@ -629,6 +651,7 @@ CONFIG_BNX2=m
|
||||
# CONFIG_JME is not set
|
||||
CONFIG_NETDEV_10000=y
|
||||
# CONFIG_CHELSIO_T1 is not set
|
||||
CONFIG_CHELSIO_T3_DEPENDS=y
|
||||
# CONFIG_CHELSIO_T3 is not set
|
||||
# CONFIG_ENIC is not set
|
||||
# CONFIG_IXGBE is not set
|
||||
@ -778,6 +801,7 @@ CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
# CONFIG_SERIAL_JSM is not set
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_IPMI_HANDLER is not set
|
||||
CONFIG_HW_RANDOM=m
|
||||
@ -870,6 +894,7 @@ CONFIG_HWMON=y
|
||||
# CONFIG_SENSORS_ADM1029 is not set
|
||||
# CONFIG_SENSORS_ADM1031 is not set
|
||||
# CONFIG_SENSORS_ADM9240 is not set
|
||||
# CONFIG_SENSORS_ADT7462 is not set
|
||||
# CONFIG_SENSORS_ADT7470 is not set
|
||||
# CONFIG_SENSORS_ADT7473 is not set
|
||||
# CONFIG_SENSORS_ATXP1 is not set
|
||||
@ -919,11 +944,11 @@ CONFIG_HWMON=y
|
||||
# CONFIG_THERMAL is not set
|
||||
# CONFIG_THERMAL_HWMON is not set
|
||||
# CONFIG_WATCHDOG is not set
|
||||
CONFIG_SSB_POSSIBLE=y
|
||||
|
||||
#
|
||||
# Sonics Silicon Backplane
|
||||
#
|
||||
CONFIG_SSB_POSSIBLE=y
|
||||
# CONFIG_SSB is not set
|
||||
|
||||
#
|
||||
@ -1071,6 +1096,7 @@ CONFIG_SND_MIXER_OSS=m
|
||||
CONFIG_SND_PCM_OSS=m
|
||||
CONFIG_SND_PCM_OSS_PLUGINS=y
|
||||
CONFIG_SND_SEQUENCER_OSS=y
|
||||
# CONFIG_SND_HRTIMER is not set
|
||||
# CONFIG_SND_DYNAMIC_MINORS is not set
|
||||
CONFIG_SND_SUPPORT_OLD_API=y
|
||||
CONFIG_SND_VERBOSE_PROCFS=y
|
||||
@ -1242,11 +1268,11 @@ CONFIG_USB_UHCI_HCD=m
|
||||
# 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_DEBUG is not set
|
||||
@ -1337,6 +1363,7 @@ CONFIG_RTC_INTF_DEV=y
|
||||
# CONFIG_RTC_DRV_M41T80 is not set
|
||||
# CONFIG_RTC_DRV_S35390A is not set
|
||||
# CONFIG_RTC_DRV_FM3130 is not set
|
||||
# CONFIG_RTC_DRV_RX8581 is not set
|
||||
|
||||
#
|
||||
# SPI RTC drivers
|
||||
@ -1365,7 +1392,6 @@ CONFIG_RTC_DRV_STARFIRE=y
|
||||
# CONFIG_DMADEVICES is not set
|
||||
# CONFIG_UIO is not set
|
||||
# CONFIG_STAGING is not set
|
||||
CONFIG_STAGING_EXCLUDE_BUILD=y
|
||||
|
||||
#
|
||||
# Misc Linux/SPARC drivers
|
||||
@ -1544,6 +1570,7 @@ CONFIG_SCHEDSTATS=y
|
||||
# CONFIG_LOCK_STAT is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
|
||||
CONFIG_STACKTRACE=y
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
@ -1552,6 +1579,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
|
||||
CONFIG_DEBUG_MEMORY_INIT=y
|
||||
# CONFIG_DEBUG_LIST is not set
|
||||
# CONFIG_DEBUG_SG is not set
|
||||
# CONFIG_DEBUG_NOTIFIERS is not set
|
||||
# CONFIG_BOOT_PRINTK_DELAY is not set
|
||||
# CONFIG_RCU_TORTURE_TEST 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_LKDTM is not set
|
||||
# CONFIG_FAULT_INJECTION is not set
|
||||
# CONFIG_LATENCYTOP is not set
|
||||
CONFIG_SYSCTL_SYSCALL_CHECK=y
|
||||
CONFIG_NOP_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_RING_BUFFER=y
|
||||
CONFIG_TRACING=y
|
||||
|
||||
#
|
||||
# Tracers
|
||||
@ -1571,7 +1603,9 @@ CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
# CONFIG_SCHED_TRACER is not set
|
||||
# CONFIG_CONTEXT_SWITCH_TRACER is not set
|
||||
# CONFIG_BOOT_TRACER is not set
|
||||
# CONFIG_TRACE_BRANCH_PROFILING is not set
|
||||
# CONFIG_STACK_TRACER is not set
|
||||
# CONFIG_FTRACE_STARTUP_TEST is not set
|
||||
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
|
||||
# CONFIG_SAMPLES is not set
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
@ -1600,11 +1634,16 @@ CONFIG_CRYPTO=y
|
||||
#
|
||||
# CONFIG_CRYPTO_FIPS is not set
|
||||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_ALGAPI2=y
|
||||
CONFIG_CRYPTO_AEAD=y
|
||||
CONFIG_CRYPTO_AEAD2=y
|
||||
CONFIG_CRYPTO_BLKCIPHER=y
|
||||
CONFIG_CRYPTO_BLKCIPHER2=y
|
||||
CONFIG_CRYPTO_HASH=y
|
||||
CONFIG_CRYPTO_RNG=y
|
||||
CONFIG_CRYPTO_HASH2=y
|
||||
CONFIG_CRYPTO_RNG2=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_MANAGER2=y
|
||||
CONFIG_CRYPTO_GF128MUL=m
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
# CONFIG_CRYPTO_CRYPTD is not set
|
||||
|
@ -1,21 +1,6 @@
|
||||
# User exported sparc header files
|
||||
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 += asi.h
|
||||
header-y += display7seg.h
|
||||
@ -23,16 +8,11 @@ header-y += envctrl.h
|
||||
header-y += fbio.h
|
||||
header-y += jsflash.h
|
||||
header-y += openprom.h
|
||||
header-y += openprom_32.h
|
||||
header-y += openprom_64.h
|
||||
header-y += openpromio.h
|
||||
header-y += perfctr.h
|
||||
header-y += psrcompat.h
|
||||
header-y += psr.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 += uctx.h
|
||||
header-y += utrap.h
|
||||
|
@ -1,16 +1,12 @@
|
||||
#ifndef _SPARC_BYTEORDER_H
|
||||
#define _SPARC_BYTEORDER_H
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/asi.h>
|
||||
|
||||
#define __BIG_ENDIAN
|
||||
|
||||
#ifdef CONFIG_SPARC32
|
||||
#define __SWAB_64_THRU_32__
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPARC64
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
static inline __u16 __arch_swab16p(const __u16 *addr)
|
||||
{
|
||||
__u16 ret;
|
||||
@ -44,7 +40,9 @@ static inline __u64 __arch_swab64p(const __u64 *addr)
|
||||
}
|
||||
#define __arch_swab64p __arch_swab64p
|
||||
|
||||
#endif /* CONFIG_SPARC64 */
|
||||
#else
|
||||
#define __SWAB_64_THRU_32__
|
||||
#endif /* defined(__sparc__) && defined(__arch64__) */
|
||||
|
||||
#include <linux/byteorder.h>
|
||||
|
||||
|
@ -1,8 +1,32 @@
|
||||
#ifndef ___ASM_SPARC_IPCBUF_H
|
||||
#define ___ASM_SPARC_IPCBUF_H
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
#include <asm/ipcbuf_64.h>
|
||||
#else
|
||||
#include <asm/ipcbuf_32.h>
|
||||
#endif
|
||||
#ifndef __SPARC_IPCBUF_H
|
||||
#define __SPARC_IPCBUF_H
|
||||
|
||||
/*
|
||||
* The ipc64_perm structure for sparc/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
|
||||
* - 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
|
||||
__kernel_mode_t mode;
|
||||
unsigned short __pad1;
|
||||
unsigned short seq;
|
||||
unsigned long long __unused1;
|
||||
unsigned long long __unused2;
|
||||
};
|
||||
|
||||
#endif /* __SPARC_IPCBUF_H */
|
||||
|
@ -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 */
|
@ -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 */
|
@ -8,7 +8,7 @@
|
||||
#define _SPARC_JSFLASH_H
|
||||
|
||||
#ifndef _SPARC_TYPES_H
|
||||
#include <asm/types.h>
|
||||
#include <linux/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1,8 +1,277 @@
|
||||
#ifndef ___ASM_SPARC_OPENPROM_H
|
||||
#define ___ASM_SPARC_OPENPROM_H
|
||||
#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,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__)
|
||||
#include <asm/openprom_64.h>
|
||||
#define PROMREG_MAX 24
|
||||
#define PROMVADDR_MAX 16
|
||||
#define PROMINTR_MAX 32
|
||||
#else
|
||||
#include <asm/openprom_32.h>
|
||||
#define PROMREG_MAX 16
|
||||
#define PROMVADDR_MAX 16
|
||||
#define PROMINTR_MAX 15
|
||||
#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
|
||||
|
||||
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) */
|
||||
|
@ -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) */
|
@ -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) */
|
@ -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__)
|
||||
#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
|
||||
#include <asm/posix_types_32.h>
|
||||
#endif
|
||||
/* sparc 32 bit */
|
||||
|
||||
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
|
||||
|
||||
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 */
|
||||
|
@ -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) */
|
@ -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) */
|
@ -99,7 +99,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
|
||||
"st\t%%g0, [%0 + %3 + 0x3c]"
|
||||
: /* no outputs */
|
||||
: "r" (regs),
|
||||
"r" (sp - sizeof(struct reg_window)),
|
||||
"r" (sp - sizeof(struct reg_window32)),
|
||||
"r" (zero),
|
||||
"i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))
|
||||
: "memory");
|
||||
|
@ -1,8 +1,448 @@
|
||||
#ifndef ___ASM_SPARC_PTRACE_H
|
||||
#define ___ASM_SPARC_PTRACE_H
|
||||
#ifndef __SPARC_PTRACE_H
|
||||
#define __SPARC_PTRACE_H
|
||||
|
||||
#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
|
||||
#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
|
||||
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
|
||||
|
||||
/* 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) */
|
||||
|
@ -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) */
|
@ -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) */
|
@ -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
|
@ -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 */
|
@ -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 */
|
@ -1,8 +1,96 @@
|
||||
#ifndef ___ASM_SPARC_SIGCONTEXT_H
|
||||
#define ___ASM_SPARC_SIGCONTEXT_H
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
#include <asm/sigcontext_64.h>
|
||||
#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 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
|
||||
#include <asm/sigcontext_32.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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 /* (CONFIG_SPARC64) */
|
||||
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif /* (__KERNEL__) */
|
||||
|
||||
#endif /* !(__SPARC_SIGCONTEXT_H) */
|
||||
|
@ -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) */
|
@ -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) */
|
@ -1,8 +1,37 @@
|
||||
#ifndef ___ASM_SPARC_SIGINFO_H
|
||||
#define ___ASM_SPARC_SIGINFO_H
|
||||
#ifndef __SPARC_SIGINFO_H
|
||||
#define __SPARC_SIGINFO_H
|
||||
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
#include <asm/siginfo_64.h>
|
||||
#else
|
||||
#include <asm/siginfo_32.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
|
||||
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
|
||||
#define __ARCH_SI_BAND_T int
|
||||
|
||||
#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) */
|
||||
|
@ -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) */
|
@ -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
|
@ -1,8 +1,210 @@
|
||||
#ifndef ___ASM_SPARC_SIGNAL_H
|
||||
#define ___ASM_SPARC_SIGNAL_H
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
#include <asm/signal_64.h>
|
||||
#ifndef __SPARC_SIGNAL_H
|
||||
#define __SPARC_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 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
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#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) */
|
||||
|
@ -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) */
|
@ -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) */
|
@ -170,7 +170,4 @@ void smp_setup_cpu_possible_map(void);
|
||||
#define smp_setup_cpu_possible_map() do { } while (0)
|
||||
|
||||
#endif /* !(SMP) */
|
||||
|
||||
#define NO_PROC_ID 0xFF
|
||||
|
||||
#endif /* !(_SPARC_SMP_H) */
|
||||
|
@ -1,8 +1,107 @@
|
||||
#ifndef ___ASM_SPARC_STAT_H
|
||||
#define ___ASM_SPARC_STAT_H
|
||||
#ifndef __SPARC_STAT_H
|
||||
#define __SPARC_STAT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#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
|
||||
#include <asm/stat_32.h>
|
||||
#endif
|
||||
#endif
|
||||
/* 32 bit sparc */
|
||||
struct stat {
|
||||
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 */
|
||||
|
@ -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
|
@ -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
|
@ -45,7 +45,7 @@ struct thread_info {
|
||||
/* A place to store user windows and stack pointers
|
||||
* 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 w_saved;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#define NUM_SPARC_TRAPS 255
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/* This is for V8 compliant Sparc CPUS */
|
||||
struct tt_entry {
|
||||
unsigned long inst_one;
|
||||
@ -22,14 +22,7 @@ struct tt_entry {
|
||||
/* We set this to _start in system setup. */
|
||||
extern struct tt_entry *sparc_ttable;
|
||||
|
||||
static inline unsigned long get_tbr(void)
|
||||
{
|
||||
unsigned long tbr;
|
||||
|
||||
__asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (tbr));
|
||||
return tbr;
|
||||
}
|
||||
|
||||
#endif /* (__KERNEL__) */
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
/* For patching the trap table at boot time, we need to know how to
|
||||
|
@ -669,7 +669,9 @@ void __init init_IRQ(void)
|
||||
btfixup();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
void init_irq_proc(void)
|
||||
{
|
||||
/* For now, nothing... */
|
||||
}
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
@ -14,14 +14,14 @@ extern unsigned long trapbase;
|
||||
|
||||
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
||||
{
|
||||
struct reg_window *win;
|
||||
struct reg_window32 *win;
|
||||
int i;
|
||||
|
||||
gdb_regs[GDB_G0] = 0;
|
||||
for (i = 0; i < 15; 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++)
|
||||
gdb_regs[GDB_L0 + i] = win->locals[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)
|
||||
{
|
||||
struct thread_info *t = task_thread_info(p);
|
||||
struct reg_window *win;
|
||||
struct reg_window32 *win;
|
||||
int 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_O7] = 0;
|
||||
|
||||
win = (struct reg_window *) t->ksp;
|
||||
win = (struct reg_window32 *) t->ksp;
|
||||
for (i = 0; i < 8; i++)
|
||||
gdb_regs[GDB_L0 + i] = win->locals[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)
|
||||
{
|
||||
struct reg_window *win;
|
||||
struct reg_window32 *win;
|
||||
int 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->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++)
|
||||
win->locals[i] = gdb_regs[GDB_L0 + i];
|
||||
for (i = 0; i < 8; i++)
|
||||
|
@ -60,7 +60,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
|
||||
}
|
||||
|
||||
#define fetch_reg(reg, regs) ({ \
|
||||
struct reg_window __user *win; \
|
||||
struct reg_window32 __user *win; \
|
||||
register unsigned long ret; \
|
||||
\
|
||||
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)]; \
|
||||
} else { \
|
||||
/* 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;\
|
||||
} \
|
||||
ret; \
|
||||
@ -77,7 +77,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
|
||||
static inline int
|
||||
store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
|
||||
{
|
||||
struct reg_window __user *win;
|
||||
struct reg_window32 __user *win;
|
||||
|
||||
if (!reg)
|
||||
return 0;
|
||||
@ -86,7 +86,7 @@ store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
|
||||
return 0;
|
||||
} else {
|
||||
/* 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]));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
* PCI controller share the same interrupt numbers and
|
||||
* drive the same front-end hardware. Whichever of the
|
||||
* two get in here first will register the IRQ handler
|
||||
* the second will just error out since we do not pass in
|
||||
* IRQF_SHARED.
|
||||
* drive the same front-end hardware.
|
||||
*/
|
||||
err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED,
|
||||
"PSYCHO_UE", pbm);
|
||||
|
@ -180,13 +180,13 @@ static DEFINE_SPINLOCK(sparc_backtrace_lock);
|
||||
|
||||
void __show_backtrace(unsigned long fp)
|
||||
{
|
||||
struct reg_window *rw;
|
||||
struct reg_window32 *rw;
|
||||
unsigned long flags;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
spin_lock_irqsave(&sparc_backtrace_lock, flags);
|
||||
|
||||
rw = (struct reg_window *)fp;
|
||||
rw = (struct reg_window32 *)fp;
|
||||
while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
|
||||
!(((unsigned long) rw) & 0x7)) {
|
||||
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[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);
|
||||
}
|
||||
@ -258,7 +258,7 @@ void show_stackframe(struct sparc_stackf *sf)
|
||||
|
||||
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",
|
||||
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 task_base;
|
||||
struct reg_window *rw;
|
||||
struct reg_window32 *rw;
|
||||
int count = 0;
|
||||
|
||||
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)) ||
|
||||
fp >= (task_base + (PAGE_SIZE << 1)))
|
||||
break;
|
||||
rw = (struct reg_window *) fp;
|
||||
rw = (struct reg_window32 *) fp;
|
||||
pc = rw->ins[7];
|
||||
printk("[%08lx : ", 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 task_base = (unsigned long) task;
|
||||
unsigned long ret = 0;
|
||||
struct reg_window *rw;
|
||||
struct reg_window32 *rw;
|
||||
int count = 0;
|
||||
|
||||
if (!task || task == current ||
|
||||
@ -692,7 +692,7 @@ unsigned long get_wchan(struct task_struct *task)
|
||||
if (fp < (task_base + sizeof(struct thread_info)) ||
|
||||
fp >= (task_base + (2 * PAGE_SIZE)))
|
||||
break;
|
||||
rw = (struct reg_window *) fp;
|
||||
rw = (struct reg_window32 *) fp;
|
||||
pc = rw->ins[7];
|
||||
if (!in_sched_functions(pc)) {
|
||||
ret = pc;
|
||||
|
@ -155,20 +155,12 @@ static struct property * __init build_one_prop(phandle node, char *prev,
|
||||
p->value = prom_early_alloc(special_len);
|
||||
memcpy(p->value, special_val, special_len);
|
||||
} else {
|
||||
#ifdef CONFIG_SPARC32
|
||||
if (prev == NULL) {
|
||||
name = prom_firstprop(node, NULL);
|
||||
name = prom_firstprop(node, p->name);
|
||||
} 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) {
|
||||
tmp = p;
|
||||
return NULL;
|
||||
|
@ -34,7 +34,7 @@ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
|
||||
|
||||
struct signal_frame {
|
||||
struct sparc_stackf ss;
|
||||
__siginfo_t info;
|
||||
__siginfo32_t info;
|
||||
__siginfo_fpu_t __user *fpu_save;
|
||||
unsigned long insns[2] __attribute__ ((aligned (8)));
|
||||
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],
|
||||
(_NSIG_WORDS - 1) * sizeof(unsigned int));
|
||||
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
|
||||
sizeof(struct reg_window));
|
||||
sizeof(struct reg_window32));
|
||||
if (err)
|
||||
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 |= __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);
|
||||
|
||||
|
@ -67,7 +67,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
|
||||
__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
|
||||
* 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)) {
|
||||
printk("Caller[%08lx]: %pS\n", rw->ins[7],
|
||||
(void *) rw->ins[7]);
|
||||
rw = (struct reg_window *)rw->ins[6];
|
||||
rw = (struct reg_window32 *)rw->ins[6];
|
||||
}
|
||||
}
|
||||
printk("Instruction DUMP:");
|
||||
|
@ -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)
|
||||
{
|
||||
struct reg_window *win;
|
||||
struct reg_window32 *win;
|
||||
|
||||
if(reg < 16)
|
||||
return (!reg ? 0 : regs->u_regs[reg]);
|
||||
|
||||
/* 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... */
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (reg < 16)
|
||||
return (!reg ? 0 : regs->u_regs[reg]);
|
||||
|
||||
/* 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)
|
||||
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)
|
||||
{
|
||||
struct reg_window *win;
|
||||
struct reg_window32 *win;
|
||||
|
||||
if(reg < 16)
|
||||
return ®s->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];
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
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. */
|
||||
if (copy_to_user((char __user *) sp, &tp->reg_window[window],
|
||||
sizeof(struct reg_window)))
|
||||
sizeof(struct reg_window32)))
|
||||
continue;
|
||||
|
||||
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) ||
|
||||
copy_to_user((char __user *) sp, &tp->reg_window[window],
|
||||
sizeof(struct reg_window)))
|
||||
sizeof(struct reg_window32)))
|
||||
do_exit(SIGILL);
|
||||
}
|
||||
tp->w_saved = 0;
|
||||
|
@ -22,10 +22,11 @@ MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/shared/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
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
ARCH_INCLUDE += -I$(ARCH_DIR)/include/shared # for two generated files
|
||||
ARCH_INCLUDE += -I$(SHARED_HEADERS)
|
||||
endif
|
||||
KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
|
||||
|
||||
@ -85,8 +86,8 @@ endef
|
||||
|
||||
KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
|
||||
|
||||
archprepare: $(ARCH_DIR)/include/shared/user_constants.h
|
||||
prepare: $(ARCH_DIR)/include/shared/kern_constants.h
|
||||
archprepare: $(SHARED_HEADERS)/user_constants.h
|
||||
archprepare: $(SHARED_HEADERS)/kern_constants.h
|
||||
|
||||
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
|
||||
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
|
||||
# TT or skas makefiles and don't clean skas_ptregs.h.
|
||||
CLEAN_FILES += linux x.i gmon.out \
|
||||
$(ARCH_DIR)/include/shared/user_constants.h \
|
||||
$(ARCH_DIR)/include/shared/kern_constants.h
|
||||
$(SHARED_HEADERS)/user_constants.h \
|
||||
$(SHARED_HEADERS)/kern_constants.h
|
||||
|
||||
archclean:
|
||||
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
|
||||
-o -name '*.gcov' \) -type f -print | xargs rm -f
|
||||
|
||||
$(objtree)/$(ARCH_DIR)/include/shared:
|
||||
@echo ' MKDIR $@'
|
||||
$(Q)mkdir -p $@
|
||||
|
||||
# Generated files
|
||||
|
||||
$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
|
||||
@ -148,11 +145,11 @@ define filechk_gen-asm-offsets
|
||||
echo ""; )
|
||||
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)
|
||||
|
||||
$(ARCH_DIR)/include/shared/kern_constants.h: $(objtree)/$(ARCH_DIR)/include/shared
|
||||
@echo ' SYMLINK $@'
|
||||
$(Q)ln -sf ../../../../include/asm/asm-offsets.h $@
|
||||
$(SHARED_HEADERS)/kern_constants.h:
|
||||
$(Q)mkdir -p $(dir $@)
|
||||
$(Q)echo '#include "../../../../include/asm/asm-offsets.h"' >$@
|
||||
|
||||
export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
|
||||
|
@ -11,21 +11,21 @@ extern int get_signals(void);
|
||||
extern void block_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)
|
||||
#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)
|
||||
|
||||
#define raw_local_irq_save(flags) do { raw_local_save_flags(flags); \
|
||||
raw_local_irq_disable(); } while(0)
|
||||
#define local_irq_save(flags) do { local_save_flags(flags); \
|
||||
local_irq_disable(); } while(0)
|
||||
|
||||
#define raw_local_irq_enable() unblock_signals()
|
||||
#define raw_local_irq_disable() block_signals()
|
||||
#define local_irq_enable() unblock_signals()
|
||||
#define local_irq_disable() block_signals()
|
||||
|
||||
#define irqs_disabled() \
|
||||
({ \
|
||||
unsigned long flags; \
|
||||
raw_local_save_flags(flags); \
|
||||
local_save_flags(flags); \
|
||||
(flags == 0); \
|
||||
})
|
||||
|
||||
|
@ -408,7 +408,7 @@ config X86_MINIMUM_CPU_FAMILY
|
||||
|
||||
config X86_DEBUGCTLMSR
|
||||
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
|
||||
bool "Supported processor vendors" if EMBEDDED
|
||||
|
@ -160,6 +160,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
|
||||
switch (c->x86_model) {
|
||||
case 0x0E: /* Core */
|
||||
case 0x0F: /* Core Duo */
|
||||
case 0x16: /* Celeron Core */
|
||||
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
|
||||
return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE);
|
||||
case 0x0D: /* Pentium M (Dothan) */
|
||||
@ -171,7 +172,9 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -274,6 +277,7 @@ static struct cpufreq_driver p4clockmod_driver = {
|
||||
.name = "p4-clockmod",
|
||||
.owner = THIS_MODULE,
|
||||
.attr = p4clockmod_attr,
|
||||
.hide_interface = 1,
|
||||
};
|
||||
|
||||
|
||||
|
@ -459,9 +459,7 @@ static int centrino_verify (struct cpufreq_policy *policy)
|
||||
* Sets a new CPUFreq policy.
|
||||
*/
|
||||
struct allmasks {
|
||||
cpumask_t online_policy_cpus;
|
||||
cpumask_t saved_mask;
|
||||
cpumask_t set_mask;
|
||||
cpumask_t covered_cpus;
|
||||
};
|
||||
|
||||
@ -475,9 +473,7 @@ static int centrino_target (struct cpufreq_policy *policy,
|
||||
int retval = 0;
|
||||
unsigned int j, k, first_cpu, tmp;
|
||||
CPUMASK_ALLOC(allmasks);
|
||||
CPUMASK_PTR(online_policy_cpus, allmasks);
|
||||
CPUMASK_PTR(saved_mask, allmasks);
|
||||
CPUMASK_PTR(set_mask, allmasks);
|
||||
CPUMASK_PTR(covered_cpus, allmasks);
|
||||
|
||||
if (unlikely(allmasks == NULL))
|
||||
@ -497,30 +493,28 @@ static int centrino_target (struct cpufreq_policy *policy,
|
||||
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;
|
||||
first_cpu = 1;
|
||||
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.
|
||||
* Make sure we are running on CPU that wants to change freq
|
||||
*/
|
||||
cpus_clear(*set_mask);
|
||||
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
|
||||
cpus_or(*set_mask, *set_mask, *online_policy_cpus);
|
||||
mask = &policy->cpus;
|
||||
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();
|
||||
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");
|
||||
retval = -EAGAIN;
|
||||
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",
|
||||
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;
|
||||
cpufreq_notify_transition(&freqs,
|
||||
CPUFREQ_PRECHANGE);
|
||||
@ -571,7 +567,9 @@ static int centrino_target (struct cpufreq_policy *policy,
|
||||
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;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
@ -584,18 +582,17 @@ static int centrino_target (struct cpufreq_policy *policy,
|
||||
* Best effort undo..
|
||||
*/
|
||||
|
||||
if (!cpus_empty(*covered_cpus))
|
||||
for_each_cpu_mask_nr(j, *covered_cpus) {
|
||||
set_cpus_allowed_ptr(current,
|
||||
&cpumask_of_cpu(j));
|
||||
wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
|
||||
}
|
||||
for_each_cpu_mask_nr(j, *covered_cpus) {
|
||||
set_cpus_allowed_ptr(current, &cpumask_of_cpu(j));
|
||||
wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
|
||||
}
|
||||
|
||||
tmp = freqs.new;
|
||||
freqs.new = freqs.old;
|
||||
freqs.old = tmp;
|
||||
for_each_cpu_mask_nr(j, *online_policy_cpus) {
|
||||
freqs.cpu = j;
|
||||
for_each_cpu_mask_nr(j, policy->cpus) {
|
||||
if (!cpu_online(j))
|
||||
continue;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
@ -139,6 +139,15 @@ static unsigned int pentium_core_get_frequency(void)
|
||||
case 3:
|
||||
fsb = 166667;
|
||||
break;
|
||||
case 2:
|
||||
fsb = 200000;
|
||||
break;
|
||||
case 0:
|
||||
fsb = 266667;
|
||||
break;
|
||||
case 4:
|
||||
fsb = 333333;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value");
|
||||
}
|
||||
|
@ -754,6 +754,11 @@ static struct kobj_type ktype_cpufreq = {
|
||||
.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
|
||||
@ -822,8 +827,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
|
||||
dprintk("initialization failed\n");
|
||||
goto err_out;
|
||||
}
|
||||
policy->user_policy.min = policy->cpuinfo.min_freq;
|
||||
policy->user_policy.max = policy->cpuinfo.max_freq;
|
||||
policy->user_policy.min = policy->min;
|
||||
policy->user_policy.max = policy->max;
|
||||
|
||||
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
|
||||
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));
|
||||
|
||||
/* prepare interface data */
|
||||
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
|
||||
"cpufreq");
|
||||
if (ret)
|
||||
goto err_out_driver_exit;
|
||||
if (!cpufreq_driver->hide_interface) {
|
||||
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
|
||||
&sys_dev->kobj, "cpufreq");
|
||||
if (ret)
|
||||
goto err_out_driver_exit;
|
||||
|
||||
/* set up files for this cpu device */
|
||||
drv_attr = cpufreq_driver->attr;
|
||||
while ((drv_attr) && (*drv_attr)) {
|
||||
ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
|
||||
if (ret)
|
||||
goto err_out_driver_exit;
|
||||
drv_attr++;
|
||||
}
|
||||
if (cpufreq_driver->get) {
|
||||
ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
|
||||
if (ret)
|
||||
goto err_out_driver_exit;
|
||||
}
|
||||
if (cpufreq_driver->target) {
|
||||
ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
|
||||
/* set up files for this cpu device */
|
||||
drv_attr = cpufreq_driver->attr;
|
||||
while ((drv_attr) && (*drv_attr)) {
|
||||
ret = sysfs_create_file(&policy->kobj,
|
||||
&((*drv_attr)->attr));
|
||||
if (ret)
|
||||
goto err_out_driver_exit;
|
||||
drv_attr++;
|
||||
}
|
||||
if (cpufreq_driver->get) {
|
||||
ret = sysfs_create_file(&policy->kobj,
|
||||
&cpuinfo_cur_freq.attr);
|
||||
if (ret)
|
||||
goto err_out_driver_exit;
|
||||
}
|
||||
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)
|
||||
goto err_out_driver_exit;
|
||||
}
|
||||
|
@ -85,14 +85,14 @@ config HID_COMPAT
|
||||
config HID_A4TECH
|
||||
tristate "A4 tech" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for A4 tech X5 and WOP-35 / Trust 450L mice.
|
||||
|
||||
config HID_APPLE
|
||||
tristate "Apple" if EMBEDDED
|
||||
depends on (USB_HID || BT_HIDP)
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for some Apple devices which less or more break
|
||||
HID specification.
|
||||
@ -103,64 +103,49 @@ config HID_APPLE
|
||||
config HID_BELKIN
|
||||
tristate "Belkin" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
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
|
||||
tristate "Cherry" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Cherry Cymotion keyboard.
|
||||
|
||||
config HID_CHICONY
|
||||
tristate "Chicony" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Chicony Tactical pad.
|
||||
|
||||
config HID_CYPRESS
|
||||
tristate "Cypress" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
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
|
||||
tristate "Ezkey" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Ezkey BTC 8193 keyboard.
|
||||
|
||||
config HID_GYRATION
|
||||
tristate "Gyration" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Gyration remote control.
|
||||
|
||||
config HID_LOGITECH
|
||||
tristate "Logitech" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Logitech devices that are not fully compliant with HID standard.
|
||||
|
||||
@ -191,21 +176,28 @@ config LOGIRUMBLEPAD2_FF
|
||||
config HID_MICROSOFT
|
||||
tristate "Microsoft" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Microsoft devices that are not fully compliant with HID standard.
|
||||
|
||||
config HID_MONTEREY
|
||||
tristate "Monterey" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
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
|
||||
tristate "Pantherlord devices support" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for PantherLord/GreenAsia based device support.
|
||||
|
||||
@ -220,31 +212,47 @@ config PANTHERLORD_FF
|
||||
config HID_PETALYNX
|
||||
tristate "Petalynx" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Petalynx Maxter remote control.
|
||||
|
||||
config HID_SAMSUNG
|
||||
tristate "Samsung" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Samsung InfraRed remote control.
|
||||
|
||||
config HID_SONY
|
||||
tristate "Sony" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Sony PS3 controller.
|
||||
|
||||
config HID_SUNPLUS
|
||||
tristate "Sunplus" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
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
|
||||
tristate "ThrustMaster devices support"
|
||||
depends on USB_HID
|
||||
|
@ -23,22 +23,23 @@ endif
|
||||
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
|
||||
obj-$(CONFIG_HID_APPLE) += hid-apple.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_CHICONY) += hid-chicony.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_GYRATION) += hid-gyration.o
|
||||
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
|
||||
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.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_PETALYNX) += hid-petalynx.o
|
||||
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
||||
obj-$(CONFIG_HID_SONY) += hid-sony.o
|
||||
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
|
||||
obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
|
||||
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
|
||||
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
|
||||
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
|
||||
|
||||
obj-$(CONFIG_USB_HID) += usbhid/
|
||||
|
@ -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);
|
@ -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_GEYSER1_TP_ONLY) },
|
||||
{ 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_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_2) },
|
||||
{ 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_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_PCS_ADAPTOR) },
|
||||
{ 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_2) },
|
||||
{ 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_EDGE) },
|
||||
{ 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_CORDLESS_DESKTOP_LX500) },
|
||||
{ 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_WIRELESS_OPTICAL_DESKTOP_3_0) },
|
||||
{ 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_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_VAIO_VGX_MOUSE) },
|
||||
{ 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_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)
|
||||
{
|
||||
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
|
||||
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;
|
||||
|
||||
/* generic wants all non-blacklisted */
|
||||
@ -1332,7 +1410,7 @@ static int hid_device_probe(struct device *dev)
|
||||
int ret = 0;
|
||||
|
||||
if (!hdev->driver) {
|
||||
id = hid_match_id(hdev, hdrv->id_table);
|
||||
id = hid_match_device(hdev, hdrv);
|
||||
if (id == NULL)
|
||||
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_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
|
||||
{ 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_EM_LT20) },
|
||||
{ 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_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_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_GEYSER1_TP_ONLY) },
|
||||
{ }
|
||||
@ -1618,9 +1700,10 @@ int hid_add_device(struct hid_device *hdev)
|
||||
if (hid_ignore(hdev))
|
||||
return -ENODEV;
|
||||
|
||||
/* XXX hack, any other cleaner solution < 20 bus_id bytes? */
|
||||
sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus,
|
||||
hdev->vendor, hdev->product, atomic_inc_return(&id));
|
||||
/* XXX hack, any other cleaner solution after the driver core
|
||||
* is converted to allow more than 20 bytes as the device name? */
|
||||
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
|
||||
hdev->vendor, hdev->product, atomic_inc_return(&id));
|
||||
|
||||
ret = device_add(&hdev->dev);
|
||||
if (!ret)
|
||||
@ -1695,18 +1778,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device);
|
||||
int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
|
||||
const char *mod_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hdrv->driver.name = hdrv->name;
|
||||
hdrv->driver.bus = &hid_bus_type;
|
||||
hdrv->driver.owner = owner;
|
||||
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);
|
||||
|
||||
void hid_unregister_driver(struct hid_driver *hdrv)
|
||||
{
|
||||
driver_remove_file(&hdrv->driver, &driver_attr_new_id);
|
||||
driver_unregister(&hdrv->driver);
|
||||
hid_free_dynids(hdrv);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_unregister_driver);
|
||||
|
||||
|
@ -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);
|
@ -43,6 +43,9 @@ static int __init hid_dummy_init(void)
|
||||
#ifdef CONFIG_HID_MONTEREY_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(monterey);
|
||||
#endif
|
||||
#ifdef CONFIG_HID_NTRIG_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(ntrig);
|
||||
#endif
|
||||
#ifdef CONFIG_HID_PANTHERLORD_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(pantherlord);
|
||||
#endif
|
||||
@ -58,6 +61,9 @@ static int __init hid_dummy_init(void)
|
||||
#ifdef CONFIG_HID_SUNPLUS_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(sunplus);
|
||||
#endif
|
||||
#ifdef CONFIG_GREENASIA_FF_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(greenasia);
|
||||
#endif
|
||||
#ifdef CONFIG_THRUSTMASTER_FF_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(thrustmaster);
|
||||
#endif
|
||||
|
185
drivers/hid/hid-gaff.c
Normal file
185
drivers/hid/hid-gaff.c
Normal 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);
|
@ -107,9 +107,6 @@
|
||||
#define USB_VENDOR_ID_BELKIN 0x050d
|
||||
#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_DEVICE_ID_BERKSHIRE_PCWD 0x1140
|
||||
|
||||
@ -141,9 +138,8 @@
|
||||
#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
|
||||
#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
|
||||
|
||||
#define USB_VENDOR_ID_DELL 0x413c
|
||||
#define USB_DEVICE_ID_DELL_W7658 0x2005
|
||||
#define USB_DEVICE_ID_DELL_SK8115 0x2105
|
||||
#define USB_VENDOR_ID_DEALEXTREAME 0x10c5
|
||||
#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a
|
||||
|
||||
#define USB_VENDOR_ID_DELORME 0x1163
|
||||
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
|
||||
@ -167,9 +163,6 @@
|
||||
|
||||
#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_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
|
||||
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
|
||||
@ -292,7 +285,6 @@
|
||||
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
|
||||
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
|
||||
#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_2 0xc517
|
||||
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
|
||||
@ -339,6 +331,9 @@
|
||||
#define USB_VENDOR_ID_NEC 0x073e
|
||||
#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_DEVICE_ID_ONTRAK_ADU100 0x0064
|
||||
|
||||
@ -383,9 +378,15 @@
|
||||
#define USB_VENDOR_ID_TOPMAX 0x0663
|
||||
#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_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_DEVICE_ID_VERNIER_LABPRO 0x0001
|
||||
#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
|
||||
|
@ -26,7 +26,6 @@
|
||||
#define LG_RDESC 0x001
|
||||
#define LG_BAD_RELATIVE_KEYS 0x002
|
||||
#define LG_DUPLICATE_USAGES 0x004
|
||||
#define LG_RESET_LEDS 0x008
|
||||
#define LG_EXPANDED_KEYMAP 0x010
|
||||
#define LG_IGNORE_DOUBLED_WHEEL 0x020
|
||||
#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;
|
||||
}
|
||||
|
||||
if (quirks & LG_RESET_LEDS)
|
||||
usbhid_set_leds(hdev);
|
||||
|
||||
if (quirks & LG_FF)
|
||||
lgff_init(hdev);
|
||||
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),
|
||||
.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),
|
||||
.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
|
||||
|
82
drivers/hid/hid-ntrig.c
Normal file
82
drivers/hid/hid-ntrig.c
Normal 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);
|
@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
}
|
||||
|
||||
ret = sony_set_operational(hdev);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
goto err_stop;
|
||||
|
||||
return 0;
|
||||
|
77
drivers/hid/hid-topseed.c
Normal file
77
drivers/hid/hid-topseed.c
Normal 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);
|
@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
|
||||
|
||||
list_del(&list->node);
|
||||
dev = hidraw_table[minor];
|
||||
if (!dev->open--) {
|
||||
if (!--dev->open) {
|
||||
if (list->hidraw->exist)
|
||||
dev->hid->ll_driver->close(dev->hid);
|
||||
else
|
||||
@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
unlock_kernel();
|
||||
@ -329,7 +357,7 @@ int hidraw_connect(struct hid_device *hid)
|
||||
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);
|
||||
|
||||
if (IS_ERR(dev->dev)) {
|
||||
|
@ -45,7 +45,7 @@ config USB_HIDDEV
|
||||
If unsure, say Y.
|
||||
|
||||
menu "USB HID Boot Protocol drivers"
|
||||
depends on USB!=n && USB_HID!=y
|
||||
depends on USB!=n && USB_HID!=y && EMBEDDED
|
||||
|
||||
config USB_KBD
|
||||
tristate "USB HIDBP Keyboard (simple Boot) support"
|
||||
|
@ -4,7 +4,7 @@
|
||||
* 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) 2006-2008 Jiri Kosina
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -641,9 +641,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type,
|
||||
unsigned int size;
|
||||
|
||||
list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
|
||||
size = ((report->size - 1) >> 3) + 1;
|
||||
if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
|
||||
size++;
|
||||
size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered;
|
||||
if (*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;
|
||||
|
||||
if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
|
||||
return -1;
|
||||
if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
|
||||
return -1;
|
||||
if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
|
||||
return -1;
|
||||
if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
|
||||
usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
|
||||
&usbhid->inbuf_dma);
|
||||
usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
|
||||
&usbhid->outbuf_dma);
|
||||
usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
|
||||
&usbhid->cr_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 0;
|
||||
@ -807,7 +808,7 @@ static int usbhid_start(struct hid_device *hid)
|
||||
int interval;
|
||||
|
||||
endpoint = &interface->endpoint[n].desc;
|
||||
if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
|
||||
if (!usb_endpoint_xfer_int(endpoint))
|
||||
continue;
|
||||
|
||||
interval = endpoint->bInterval;
|
||||
@ -876,6 +877,15 @@ static int usbhid_start(struct hid_device *hid)
|
||||
|
||||
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;
|
||||
|
||||
fail:
|
||||
|
@ -54,6 +54,7 @@ static const struct hid_blacklist {
|
||||
{ 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_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_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
struct hiddev {
|
||||
int exist;
|
||||
int open;
|
||||
struct mutex existancelock;
|
||||
wait_queue_head_t wait;
|
||||
struct hid_device *hid;
|
||||
struct list_head list;
|
||||
@ -63,6 +64,7 @@ struct hiddev_list {
|
||||
struct fasync_struct *fasync;
|
||||
struct hiddev *hiddev;
|
||||
struct list_head node;
|
||||
struct mutex thread_lock;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
struct hiddev_list *list;
|
||||
unsigned long flags;
|
||||
int res;
|
||||
|
||||
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;
|
||||
|
||||
if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
mutex_init(&list->thread_lock);
|
||||
|
||||
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;
|
||||
|
||||
if (!list->hiddev->open++)
|
||||
if (list->hiddev->exist)
|
||||
usbhid_open(hiddev_table[i]->hid);
|
||||
/*
|
||||
* no need for locking because the USB major number
|
||||
* 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;
|
||||
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);
|
||||
struct hiddev_list *list = file->private_data;
|
||||
int event_size;
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
|
||||
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)
|
||||
return 0;
|
||||
|
||||
/* lock against other threads */
|
||||
retval = mutex_lock_interruptible(&list->thread_lock);
|
||||
if (retval)
|
||||
return -ERESTARTSYS;
|
||||
|
||||
while (retval == 0) {
|
||||
if (list->head == list->tail) {
|
||||
add_wait_queue(&list->hiddev->wait, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
|
||||
|
||||
while (list->head == list->tail) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* let O_NONBLOCK tasks run */
|
||||
mutex_unlock(&list->thread_lock);
|
||||
schedule();
|
||||
if (mutex_lock_interruptible(&list->thread_lock))
|
||||
return -EINTR;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
while (list->head != list->tail &&
|
||||
retval + event_size <= count) {
|
||||
if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
|
||||
if (list->buffer[list->tail].field_index !=
|
||||
HID_FIELD_INDEX_NONE) {
|
||||
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) {
|
||||
struct hiddev_event event;
|
||||
|
||||
event.hid = list->buffer[list->tail].usage_code;
|
||||
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;
|
||||
}
|
||||
retval += sizeof(struct hiddev_event);
|
||||
}
|
||||
} else {
|
||||
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
|
||||
(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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
struct hid_field *field;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
void __user *user_arg = (void __user *)arg;
|
||||
int i;
|
||||
int i, r;
|
||||
|
||||
/* 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:
|
||||
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:
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (!hiddev->exist) {
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return -ENODEV;
|
||||
}
|
||||
usbhid_init_reports(hid);
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
usbhid_submit_report(hid, report, USB_DIR_IN);
|
||||
usbhid_wait_io(hid);
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist) {
|
||||
usbhid_submit_report(hid, report, USB_DIR_IN);
|
||||
usbhid_wait_io(hid);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
usbhid_wait_io(hid);
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist) {
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
usbhid_wait_io(hid);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
case HIDIOCGUSAGES:
|
||||
case HIDIOCSUSAGES:
|
||||
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:
|
||||
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)))
|
||||
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);
|
||||
if (retval) {
|
||||
err_hid("Not able to get a minor for this device.");
|
||||
kfree(hiddev);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -839,7 +900,9 @@ void hiddev_disconnect(struct hid_device *hid)
|
||||
struct hiddev *hiddev = hid->hiddev;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
hiddev->exist = 0;
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
|
||||
usb_deregister_dev(usbhid->intf, &hiddev_class);
|
||||
|
@ -40,6 +40,16 @@ int usbhid_open(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);
|
||||
|
||||
/* 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
|
||||
* from struct hid_device->driver_data
|
||||
|
@ -2,13 +2,16 @@
|
||||
* TI OMAP I2C master mode driver
|
||||
*
|
||||
* 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) 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -33,8 +36,14 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/platform_device.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 */
|
||||
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
|
||||
@ -43,6 +52,8 @@
|
||||
#define OMAP_I2C_IE_REG 0x04
|
||||
#define OMAP_I2C_STAT_REG 0x08
|
||||
#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_BUF_REG 0x14
|
||||
#define OMAP_I2C_CNT_REG 0x18
|
||||
@ -55,8 +66,11 @@
|
||||
#define OMAP_I2C_SCLL_REG 0x34
|
||||
#define OMAP_I2C_SCLH_REG 0x38
|
||||
#define OMAP_I2C_SYSTEST_REG 0x3c
|
||||
#define OMAP_I2C_BUFSTAT_REG 0x40
|
||||
|
||||
/* 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_RRDY (1 << 3) /* RX data 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 */
|
||||
|
||||
/* 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_ROVR (1 << 11) /* Receive overrun */
|
||||
#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_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): */
|
||||
#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_TXFIF_CLR (1 << 6) /* TX FIFO Clear */
|
||||
|
||||
/* I2C Configuration Register (OMAP_I2C_CON): */
|
||||
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
|
||||
#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_MST (1 << 10) /* Master/slave mode */
|
||||
#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_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): */
|
||||
#ifdef DEBUG
|
||||
#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 */
|
||||
#endif
|
||||
|
||||
/* I2C System Status register (OMAP_I2C_SYSS): */
|
||||
#define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */
|
||||
/* OCP_SYSSTATUS bit definitions */
|
||||
#define SYSS_RESETDONE_MASK (1 << 0)
|
||||
|
||||
/* I2C System Configuration Register (OMAP_I2C_SYSC): */
|
||||
#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
|
||||
/* OCP_SYSCONFIG bit definitions */
|
||||
#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 device *dev;
|
||||
@ -123,11 +165,17 @@ struct omap_i2c_dev {
|
||||
struct clk *fclk; /* Functional clock */
|
||||
struct completion cmd_complete;
|
||||
struct resource *ioarea;
|
||||
u32 speed; /* Speed of bus in Khz */
|
||||
u16 cmd_err;
|
||||
u8 *buf;
|
||||
size_t buf_len;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
if (IS_ERR(dev->iclk)) {
|
||||
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)
|
||||
{
|
||||
WARN_ON(!dev->idle);
|
||||
|
||||
if (dev->iclk != NULL)
|
||||
clk_enable(dev->iclk);
|
||||
clk_enable(dev->fclk);
|
||||
dev->idle = 0;
|
||||
if (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)
|
||||
{
|
||||
u16 iv;
|
||||
|
||||
dev->idle = 1;
|
||||
WARN_ON(dev->idle);
|
||||
|
||||
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
|
||||
if (dev->rev1)
|
||||
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
|
||||
else
|
||||
if (dev->rev < OMAP_I2C_REV_2) {
|
||||
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
|
||||
} else {
|
||||
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);
|
||||
if (dev->iclk != NULL)
|
||||
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)
|
||||
{
|
||||
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 timeout;
|
||||
unsigned long internal_clk = 0;
|
||||
|
||||
if (!dev->rev1) {
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
|
||||
if (dev->rev >= OMAP_I2C_REV_2) {
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
|
||||
/* For some reason we need to set the EN bit before the
|
||||
* reset done bit gets set. */
|
||||
timeout = jiffies + OMAP_I2C_TIMEOUT;
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
|
||||
while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
|
||||
OMAP_I2C_SYSS_RDONE)) {
|
||||
SYSS_RESETDONE_MASK)) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_warn(dev->dev, "timeout waiting "
|
||||
"for controller reset\n");
|
||||
@ -223,6 +281,33 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
|
||||
}
|
||||
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);
|
||||
|
||||
@ -249,27 +334,65 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
|
||||
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: */
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
|
||||
|
||||
/* Program desired operating rate */
|
||||
fclk_rate /= (psc + 1) * 1000;
|
||||
if (psc > 2)
|
||||
psc = 2;
|
||||
/* SCL low and high time values */
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
|
||||
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
|
||||
fclk_rate / (clock * 2) - 7 + psc);
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
|
||||
fclk_rate / (clock * 2) - 7 + psc);
|
||||
if (dev->fifo_size)
|
||||
/* Note: setup required fifo size - 1 */
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
|
||||
(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: */
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
|
||||
|
||||
/* Enable interrupts */
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
|
||||
(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
|
||||
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
|
||||
OMAP_I2C_IE_AL));
|
||||
(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
|
||||
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
|
||||
OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
|
||||
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 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);
|
||||
|
||||
/* 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);
|
||||
dev->cmd_err = 0;
|
||||
|
||||
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)
|
||||
w |= OMAP_I2C_CON_XA;
|
||||
if (!(msg->flags & I2C_M_RD))
|
||||
w |= OMAP_I2C_CON_TRX;
|
||||
if (stop)
|
||||
|
||||
if (!dev->b_hw && stop)
|
||||
w |= OMAP_I2C_CON_STP;
|
||||
|
||||
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;
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -376,7 +538,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* rev1 devices are apparently only on some 15xx */
|
||||
#ifdef CONFIG_ARCH_OMAP15XX
|
||||
|
||||
static irqreturn_t
|
||||
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;
|
||||
}
|
||||
#else
|
||||
#define omap_i2c_rev1_isr NULL
|
||||
#endif
|
||||
|
||||
static irqreturn_t
|
||||
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;
|
||||
u16 bits;
|
||||
u16 stat, w;
|
||||
int count = 0;
|
||||
int err, count = 0;
|
||||
|
||||
if (dev->idle)
|
||||
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);
|
||||
|
||||
if (stat & OMAP_I2C_STAT_ARDY) {
|
||||
omap_i2c_complete_cmd(dev, 0);
|
||||
err = 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;
|
||||
}
|
||||
if (stat & OMAP_I2C_STAT_RRDY) {
|
||||
w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
|
||||
if (dev->buf_len) {
|
||||
*dev->buf++ = w;
|
||||
dev->buf_len--;
|
||||
if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
|
||||
u8 num_bytes = 1;
|
||||
if (dev->fifo_size) {
|
||||
if (stat & OMAP_I2C_STAT_XRDY)
|
||||
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) {
|
||||
*dev->buf++ = w >> 8;
|
||||
w = *dev->buf++;
|
||||
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
|
||||
dev_err(dev->dev, "RRDY IRQ while no data "
|
||||
"requested\n");
|
||||
omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
|
||||
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);
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
|
||||
}
|
||||
omap_i2c_ack_stat(dev,
|
||||
stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
@ -549,13 +766,15 @@ static const struct i2c_algorithm omap_i2c_algo = {
|
||||
.functionality = omap_i2c_func,
|
||||
};
|
||||
|
||||
static int
|
||||
static int __init
|
||||
omap_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_i2c_dev *dev;
|
||||
struct i2c_adapter *adap;
|
||||
struct resource *mem, *irq, *ioarea;
|
||||
irq_handler_t isr;
|
||||
int r;
|
||||
u32 speed = 0;
|
||||
|
||||
/* NOTE: driver uses the static register mapping */
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@ -576,17 +795,19 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (clock > 200)
|
||||
clock = 400; /* Fast mode */
|
||||
else
|
||||
clock = 100; /* Standard mode */
|
||||
|
||||
dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
r = -ENOMEM;
|
||||
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->irq = irq->start;
|
||||
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);
|
||||
|
||||
if (cpu_is_omap15xx())
|
||||
dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
|
||||
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
|
||||
|
||||
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 */
|
||||
omap_i2c_init(dev);
|
||||
|
||||
r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
|
||||
0, pdev->name, dev);
|
||||
isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
|
||||
r = request_irq(dev->irq, isr, 0, pdev->name, dev);
|
||||
|
||||
if (r) {
|
||||
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
|
||||
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",
|
||||
pdev->id, r >> 4, r & 0xf, clock);
|
||||
pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
|
||||
|
||||
omap_i2c_idle(dev);
|
||||
|
||||
adap = &dev->adapter;
|
||||
i2c_set_adapdata(adap, dev);
|
||||
@ -635,8 +873,6 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
omap_i2c_idle(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
|
@ -35,11 +35,9 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <mach/regs-gpio.h>
|
||||
#include <plat/regs-iic.h>
|
||||
#include <plat/iic.h>
|
||||
|
||||
@ -64,6 +62,7 @@ struct s3c24xx_i2c {
|
||||
unsigned int msg_ptr;
|
||||
|
||||
unsigned int tx_setup;
|
||||
unsigned int irq;
|
||||
|
||||
enum s3c24xx_i2c_state state;
|
||||
unsigned long clkrate;
|
||||
@ -71,7 +70,6 @@ struct s3c24xx_i2c {
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct resource *irq;
|
||||
struct resource *ioarea;
|
||||
struct i2c_adapter adap;
|
||||
|
||||
@ -80,16 +78,7 @@ struct s3c24xx_i2c {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* default platform data to use if not supplied in the platform_device
|
||||
*/
|
||||
|
||||
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,
|
||||
};
|
||||
/* default platform data removed, dev should always carry data. */
|
||||
|
||||
/* s3c24xx_i2c_is2440()
|
||||
*
|
||||
@ -103,21 +92,6 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *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
|
||||
*
|
||||
* 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 = NULL;
|
||||
i2c->msg_idx ++;
|
||||
i2c->msg_idx++;
|
||||
i2c->msg_num = 0;
|
||||
if (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)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
|
||||
tmp = readl(i2c->regs + S3C2410_IICCON);
|
||||
writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
|
||||
|
||||
}
|
||||
|
||||
static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
|
||||
tmp = readl(i2c->regs + S3C2410_IICCON);
|
||||
writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
|
||||
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
|
||||
tmp = readl(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)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
|
||||
tmp = readl(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
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
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)
|
||||
addr ^= 1;
|
||||
|
||||
// todo - check for wether ack wanted or not
|
||||
/* todo - check for wether ack wanted or not */
|
||||
s3c24xx_i2c_enable_ack(i2c);
|
||||
|
||||
iiccon = readl(i2c->regs + S3C2410_IICCON);
|
||||
writel(stat, i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
|
||||
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
|
||||
writeb(addr, i2c->regs + S3C2410_IICDS);
|
||||
|
||||
|
||||
/* delay here to ensure the data byte has gotten onto the bus
|
||||
* 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);
|
||||
writel(iiccon, i2c->regs + S3C2410_IICCON);
|
||||
|
||||
stat |= S3C2410_IICSTAT_START;
|
||||
|
||||
stat |= S3C2410_IICSTAT_START;
|
||||
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");
|
||||
|
||||
/* stop the transfer */
|
||||
iicstat &= ~ S3C2410_IICSTAT_START;
|
||||
iicstat &= ~S3C2410_IICSTAT_START;
|
||||
writel(iicstat, i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
|
||||
i2c->state = STATE_STOP;
|
||||
|
||||
|
||||
s3c24xx_i2c_master_complete(i2c, ret);
|
||||
s3c24xx_i2c_disable_irq(i2c);
|
||||
}
|
||||
@ -241,7 +213,7 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
|
||||
|
||||
/* 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)
|
||||
@ -289,14 +261,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
||||
|
||||
case STATE_STOP:
|
||||
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
|
||||
s3c24xx_i2c_disable_irq(i2c);
|
||||
s3c24xx_i2c_disable_irq(i2c);
|
||||
goto out_ack;
|
||||
|
||||
case STATE_START:
|
||||
/* last thing we did was send a start condition on the
|
||||
* bus, or started a new i2c message
|
||||
*/
|
||||
|
||||
|
||||
if (iicstat & S3C2410_IICSTAT_LASTBIT &&
|
||||
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
|
||||
/* 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)
|
||||
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 */
|
||||
|
||||
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)) {
|
||||
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");
|
||||
|
||||
i2c->msg_ptr = 0;
|
||||
i2c->msg_idx ++;
|
||||
i2c->msg_idx++;
|
||||
i2c->msg++;
|
||||
|
||||
|
||||
/* check to see if we need to do another message */
|
||||
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;
|
||||
} else {
|
||||
|
||||
/* send the new start */
|
||||
s3c24xx_i2c_message_start(i2c, i2c->msg);
|
||||
i2c->state = STATE_START;
|
||||
@ -389,7 +360,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
||||
break;
|
||||
|
||||
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
|
||||
* 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);
|
||||
i2c->msg->buf[i2c->msg_ptr++] = byte;
|
||||
|
||||
prepare_read:
|
||||
prepare_read:
|
||||
if (is_msglast(i2c)) {
|
||||
/* last byte of buffer */
|
||||
|
||||
if (is_lastmsg(i2c))
|
||||
s3c24xx_i2c_disable_ack(i2c);
|
||||
|
||||
|
||||
} else if (is_msgend(i2c)) {
|
||||
/* ok, we've read the entire buffer, see if there
|
||||
* 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 */
|
||||
|
||||
out_ack:
|
||||
tmp = readl(i2c->regs + S3C2410_IICCON);
|
||||
tmp = readl(i2c->regs + S3C2410_IICCON);
|
||||
tmp &= ~S3C2410_IICCON_IRQPEND;
|
||||
writel(tmp, i2c->regs + S3C2410_IICCON);
|
||||
out:
|
||||
@ -450,19 +421,19 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
|
||||
status = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
if (status & S3C2410_IICSTAT_ARBITR) {
|
||||
// deal with arbitration loss
|
||||
/* deal with arbitration loss */
|
||||
dev_err(i2c->dev, "deal with arbitration loss\n");
|
||||
}
|
||||
|
||||
if (i2c->state == STATE_IDLE) {
|
||||
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;
|
||||
writel(tmp, i2c->regs + S3C2410_IICCON);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/* pretty much this leaves us with the fact that we've
|
||||
* 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) {
|
||||
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
|
||||
if (!(iicstat & S3C2410_IICSTAT_BUSBUSY))
|
||||
return 0;
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
dev_dbg(i2c->dev, "timeout: GPEDAT is %08x\n",
|
||||
__raw_readl(S3C2410_GPEDAT));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -503,7 +471,8 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
|
||||
* 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;
|
||||
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_message_start(i2c, msgs);
|
||||
spin_unlock_irq(&i2c->lock);
|
||||
|
||||
|
||||
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
||||
|
||||
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 */
|
||||
|
||||
if (timeout == 0)
|
||||
@ -591,19 +560,6 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
|
||||
.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
|
||||
*
|
||||
* 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;
|
||||
|
||||
return (diff >= -2 && diff <= 2);
|
||||
return diff >= -2 && diff <= 2;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct s3c2410_platform_i2c *pdata;
|
||||
struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
|
||||
unsigned long clkin = clk_get_rate(i2c->clk);
|
||||
unsigned int divs, div1;
|
||||
u32 iiccon;
|
||||
@ -663,10 +619,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
|
||||
int start, end;
|
||||
|
||||
i2c->clkrate = clkin;
|
||||
|
||||
pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
|
||||
clkin /= 1000; /* clkin now in KHz */
|
||||
|
||||
|
||||
dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
|
||||
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
|
||||
*
|
||||
* 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)
|
||||
@ -785,15 +739,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
|
||||
|
||||
/* get the plafrom data */
|
||||
|
||||
pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
|
||||
pdata = i2c->dev->platform_data;
|
||||
|
||||
/* inititalise the gpio */
|
||||
|
||||
s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA);
|
||||
s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL);
|
||||
if (pdata->cfg_gpio)
|
||||
pdata->cfg_gpio(to_platform_device(i2c->dev));
|
||||
|
||||
/* write slave address */
|
||||
|
||||
|
||||
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
|
||||
|
||||
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)
|
||||
{
|
||||
struct s3c24xx_i2c *i2c = &s3c24xx_i2c;
|
||||
struct s3c24xx_i2c *i2c;
|
||||
struct s3c2410_platform_i2c *pdata;
|
||||
struct resource *res;
|
||||
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 */
|
||||
|
||||
@ -878,7 +852,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
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 */
|
||||
|
||||
@ -892,29 +867,23 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
goto err_iomap;
|
||||
|
||||
/* 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);
|
||||
if (res == NULL) {
|
||||
i2c->irq = ret = platform_get_irq(pdev, 0);
|
||||
if (ret <= 0) {
|
||||
dev_err(&pdev->dev, "cannot find IRQ\n");
|
||||
ret = -ENOENT;
|
||||
goto err_iomap;
|
||||
}
|
||||
|
||||
ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
|
||||
pdev->name, i2c);
|
||||
ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
|
||||
dev_name(&pdev->dev), i2c);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
i2c->irq = res;
|
||||
|
||||
dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
|
||||
(unsigned long)res->start);
|
||||
|
||||
ret = s3c24xx_i2c_register_cpufreq(i2c);
|
||||
if (ret < 0) {
|
||||
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);
|
||||
|
||||
err_irq:
|
||||
free_irq(i2c->irq->start, i2c);
|
||||
free_irq(i2c->irq, i2c);
|
||||
|
||||
err_iomap:
|
||||
iounmap(i2c->regs);
|
||||
@ -958,6 +927,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
clk_put(i2c->clk);
|
||||
|
||||
err_noclk:
|
||||
kfree(i2c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -973,7 +943,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
|
||||
s3c24xx_i2c_deregister_cpufreq(i2c);
|
||||
|
||||
i2c_del_adapter(&i2c->adap);
|
||||
free_irq(i2c->irq->start, i2c);
|
||||
free_irq(i2c->irq, i2c);
|
||||
|
||||
clk_disable(i2c->clk);
|
||||
clk_put(i2c->clk);
|
||||
@ -982,6 +952,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
|
||||
|
||||
release_resource(i2c->ioarea);
|
||||
kfree(i2c->ioarea);
|
||||
kfree(i2c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -126,19 +126,6 @@ config ISP1301_OMAP
|
||||
This driver can also be built as a module. If so, the module
|
||||
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
|
||||
tristate "Maxim MAX6875 Power supply supervisor"
|
||||
depends on EXPERIMENTAL
|
||||
@ -164,16 +151,6 @@ config SENSORS_TSL2550
|
||||
This driver can also be built as a module. If so, the module
|
||||
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
|
||||
tristate "MPC8349E-mITX MCU driver"
|
||||
depends on I2C && PPC_83xx
|
||||
|
@ -19,8 +19,6 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
|
||||
obj-$(CONFIG_PCF8575) += pcf8575.o
|
||||
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.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_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
|
||||
|
||||
|
@ -57,9 +57,6 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
|
||||
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_private = data;
|
||||
if ((mode & S_IFMT) == S_IFDIR) {
|
||||
|
@ -1519,7 +1519,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
|
||||
int digit2 = 0;
|
||||
if (!isdigit(*s)) return -3;
|
||||
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 == ' ') {
|
||||
bmask |= (1 << digit1);
|
||||
digit1 = 0;
|
||||
@ -1530,7 +1530,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
|
||||
s++;
|
||||
if (!isdigit(*s)) return -3;
|
||||
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 (digit1 > digit2)
|
||||
for (i = digit2; i <= digit1 ; i++)
|
||||
|
@ -111,8 +111,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent)
|
||||
goto fail;
|
||||
inode->i_ino = 1;
|
||||
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_op = &simple_dir_inode_operations;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
|
@ -3,9 +3,10 @@
|
||||
#
|
||||
|
||||
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-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
|
||||
md-mod-objs := md.o bitmap.o
|
||||
raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \
|
||||
|
@ -1322,11 +1322,7 @@ static int __init dm_crypt_init(void)
|
||||
|
||||
static void __exit dm_crypt_exit(void)
|
||||
{
|
||||
int r = dm_unregister_target(&crypt_target);
|
||||
|
||||
if (r < 0)
|
||||
DMERR("unregister failed %d", r);
|
||||
|
||||
dm_unregister_target(&crypt_target);
|
||||
kmem_cache_destroy(_crypt_io_pool);
|
||||
}
|
||||
|
||||
|
@ -364,11 +364,7 @@ bad_queue:
|
||||
|
||||
static void __exit dm_delay_exit(void)
|
||||
{
|
||||
int r = dm_unregister_target(&delay_target);
|
||||
|
||||
if (r < 0)
|
||||
DMERR("unregister failed %d", r);
|
||||
|
||||
dm_unregister_target(&delay_target);
|
||||
kmem_cache_destroy(delayed_cache);
|
||||
destroy_workqueue(kdelayd_wq);
|
||||
}
|
||||
|
@ -1,756 +1,45 @@
|
||||
/*
|
||||
* dm-exception-store.c
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "dm-snap.h"
|
||||
#include "dm-exception-store.h"
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dm-io.h>
|
||||
#include <linux/dm-kcopyd.h>
|
||||
|
||||
#define DM_MSG_PREFIX "snapshots"
|
||||
#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
|
||||
#define DM_MSG_PREFIX "snapshot exception stores"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* 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 dm_exception_store_init(void)
|
||||
{
|
||||
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);
|
||||
if (r)
|
||||
return r;
|
||||
r = dm_persistent_snapshot_init();
|
||||
if (r) {
|
||||
DMERR("Unable to register persistent exception store type");
|
||||
goto persistent_fail;
|
||||
}
|
||||
|
||||
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);
|
||||
persistent_fail:
|
||||
dm_persistent_snapshot_exit();
|
||||
transient_fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int write_header(struct pstore *ps)
|
||||
void dm_exception_store_exit(void)
|
||||
{
|
||||
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 *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;
|
||||
dm_persistent_snapshot_exit();
|
||||
dm_transient_snapshot_exit();
|
||||
}
|
||||
|
148
drivers/md/dm-exception-store.h
Normal file
148
drivers/md/dm-exception-store.h
Normal 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 */
|
@ -233,7 +233,7 @@ static void __hash_remove(struct hash_cell *hc)
|
||||
}
|
||||
|
||||
if (hc->new_map)
|
||||
dm_table_put(hc->new_map);
|
||||
dm_table_destroy(hc->new_map);
|
||||
dm_put(hc->md);
|
||||
free_cell(hc);
|
||||
}
|
||||
@ -827,8 +827,8 @@ static int do_resume(struct dm_ioctl *param)
|
||||
|
||||
r = dm_swap_table(md, new_map);
|
||||
if (r) {
|
||||
dm_table_destroy(new_map);
|
||||
dm_put(md);
|
||||
dm_table_put(new_map);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -836,8 +836,6 @@ static int do_resume(struct dm_ioctl *param)
|
||||
set_disk_ro(dm_disk(md), 0);
|
||||
else
|
||||
set_disk_ro(dm_disk(md), 1);
|
||||
|
||||
dm_table_put(new_map);
|
||||
}
|
||||
|
||||
if (dm_suspended(md))
|
||||
@ -1080,7 +1078,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
|
||||
}
|
||||
|
||||
if (hc->new_map)
|
||||
dm_table_put(hc->new_map);
|
||||
dm_table_destroy(hc->new_map);
|
||||
hc->new_map = t;
|
||||
up_write(&_hash_lock);
|
||||
|
||||
@ -1109,7 +1107,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size)
|
||||
}
|
||||
|
||||
if (hc->new_map) {
|
||||
dm_table_put(hc->new_map);
|
||||
dm_table_destroy(hc->new_map);
|
||||
hc->new_map = NULL;
|
||||
}
|
||||
|
||||
@ -1550,8 +1548,10 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid)
|
||||
goto out;
|
||||
}
|
||||
|
||||
strcpy(name, hc->name);
|
||||
strcpy(uuid, hc->uuid ? : "");
|
||||
if (name)
|
||||
strcpy(name, hc->name);
|
||||
if (uuid)
|
||||
strcpy(uuid, hc->uuid ? : "");
|
||||
|
||||
out:
|
||||
up_read(&_hash_lock);
|
||||
|
@ -142,6 +142,7 @@ static struct target_type linear_target = {
|
||||
.status = linear_status,
|
||||
.ioctl = linear_ioctl,
|
||||
.merge = linear_merge,
|
||||
.features = DM_TARGET_SUPPORTS_BARRIERS,
|
||||
};
|
||||
|
||||
int __init dm_linear_init(void)
|
||||
@ -156,8 +157,5 @@ int __init dm_linear_init(void)
|
||||
|
||||
void dm_linear_exit(void)
|
||||
{
|
||||
int r = dm_unregister_target(&linear_target);
|
||||
|
||||
if (r < 0)
|
||||
DMERR("unregister failed %d", r);
|
||||
dm_unregister_target(&linear_target);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@ -362,10 +360,15 @@ static int read_header(struct log_c *log)
|
||||
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);
|
||||
return rw_header(log, WRITE);
|
||||
if (region_size < 2 || region_size > ti->len)
|
||||
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", ®ion_size) != 1) {
|
||||
DMWARN("invalid region size string");
|
||||
if (sscanf(argv[0], "%u", ®ion_size) != 1 ||
|
||||
!_check_region_size(ti, region_size)) {
|
||||
DMWARN("invalid region size %s", argv[0]);
|
||||
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) +
|
||||
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->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,
|
||||
PAGE_SIZE));
|
||||
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);
|
||||
if (!lc->disk_header) {
|
||||
DMWARN("couldn't allocate disk log buffer");
|
||||
dm_io_client_destroy(lc->io_req.client);
|
||||
kfree(lc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lc->io_req.mem.ptr.vma = lc->disk_header;
|
||||
lc->clean_bits = (void *)lc->disk_header +
|
||||
(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");
|
||||
if (!dev)
|
||||
vfree(lc->clean_bits);
|
||||
else
|
||||
dm_io_client_destroy(lc->io_req.client);
|
||||
vfree(lc->disk_header);
|
||||
kfree(lc);
|
||||
return -ENOMEM;
|
||||
@ -495,6 +513,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
|
||||
vfree(lc->sync_bits);
|
||||
if (!dev)
|
||||
vfree(lc->clean_bits);
|
||||
else
|
||||
dm_io_client_destroy(lc->io_req.client);
|
||||
vfree(lc->disk_header);
|
||||
kfree(lc);
|
||||
return -ENOMEM;
|
||||
@ -631,8 +651,10 @@ static int disk_resume(struct dm_dirty_log *log)
|
||||
/* set the correct number of regions in the header */
|
||||
lc->header.nr_regions = lc->region_count;
|
||||
|
||||
header_to_disk(&lc->header, lc->disk_header);
|
||||
|
||||
/* write the new header */
|
||||
r = write_header(lc);
|
||||
r = rw_header(lc, WRITE);
|
||||
if (r) {
|
||||
DMWARN("%s: Failed to write header on dirty region log device",
|
||||
lc->log_dev->name);
|
||||
@ -682,7 +704,7 @@ static int disk_flush(struct dm_dirty_log *log)
|
||||
if (!lc->touched)
|
||||
return 0;
|
||||
|
||||
r = write_header(lc);
|
||||
r = rw_header(lc, WRITE);
|
||||
if (r)
|
||||
fail_log_device(lc);
|
||||
else
|
||||
|
@ -889,7 +889,7 @@ static int fail_path(struct pgpath *pgpath)
|
||||
dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
|
||||
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);
|
||||
|
||||
out:
|
||||
@ -932,7 +932,7 @@ static int reinstate_path(struct pgpath *pgpath)
|
||||
dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
|
||||
pgpath->path.dev->name, m->nr_valid_paths);
|
||||
|
||||
queue_work(kmultipathd, &m->trigger_event);
|
||||
schedule_work(&m->trigger_event);
|
||||
|
||||
out:
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
queue_work(kmultipathd, &m->trigger_event);
|
||||
schedule_work(&m->trigger_event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1495,14 +1495,10 @@ static int __init dm_multipath_init(void)
|
||||
|
||||
static void __exit dm_multipath_exit(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
destroy_workqueue(kmpath_handlerd);
|
||||
destroy_workqueue(kmultipathd);
|
||||
|
||||
r = dm_unregister_target(&multipath_target);
|
||||
if (r < 0)
|
||||
DMERR("target unregister failed %d", r);
|
||||
dm_unregister_target(&multipath_target);
|
||||
kmem_cache_destroy(_mpio_cache);
|
||||
}
|
||||
|
||||
|
@ -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 *new;
|
||||
|
||||
if (!errors_handled(ms))
|
||||
return;
|
||||
|
||||
/*
|
||||
* error_count is used for nothing more than a
|
||||
* 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))
|
||||
return;
|
||||
|
||||
if (!errors_handled(ms))
|
||||
return;
|
||||
|
||||
if (m != get_default_mirror(ms))
|
||||
goto out;
|
||||
|
||||
@ -808,12 +808,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
|
||||
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,
|
||||
unsigned int mirror, char **argv)
|
||||
{
|
||||
@ -872,12 +866,6 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1300,11 +1288,7 @@ static int __init dm_mirror_init(void)
|
||||
|
||||
static void __exit dm_mirror_exit(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = dm_unregister_target(&mirror_target);
|
||||
if (r < 0)
|
||||
DMERR("unregister failed %d", r);
|
||||
dm_unregister_target(&mirror_target);
|
||||
}
|
||||
|
||||
/* Module hooks */
|
||||
|
704
drivers/md/dm-snap-persistent.c
Normal file
704
drivers/md/dm-snap-persistent.c
Normal 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)
|
||||
{
|
||||
}
|
98
drivers/md/dm-snap-transient.c
Normal file
98
drivers/md/dm-snap-transient.c
Normal 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)
|
||||
{
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/device-mapper.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kdev_t.h>
|
||||
@ -20,6 +21,7 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/dm-kcopyd.h>
|
||||
|
||||
#include "dm-exception-store.h"
|
||||
#include "dm-snap.h"
|
||||
#include "dm-bio-list.h"
|
||||
|
||||
@ -428,8 +430,13 @@ out:
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
/* 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) {
|
||||
ti->error = "Failed to read snapshot metadata";
|
||||
goto bad_load_and_register;
|
||||
@ -735,7 +742,7 @@ static void snapshot_dtr(struct dm_target *ti)
|
||||
unregister_snapshot(s);
|
||||
|
||||
while (atomic_read(&s->pending_exceptions_count))
|
||||
yield();
|
||||
msleep(1);
|
||||
/*
|
||||
* Ensure instructions in mempool_destroy aren't reordered
|
||||
* 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,
|
||||
* 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))
|
||||
yield();
|
||||
msleep(1);
|
||||
|
||||
/*
|
||||
* Add a proper exception, and remove the
|
||||
@ -1404,6 +1411,12 @@ static int __init dm_snapshot_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = dm_exception_store_init();
|
||||
if (r) {
|
||||
DMERR("Failed to initialize exception stores");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dm_register_target(&snapshot_target);
|
||||
if (r) {
|
||||
DMERR("snapshot target register failed %d", r);
|
||||
@ -1452,39 +1465,34 @@ static int __init dm_snapshot_init(void)
|
||||
|
||||
return 0;
|
||||
|
||||
bad_pending_pool:
|
||||
bad_pending_pool:
|
||||
kmem_cache_destroy(tracked_chunk_cache);
|
||||
bad5:
|
||||
bad5:
|
||||
kmem_cache_destroy(pending_cache);
|
||||
bad4:
|
||||
bad4:
|
||||
kmem_cache_destroy(exception_cache);
|
||||
bad3:
|
||||
bad3:
|
||||
exit_origin_hash();
|
||||
bad2:
|
||||
bad2:
|
||||
dm_unregister_target(&origin_target);
|
||||
bad1:
|
||||
bad1:
|
||||
dm_unregister_target(&snapshot_target);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit dm_snapshot_exit(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
destroy_workqueue(ksnapd);
|
||||
|
||||
r = dm_unregister_target(&snapshot_target);
|
||||
if (r)
|
||||
DMERR("snapshot unregister failed %d", r);
|
||||
|
||||
r = dm_unregister_target(&origin_target);
|
||||
if (r)
|
||||
DMERR("origin unregister failed %d", r);
|
||||
dm_unregister_target(&snapshot_target);
|
||||
dm_unregister_target(&origin_target);
|
||||
|
||||
exit_origin_hash();
|
||||
kmem_cache_destroy(pending_cache);
|
||||
kmem_cache_destroy(exception_cache);
|
||||
kmem_cache_destroy(tracked_chunk_cache);
|
||||
|
||||
dm_exception_store_exit();
|
||||
}
|
||||
|
||||
/* Module hooks */
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* dm-snapshot.c
|
||||
*
|
||||
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
@ -10,6 +8,7 @@
|
||||
#define DM_SNAPSHOT_H
|
||||
|
||||
#include <linux/device-mapper.h>
|
||||
#include "dm-exception-store.h"
|
||||
#include "dm-bio-list.h"
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/workqueue.h>
|
||||
@ -20,116 +19,6 @@ struct exception_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(x) ((unsigned long)(x) & \
|
||||
(DM_TRACKED_CHUNK_HASH_SIZE - 1))
|
||||
@ -172,7 +61,7 @@ struct dm_snapshot {
|
||||
spinlock_t pe_lock;
|
||||
|
||||
/* The on disk metadata handler */
|
||||
struct exception_store store;
|
||||
struct dm_exception_store store;
|
||||
|
||||
struct dm_kcopyd_client *kcopyd_client;
|
||||
|
||||
@ -186,20 +75,6 @@ struct dm_snapshot {
|
||||
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.
|
||||
*/
|
||||
|
@ -337,9 +337,7 @@ int __init dm_stripe_init(void)
|
||||
|
||||
void dm_stripe_exit(void)
|
||||
{
|
||||
if (dm_unregister_target(&stripe_target))
|
||||
DMWARN("target unregistration failed");
|
||||
|
||||
dm_unregister_target(&stripe_target);
|
||||
destroy_workqueue(kstriped);
|
||||
|
||||
return;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user